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

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 {

View File

@@ -12,21 +12,32 @@ 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 {
RootDir string
resultsPath string
downloadsPath string
screenShotsPath string
StartTime time.Time
ActionLogFilePath string
DeviceActionLogFilePath string
mu sync.Mutex
StartTime time.Time
RootDir string
resultsPath string
downloadsPath string
screenShotsPath string
summaryFilePath string
logFilePath string
reportFilePath string
actionLogDirPath string
mu sync.Mutex
}
var (
@@ -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
}

View File

@@ -1 +1 @@
v5.0.0-beta-2506150047
v5.0.0-beta-2506171409

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)

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"`

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")

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)