mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-06 07:57:27 +08:00
feat: add comprehensive HTML report generation with log filtering
- Add complete HTML report generator with template-based rendering - Implement log time filtering for step-specific logs - Support responsive design and interactive UI features - Consolidate duplicate report implementations
This commit is contained in:
@@ -17,6 +17,7 @@ func addAllCommands() {
|
|||||||
cmd.RootCmd.AddCommand(cmd.CmdBuild)
|
cmd.RootCmd.AddCommand(cmd.CmdBuild)
|
||||||
cmd.RootCmd.AddCommand(cmd.CmdConvert)
|
cmd.RootCmd.AddCommand(cmd.CmdConvert)
|
||||||
cmd.RootCmd.AddCommand(cmd.CmdPytest)
|
cmd.RootCmd.AddCommand(cmd.CmdPytest)
|
||||||
|
cmd.RootCmd.AddCommand(cmd.CmdReport)
|
||||||
cmd.RootCmd.AddCommand(cmd.CmdRun)
|
cmd.RootCmd.AddCommand(cmd.CmdRun)
|
||||||
cmd.RootCmd.AddCommand(cmd.CmdScaffold)
|
cmd.RootCmd.AddCommand(cmd.CmdScaffold)
|
||||||
cmd.RootCmd.AddCommand(cmd.CmdServer)
|
cmd.RootCmd.AddCommand(cmd.CmdServer)
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CmdReport = &cobra.Command{
|
||||||
|
Use: "report [result_folder]",
|
||||||
|
Short: "Generate HTML report from test results",
|
||||||
|
Long: `Generate report.html from test results in the specified folder.
|
||||||
|
The folder should contain summary.json and optionally hrp.log files.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$ hrp report results/20250607234602/
|
||||||
|
$ hrp report /path/to/test/results/`,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
resultFolder := args[0]
|
||||||
|
|
||||||
|
// Construct file paths
|
||||||
|
summaryFile := filepath.Join(resultFolder, "summary.json")
|
||||||
|
logFile := filepath.Join(resultFolder, "hrp.log")
|
||||||
|
reportFile := filepath.Join(resultFolder, "report.html")
|
||||||
|
|
||||||
|
// Generate HTML report
|
||||||
|
if err := hrp.GenerateHTMLReportFromFiles(summaryFile, logFile, reportFile); err != nil {
|
||||||
|
return fmt.Errorf("failed to generate HTML report: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Str("report_file", reportFile).Msg("HTML report generated successfully")
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
v5.0.0-beta-2506072359
|
v5.0.0-beta-2506080923
|
||||||
|
|||||||
+11
-25
@@ -1,11 +1,8 @@
|
|||||||
package hrp
|
package hrp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
@@ -94,27 +91,19 @@ func (s *Summary) GenHTMLReport() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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")
|
reportPath := filepath.Join(reportsDir, "report.html")
|
||||||
file, err := os.Open(reportPath)
|
|
||||||
if err != nil {
|
// Check if summary.json exists, if not create it first
|
||||||
log.Error().Err(err).Msg("open file failed")
|
if !builtin.FileExists(summaryPath) {
|
||||||
return err
|
if _, err := s.GenSummary(); err != nil {
|
||||||
|
return fmt.Errorf("failed to generate summary.json: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defer file.Close()
|
|
||||||
writer := bufio.NewWriter(file)
|
return GenerateHTMLReportFromFiles(summaryPath, logPath, reportPath)
|
||||||
tmpl := template.Must(template.New("report").Parse(reportTemplate))
|
|
||||||
err = tmpl.Execute(writer, s)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("execute applies a parsed template to the specified data object failed")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = writer.Flush()
|
|
||||||
if err == nil {
|
|
||||||
log.Info().Str("path", reportPath).Msg("generate HTML report")
|
|
||||||
} else {
|
|
||||||
log.Error().Str("path", reportPath).Msg("generate HTML report failed")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Summary) GenSummary() (path string, err error) {
|
func (s *Summary) GenSummary() (path string, err error) {
|
||||||
@@ -131,9 +120,6 @@ func (s *Summary) GenSummary() (path string, err error) {
|
|||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed internal/scaffold/templates/report/template.html
|
|
||||||
var reportTemplate string
|
|
||||||
|
|
||||||
type Stat struct {
|
type Stat struct {
|
||||||
TestCases TestCaseStat `json:"testcases" yaml:"testcases"`
|
TestCases TestCaseStat `json:"testcases" yaml:"testcases"`
|
||||||
TestSteps TestStepStat `json:"teststeps" yaml:"teststeps"`
|
TestSteps TestStepStat `json:"teststeps" yaml:"teststeps"`
|
||||||
|
|||||||
Reference in New Issue
Block a user