Merge 'merge-wings' into 'master'

fix: create results dir

See merge request: !100
This commit is contained in:
李隆
2025-06-17 11:41:12 +00:00
7 changed files with 123 additions and 43 deletions
+4 -3
View File
@@ -8,6 +8,7 @@ import (
"github.com/spf13/cobra"
hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/internal/config"
)
var CmdReport = &cobra.Command{
@@ -24,9 +25,9 @@ Examples:
resultFolder := args[0]
// Construct file paths
summaryFile := filepath.Join(resultFolder, "summary.json")
logFile := filepath.Join(resultFolder, "hrp.log")
reportFile := filepath.Join(resultFolder, "report.html")
summaryFile := filepath.Join(resultFolder, config.SummaryFileName)
logFile := filepath.Join(resultFolder, config.LogFileName)
reportFile := filepath.Join(resultFolder, config.ReportFileName)
// Generate HTML report
if err := hrp.GenerateHTMLReportFromFiles(summaryFile, logFile, reportFile); err != nil {
+87 -15
View File
@@ -12,20 +12,31 @@ import (
)
const (
ResultsDirName = "results"
DownloadsDirName = "downloads"
ScreenshotsDirName = "screenshots"
ActionLogDirName = "action_log"
// results directory names
ResultsDirName = "results" // $PWD/results/
DownloadsDirName = "downloads" // $PWD/results/20060102150405/downloads/
ScreenshotsDirName = "screenshots" // $PWD/results/20060102150405/screenshots/
ActionLogDirName = "action_log" // $PWD/results/20060102150405/action_log/
// results file names
SummaryFileName = "hrp_summary.json" // $PWD/results/20060102150405/hrp_summary.json
LogFileName = "hrp.log" // $PWD/results/20060102150405/hrp.log
ReportFileName = "report.html" // $PWD/results/20060102150405/report.html
// mobile device path
DeviceActionLogFilePath = "/sdcard/Android/data/io.appium.uiautomator2.server/files/hodor"
)
type Config struct {
StartTime time.Time
RootDir string
resultsPath string
downloadsPath string
screenShotsPath string
StartTime time.Time
ActionLogFilePath string
DeviceActionLogFilePath string
summaryFilePath string
logFilePath string
reportFilePath string
actionLogDirPath string
mu sync.Mutex
}
@@ -51,20 +62,15 @@ func GetConfig() *Config {
cfg.resultsPath = filepath.Join(cfg.RootDir, resultsDir)
cfg.downloadsPath = filepath.Join(cfg.RootDir, filepath.Join(DownloadsDirName, startTimeStr))
cfg.screenShotsPath = filepath.Join(cfg.resultsPath, ScreenshotsDirName)
cfg.ActionLogFilePath = filepath.Join(resultsDir, ActionLogDirName)
cfg.DeviceActionLogFilePath = "/sdcard/Android/data/io.appium.uiautomator2.server/files/hodor"
cfg.actionLogDirPath = filepath.Join(resultsDir, ActionLogDirName)
globalConfig = cfg
})
return globalConfig
}
// ResultsPath returns the results path and creates the directory if it doesn't exist
func (c *Config) ResultsPath() string {
c.mu.Lock()
defer c.mu.Unlock()
// resultsPathUnlocked returns the results path and creates the directory if it doesn't exist (internal use, no lock)
func (c *Config) resultsPathUnlocked() string {
// Check if directory exists, create if it doesn't
if _, err := os.Stat(c.resultsPath); os.IsNotExist(err) {
if err := builtin.EnsureFolderExists(c.resultsPath); err != nil {
@@ -76,6 +82,14 @@ func (c *Config) ResultsPath() string {
return c.resultsPath
}
// ResultsPath returns the results path and creates the directory if it doesn't exist
func (c *Config) ResultsPath() string {
c.mu.Lock()
defer c.mu.Unlock()
return c.resultsPathUnlocked()
}
// DownloadsPath returns the downloads path and creates the directory if it doesn't exist
func (c *Config) DownloadsPath() string {
c.mu.Lock()
@@ -107,3 +121,61 @@ func (c *Config) ScreenShotsPath() string {
}
return c.screenShotsPath
}
// $PWD/results/20060102150405/action_log/
func (c *Config) ActionLogDirPath() string {
c.mu.Lock()
defer c.mu.Unlock()
// Check if directory exists, create if it doesn't
if _, err := os.Stat(c.actionLogDirPath); os.IsNotExist(err) {
if err := builtin.EnsureFolderExists(c.actionLogDirPath); err != nil {
log.Fatal().Err(err).Str("path", c.actionLogDirPath).Msg("failed to create action log directory")
} else {
log.Info().Str("path", c.actionLogDirPath).Msg("created action log folder")
}
}
return c.actionLogDirPath
}
// $PWD/results/20060102150405/hrp_summary.json
func (c *Config) SummaryFilePath() string {
c.mu.Lock()
defer c.mu.Unlock()
if c.summaryFilePath != "" {
return c.summaryFilePath
}
// Ensure directory creation and set cached path
c.summaryFilePath = filepath.Join(c.resultsPathUnlocked(), SummaryFileName)
return c.summaryFilePath
}
// $PWD/results/20060102150405/hrp.log
func (c *Config) LogFilePath() string {
c.mu.Lock()
defer c.mu.Unlock()
if c.logFilePath != "" {
return c.logFilePath
}
// Ensure directory creation and set cached path
c.logFilePath = filepath.Join(c.resultsPathUnlocked(), LogFileName)
return c.logFilePath
}
// $PWD/results/20060102150405/report.html
func (c *Config) ReportFilePath() string {
c.mu.Lock()
defer c.mu.Unlock()
if c.reportFilePath != "" {
return c.reportFilePath
}
// Ensure directory creation and set cached path
c.reportFilePath = filepath.Join(c.resultsPathUnlocked(), ReportFileName)
return c.reportFilePath
}
+1 -1
View File
@@ -1 +1 @@
v5.0.0-beta-2506150047
v5.0.0-beta-2506171409
+1 -3
View File
@@ -3,7 +3,6 @@ package hrp
import (
"io"
"os"
"path/filepath"
"runtime"
"strings"
"time"
@@ -65,8 +64,7 @@ func InitLogger(logLevel string, logJSON bool, logFile bool) {
}
// file writer - write to results/taskID/hrp.log
cfg := config.GetConfig()
logFilePath := filepath.Join(cfg.ResultsPath(), "hrp.log")
logFilePath := config.GetConfig().LogFilePath()
// create or open log file
logFileWriter, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666)
+20 -12
View File
@@ -3,7 +3,6 @@ package hrp
import (
_ "embed"
"fmt"
"path/filepath"
"runtime"
"time"
@@ -76,17 +75,11 @@ func (s *Summary) AddCaseSummary(caseSummary *TestCaseSummary) {
}
}
func (s *Summary) GetResultsPath() string {
return config.GetConfig().ResultsPath()
}
func (s *Summary) GenHTMLReport() error {
reportsDir := s.GetResultsPath()
// Find summary.json and hrp.log files
summaryPath := filepath.Join(reportsDir, "summary.json")
logPath := filepath.Join(reportsDir, "hrp.log")
reportPath := filepath.Join(reportsDir, "report.html")
summaryPath := config.GetConfig().SummaryFilePath()
logPath := config.GetConfig().LogFilePath()
reportPath := config.GetConfig().ReportFilePath()
// Check if summary.json exists, if not create it first
if !builtin.FileExists(summaryPath) {
@@ -99,8 +92,7 @@ func (s *Summary) GenHTMLReport() error {
}
func (s *Summary) GenSummary() (path string, err error) {
reportsDir := config.GetConfig().ResultsPath()
path = filepath.Join(reportsDir, "summary.json")
path = config.GetConfig().SummaryFilePath()
err = builtin.Dump2JSON(s, path)
if err != nil {
return "", err
@@ -108,6 +100,22 @@ func (s *Summary) GenSummary() (path string, err error) {
return path, nil
}
func (s *Summary) GetResultsPath() string {
return config.GetConfig().ResultsPath()
}
func (s *Summary) GetSummaryFilePath() string {
return config.GetConfig().SummaryFilePath()
}
func (s *Summary) GetLogFilePath() string {
return config.GetConfig().LogFilePath()
}
func (s *Summary) GetReportFilePath() string {
return config.GetConfig().ReportFilePath()
}
type Stat struct {
TestCases TestCaseStat `json:"testcases" yaml:"testcases"`
TestSteps TestStepStat `json:"teststeps" yaml:"teststeps"`
+1 -1
View File
@@ -100,7 +100,7 @@ type AndroidDevice struct {
func (dev *AndroidDevice) Setup() error {
dev.Device.RunShellCommand("ime", "enable", option.UnicodeImePackageName)
dev.Device.RunShellCommand("rm", "-r", config.GetConfig().DeviceActionLogFilePath)
dev.Device.RunShellCommand("rm", "-r", config.DeviceActionLogFilePath)
// setup evalite
evalToolRaw, err := evalite.ReadFile("evalite")
+4 -3
View File
@@ -676,10 +676,11 @@ func (ad *ADBDriver) StopCaptureLog() (result interface{}, err error) {
// 没有解析到打点日志,走兜底逻辑
if len(pointRes) == 0 {
log.Info().Msg("action log is null, use action file >>>")
logFilePathPrefix := fmt.Sprintf("%v/data", config.GetConfig().ActionLogFilePath)
actionLogDirPath := config.GetConfig().ActionLogDirPath()
logFilePathPrefix := fmt.Sprintf("%v/data", actionLogDirPath)
files := []string{}
ad.Device.RunShellCommand("pull", config.GetConfig().DeviceActionLogFilePath, config.GetConfig().ActionLogFilePath)
err = filepath.Walk(config.GetConfig().ActionLogFilePath, func(path string, info fs.FileInfo, err error) error {
ad.Device.RunShellCommand("pull", config.DeviceActionLogFilePath, actionLogDirPath)
err = filepath.Walk(actionLogDirPath, func(path string, info fs.FileInfo, err error) error {
// 只是需要日志文件
if ok := strings.Contains(path, logFilePathPrefix); ok {
files = append(files, path)