From 6e3153dd44c623cca9a42549b2dae80b157ed969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Stemmer?= Date: Sat, 26 Mar 2022 23:15:42 +0000 Subject: [PATCH] Refactor and simplify tests For most testcases we shouldn't need to specify the input and report files, instead just look at the testdata/ dir and process each input file. For the few testcases that need a non-standard config, an entry can be added to `testConfigs` map (indexed by the test number). The testdata files must follow a certain naming pattern to be valid. They should start with a number, followed by a dash, then any text describing the test and finally end with `.txt`. The corresponding report file must start with the same number, a dash, followed by `report.xml`. --- go-junit-report_test.go | 292 ++++++++-------------------------------- 1 file changed, 57 insertions(+), 235 deletions(-) diff --git a/go-junit-report_test.go b/go-junit-report_test.go index 2289907..1091294 100644 --- a/go-junit-report_test.go +++ b/go-junit-report_test.go @@ -1,13 +1,12 @@ package main import ( - "encoding/xml" + "bytes" "flag" "fmt" - "io/ioutil" "os" + "path/filepath" "regexp" - "runtime" "strconv" "strings" "testing" @@ -19,276 +18,99 @@ import ( "github.com/google/go-cmp/cmp" ) +const testDataDir = "testdata/" + var matchTest = flag.String("match", "", "only test testdata matching this pattern") -type TestCase struct { - name string - reportName string +type TestConfig struct { noXMLHeader bool packageName string } -var testCases = []TestCase{ - { - name: "001-pass.txt", - reportName: "001-report.xml", - }, - { - name: "002-fail.txt", - reportName: "002-report.xml", - }, - { - name: "003-skip.txt", - reportName: "003-report.xml", - }, - { - name: "004-go_1_4.txt", - reportName: "004-report.xml", - }, - { - name: "005-no_xml_header.txt", - reportName: "005-report.xml", - noXMLHeader: true, - }, - { - name: "006-mixed.txt", - reportName: "006-report.xml", - noXMLHeader: true, - }, - { - name: "007-compiled_test.txt", - reportName: "007-report.xml", - packageName: "test/package", - }, - { - name: "008-parallel.txt", - reportName: "008-report.xml", - }, - { - name: "009-coverage.txt", - reportName: "009-report.xml", - }, - { - name: "010-multipkg-coverage.txt", - reportName: "010-report.xml", - }, - { - name: "011-go_1_5.txt", - reportName: "011-report.xml", - }, - { - name: "012-go_1_7.txt", - reportName: "012-report.xml", - }, - { - name: "013-syntax-error.txt", - reportName: "013-report.xml", - }, - { - name: "014-panic.txt", - reportName: "014-report.xml", - }, - { - name: "015-empty.txt", - reportName: "015-report.xml", - }, - { - name: "016-repeated-names.txt", - reportName: "016-report.xml", - }, - { - name: "017-race.txt", - reportName: "017-report.xml", - }, - { - name: "018-coverpkg.txt", - reportName: "018-report.xml", - }, - { - name: "019-pass.txt", - reportName: "019-report.xml", - }, - { - name: "020-parallel.txt", - reportName: "020-report.xml", - }, - { - name: "021-cached.txt", - reportName: "021-report.xml", - }, - { - name: "022-bench.txt", - reportName: "022-report.xml", - }, - { - name: "023-benchmem.txt", - reportName: "023-report.xml", - }, - { - name: "024-benchtests.txt", - reportName: "024-report.xml", - }, - { - name: "025-benchcount.txt", - reportName: "025-report.xml", - }, - { - name: "026-testbenchmultiple.txt", - reportName: "026-report.xml", - }, - { - name: "027-benchdecimal.txt", - reportName: "027-report.xml", - }, - { - name: "028-bench-1cpu.txt", - reportName: "028-report.xml", - }, - { - name: "029-bench-16cpu.txt", - reportName: "029-report.xml", - }, - { - // generated by running go test on https://gist.github.com/liggitt/09a021ccec988b19917e0c2d60a18ee9 - name: "030-stdout.txt", - reportName: "030-report.xml", - }, - { - name: "031-syntax-error-test-binary.txt", - reportName: "031-report.xml", - }, - { - name: "032-failed-summary.txt", - reportName: "032-report.xml", - }, - { - name: "033-bench-mb.txt", - reportName: "033-report.xml", - }, - { - name: "034-notest.txt", - reportName: "034-report.xml", - }, - { - name: "035-whitespace.txt", - reportName: "035-report.xml", - }, +var testConfigs = map[int]TestConfig{ + 5: {noXMLHeader: true}, + 6: {noXMLHeader: true}, + 7: {packageName: "test/package"}, } -func TestNewOutput(t *testing.T) { +func TestRun(t *testing.T) { matchRegex := compileMatch(t) - for _, testCase := range testCases { - if !matchRegex.MatchString(testCase.name) { + + files, err := filepath.Glob(testDataDir + "*.txt") + if err != nil { + t.Fatalf("error finding files in testdata: %v", err) + } + + for _, file := range files { + if !matchRegex.MatchString(file) { continue } - t.Run(testCase.name, func(t *testing.T) { - testReport(testCase.name, testCase.reportName, testCase.packageName, t) + conf, reportFile, err := testFileConfig(strings.TrimPrefix(file, testDataDir)) + if err != nil { + t.Errorf("testFileConfig error: %v", err) + continue + } + + t.Run(file, func(t *testing.T) { + testRun(file, testDataDir+reportFile, conf, t) }) } } -func testReport(input, reportFile, packageName string, t *testing.T) { - file, err := os.Open("testdata/" + input) +func testRun(inputFile, reportFile string, config TestConfig, t *testing.T) { + input, err := os.Open(inputFile) if err != nil { - t.Fatal(err) + t.Fatalf("error opening input file: %v", err) + } + defer input.Close() + + wantReport, err := os.ReadFile(reportFile) + if os.IsNotExist(err) { + t.Skipf("Skipping test with missing report file: %s", reportFile) + } else if err != nil { + t.Fatalf("error loading report file: %v", err) } - defer file.Close() parser := gotest.New( - gotest.PackageName(packageName), + gotest.PackageName(config.packageName), gotest.TimestampFunc(func() time.Time { return time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) }), ) - report, err := parser.Parse(file) + report, err := parser.Parse(input) if err != nil { t.Fatal(err) } - if *printEvents { - for _, event := range parser.Events() { - t.Logf("Event: %+v", event) - } + for i := range report.Packages { + report.Packages[i].SetProperty("go.version", "1.0") + } + testsuites := junit.CreateFromReport(report, "hostname") + + var output bytes.Buffer + if err := writeXML(&output, testsuites, config.noXMLHeader); err != nil { + t.Fatalf("error writing XML: %v", err) } - actual := junit.CreateFromReport(report, "hostname") - - expectedXML, err := loadTestReport(reportFile, "") - if err != nil { - t.Fatal(err) - } - - var expected junit.Testsuites - if err := xml.Unmarshal([]byte(expectedXML), &expected); err != nil { - t.Fatal(err) - } - - expected = modifyForBackwardsCompat(expected) - if diff := cmp.Diff(actual, expected); diff != "" { + if diff := cmp.Diff(output.String(), string(wantReport)); diff != "" { t.Errorf("Unexpected report diff (-got, +want):\n%v", diff) } } -func modifyForBackwardsCompat(testsuites junit.Testsuites) junit.Testsuites { - testsuites.XMLName.Local = "" - for i, suite := range testsuites.Suites { - for j := range suite.Testcases { - testsuites.Suites[i].Testcases[j].Classname = suite.Name - } - - if suite.Properties != nil { - if covIdx, covProp := getProperty("coverage.statements.pct", *suite.Properties); covIdx > -1 { - pct, _ := strconv.ParseFloat(covProp.Value, 64) - (*testsuites.Suites[i].Properties)[covIdx].Value = fmt.Sprintf("%.2f", pct) - } - testsuites.Suites[i].Properties = dropProperty("go.version", suite.Properties) - } +func testFileConfig(filename string) (conf TestConfig, reportFile string, err error) { + var prefix string + if idx := strings.IndexByte(filename, '-'); idx < 0 { + return conf, "", fmt.Errorf("testdata file does not contain a dash (-); expected name `{id}-{name}.txt` got `%s`", filename) + } else { + prefix = filename[:idx] } - return testsuites -} - -func dropProperty(name string, properties *[]junit.Property) *[]junit.Property { - if properties == nil { - return nil - } - var props []junit.Property - for _, prop := range *properties { - if prop.Name != name { - props = append(props, prop) - } - } - if len(props) == 0 { - return nil - } - return &props -} - -func getProperty(name string, properties []junit.Property) (int, junit.Property) { - for i, prop := range properties { - if prop.Name == name { - return i, prop - } - } - return -1, junit.Property{} -} - -func loadTestReport(name, goVersion string) (string, error) { - contents, err := ioutil.ReadFile("testdata/" + name) + id, err := strconv.Atoi(prefix) if err != nil { - return "", err + return conf, "", fmt.Errorf("testdata file did not start with a valid number: %w", err) } - - if goVersion == "" { - // if goVersion is not specified, default to runtime version - goVersion = runtime.Version() - } - - // replace value="1.0" With actual version - report := strings.Replace(string(contents), `value="1.0"`, fmt.Sprintf(`value="%s"`, goVersion), -1) - - return report, nil + return testConfigs[id], fmt.Sprintf("%s-report.xml", prefix), nil } func compileMatch(t *testing.T) *regexp.Regexp {