Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: create parent directory before report files #1212

Merged
merged 2 commits into from
May 31, 2023
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
13 changes: 10 additions & 3 deletions reporters/json_report.go
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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")
})
})
})