Skip to content

Commit

Permalink
fix: create parent directory before report files (#1212)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanperkins committed May 31, 2023
1 parent 4c2ae23 commit 0ac65de
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 3 deletions.
13 changes: 10 additions & 3 deletions reporters/json_report.go
Expand Up @@ -4,12 +4,16 @@ import (
"encoding/json"
"fmt"
"os"
"path"

"github.com/onsi/ginkgo/v2/types"
)

//GenerateJSONReport produces a JSON-formatted report at the passed in destination
// GenerateJSONReport produces a JSON-formatted report at the passed in destination
func GenerateJSONReport(report types.Report, destination string) error {
if err := os.MkdirAll(path.Dir(destination), 0770); err != nil {
return err
}
f, err := os.Create(destination)
if err != nil {
return err
Expand All @@ -25,8 +29,8 @@ func GenerateJSONReport(report types.Report, destination string) error {
return f.Close()
}

//MergeJSONReports produces a single JSON-formatted report at the passed in destination by merging the JSON-formatted reports provided in sources
//It skips over reports that fail to decode but reports on them via the returned messages []string
// MergeJSONReports produces a single JSON-formatted report at the passed in destination by merging the JSON-formatted reports provided in sources
// It skips over reports that fail to decode but reports on them via the returned messages []string
func MergeAndCleanupJSONReports(sources []string, destination string) ([]string, error) {
messages := []string{}
allReports := []types.Report{}
Expand All @@ -46,6 +50,9 @@ func MergeAndCleanupJSONReports(sources []string, destination string) ([]string,
allReports = append(allReports, reports...)
}

if err := os.MkdirAll(path.Dir(destination), 0770); err != nil {
return messages, err
}
f, err := os.Create(destination)
if err != nil {
return messages, err
Expand Down
75 changes: 75 additions & 0 deletions reporters/json_report_test.go
@@ -0,0 +1,75 @@
package reporters_test

import (
"fmt"
"os"
"path/filepath"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/onsi/ginkgo/v2/reporters"
"github.com/onsi/ginkgo/v2/types"
)

var _ = Describe("JSONReport", func() {
var report types.Report

BeforeEach(func() {
report = types.Report{
SuiteDescription: "My Suite",
SuitePath: "/path/to/suite",
PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
RunTime: time.Minute,
SpecReports: types.SpecReports{
S(types.NodeTypeIt, Label("cat", "dog"), CLabels(Label("dolphin"), Label("gorilla", "cow")), CTS("A", "B"), CLS(cl0, cl1), "C", cl2, types.SpecStateTimedout, STD("some captured stdout\n"), GW("ginkgowriter\noutput\ncleanup!"), SE(types.SpecEventByStart, "a by step", cl0),
SE(types.SpecEventNodeStart, types.NodeTypeIt, "C", cl2, TL(0)),
F("failure\nmessage", cl3, types.FailureNodeIsLeafNode, FailureNodeLocation(cl2), types.NodeTypeIt, TL("ginkgowriter\n"), AF(types.SpecStatePanicked, cl4, types.FailureNodeIsLeafNode, FailureNodeLocation(cl2), types.NodeTypeIt, TL("ginkgowriter\noutput\n"), ForwardedPanic("the panic!"))),
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "C", cl2, TL("ginkgowriter\noutput\n"), time.Microsecond*87230),
RE("a report entry", cl1, TL("ginkgowriter\noutput\n")),
RE("a hidden report entry", cl1, TL("ginkgowriter\noutput\n"), types.ReportEntryVisibilityNever),
AF(types.SpecStateFailed, "a subsequent failure", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeAfterEach, 0, TL("ginkgowriter\noutput\ncleanup!")),
),
S(types.NodeTypeIt, "A", cl0, STD("some captured stdout\n"), GW("some GinkgoWriter\noutput is interspersed\nhere and there\n"),
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
PR("my progress report", LeafNodeText("A"), TL("some GinkgoWriter\n")),
SE(types.SpecEventByStart, "My Step", cl1, TL("some GinkgoWriter\n")),
RE("my entry", cl1, types.ReportEntryVisibilityFailureOrVerbose, TL("some GinkgoWriter\noutput is interspersed\n")),
RE("my hidden entry", cl1, types.ReportEntryVisibilityNever, TL("some GinkgoWriter\noutput is interspersed\n")),
SE(types.SpecEventByEnd, "My Step", cl1, time.Millisecond*200, TL("some GinkgoWriter\noutput is interspersed\n")),
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
),
S(types.NodeTypeIt, "A", cl0, types.SpecStatePending),
S(types.NodeTypeIt, "A", cl0, types.SpecStatePanicked, STD("some captured stdout\n"),
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
F("failure\nmessage", cl1, types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeIt, ForwardedPanic("the panic")),
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
),
S(types.NodeTypeBeforeSuite, "A", cl0, types.SpecStatePassed),
},
}
})

Describe("when configured to write the report inside a folder", func() {
var folderPath string
var filePath string

BeforeEach(func() {
folderPath = filepath.Join("test_outputs")
fileName := fmt.Sprintf("report-%d", GinkgoParallelProcess())
filePath = filepath.Join(folderPath, fileName)

Ω(reporters.GenerateJSONReport(report, filePath)).Should(Succeed())
DeferCleanup(os.RemoveAll, folderPath)
})

It("creates the folder and the report file", func() {
_, err := os.Stat(folderPath)
Ω(err).Should(Succeed(), "Parent folder should be created")
_, err = os.Stat(filePath)
Ω(err).Should(Succeed(), "Report file should be created")
})
})
})
7 changes: 7 additions & 0 deletions reporters/junit_report.go
Expand Up @@ -14,6 +14,7 @@ import (
"encoding/xml"
"fmt"
"os"
"path"
"strings"

"github.com/onsi/ginkgo/v2/config"
Expand Down Expand Up @@ -285,6 +286,9 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit
TestSuites: []JUnitTestSuite{suite},
}

if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
return err
}
f, err := os.Create(dst)
if err != nil {
return err
Expand Down Expand Up @@ -322,6 +326,9 @@ func MergeAndCleanupJUnitReports(sources []string, dst string) ([]string, error)
mergedReport.TestSuites = append(mergedReport.TestSuites, report.TestSuites...)
}

if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
return messages, err
}
f, err := os.Create(dst)
if err != nil {
return messages, err
Expand Down
22 changes: 22 additions & 0 deletions reporters/junit_report_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/xml"
"fmt"
"os"
"path/filepath"
"time"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -372,4 +373,25 @@ var _ = Describe("JunitReport", func() {
))
})
})

Describe("when configured to write the report inside a folder", func() {
var folderPath string
var filePath string

BeforeEach(func() {
folderPath = filepath.Join("test_outputs")
fileName := fmt.Sprintf("report-%d", GinkgoParallelProcess())
filePath = filepath.Join(folderPath, fileName)

Ω(reporters.GenerateJUnitReport(report, filePath)).Should(Succeed())
DeferCleanup(os.RemoveAll, folderPath)
})

It("creates the folder and the report file", func() {
_, err := os.Stat(folderPath)
Ω(err).Should(Succeed(), "Parent folder should be created")
_, err = os.Stat(filePath)
Ω(err).Should(Succeed(), "Report file should be created")
})
})
})
4 changes: 4 additions & 0 deletions reporters/teamcity_report.go
Expand Up @@ -11,6 +11,7 @@ package reporters
import (
"fmt"
"os"
"path"
"strings"

"github.com/onsi/ginkgo/v2/types"
Expand All @@ -27,6 +28,9 @@ func tcEscape(s string) string {
}

func GenerateTeamcityReport(report types.Report, dst string) error {
if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
return err
}
f, err := os.Create(dst)
if err != nil {
return err
Expand Down
75 changes: 75 additions & 0 deletions reporters/teamcity_report_test.go
@@ -0,0 +1,75 @@
package reporters_test

import (
"fmt"
"os"
"path/filepath"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/onsi/ginkgo/v2/reporters"
"github.com/onsi/ginkgo/v2/types"
)

var _ = Describe("TeamCityReport", func() {
var report types.Report

BeforeEach(func() {
report = types.Report{
SuiteDescription: "My Suite",
SuitePath: "/path/to/suite",
PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
RunTime: time.Minute,
SpecReports: types.SpecReports{
S(types.NodeTypeIt, Label("cat", "dog"), CLabels(Label("dolphin"), Label("gorilla", "cow")), CTS("A", "B"), CLS(cl0, cl1), "C", cl2, types.SpecStateTimedout, STD("some captured stdout\n"), GW("ginkgowriter\noutput\ncleanup!"), SE(types.SpecEventByStart, "a by step", cl0),
SE(types.SpecEventNodeStart, types.NodeTypeIt, "C", cl2, TL(0)),
F("failure\nmessage", cl3, types.FailureNodeIsLeafNode, FailureNodeLocation(cl2), types.NodeTypeIt, TL("ginkgowriter\n"), AF(types.SpecStatePanicked, cl4, types.FailureNodeIsLeafNode, FailureNodeLocation(cl2), types.NodeTypeIt, TL("ginkgowriter\noutput\n"), ForwardedPanic("the panic!"))),
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "C", cl2, TL("ginkgowriter\noutput\n"), time.Microsecond*87230),
RE("a report entry", cl1, TL("ginkgowriter\noutput\n")),
RE("a hidden report entry", cl1, TL("ginkgowriter\noutput\n"), types.ReportEntryVisibilityNever),
AF(types.SpecStateFailed, "a subsequent failure", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeAfterEach, 0, TL("ginkgowriter\noutput\ncleanup!")),
),
S(types.NodeTypeIt, "A", cl0, STD("some captured stdout\n"), GW("some GinkgoWriter\noutput is interspersed\nhere and there\n"),
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
PR("my progress report", LeafNodeText("A"), TL("some GinkgoWriter\n")),
SE(types.SpecEventByStart, "My Step", cl1, TL("some GinkgoWriter\n")),
RE("my entry", cl1, types.ReportEntryVisibilityFailureOrVerbose, TL("some GinkgoWriter\noutput is interspersed\n")),
RE("my hidden entry", cl1, types.ReportEntryVisibilityNever, TL("some GinkgoWriter\noutput is interspersed\n")),
SE(types.SpecEventByEnd, "My Step", cl1, time.Millisecond*200, TL("some GinkgoWriter\noutput is interspersed\n")),
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
),
S(types.NodeTypeIt, "A", cl0, types.SpecStatePending),
S(types.NodeTypeIt, "A", cl0, types.SpecStatePanicked, STD("some captured stdout\n"),
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
F("failure\nmessage", cl1, types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeIt, ForwardedPanic("the panic")),
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
),
S(types.NodeTypeBeforeSuite, "A", cl0, types.SpecStatePassed),
},
}
})

Describe("when configured to write the report inside a folder", func() {
var folderPath string
var filePath string

BeforeEach(func() {
folderPath = filepath.Join("test_outputs")
fileName := fmt.Sprintf("report-%d", GinkgoParallelProcess())
filePath = filepath.Join(folderPath, fileName)

Ω(reporters.GenerateTeamcityReport(report, filePath)).Should(Succeed())
DeferCleanup(os.RemoveAll, folderPath)
})

It("creates the folder and the report file", func() {
_, err := os.Stat(folderPath)
Ω(err).Should(Succeed(), "Parent folder should be created")
_, err = os.Stat(filePath)
Ω(err).Should(Succeed(), "Report file should be created")
})
})
})

0 comments on commit 0ac65de

Please sign in to comment.