Skip to content

Commit

Permalink
feat: Add additional testOptions for xcuitest (#819)
Browse files Browse the repository at this point in the history
* Add more test options and conversion to map[string]interface{}

* Add new testOptions to json schema

* note that new props are simulator only

* lint

* typo

* Mention time units

* Update internal/xcuitest/config.go

Co-authored-by: Alex Plischke <alex.plischke@saucelabs.com>

* Cast ints to strings

* cleanup

* More context around why test options are being cast

* typo

* scope the test function

---------

Co-authored-by: Alex Plischke <alex.plischke@saucelabs.com>
  • Loading branch information
mhan83 and alexplischke authored Aug 11, 2023
1 parent 79ef155 commit 3fd3738
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 6 deletions.
24 changes: 24 additions & 0 deletions api/saucectl.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2176,6 +2176,30 @@
"notClass": {
"description": "Run all classes except those specified here.",
"type": "array"
},
"testLanguage": {
"description": "Specifies ISO 639-1 language during testing. Supported on Simulators only.",
"type": "string"
},
"testRegion": {
"description": "Specifies ISO 3166-1 region during testing.",
"type": "string"
},
"testTimeoutsEnabled": {
"description": "By default there is no timeout, if enabled, then the timeout is 600 seconds. This can be changed by adding the defaultTestExecutionTimeAllowance value. Supported on Simulators only.",
"type": "string",
"enum": [
"Yes",
"No"
]
},
"maximumTestExecutionTimeAllowance": {
"description": "The maximum execution time, in seconds, an individual test is given to execute, regardless of the test's preferred allowance. Supported on Simulators only.",
"type": "number"
},
"defaultTestExecutionTimeAllowance": {
"description": "The default execution time, in seconds, an individual test is given to execute if test timeouts are enabled. Supported on Simulators only.",
"type": "number"
}
},
"additionalProperties": false
Expand Down
21 changes: 21 additions & 0 deletions api/v1alpha/framework/xcuitest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,27 @@
"notClass": {
"description": "Run all classes except those specified here.",
"type": "array"
},
"testLanguage": {
"description": "Specifies ISO 639-1 language during testing. Supported on Simulators only.",
"type": "string"
},
"testRegion": {
"description": "Specifies ISO 3166-1 region during testing.",
"type": "string"
},
"testTimeoutsEnabled": {
"description": "By default there is no timeout, if enabled, then the timeout is 600 seconds. This can be changed by adding the defaultTestExecutionTimeAllowance value. Supported on Simulators only.",
"type": "string",
"enum": ["Yes", "No"]
},
"maximumTestExecutionTimeAllowance": {
"description": "The maximum execution time, in seconds, an individual test is given to execute, regardless of the test's preferred allowance. Supported on Simulators only.",
"type": "number"
},
"defaultTestExecutionTimeAllowance": {
"description": "The default execution time, in seconds, an individual test is given to execute if test timeouts are enabled. Supported on Simulators only.",
"type": "number"
}
},
"additionalProperties": false
Expand Down
5 changes: 1 addition & 4 deletions internal/saucecloud/xcuitest.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,7 @@ func (r *XcuitestRunner) startJob(jobOpts chan<- job.StartOptions, appFileID, te
SmartRetry: job.SmartRetry{
FailedOnly: s.SmartRetry.IsRetryFailedOnly(),
},
TestOptions: map[string]interface{}{
"class": s.TestOptions.Class,
"notClass": s.TestOptions.NotClass,
},
TestOptions: s.TestOptions.ToMap(),

// RDC Specific flags
RealDevice: d.isRealDevice,
Expand Down
42 changes: 40 additions & 2 deletions internal/xcuitest/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os"
"reflect"
"strings"
"time"

Expand Down Expand Up @@ -55,8 +56,45 @@ type Xcuitest struct {

// TestOptions represents the xcuitest test filter options configuration.
type TestOptions struct {
NotClass []string `yaml:"notClass,omitempty" json:"notClass"`
Class []string `yaml:"class,omitempty" json:"class"`
NotClass []string `yaml:"notClass,omitempty" json:"notClass"`
Class []string `yaml:"class,omitempty" json:"class"`
TestLanguage string `yaml:"testLanguage,omitempty" json:"testLanguage"`
TestRegion string `yaml:"testRegion,omitempty" json:"testRegion"`
TestTimeoutsEnabled string `yaml:"testTimeoutsEnabled,omitempty" json:"testTimeoutsEnabled"`
MaximumTestExecutionTimeAllowance int `yaml:"maximumTestExecutionTimeAllowance,omitempty" json:"maximumTestExecutionTimeAllowance"`
DefaultTestExecutionTimeAllowance int `yaml:"defaultTestExecutionTimeAllowance,omitempty" json:"defaultTestExecutionTimeAllowance"`
}

// ToMap converts the TestOptions to a map where the keys are derived from json struct tags.
func (t TestOptions) ToMap() map[string]interface{} {
m := make(map[string]interface{})
v := reflect.ValueOf(t)
tt := v.Type()

count := v.NumField()
for i := 0; i < count; i++ {
if v.Field(i).CanInterface() {
tag := tt.Field(i).Tag
tname, ok := tag.Lookup("json")
if ok && tname != "-" {
fv := v.Field(i).Interface()
ft := v.Field(i).Type()
switch ft.Kind() {
// Convert int to string to match chef expectation that all test option values are strings
case reflect.Int:
// Conventionally, test options with value "" will be ignored.
if fv.(int) == 0 {
m[tname] = ""
} else {
m[tname] = fmt.Sprintf("%v", fv)
}
default:
m[tname] = fv
}
}
}
}
return m
}

// Suite represents the xcuitest test suite configuration.
Expand Down
29 changes: 29 additions & 0 deletions internal/xcuitest/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,35 @@ import (
"gotest.tools/v3/fs"
)

func TestTestOptions_ToMap(t *testing.T) {
opts := TestOptions{
Class: []string{},
NotClass: []string{},
TestLanguage: "",
TestRegion: "",
TestTimeoutsEnabled: "",
MaximumTestExecutionTimeAllowance: 20,
DefaultTestExecutionTimeAllowance: 0,
}
wantLength := 7

m := opts.ToMap()

if len(m) != wantLength {
t.Errorf("Length of converted TestOptions should match original, got (%v) want (%v)", len(m), wantLength)
}

v := reflect.ValueOf(m["maximumTestExecutionTimeAllowance"])
vtype := v.Type()
if vtype.Kind() != reflect.String {
t.Errorf("ints should be converted to strings when mapping, got (%v) want (%v)", vtype, reflect.String)
}

if v := m["defaultTestExecutionTimeAllowance"]; v != "" {
t.Errorf("0 values should be cast to empty strings, got (%v)", v)
}
}

func TestValidate(t *testing.T) {
dir := fs.NewDir(t, "xcuitest-config",
fs.WithFile("test.ipa", "", fs.WithMode(0655)),
Expand Down

0 comments on commit 3fd3738

Please sign in to comment.