diff --git a/hrp/runner.go b/hrp/runner.go index 6775db96..30a0992d 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -201,7 +201,7 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) { }() // record execution data to summary - s := newOutSummary() + s := NewSummary() // load all testcases testCases, err := LoadTestCases(testcases...) @@ -242,7 +242,7 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) { // each run has its own session runner sessionRunner := caseRunner.NewSession() caseSummary, err := sessionRunner.Start(it.Next()) - s.appendCaseSummary(caseSummary) + s.AddCaseSummary(caseSummary) if err != nil { log.Error().Err(err).Msg("[Run] run testcase failed") runErr = err @@ -257,14 +257,14 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) { // save summary if r.saveTests { - if err := s.genSummary(); err != nil { + if err := s.GenSummary(); err != nil { return err } } // generate HTML report if r.genHTMLReport { - if err := s.genHTMLReport(); err != nil { + if err := s.GenHTMLReport(); err != nil { return err } } @@ -414,7 +414,7 @@ func (r *CaseRunner) NewSession() *SessionRunner { sessionRunner := &SessionRunner{ caseRunner: r, sessionVariables: make(map[string]interface{}), - summary: newSummary(), + summary: NewCaseSummary(), transactions: make(map[string]map[transactionType]time.Time), ws: newWSSession(), @@ -538,7 +538,7 @@ func (r *SessionRunner) Start(givenVars map[string]interface{}) (summary *TestCa stepResult.Name = stepName + loopIndex stepResult.StartTime = startTime - r.updateSummary(stepResult) + r.summary.AddStepResult(stepResult) } // update extracted variables @@ -657,33 +657,3 @@ func (r *SessionRunner) IgnorePopup() bool { } return false } - -// updateSummary updates summary of StepResult. -func (r *SessionRunner) updateSummary(stepResult *StepResult) { - switch stepResult.StepType { - case stepTypeTestCase: - // record requests of testcase step - if records, ok := stepResult.Data.([]*StepResult); ok { - for _, result := range records { - r.addSingleStepResult(result) - } - } else { - r.addSingleStepResult(stepResult) - } - default: - r.addSingleStepResult(stepResult) - } -} - -func (r *SessionRunner) addSingleStepResult(stepResult *StepResult) { - // update summary - r.summary.Records = append(r.summary.Records, stepResult) - r.summary.Stat.Total += 1 - if stepResult.Success { - r.summary.Stat.Successes += 1 - } else { - r.summary.Stat.Failures += 1 - // update summary result to failed - r.summary.Success = false - } -} diff --git a/hrp/step.go b/hrp/step.go index 5c60078f..94e9287c 100644 --- a/hrp/step.go +++ b/hrp/step.go @@ -26,7 +26,7 @@ type StepResult struct { Success bool `json:"success" yaml:"success"` // step execution result Elapsed int64 `json:"elapsed_ms" yaml:"elapsed_ms"` // step execution time in millisecond(ms) HttpStat map[string]int64 `json:"httpstat,omitempty" yaml:"httpstat,omitempty"` // httpstat in millisecond(ms) - Data interface{} `json:"data,omitempty" yaml:"data,omitempty"` // session data or slice of step data + Data interface{} `json:"data,omitempty" yaml:"data,omitempty"` // step data, *StepResult or []*StepResult ContentSize int64 `json:"content_size" yaml:"content_size"` // response body length ExportVars map[string]interface{} `json:"export_vars,omitempty" yaml:"export_vars,omitempty"` // extract variables Attachments interface{} `json:"attachments,omitempty" yaml:"attachments,omitempty"` // store extra step information, such as error message or screenshots diff --git a/hrp/summary.go b/hrp/summary.go index a536de7d..eaf541d7 100644 --- a/hrp/summary.go +++ b/hrp/summary.go @@ -17,7 +17,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp/internal/version" ) -func newOutSummary() *Summary { +func NewSummary() *Summary { platForm := &Platform{ HttprunnerVersion: version.VERSION, GoVersion: runtime.Version(), @@ -43,7 +43,8 @@ type Summary struct { rootDir string } -func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) { +func (s *Summary) AddCaseSummary(caseSummary *TestCaseSummary) { + log.Info().Interface("caseSummary", caseSummary).Msg("add case summary") s.Success = s.Success && caseSummary.Success s.Stat.TestCases.Total += 1 s.Stat.TestSteps.Total += caseSummary.Stat.Total @@ -55,7 +56,6 @@ func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) { s.Stat.TestSteps.Successes += caseSummary.Stat.Successes s.Stat.TestSteps.Failures += caseSummary.Stat.Failures s.Details = append(s.Details, caseSummary) - s.Success = s.Success && caseSummary.Success // specify output reports dir if len(s.Details) == 1 { @@ -66,7 +66,7 @@ func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) { } } -func (s *Summary) genHTMLReport() error { +func (s *Summary) GenHTMLReport() error { reportsDir := filepath.Join(s.rootDir, env.ResultsDir) err := builtin.EnsureFolderExists(reportsDir) if err != nil { @@ -96,7 +96,7 @@ func (s *Summary) genHTMLReport() error { return err } -func (s *Summary) genSummary() error { +func (s *Summary) GenSummary() error { reportsDir := filepath.Join(s.rootDir, env.ResultsDir) err := builtin.EnsureFolderExists(reportsDir) if err != nil { @@ -142,6 +142,18 @@ type Platform struct { Platform string `json:"platform" yaml:"platform"` } +func NewCaseSummary() *TestCaseSummary { + return &TestCaseSummary{ + Success: true, + Stat: &TestStepStat{}, + Time: &TestCaseTime{ + StartAt: time.Now(), + }, + InOut: &TestCaseInOut{}, + Records: []*StepResult{}, + } +} + // TestCaseSummary stores tests summary for one testcase type TestCaseSummary struct { Name string `json:"name" yaml:"name"` @@ -155,6 +167,38 @@ type TestCaseSummary struct { RootDir string `json:"root_dir" yaml:"root_dir"` } +// AddStepResult updates summary of StepResult. +func (s *TestCaseSummary) AddStepResult(stepResult *StepResult) { + switch stepResult.StepType { + case stepTypeTestCase: + // record requests of testcase step + records, ok := stepResult.Data.([]*StepResult) + if !ok { + log.Warn(). + Interface("data", stepResult.Data). + Msg("get unexpected testcase step data") + return + } + s.Success = s.Success && stepResult.Success + for _, result := range records { + s.addSingleStepResult(result) + } + default: + s.addSingleStepResult(stepResult) + } +} + +func (s *TestCaseSummary) addSingleStepResult(stepResult *StepResult) { + s.Success = s.Success && stepResult.Success + s.Stat.Total += 1 + if stepResult.Success { + s.Stat.Successes += 1 + } else { + s.Stat.Failures += 1 + } + s.Records = append(s.Records, stepResult) +} + type TestCaseInOut struct { ConfigVars map[string]interface{} `json:"config_vars" yaml:"config_vars"` ExportVars map[string]interface{} `json:"export_vars" yaml:"export_vars"` @@ -191,15 +235,3 @@ type ValidationResult struct { CheckValue interface{} `json:"check_value" yaml:"check_value"` CheckResult string `json:"check_result" yaml:"check_result"` } - -func newSummary() *TestCaseSummary { - return &TestCaseSummary{ - Success: true, - Stat: &TestStepStat{}, - Time: &TestCaseTime{ - StartAt: time.Now(), - }, - InOut: &TestCaseInOut{}, - Records: []*StepResult{}, - } -} diff --git a/hrp/summary_test.go b/hrp/summary_test.go index 034ded16..cf440f59 100644 --- a/hrp/summary_test.go +++ b/hrp/summary_test.go @@ -1,12 +1,20 @@ package hrp -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/assert" +) func TestGenHTMLReport(t *testing.T) { - summary := newOutSummary() - caseSummary1 := newSummary() - caseSummary2 := newSummary() + summary := NewSummary() + + caseSummary1 := NewCaseSummary() stepResult1 := &StepResult{} + caseSummary1.AddStepResult(stepResult1) + summary.AddCaseSummary(caseSummary1) + + caseSummary2 := NewCaseSummary() stepResult2 := &StepResult{ Name: "Test", StepType: stepTypeRequest, @@ -14,11 +22,39 @@ func TestGenHTMLReport(t *testing.T) { ContentSize: 0, Attachments: "err", } - caseSummary1.Records = []*StepResult{stepResult1, stepResult2, nil} - summary.appendCaseSummary(caseSummary1) - summary.appendCaseSummary(caseSummary2) - err := summary.genHTMLReport() + caseSummary2.AddStepResult(stepResult2) + summary.AddCaseSummary(caseSummary2) + + err := summary.GenHTMLReport() if err != nil { t.Error(err) } } + +func TestTestCaseSummary_AddStepResult(t *testing.T) { + caseSummary := NewCaseSummary() + stepResult1 := &StepResult{ + Name: "Test1", + StepType: stepTypeRequest, + Success: true, + ContentSize: 0, + Attachments: "err", + } + caseSummary.AddStepResult(stepResult1) + stepResult2 := &StepResult{ + Name: "Test2", + StepType: stepTypeTestCase, + Success: false, + ContentSize: 0, + Attachments: "err", + Data: []*StepResult{stepResult1}, + } + caseSummary.AddStepResult(stepResult2) + + if !assert.Equal(t, 2, len(caseSummary.Records)) { + t.Fatal() + } + if !assert.False(t, caseSummary.Success) { + t.Fatal() + } +}