Skip to content

Commit

Permalink
Merge pull request #1 from bahrimootaz/parse_all_test_config
Browse files Browse the repository at this point in the history
Read all of test configs from xctestrun file
  • Loading branch information
bahrimootaz authored Dec 10, 2024
2 parents 8451b6b + 6716cf6 commit c088386
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 33 deletions.
82 changes: 74 additions & 8 deletions ios/testmanagerd/xctestrunnerutils_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package testmanagerd

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestParseXCTestRun(t *testing.T) {
func TestParseXCTestRunFormatVersion1(t *testing.T) {
// Arrange: Create a temporary .xctestrun file with mock data
tempFile, err := os.CreateTemp("", "testfile*.xctestrun")
assert.NoError(t, err, "Failed to create temp file")
defer os.Remove(tempFile.Name()) // Cleanup after test

mockData := `
xcTestRunFileFormatVersion1 := `
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Expand Down Expand Up @@ -89,6 +88,16 @@ func TestParseXCTestRun(t *testing.T) {
<array/>
<key>UserAttachmentLifetime</key>
<string>deleteOnSuccess</string>
<key>OnlyTestIdentifiers</key>
<array>
<string>TestClass1/testMethod1</string>
<string>TestClass2/testMethod1</string>
</array>
<key>SkipTestIdentifiers</key>
<array>
<string>TestClass1/testMethod2</string>
<string>TestClass2/testMethod2</string>
</array>
</dict>
<key>__xctestrun_metadata__</key>
<dict>
Expand All @@ -105,25 +114,82 @@ func TestParseXCTestRun(t *testing.T) {
</dict>
</plist>
`
_, err = tempFile.WriteString(mockData)
_, err = tempFile.WriteString(xcTestRunFileFormatVersion1)
assert.NoError(t, err, "Failed to write mock data to temp file")
tempFile.Close()

// Act: Use the codec to parse the temp file
codec := NewXCTestRunCodec()
data, err := codec.ParseFile(tempFile.Name())

// Print the parsed data before asserting
fmt.Printf("Parsed Data: %+v\n", data)

// Assert: Verify the parsed data
assert.NoError(t, err, "Failed to parse .xctestrun file")
assert.NotNil(t, data, "Parsed data should not be nil")

// Check specific fields in the parsed data
// Assert TestHostBundleIdentifier value
assert.Equal(t, "com.example.myApp", data.RunnerTests.TestHostBundleIdentifier, "TestHostBundleIdentifier mismatch")

// Assert TestBundlePath value
assert.Equal(t, "__TESTHOST__/PlugIns/RunnerTests.xctest", data.RunnerTests.TestBundlePath, "TestBundlePath mismatch")

// Assert EnvironmentVariables values
assert.Equal(t, map[string]string{
"APP_DISTRIBUTOR_ID_OVERRIDE": "com.apple.AppStore",
"OS_ACTIVITY_DT_MODE": "YES",
"SQLITE_ENABLE_THREAD_ASSERTIONS": "1",
"TERM": "dumb",
}, data.RunnerTests.EnvironmentVariables, "EnvironmentVariables mismatch")

// Assert CommandLineArguments values
assert.Equal(t, []string{}, data.RunnerTests.CommandLineArguments, "CommandLineArguments mismatch")

// Assert TestingEnvironmentVariables values
assert.Equal(t, "unused", data.RunnerTests.TestingEnvironmentVariables.XCInjectBundleInto, "XCInjectBundleInto mismatch")
assert.Equal(t, "__TESTHOST__/Frameworks/libXCTestBundleInject.dylib", data.RunnerTests.TestingEnvironmentVariables.DYLD_INSERT_LIBRARIES, "DYLD_INSERT_LIBRARIES mismatch")

// Assert OnlyTestIdentifiers values
assert.Equal(t, []string{
"TestClass1/testMethod1",
"TestClass2/testMethod1",
}, data.RunnerTests.OnlyTestIdentifiers, "OnlyTestIdentifiers mismatch")

// Assert SkipTestIdentifiers values
assert.Equal(t, []string{
"TestClass1/testMethod2",
"TestClass2/testMethod2",
}, data.RunnerTests.SkipTestIdentifiers, "SkipTestIdentifiers mismatch")

// Assert XCTestRunMetadata values
assert.Equal(t, 1, data.XCTestRunMetadata.FormatVersion, "FormatVersion mismatch")
}

func TestParseXCTestRunNotSupportedForFormatVersionOtherThanOne(t *testing.T) {
// Arrange: Create a temporary .xctestrun file with mock data
tempFile, err := os.CreateTemp("", "testfile*.xctestrun")
assert.NoError(t, err, "Failed to create temp file")
defer os.Remove(tempFile.Name()) // Cleanup after test

xcTestRunFileFormatVersion2 := `
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>__xctestrun_metadata__</key>
<dict>
<key>FormatVersion</key>
<integer>2</integer>
</dict>
</dict>
</plist>
`
_, err = tempFile.WriteString(xcTestRunFileFormatVersion2)
assert.NoError(t, err, "Failed to write mock data to temp file")
tempFile.Close()

// Act: Use the codec to parse the temp file
codec := NewXCTestRunCodec()
_, err = codec.ParseFile(tempFile.Name())

// Assert the Error Message
assert.Equal(t, "go-ios currently only supports .xctestrun files in formatVersion 1: The formatVersion of your xctestrun file is 2, feel free to open an issue in https://github.com/danielpaulus/go-ios/issues to add support", err.Error(), "Error Message mismatch")
}
24 changes: 21 additions & 3 deletions ios/testmanagerd/xctestrunutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@ import (

type XCTestRunData struct {
RunnerTests struct {
TestHostBundleIdentifier string `plist:"TestHostBundleIdentifier"`
TestBundlePath string `plist:"TestBundlePath"`
TestHostBundleIdentifier string `plist:"TestHostBundleIdentifier"`
TestBundlePath string `plist:"TestBundlePath"`
SkipTestIdentifiers []string `plist:"SkipTestIdentifiers"`
OnlyTestIdentifiers []string `plist:"OnlyTestIdentifiers"`
CommandLineArguments []string `plist:"CommandLineArguments"`
EnvironmentVariables map[string]string `plist:"EnvironmentVariables"`
TestingEnvironmentVariables struct {
DYLD_INSERT_LIBRARIES string `plist:"DYLD_INSERT_LIBRARIES"`
XCInjectBundleInto string `plist:"XCInjectBundleInto"`
} `plist:"TestingEnvironmentVariables"`
} `plist:"RunnerTests"`
XCTestRunMetadata struct {
FormatVersion int `plist:"FormatVersion"`
Expand All @@ -37,7 +45,17 @@ func (codec XCTestRunCodec) ParseFile(filePath string) (XCTestRunData, error) {
}
defer file.Close()

return codec.Decode(file)
xctestRunDate, err := codec.Decode(file)

// Verify that the FormatVersion is 1
if xctestRunDate.XCTestRunMetadata.FormatVersion != 1 {
log.Errorf("Invalid FormatVersion in .xctestrun file: got %d, expected 1", xctestRunDate.XCTestRunMetadata.FormatVersion)
return xctestRunDate, fmt.Errorf("go-ios currently only supports .xctestrun files in formatVersion 1: "+
"The formatVersion of your xctestrun file is %d, feel free to open an issue in https://github.com/danielpaulus/go-ios/issues to "+
"add support", xctestRunDate.XCTestRunMetadata.FormatVersion)
}

return xctestRunDate, err
}

// Decode reads and decodes the binary xctestrun content from a reader
Expand Down
30 changes: 24 additions & 6 deletions ios/testmanagerd/xcuitestrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ type TestConfig struct {
Listener *TestListener
}

func StartXCTestWithConfig(ctx context.Context, xctestrunFilePath string, testsToSkip []string, testsToRun []string, testArgs []string, testEnv map[string]interface{}, device ios.DeviceEntry, listener *TestListener) ([]TestSuite, error) {
func StartXCTestWithConfig(ctx context.Context, xctestrunFilePath string, device ios.DeviceEntry, listener *TestListener) ([]TestSuite, error) {
// Parse the .xctestrun file to get the necessary details for TestConfig
codec := NewXCTestRunCodec()
result, err := codec.ParseFile(xctestrunFilePath)
Expand All @@ -259,20 +259,38 @@ func StartXCTestWithConfig(ctx context.Context, xctestrunFilePath string, testsT
return nil, err
}

// Verify that the FormatVersion is 1
if result.XCTestRunMetadata.FormatVersion != 1 {
log.Errorf("Invalid FormatVersion in .xctestrun file: got %d, expected 1", result.XCTestRunMetadata.FormatVersion)
return nil, fmt.Errorf("invalid FormatVersion in .xctestrun file: %d (expected 1)", result.XCTestRunMetadata.FormatVersion)
testsToRunArg := result.RunnerTests.OnlyTestIdentifiers
var testsToRun []string
if testsToRunArg != nil && len(testsToRunArg) > 0 {
testsToRun = testsToRunArg
}

testsToSkipArg := result.RunnerTests.SkipTestIdentifiers
var testsToSkip []string
testsToSkip = nil
if testsToSkipArg != nil && len(testsToSkipArg) > 0 {
testsToSkip = testsToSkipArg
}

testEnv := make(map[string]any)

// Add EnvironmentVariables to the map
for key, value := range result.RunnerTests.EnvironmentVariables {
testEnv[key] = value
}

// Add TestingEnvironmentVariables to the map
testEnv["DYLD_INSERT_LIBRARIES"] = result.RunnerTests.TestingEnvironmentVariables.DYLD_INSERT_LIBRARIES
testEnv["XCInjectBundleInto"] = result.RunnerTests.TestingEnvironmentVariables.XCInjectBundleInto

// Extract only the file name
var testBundlePath = filepath.Base(result.RunnerTests.TestBundlePath)

// Build the TestConfig object from parsed data
testConfig := TestConfig{
TestRunnerBundleId: result.RunnerTests.TestHostBundleIdentifier,
XctestConfigName: testBundlePath,
Args: testArgs,
Args: result.RunnerTests.CommandLineArguments,
Env: testEnv,
TestsToRun: testsToRun,
TestsToSkip: testsToSkip,
Expand Down
18 changes: 2 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1010,21 +1010,7 @@ The commands work as following:
if b {
xctestrunFilePath, _ := arguments.String("--xctestrun-file-path")

testsToRunArg := arguments["--test-to-run"]
var testsToRun []string
if testsToRunArg != nil && len(testsToRunArg.([]string)) > 0 {
testsToRun = testsToRunArg.([]string)
}

testsToSkipArg := arguments["--test-to-skip"]
var testsToSkip []string
testsToSkip = nil
if testsToSkipArg != nil && len(testsToSkipArg.([]string)) > 0 {
testsToSkip = testsToSkipArg.([]string)
}

rawTestlog, rawTestlogErr := arguments.String("--log-output")
env := splitKeyValuePairs(arguments["--env"].([]string), "=")

if rawTestlogErr == nil {
var writer *os.File = os.Stdout
Expand All @@ -1036,15 +1022,15 @@ The commands work as following:
defer writer.Close()
var listener = testmanagerd.NewTestListener(writer, writer, os.TempDir())

testResults, err := testmanagerd.StartXCTestWithConfig(context.TODO(), xctestrunFilePath, testsToSkip, testsToRun, []string{}, env, device, listener)
testResults, err := testmanagerd.StartXCTestWithConfig(context.TODO(), xctestrunFilePath, device, listener)
if err != nil {
log.WithFields(log.Fields{"error": err}).Info("Failed running Xctest")
}

log.Info(fmt.Printf("%+v", testResults))
} else {
var listener = testmanagerd.NewTestListener(io.Discard, io.Discard, os.TempDir())
_, err := testmanagerd.StartXCTestWithConfig(context.TODO(), xctestrunFilePath, testsToSkip, testsToRun, []string{}, env, device, listener)
_, err := testmanagerd.StartXCTestWithConfig(context.TODO(), xctestrunFilePath, device, listener)
if err != nil {
log.WithFields(log.Fields{"error": err}).Info("Failed running Xctest")
}
Expand Down

0 comments on commit c088386

Please sign in to comment.