Skip to content

Commit

Permalink
Option to print output into report, when tests have passed
Browse files Browse the repository at this point in the history
A new CLI option: -ginkgo.reportPassed
It will print output for each passed test in the generated report,
including JUnit, Teamcity, and Default reporters.

For example, in JUnit (XML), the test output will be added under:
`<testcase> <passed>`

The default behavior (without this option), prints test output
only if the test case (spec) has failed.

[Fixes #583]
  • Loading branch information
manosnoam authored and williammartin committed Jul 16, 2019
1 parent 4cb7441 commit 0545415
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 17 deletions.
6 changes: 6 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type DefaultReporterConfigType struct {
Succinct bool
Verbose bool
FullTrace bool
ReportPassed bool
}

var DefaultReporterConfig = DefaultReporterConfigType{}
Expand Down Expand Up @@ -98,6 +99,7 @@ func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) {
flagSet.BoolVar(&(DefaultReporterConfig.Verbose), prefix+"v", false, "If set, default reporter print out all specs as they begin.")
flagSet.BoolVar(&(DefaultReporterConfig.Succinct), prefix+"succinct", false, "If set, default reporter prints out a very succinct report")
flagSet.BoolVar(&(DefaultReporterConfig.FullTrace), prefix+"trace", false, "If set, default reporter prints out the full stack trace when a failure occurs")
flagSet.BoolVar(&(DefaultReporterConfig.ReportPassed), prefix+"reportPassed", false, "If set, default reporter prints out captured output of passed tests.")
}

func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultReporterConfigType) []string {
Expand Down Expand Up @@ -196,5 +198,9 @@ func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultRepor
result = append(result, fmt.Sprintf("--%strace", prefix))
}

if reporter.ReportPassed {
result = append(result, fmt.Sprintf("--%sreportPassed", prefix))
}

return result
}
2 changes: 1 addition & 1 deletion internal/specrunner/spec_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (runner *SpecRunner) reportSpecWillRun(summary *types.SpecSummary) {
}

func (runner *SpecRunner) reportSpecDidComplete(summary *types.SpecSummary, failed bool) {
if failed && len(summary.CapturedOutput) == 0 {
if len(summary.CapturedOutput) == 0 {
summary.CapturedOutput = string(runner.writer.Bytes())
}
for i := len(runner.reporters) - 1; i >= 1; i-- {
Expand Down
2 changes: 2 additions & 0 deletions internal/specrunner/spec_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ var _ = Describe("Spec Runner", func() {
"R1.WillRun",
"R2.WillRun",
"A",
"BYTES",
"R2.DidComplete",
"R1.DidComplete",
"TRUNCATE",
Expand All @@ -734,6 +735,7 @@ var _ = Describe("Spec Runner", func() {
"R1.WillRun",
"R2.WillRun",
"C",
"BYTES",
"R2.DidComplete",
"R1.DidComplete",
}))
Expand Down
9 changes: 6 additions & 3 deletions reporters/default_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import (
)

type DefaultReporter struct {
config config.DefaultReporterConfigType
stenographer stenographer.Stenographer
specSummaries []*types.SpecSummary
config config.DefaultReporterConfigType
stenographer stenographer.Stenographer
specSummaries []*types.SpecSummary
}

func NewDefaultReporter(config config.DefaultReporterConfigType, stenographer stenographer.Stenographer) *DefaultReporter {
Expand Down Expand Up @@ -62,6 +62,9 @@ func (reporter *DefaultReporter) SpecDidComplete(specSummary *types.SpecSummary)
reporter.stenographer.AnnounceSuccesfulSlowSpec(specSummary, reporter.config.Succinct)
} else {
reporter.stenographer.AnnounceSuccesfulSpec(specSummary)
if reporter.config.ReportPassed {
reporter.stenographer.AnnounceCapturedOutput(specSummary.CapturedOutput)
}
}
case types.SpecStatePending:
reporter.stenographer.AnnouncePendingSpec(specSummary, reporter.config.NoisyPendings && !reporter.config.Succinct)
Expand Down
32 changes: 28 additions & 4 deletions reporters/default_reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,22 @@ var _ = Describe("DefaultReporter", func() {
})
})

Context("Otherwise", func() {
It("should announce the succesful spec", func() {
Context("When the spec is successful", func() {
It("should announce the successful spec", func() {
Ω(stenographer.Calls()[0]).Should(Equal(call("AnnounceSuccesfulSpec", spec)))
})

Context("When ReportPassed flag is set", func() {
BeforeEach(func() {
reporterConfig.ReportPassed = true
reporter = reporters.NewDefaultReporter(reporterConfig, stenographer)
spec.CapturedOutput = "test scenario"
})

It("should announce the captured output", func() {
Ω(stenographer.Calls()[1]).Should(Equal(call("AnnounceCapturedOutput", spec.CapturedOutput)))
})
})
})
})

Expand Down Expand Up @@ -361,10 +373,22 @@ var _ = Describe("DefaultReporter", func() {
})
})

Context("Otherwise", func() {
It("should announce the succesful spec", func() {
Context("When the spec is successful", func() {
It("should announce the successful spec", func() {
Ω(stenographer.Calls()[0]).Should(Equal(call("AnnounceSuccesfulSpec", spec)))
})

Context("When ReportPassed flag is set", func() {
BeforeEach(func() {
reporterConfig.ReportPassed = true
reporter = reporters.NewDefaultReporter(reporterConfig, stenographer)
spec.CapturedOutput = "test scenario"
})

It("should announce the captured output", func() {
Ω(stenographer.Calls()[1]).Should(Equal(call("AnnounceCapturedOutput", spec.CapturedOutput)))
})
})
})
})

Expand Down
20 changes: 16 additions & 4 deletions reporters/junit_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,17 @@ type JUnitTestSuite struct {
type JUnitTestCase struct {
Name string `xml:"name,attr"`
ClassName string `xml:"classname,attr"`
PassedMessage *JUnitPassedMessage `xml:"passed,omitempty"`
FailureMessage *JUnitFailureMessage `xml:"failure,omitempty"`
Skipped *JUnitSkipped `xml:"skipped,omitempty"`
Time float64 `xml:"time,attr"`
SystemOut string `xml:"system-out,omitempty"`
}

type JUnitPassedMessage struct {
Message string `xml:",chardata"`
}

type JUnitFailureMessage struct {
Type string `xml:"type,attr"`
Message string `xml:",chardata"`
Expand All @@ -48,9 +53,10 @@ type JUnitSkipped struct {
}

type JUnitReporter struct {
suite JUnitTestSuite
filename string
testSuiteName string
suite JUnitTestSuite
filename string
testSuiteName string
ReporterConfig config.DefaultReporterConfigType
}

//NewJUnitReporter creates a new JUnit XML reporter. The XML will be stored in the passed in filename.
Expand All @@ -60,12 +66,13 @@ func NewJUnitReporter(filename string) *JUnitReporter {
}
}

func (reporter *JUnitReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
func (reporter *JUnitReporter) SpecSuiteWillBegin(ginkgoConfig config.GinkgoConfigType, summary *types.SuiteSummary) {
reporter.suite = JUnitTestSuite{
Name: summary.SuiteDescription,
TestCases: []JUnitTestCase{},
}
reporter.testSuiteName = summary.SuiteDescription
reporter.ReporterConfig = config.DefaultReporterConfig
}

func (reporter *JUnitReporter) SpecWillRun(specSummary *types.SpecSummary) {
Expand Down Expand Up @@ -105,6 +112,11 @@ func (reporter *JUnitReporter) SpecDidComplete(specSummary *types.SpecSummary) {
Name: strings.Join(specSummary.ComponentTexts[1:], " "),
ClassName: reporter.testSuiteName,
}
if reporter.ReporterConfig.ReportPassed && specSummary.State == types.SpecStatePassed {
testCase.PassedMessage = &JUnitPassedMessage{
Message: specSummary.CapturedOutput,
}
}
if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked {
testCase.FailureMessage = &JUnitFailureMessage{
Type: reporter.failureTypeForState(specSummary.State),
Expand Down
9 changes: 7 additions & 2 deletions reporters/junit_reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (

var _ = Describe("JUnit Reporter", func() {
var (
outputFile string
reporter Reporter
outputFile string
reporter *reporters.JUnitReporter
)
testSuiteTime := 12456999 * time.Microsecond
reportedSuiteTime := 12.456
Expand Down Expand Up @@ -61,8 +61,12 @@ var _ = Describe("JUnit Reporter", func() {
}
reporter.AfterSuiteDidRun(afterSuite)

// Set the ReportPassed config flag, in order to show captured output when tests have passed.
reporter.ReporterConfig.ReportPassed = true

spec := &types.SpecSummary{
ComponentTexts: []string{"[Top Level]", "A", "B", "C"},
CapturedOutput: "Test scenario...",
State: types.SpecStatePassed,
RunTime: 5 * time.Second,
}
Expand All @@ -89,6 +93,7 @@ var _ = Describe("JUnit Reporter", func() {
Ω(output.TestCases[0].FailureMessage).Should(BeNil())
Ω(output.TestCases[0].Skipped).Should(BeNil())
Ω(output.TestCases[0].Time).Should(Equal(5.0))
Ω(output.TestCases[0].PassedMessage.Message).Should(ContainSubstring("Test scenario"))
})
})

Expand Down
9 changes: 7 additions & 2 deletions reporters/teamcity_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ const (
)

type TeamCityReporter struct {
writer io.Writer
testSuiteName string
writer io.Writer
testSuiteName string
ReporterConfig config.DefaultReporterConfigType
}

func NewTeamCityReporter(writer io.Writer) *TeamCityReporter {
Expand Down Expand Up @@ -65,6 +66,10 @@ func (reporter *TeamCityReporter) SpecWillRun(specSummary *types.SpecSummary) {
func (reporter *TeamCityReporter) SpecDidComplete(specSummary *types.SpecSummary) {
testName := escape(strings.Join(specSummary.ComponentTexts[1:], " "))

if reporter.ReporterConfig.ReportPassed && specSummary.State == types.SpecStatePassed {
details := escape(specSummary.CapturedOutput)
fmt.Fprintf(reporter.writer, "%s[testPassed name='%s' details='%s']", messageId, testName, details)
}
if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked {
message := escape(specSummary.Failure.ComponentCodeLocation.String())
details := escape(specSummary.Failure.Message)
Expand Down
7 changes: 6 additions & 1 deletion reporters/teamcity_reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
var _ = Describe("TeamCity Reporter", func() {
var (
buffer bytes.Buffer
reporter Reporter
reporter *reporters.TeamCityReporter
)

BeforeEach(func() {
Expand All @@ -40,8 +40,12 @@ var _ = Describe("TeamCity Reporter", func() {
}
reporter.AfterSuiteDidRun(afterSuite)

// Set the ReportPassed config flag, in order to show captured output when tests have passed.
reporter.ReporterConfig.ReportPassed = true

spec := &types.SpecSummary{
ComponentTexts: []string{"[Top Level]", "A", "B", "C"},
CapturedOutput: "Test scenario...",
State: types.SpecStatePassed,
RunTime: 5 * time.Second,
}
Expand All @@ -60,6 +64,7 @@ var _ = Describe("TeamCity Reporter", func() {
expected :=
"##teamcity[testSuiteStarted name='Foo|'s test suite']" +
"##teamcity[testStarted name='A B C']" +
"##teamcity[testPassed name='A B C' details='Test scenario...']" +
"##teamcity[testFinished name='A B C' duration='5000']" +
"##teamcity[testSuiteFinished name='Foo|'s test suite']"
Ω(actual).Should(Equal(expected))
Expand Down

0 comments on commit 0545415

Please sign in to comment.