Skip to content

Commit 0ac65de

Browse files
authoredMay 31, 2023
fix: create parent directory before report files (#1212)
1 parent 4c2ae23 commit 0ac65de

6 files changed

+193
-3
lines changed
 

‎reporters/json_report.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import (
44
"encoding/json"
55
"fmt"
66
"os"
7+
"path"
78

89
"github.com/onsi/ginkgo/v2/types"
910
)
1011

11-
//GenerateJSONReport produces a JSON-formatted report at the passed in destination
12+
// GenerateJSONReport produces a JSON-formatted report at the passed in destination
1213
func GenerateJSONReport(report types.Report, destination string) error {
14+
if err := os.MkdirAll(path.Dir(destination), 0770); err != nil {
15+
return err
16+
}
1317
f, err := os.Create(destination)
1418
if err != nil {
1519
return err
@@ -25,8 +29,8 @@ func GenerateJSONReport(report types.Report, destination string) error {
2529
return f.Close()
2630
}
2731

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

53+
if err := os.MkdirAll(path.Dir(destination), 0770); err != nil {
54+
return messages, err
55+
}
4956
f, err := os.Create(destination)
5057
if err != nil {
5158
return messages, err

‎reporters/json_report_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package reporters_test
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"time"
8+
9+
. "github.com/onsi/ginkgo/v2"
10+
. "github.com/onsi/gomega"
11+
12+
"github.com/onsi/ginkgo/v2/reporters"
13+
"github.com/onsi/ginkgo/v2/types"
14+
)
15+
16+
var _ = Describe("JSONReport", func() {
17+
var report types.Report
18+
19+
BeforeEach(func() {
20+
report = types.Report{
21+
SuiteDescription: "My Suite",
22+
SuitePath: "/path/to/suite",
23+
PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
24+
SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
25+
RunTime: time.Minute,
26+
SpecReports: types.SpecReports{
27+
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),
28+
SE(types.SpecEventNodeStart, types.NodeTypeIt, "C", cl2, TL(0)),
29+
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!"))),
30+
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "C", cl2, TL("ginkgowriter\noutput\n"), time.Microsecond*87230),
31+
RE("a report entry", cl1, TL("ginkgowriter\noutput\n")),
32+
RE("a hidden report entry", cl1, TL("ginkgowriter\noutput\n"), types.ReportEntryVisibilityNever),
33+
AF(types.SpecStateFailed, "a subsequent failure", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeAfterEach, 0, TL("ginkgowriter\noutput\ncleanup!")),
34+
),
35+
S(types.NodeTypeIt, "A", cl0, STD("some captured stdout\n"), GW("some GinkgoWriter\noutput is interspersed\nhere and there\n"),
36+
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
37+
PR("my progress report", LeafNodeText("A"), TL("some GinkgoWriter\n")),
38+
SE(types.SpecEventByStart, "My Step", cl1, TL("some GinkgoWriter\n")),
39+
RE("my entry", cl1, types.ReportEntryVisibilityFailureOrVerbose, TL("some GinkgoWriter\noutput is interspersed\n")),
40+
RE("my hidden entry", cl1, types.ReportEntryVisibilityNever, TL("some GinkgoWriter\noutput is interspersed\n")),
41+
SE(types.SpecEventByEnd, "My Step", cl1, time.Millisecond*200, TL("some GinkgoWriter\noutput is interspersed\n")),
42+
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
43+
),
44+
S(types.NodeTypeIt, "A", cl0, types.SpecStatePending),
45+
S(types.NodeTypeIt, "A", cl0, types.SpecStatePanicked, STD("some captured stdout\n"),
46+
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
47+
F("failure\nmessage", cl1, types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeIt, ForwardedPanic("the panic")),
48+
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
49+
),
50+
S(types.NodeTypeBeforeSuite, "A", cl0, types.SpecStatePassed),
51+
},
52+
}
53+
})
54+
55+
Describe("when configured to write the report inside a folder", func() {
56+
var folderPath string
57+
var filePath string
58+
59+
BeforeEach(func() {
60+
folderPath = filepath.Join("test_outputs")
61+
fileName := fmt.Sprintf("report-%d", GinkgoParallelProcess())
62+
filePath = filepath.Join(folderPath, fileName)
63+
64+
Ω(reporters.GenerateJSONReport(report, filePath)).Should(Succeed())
65+
DeferCleanup(os.RemoveAll, folderPath)
66+
})
67+
68+
It("creates the folder and the report file", func() {
69+
_, err := os.Stat(folderPath)
70+
Ω(err).Should(Succeed(), "Parent folder should be created")
71+
_, err = os.Stat(filePath)
72+
Ω(err).Should(Succeed(), "Report file should be created")
73+
})
74+
})
75+
})

‎reporters/junit_report.go

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"encoding/xml"
1515
"fmt"
1616
"os"
17+
"path"
1718
"strings"
1819

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

289+
if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
290+
return err
291+
}
288292
f, err := os.Create(dst)
289293
if err != nil {
290294
return err
@@ -322,6 +326,9 @@ func MergeAndCleanupJUnitReports(sources []string, dst string) ([]string, error)
322326
mergedReport.TestSuites = append(mergedReport.TestSuites, report.TestSuites...)
323327
}
324328

329+
if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
330+
return messages, err
331+
}
325332
f, err := os.Create(dst)
326333
if err != nil {
327334
return messages, err

‎reporters/junit_report_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/xml"
55
"fmt"
66
"os"
7+
"path/filepath"
78
"time"
89

910
. "github.com/onsi/ginkgo/v2"
@@ -372,4 +373,25 @@ var _ = Describe("JunitReport", func() {
372373
))
373374
})
374375
})
376+
377+
Describe("when configured to write the report inside a folder", func() {
378+
var folderPath string
379+
var filePath string
380+
381+
BeforeEach(func() {
382+
folderPath = filepath.Join("test_outputs")
383+
fileName := fmt.Sprintf("report-%d", GinkgoParallelProcess())
384+
filePath = filepath.Join(folderPath, fileName)
385+
386+
Ω(reporters.GenerateJUnitReport(report, filePath)).Should(Succeed())
387+
DeferCleanup(os.RemoveAll, folderPath)
388+
})
389+
390+
It("creates the folder and the report file", func() {
391+
_, err := os.Stat(folderPath)
392+
Ω(err).Should(Succeed(), "Parent folder should be created")
393+
_, err = os.Stat(filePath)
394+
Ω(err).Should(Succeed(), "Report file should be created")
395+
})
396+
})
375397
})

‎reporters/teamcity_report.go

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package reporters
1111
import (
1212
"fmt"
1313
"os"
14+
"path"
1415
"strings"
1516

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

2930
func GenerateTeamcityReport(report types.Report, dst string) error {
31+
if err := os.MkdirAll(path.Dir(dst), 0770); err != nil {
32+
return err
33+
}
3034
f, err := os.Create(dst)
3135
if err != nil {
3236
return err

‎reporters/teamcity_report_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package reporters_test
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"time"
8+
9+
. "github.com/onsi/ginkgo/v2"
10+
. "github.com/onsi/gomega"
11+
12+
"github.com/onsi/ginkgo/v2/reporters"
13+
"github.com/onsi/ginkgo/v2/types"
14+
)
15+
16+
var _ = Describe("TeamCityReport", func() {
17+
var report types.Report
18+
19+
BeforeEach(func() {
20+
report = types.Report{
21+
SuiteDescription: "My Suite",
22+
SuitePath: "/path/to/suite",
23+
PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
24+
SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
25+
RunTime: time.Minute,
26+
SpecReports: types.SpecReports{
27+
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),
28+
SE(types.SpecEventNodeStart, types.NodeTypeIt, "C", cl2, TL(0)),
29+
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!"))),
30+
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "C", cl2, TL("ginkgowriter\noutput\n"), time.Microsecond*87230),
31+
RE("a report entry", cl1, TL("ginkgowriter\noutput\n")),
32+
RE("a hidden report entry", cl1, TL("ginkgowriter\noutput\n"), types.ReportEntryVisibilityNever),
33+
AF(types.SpecStateFailed, "a subsequent failure", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeAfterEach, 0, TL("ginkgowriter\noutput\ncleanup!")),
34+
),
35+
S(types.NodeTypeIt, "A", cl0, STD("some captured stdout\n"), GW("some GinkgoWriter\noutput is interspersed\nhere and there\n"),
36+
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
37+
PR("my progress report", LeafNodeText("A"), TL("some GinkgoWriter\n")),
38+
SE(types.SpecEventByStart, "My Step", cl1, TL("some GinkgoWriter\n")),
39+
RE("my entry", cl1, types.ReportEntryVisibilityFailureOrVerbose, TL("some GinkgoWriter\noutput is interspersed\n")),
40+
RE("my hidden entry", cl1, types.ReportEntryVisibilityNever, TL("some GinkgoWriter\noutput is interspersed\n")),
41+
SE(types.SpecEventByEnd, "My Step", cl1, time.Millisecond*200, TL("some GinkgoWriter\noutput is interspersed\n")),
42+
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
43+
),
44+
S(types.NodeTypeIt, "A", cl0, types.SpecStatePending),
45+
S(types.NodeTypeIt, "A", cl0, types.SpecStatePanicked, STD("some captured stdout\n"),
46+
SE(types.SpecEventNodeStart, types.NodeTypeIt, "A", cl0),
47+
F("failure\nmessage", cl1, types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeIt, ForwardedPanic("the panic")),
48+
SE(types.SpecEventNodeEnd, types.NodeTypeIt, "A", cl0, time.Millisecond*300, TL("some GinkgoWriter\noutput is interspersed\nhere and there\n")),
49+
),
50+
S(types.NodeTypeBeforeSuite, "A", cl0, types.SpecStatePassed),
51+
},
52+
}
53+
})
54+
55+
Describe("when configured to write the report inside a folder", func() {
56+
var folderPath string
57+
var filePath string
58+
59+
BeforeEach(func() {
60+
folderPath = filepath.Join("test_outputs")
61+
fileName := fmt.Sprintf("report-%d", GinkgoParallelProcess())
62+
filePath = filepath.Join(folderPath, fileName)
63+
64+
Ω(reporters.GenerateTeamcityReport(report, filePath)).Should(Succeed())
65+
DeferCleanup(os.RemoveAll, folderPath)
66+
})
67+
68+
It("creates the folder and the report file", func() {
69+
_, err := os.Stat(folderPath)
70+
Ω(err).Should(Succeed(), "Parent folder should be created")
71+
_, err = os.Stat(filePath)
72+
Ω(err).Should(Succeed(), "Report file should be created")
73+
})
74+
})
75+
})

0 commit comments

Comments
 (0)
Please sign in to comment.