Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

terraform test: Another round of the JUnit XML output experiment #34973

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/backend/local/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,9 @@ func (runner *TestFileRunner) Test(file *moduletest.File) {
}
}

startTime := time.Now()
state, updatedState := runner.run(run, file, runner.RelevantStates[key].State, config)
runDuration := time.Since(startTime)
if updatedState {
// Only update the most recent run and state if the state was
// actually updated by this change. We want to use the run that
Expand All @@ -359,6 +361,11 @@ func (runner *TestFileRunner) Test(file *moduletest.File) {
runner.RelevantStates[key].Run = run
}

// If we got far enough to actually execute the run then we'll give
// the view some additional metadata about the execution.
run.ExecutionMeta = &moduletest.RunExecutionMeta{
Duration: runDuration,
}
runner.Suite.View.Run(run, file, moduletest.Complete, 0)
file.Status = file.Status.Merge(run.Status)
}
Expand Down
34 changes: 29 additions & 5 deletions internal/command/views/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -880,15 +880,39 @@ func junitXMLTestReport(suite *moduletest.Suite) ([]byte, error) {
Body string `xml:",cdata"`
}
type TestCase struct {
Name string `xml:"name,attr"`
Skipped *WithMessage `xml:"skipped,omitempty"`
Failure *WithMessage `xml:"failure,omitempty"`
Error *WithMessage `xml:"error,omitempty"`
Stderr *WithMessage `xml:"system-err,omitempty"`
Name string `xml:"name,attr"`
Classname string `xml:"classname,attr"`
Skipped *WithMessage `xml:"skipped,omitempty"`
Failure *WithMessage `xml:"failure,omitempty"`
Error *WithMessage `xml:"error,omitempty"`
Stderr *WithMessage `xml:"system-err,omitempty"`

// RunTime is the time spent executing the run associated
// with this test case, in seconds with the fractional component
// representing partial seconds.
//
// We assume here that it's not practically possible for an
// execution to take literally zero fractional seconds at
// the accuracy we're using here (nanoseconds converted into
// floating point seconds) and so use zero to represent
// "not known", and thus omit that case. (In practice many
// JUnit XML consumers treat the absense of this attribute
// as zero anyway.)
RunTime float64 `xml:"time,attr,omitempty"`
}

testCase := TestCase{
Name: run.Name,

// We treat the test scenario filename as the "class name",
// implying that the run name is the "method name", just
// because that seems to inspire more useful rendering in
// some consumers of JUnit XML that were designed for
// Java-shaped languages.
Classname: file.Name,
}
if execMeta := run.ExecutionMeta; execMeta != nil {
testCase.RunTime = execMeta.Duration.Seconds()
}
switch run.Status {
case moduletest.Skip:
Expand Down
17 changes: 17 additions & 0 deletions internal/moduletest/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package moduletest

import (
"fmt"
"time"

"github.com/hashicorp/hcl/v2"

Expand All @@ -27,6 +28,22 @@ type Run struct {
Status Status

Diagnostics tfdiags.Diagnostics

// ExecutionMeta captures metadata about how the test run was executed.
//
// This field is not always populated. A run that has never been executed
// will definitely have a nil value for this field. A run that was
// executed may or may not populate this field, depending on exactly what
// happened during the run execution. Callers accessing this field MUST
// check for nil and handle that case in some reasonable way.
//
// Executing the same run multiple times may or may not update this field
// on each execution.
ExecutionMeta *RunExecutionMeta
}

type RunExecutionMeta struct {
Duration time.Duration
}

// Verbose is a utility struct that holds all the information required for a run
Expand Down
Loading