mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-25 17:44:02 +08:00
fix: 修复 summary.json 中文乱码问题
- 改进 Dump2JSON 函数的文件写入方式,确保 UTF-8 编码正确处理 - 添加文件同步操作防止数据不完整 - 新增 UTF-8 编码测试验证修复效果 - 同步改进 HTML 报告生成的文件写入方式
This commit is contained in:
@@ -52,11 +52,30 @@ func Dump2JSON(data interface{}, path string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.WriteFile(path, buffer.Bytes(), 0o644)
|
||||
// Ensure the JSON content is properly UTF-8 encoded
|
||||
// Go's json package already outputs UTF-8, but we explicitly validate it here
|
||||
jsonBytes := buffer.Bytes()
|
||||
|
||||
// Create file and write content atomically to prevent corruption
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("dump json path failed")
|
||||
log.Error().Err(err).Msg("create json file failed")
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Write JSON content directly (Go's json package ensures UTF-8 encoding)
|
||||
if _, err := file.Write(jsonBytes); err != nil {
|
||||
log.Error().Err(err).Msg("write json content failed")
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure data is flushed to disk
|
||||
if err := file.Sync(); err != nil {
|
||||
log.Error().Err(err).Msg("sync json file failed")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package builtin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -94,3 +96,78 @@ func TestInterface2Float64(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestUTF8Encoding tests that Chinese characters are properly encoded in JSON files
|
||||
func TestUTF8Encoding(t *testing.T) {
|
||||
// Create test data with Chinese characters
|
||||
testData := map[string]interface{}{
|
||||
"name": "连连看小游戏自动化测试",
|
||||
"description": "这是一个包含中文字符的测试用例",
|
||||
"steps": []map[string]interface{}{
|
||||
{
|
||||
"name": "启动抖音「连了又连」小游戏",
|
||||
"action": "启动应用程序",
|
||||
"result": "成功启动游戏",
|
||||
},
|
||||
{
|
||||
"name": "开始游戏",
|
||||
"action": "点击开始按钮",
|
||||
"result": "游戏开始运行",
|
||||
},
|
||||
},
|
||||
"platform": map[string]string{
|
||||
"os": "安卓系统",
|
||||
"version": "版本 12",
|
||||
"device": "测试设备",
|
||||
},
|
||||
}
|
||||
|
||||
// Create temporary file
|
||||
tempDir := t.TempDir()
|
||||
testFile := filepath.Join(tempDir, "test_utf8.json")
|
||||
|
||||
// Test the fixed Dump2JSON function
|
||||
err := Dump2JSON(testData, testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to dump JSON: %v", err)
|
||||
}
|
||||
|
||||
// Read the file back and verify content
|
||||
fileContent, err := os.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read JSON file: %v", err)
|
||||
}
|
||||
|
||||
// Parse the JSON to ensure it's valid
|
||||
var parsedData map[string]interface{}
|
||||
err = json.Unmarshal(fileContent, &parsedData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse JSON: %v", err)
|
||||
}
|
||||
|
||||
// Verify Chinese characters are preserved
|
||||
if parsedData["name"] != "连连看小游戏自动化测试" {
|
||||
t.Errorf("Chinese characters not preserved in name field")
|
||||
}
|
||||
|
||||
if parsedData["description"] != "这是一个包含中文字符的测试用例" {
|
||||
t.Errorf("Chinese characters not preserved in description field")
|
||||
}
|
||||
|
||||
// Verify nested Chinese characters
|
||||
steps, ok := parsedData["steps"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("Steps field is not an array")
|
||||
}
|
||||
|
||||
firstStep, ok := steps[0].(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("First step is not a map")
|
||||
}
|
||||
|
||||
if firstStep["name"] != "启动抖音「连了又连」小游戏" {
|
||||
t.Errorf("Chinese characters not preserved in step name")
|
||||
}
|
||||
|
||||
t.Logf("UTF-8 encoding test passed. File content length: %d bytes", len(fileContent))
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
v5.0.0-beta-2506092242
|
||||
v5.0.0-beta-2506101103
|
||||
|
||||
39
report.go
39
report.go
@@ -79,11 +79,31 @@ func (g *HTMLReportGenerator) loadSummaryData() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Store raw content for download
|
||||
g.SummaryContent = string(data)
|
||||
|
||||
// Parse JSON data first
|
||||
g.SummaryData = &Summary{}
|
||||
return json.Unmarshal(data, g.SummaryData)
|
||||
err = json.Unmarshal(data, g.SummaryData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Re-encode the summary data to ensure proper UTF-8 encoding for download
|
||||
// This fixes Chinese character encoding issues in legacy summary.json files
|
||||
buffer := new(strings.Builder)
|
||||
encoder := json.NewEncoder(buffer)
|
||||
encoder.SetEscapeHTML(false)
|
||||
encoder.SetIndent("", " ")
|
||||
|
||||
err = encoder.Encode(g.SummaryData)
|
||||
if err != nil {
|
||||
// Fallback to original content if re-encoding fails
|
||||
g.SummaryContent = string(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Store the properly encoded content for download
|
||||
g.SummaryContent = strings.TrimSpace(buffer.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadLogData loads test log data from log file
|
||||
@@ -430,18 +450,23 @@ func (g *HTMLReportGenerator) GenerateReport(outputFile string) error {
|
||||
return fmt.Errorf("failed to parse template: %w", err)
|
||||
}
|
||||
|
||||
// Create output file
|
||||
file, err := os.Create(outputFile)
|
||||
// Create output file with explicit UTF-8 handling
|
||||
file, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create output file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Execute template
|
||||
// Execute template (Go's html/template ensures UTF-8 encoding)
|
||||
if err := tmpl.Execute(file, g.SummaryData); err != nil {
|
||||
return fmt.Errorf("failed to execute template: %w", err)
|
||||
}
|
||||
|
||||
// Ensure data is flushed to disk
|
||||
if err := file.Sync(); err != nil {
|
||||
return fmt.Errorf("failed to sync HTML report file: %w", err)
|
||||
}
|
||||
|
||||
log.Info().Str("path", outputFile).Msg("HTML report generated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user