mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-08 01:09:44 +08:00
fix: gen html report path
This commit is contained in:
@@ -35,4 +35,4 @@ Copyright 2021 debugtalk
|
|||||||
* [hrp run](hrp_run.md) - run API test with go engine
|
* [hrp run](hrp_run.md) - run API test with go engine
|
||||||
* [hrp startproject](hrp_startproject.md) - create a scaffold project
|
* [hrp startproject](hrp_startproject.md) - create a scaffold project
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 16-Apr-2022
|
###### Auto generated by spf13/cobra on 17-Apr-2022
|
||||||
|
|||||||
@@ -41,4 +41,4 @@ hrp boom [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 16-Apr-2022
|
###### Auto generated by spf13/cobra on 17-Apr-2022
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ hrp har2case $har_path... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 16-Apr-2022
|
###### Auto generated by spf13/cobra on 17-Apr-2022
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ hrp pytest $path ... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 16-Apr-2022
|
###### Auto generated by spf13/cobra on 17-Apr-2022
|
||||||
|
|||||||
@@ -34,4 +34,4 @@ hrp run $path... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 16-Apr-2022
|
###### Auto generated by spf13/cobra on 17-Apr-2022
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ hrp startproject $project_name [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 16-Apr-2022
|
###### Auto generated by spf13/cobra on 17-Apr-2022
|
||||||
|
|||||||
@@ -19,15 +19,17 @@ const (
|
|||||||
hashicorpPyPluginFile = "debugtalk.py" // used for hashicorp python plugin
|
hashicorpPyPluginFile = "debugtalk.py" // used for hashicorp python plugin
|
||||||
)
|
)
|
||||||
|
|
||||||
func initPlugin(path string, logOn bool) (plugin funplugin.IPlugin, err error) {
|
func initPlugin(path string, logOn bool) (plugin funplugin.IPlugin, pluginDir string, err error) {
|
||||||
// plugin file not found
|
// plugin file not found
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return nil, nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
pluginPath, err := locatePlugin(path)
|
pluginPath, err := locatePlugin(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
|
// TODO: move pluginDir to funplugin
|
||||||
|
pluginDir = filepath.Dir(pluginPath)
|
||||||
|
|
||||||
// found plugin file
|
// found plugin file
|
||||||
plugin, err = funplugin.Init(pluginPath, funplugin.WithLogOn(logOn))
|
plugin, err = funplugin.Init(pluginPath, funplugin.WithLogOn(logOn))
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ package hrp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -15,7 +13,6 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/hrp/internal/builtin"
|
|
||||||
"github.com/httprunner/httprunner/hrp/internal/sdk"
|
"github.com/httprunner/httprunner/hrp/internal/sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -175,22 +172,9 @@ func (r *HRPRunner) Run(testcases ...ITestCase) error {
|
|||||||
}
|
}
|
||||||
s.Time.Duration = time.Since(s.Time.StartAt).Seconds()
|
s.Time.Duration = time.Since(s.Time.StartAt).Seconds()
|
||||||
|
|
||||||
// update the report output path
|
|
||||||
pluginPath, err := locatePlugin(testcases[0].GetPath())
|
|
||||||
if err == nil {
|
|
||||||
outputPath, _ := filepath.Split(pluginPath)
|
|
||||||
summaryPath = filepath.Join(outputPath, summaryPath)
|
|
||||||
reportPath = filepath.Join(outputPath, reportPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// save summary
|
// save summary
|
||||||
if r.saveTests {
|
if r.saveTests {
|
||||||
dir, _ := filepath.Split(summaryPath)
|
err := s.genSummary()
|
||||||
err := builtin.EnsureFolderExists(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = builtin.Dump2JSON(s, fmt.Sprintf(summaryPath, s.Time.StartAt.Unix()))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -229,11 +213,12 @@ func (r *HRPRunner) newCaseRunner(testcase *TestCase) (*testCaseRunner, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init parser plugin
|
// init parser plugin
|
||||||
plugin, err := initPlugin(testcase.Config.Path, r.pluginLogOn)
|
plugin, pluginDir, err := initPlugin(testcase.Config.Path, r.pluginLogOn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "init plugin failed")
|
return nil, errors.Wrap(err, "init plugin failed")
|
||||||
}
|
}
|
||||||
runner.parser.plugin = plugin
|
runner.parser.plugin = plugin
|
||||||
|
runner.rootDir = pluginDir
|
||||||
|
|
||||||
// parse testcase config
|
// parse testcase config
|
||||||
if err := runner.parseConfig(); err != nil {
|
if err := runner.parseConfig(); err != nil {
|
||||||
@@ -249,6 +234,7 @@ type testCaseRunner struct {
|
|||||||
parser *Parser
|
parser *Parser
|
||||||
parsedConfig *TConfig
|
parsedConfig *TConfig
|
||||||
parametersIterator *ParametersIterator
|
parametersIterator *ParametersIterator
|
||||||
|
rootDir string // project root dir
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseConfig parses testcase config, stores to parsedConfig.
|
// parseConfig parses testcase config, stores to parsedConfig.
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ type Summary struct {
|
|||||||
Time *TestCaseTime `json:"time" yaml:"time"`
|
Time *TestCaseTime `json:"time" yaml:"time"`
|
||||||
Platform *Platform `json:"platform" yaml:"platform"`
|
Platform *Platform `json:"platform" yaml:"platform"`
|
||||||
Details []*TestCaseSummary `json:"details" yaml:"details"`
|
Details []*TestCaseSummary `json:"details" yaml:"details"`
|
||||||
|
rootDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) {
|
func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) {
|
||||||
@@ -53,15 +54,24 @@ func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) {
|
|||||||
s.Stat.TestSteps.Failures += caseSummary.Stat.Failures
|
s.Stat.TestSteps.Failures += caseSummary.Stat.Failures
|
||||||
s.Details = append(s.Details, caseSummary)
|
s.Details = append(s.Details, caseSummary)
|
||||||
s.Success = s.Success && caseSummary.Success
|
s.Success = s.Success && caseSummary.Success
|
||||||
|
|
||||||
|
// specify output reports dir
|
||||||
|
if len(s.Details) == 1 {
|
||||||
|
s.rootDir = caseSummary.RootDir
|
||||||
|
} else if s.rootDir != caseSummary.RootDir {
|
||||||
|
// if multiple testcases have different root path, use current working dir
|
||||||
|
s.rootDir, _ = os.Getwd()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Summary) genHTMLReport() error {
|
func (s *Summary) genHTMLReport() error {
|
||||||
dir, _ := filepath.Split(reportPath)
|
reportsDir := filepath.Join(s.rootDir, resultsDir)
|
||||||
err := builtin.EnsureFolderExists(dir)
|
err := builtin.EnsureFolderExists(reportsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
reportPath := fmt.Sprintf(reportPath, s.Time.StartAt.Unix())
|
|
||||||
|
reportPath := filepath.Join(reportsDir, fmt.Sprintf("report-%v.html", s.Time.StartAt.Unix()))
|
||||||
file, err := os.OpenFile(reportPath, os.O_WRONLY|os.O_CREATE, 0666)
|
file, err := os.OpenFile(reportPath, os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("open file failed")
|
log.Error().Err(err).Msg("open file failed")
|
||||||
@@ -84,13 +94,25 @@ func (s *Summary) genHTMLReport() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Summary) genSummary() error {
|
||||||
|
reportsDir := filepath.Join(s.rootDir, resultsDir)
|
||||||
|
err := builtin.EnsureFolderExists(reportsDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
summaryPath := filepath.Join(reportsDir, fmt.Sprintf("summary-%v.json", s.Time.StartAt.Unix()))
|
||||||
|
err = builtin.Dump2JSON(s, summaryPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//go:embed internal/scaffold/templates/report/template.html
|
//go:embed internal/scaffold/templates/report/template.html
|
||||||
var reportTemplate string
|
var reportTemplate string
|
||||||
|
|
||||||
var (
|
const resultsDir = "reports"
|
||||||
reportPath = "reports/report-%v.html"
|
|
||||||
summaryPath = "reports/summary-%v.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Stat struct {
|
type Stat struct {
|
||||||
TestCases TestCaseStat `json:"testcases" yaml:"test_cases"`
|
TestCases TestCaseStat `json:"testcases" yaml:"test_cases"`
|
||||||
@@ -130,6 +152,7 @@ type TestCaseSummary struct {
|
|||||||
InOut *TestCaseInOut `json:"in_out" yaml:"in_out"`
|
InOut *TestCaseInOut `json:"in_out" yaml:"in_out"`
|
||||||
Log string `json:"log,omitempty" yaml:"log,omitempty"` // TODO
|
Log string `json:"log,omitempty" yaml:"log,omitempty"` // TODO
|
||||||
Records []*StepResult `json:"records" yaml:"records"`
|
Records []*StepResult `json:"records" yaml:"records"`
|
||||||
|
RootDir string `json:"root_dir" yaml:"root_dir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestCaseInOut struct {
|
type TestCaseInOut struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user