// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 package junit_test import ( "bytes" "fmt" "os" "testing" "github.com/hashicorp/terraform/internal/backend/local" "github.com/hashicorp/terraform/internal/command/junit" "github.com/hashicorp/terraform/internal/configs/configload" "github.com/hashicorp/terraform/internal/moduletest" "github.com/hashicorp/terraform/internal/tfdiags" ) // This test cannot access sources when contructing output for XML files. Due to this, the majority of testing // for TestJUnitXMLFile is in internal/command/test_test.go // In the junit package we can write some limited tests about XML output as long as there are no errors and/or // failing tests in the test. func Test_TestJUnitXMLFile_Save(t *testing.T) { cases := map[string]struct { filename string runner *local.TestSuiteRunner suite moduletest.Suite expectedOuput []byte expectError bool }{ " element can explain when skip is due to the runner being stopped by an interrupt": { filename: "output.xml", runner: &local.TestSuiteRunner{ Stopped: true, }, suite: moduletest.Suite{ Status: moduletest.Skip, Files: map[string]*moduletest.File{ "file1.tftest.hcl": { Name: "file1.tftest.hcl", Status: moduletest.Fail, Runs: []*moduletest.Run{ { Name: "my_test", Status: moduletest.Skip, }, }, }, }, }, expectedOuput: []byte(` `), }, " element can explain when skip is due to the previously errored runs/testcases in the file": { filename: "output.xml", runner: &local.TestSuiteRunner{}, suite: moduletest.Suite{ Status: moduletest.Error, Files: map[string]*moduletest.File{ "file1.tftest.hcl": { Name: "file1.tftest.hcl", Status: moduletest.Error, Runs: []*moduletest.Run{ { Name: "my_test_1", Status: moduletest.Error, }, { Name: "my_test_2", Status: moduletest.Skip, }, }, }, }, }, expectedOuput: []byte(` `), }, " element is present without additional details when contextual data is not available": { filename: "output.xml", runner: &local.TestSuiteRunner{ // No data about being stopped }, suite: moduletest.Suite{ Status: moduletest.Pending, Files: map[string]*moduletest.File{ "file1.tftest.hcl": { Name: "file1.tftest.hcl", Status: moduletest.Pending, Runs: []*moduletest.Run{ { Name: "my_test", Status: moduletest.Skip, // Only run present is skipped, no previous errors }, }, }, }, }, expectedOuput: []byte(` `), }, "suite-level includes file-level error diagnostics when tests are skipped": { filename: "output.xml", runner: &local.TestSuiteRunner{}, suite: func() moduletest.Suite { file := &moduletest.File{ Name: "file1.tftest.hcl", Status: moduletest.Error, Runs: []*moduletest.Run{ { Name: "my_test", Status: moduletest.Skip, }, }, } // Simulate file-level error diagnostic (e.g., invalid variable reference) var diags tfdiags.Diagnostics diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Invalid reference", "You can only reference global variables within the test file variables block.", )) file.AppendDiagnostics(diags) return moduletest.Suite{ Status: moduletest.Error, Files: map[string]*moduletest.File{ "file1.tftest.hcl": file, }, } }(), expectedOuput: []byte(` `), }, } for tn, tc := range cases { t.Run(tn, func(t *testing.T) { // Setup test td := t.TempDir() path := fmt.Sprintf("%s/%s", td, tc.filename) loader, cleanup := configload.NewLoaderForTests(t) defer cleanup() j := junit.NewTestJUnitXMLFile(path, loader, tc.runner) // Process data & save file j.Save(&tc.suite) // Assertions actualOut, err := os.ReadFile(path) if err != nil { t.Fatalf("error opening XML file: %s", err) } if !bytes.Equal(actualOut, tc.expectedOuput) { t.Fatalf("expected output:\n%s\ngot:\n%s", tc.expectedOuput, actualOut) } }) } }