diff --git a/src/internal/tester/integration_runners.go b/src/internal/tester/integration_runners.go deleted file mode 100644 index 2b982edaf..000000000 --- a/src/internal/tester/integration_runners.go +++ /dev/null @@ -1,103 +0,0 @@ -package tester - -import ( - "os" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" -) - -const ( - CorsoLoadTests = "CORSO_LOAD_TESTS" - CorsoCITests = "CORSO_CI_TESTS" - CorsoCLIBackupTests = "CORSO_COMMAND_LINE_BACKUP_TESTS" - CorsoCLIConfigTests = "CORSO_COMMAND_LINE_CONFIG_TESTS" - CorsoCLIRepoTests = "CORSO_COMMAND_LINE_REPO_TESTS" - CorsoCLIRestoreTests = "CORSO_COMMAND_LINE_RESTORE_TESTS" - CorsoCLITests = "CORSO_COMMAND_LINE_TESTS" - CorsoConnectorCreateCollectionTests = "CORSO_CONNECTOR_CREATE_COLLECTION_TESTS" - CorsoConnectorCreateExchangeCollectionTests = "CORSO_CONNECTOR_CREATE_EXCHANGE_COLLECTION_TESTS" - CorsoConnectorCreateSharePointCollectionTests = "CORSO_CONNECTOR_CREATE_SHAREPOINT_COLLECTION_TESTS" - CorsoConnectorDataCollectionTests = "CORSO_CONNECTOR_DATA_COLLECTION_TESTS" - CorsoConnectorExchangeFolderCacheTests = "CORSO_CONNECTOR_EXCHANGE_FOLDER_CACHE_TESTS" - CorsoConnectorRestoreExchangeCollectionTests = "CORSO_CONNECTOR_RESTORE_EXCHANGE_COLLECTION_TESTS" - CorsoGraphConnectorTests = "CORSO_GRAPH_CONNECTOR_TESTS" - CorsoGraphConnectorExchangeTests = "CORSO_GRAPH_CONNECTOR_EXCHANGE_TESTS" - CorsoGraphConnectorOneDriveTests = "CORSO_GRAPH_CONNECTOR_ONE_DRIVE_TESTS" - CorsoGraphConnectorSharePointTests = "CORSO_GRAPH_CONNECTOR_SHAREPOINT_TESTS" - CorsoKopiaWrapperTests = "CORSO_KOPIA_WRAPPER_TESTS" - CorsoModelStoreTests = "CORSO_MODEL_STORE_TESTS" - CorsoOneDriveTests = "CORSO_ONE_DRIVE_TESTS" - CorsoOperationTests = "CORSO_OPERATION_TESTS" - CorsoOperationBackupTests = "CORSO_OPERATION_BACKUP_TESTS" - CorsoRepositoryTests = "CORSO_REPOSITORY_TESTS" -) - -// File needs to be a single message .json -// Use: https://developer.microsoft.com/en-us/graph/graph-explorer for details -const CorsoGraphConnectorTestSupportFile = "CORSO_TEST_SUPPORT_FILE" - -// RunOnAny takes in a list of env variable names and returns -// an error if all of them are zero valued. Implication being: -// if any of those env vars are truthy, you should run the -// subsequent tests. -func RunOnAny(t *testing.T, tests ...string) { - var l int - for _, test := range tests { - l += len(os.Getenv(test)) - } - - if l == 0 { - t.Skipf( - "one or more env vars must be flagged to run this test: %v", - strings.Join(tests, ", ")) - } -} - -// LogTimeOfTest logs the test name and the time that it was run. -func LogTimeOfTest(t *testing.T) string { - now := time.Now().UTC().Format(time.RFC3339Nano) - name := t.Name() - - if name == "" { - t.Logf("Test run at %s.", now) - return now - } - - t.Logf("%s run at %s", name, now) - - return now -} - -// MustGetEnvVars retrieves the provided env vars from the os. -// Retrieved values are populated into the resulting map. -// If any of the env values are zero length, the test errors. -func MustGetEnvVars(t *testing.T, evs ...string) map[string]string { - vals := map[string]string{} - - for _, ev := range evs { - ge := os.Getenv(ev) - require.NotEmpty(t, ev, ev+" env var required for test suite") - - vals[ev] = ge - } - - return vals -} - -// MustGetEnvSls retrieves the provided env vars from the os. -// Retrieved values are populated into the resulting map. -// If any of the env values are zero length, the test errors. -func MustGetEnvSets(t *testing.T, evs ...[]string) map[string]string { - vals := map[string]string{} - - for _, ev := range evs { - r := MustGetEnvVars(t, ev...) - maps.Copy(vals, r) - } - - return vals -} diff --git a/src/internal/tester/suite.go b/src/internal/tester/suite.go index 9552ea13d..ae40c583f 100644 --- a/src/internal/tester/suite.go +++ b/src/internal/tester/suite.go @@ -1,9 +1,42 @@ package tester import ( + "os" + "strings" "testing" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "golang.org/x/exp/maps" +) + +// Flags for declaring which scope of tests to run. +const ( + CorsoCITests = "CORSO_CI_TESTS" + CorsoE2ETests = "CORSO_E2E_TESTS" + CorsoLoadTests = "CORSO_LOAD_TESTS" + + CorsoCLIBackupTests = "CORSO_COMMAND_LINE_BACKUP_TESTS" + CorsoCLIConfigTests = "CORSO_COMMAND_LINE_CONFIG_TESTS" + CorsoCLIRepoTests = "CORSO_COMMAND_LINE_REPO_TESTS" + CorsoCLIRestoreTests = "CORSO_COMMAND_LINE_RESTORE_TESTS" + CorsoCLITests = "CORSO_COMMAND_LINE_TESTS" + CorsoConnectorCreateCollectionTests = "CORSO_CONNECTOR_CREATE_COLLECTION_TESTS" + CorsoConnectorCreateExchangeCollectionTests = "CORSO_CONNECTOR_CREATE_EXCHANGE_COLLECTION_TESTS" + CorsoConnectorCreateSharePointCollectionTests = "CORSO_CONNECTOR_CREATE_SHAREPOINT_COLLECTION_TESTS" + CorsoConnectorDataCollectionTests = "CORSO_CONNECTOR_DATA_COLLECTION_TESTS" + CorsoConnectorExchangeFolderCacheTests = "CORSO_CONNECTOR_EXCHANGE_FOLDER_CACHE_TESTS" + CorsoConnectorRestoreExchangeCollectionTests = "CORSO_CONNECTOR_RESTORE_EXCHANGE_COLLECTION_TESTS" + CorsoGraphConnectorTests = "CORSO_GRAPH_CONNECTOR_TESTS" + CorsoGraphConnectorExchangeTests = "CORSO_GRAPH_CONNECTOR_EXCHANGE_TESTS" + CorsoGraphConnectorOneDriveTests = "CORSO_GRAPH_CONNECTOR_ONE_DRIVE_TESTS" + CorsoGraphConnectorSharePointTests = "CORSO_GRAPH_CONNECTOR_SHAREPOINT_TESTS" + CorsoKopiaWrapperTests = "CORSO_KOPIA_WRAPPER_TESTS" + CorsoModelStoreTests = "CORSO_MODEL_STORE_TESTS" + CorsoOneDriveTests = "CORSO_ONE_DRIVE_TESTS" + CorsoOperationTests = "CORSO_OPERATION_TESTS" + CorsoOperationBackupTests = "CORSO_OPERATION_BACKUP_TESTS" + CorsoRepositoryTests = "CORSO_REPOSITORY_TESTS" ) type Suite interface { @@ -11,6 +44,10 @@ type Suite interface { Run(name string, subtest func()) bool } +// --------------------------------------------------------------------------- +// Unit +// --------------------------------------------------------------------------- + func NewUnitSuite(t *testing.T) *unitSuite { return new(unitSuite) } @@ -19,16 +56,20 @@ type unitSuite struct { suite.Suite } +// --------------------------------------------------------------------------- +// Integration +// --------------------------------------------------------------------------- + func NewIntegrationSuite( t *testing.T, envSets [][]string, - includeGroups ...string, + runOnAnyEnv ...string, ) *integrationSuite { RunOnAny( t, append( []string{CorsoCITests}, - includeGroups..., + runOnAnyEnv..., )..., ) @@ -40,3 +81,80 @@ func NewIntegrationSuite( type integrationSuite struct { suite.Suite } + +// --------------------------------------------------------------------------- +// Smoke/e2e +// --------------------------------------------------------------------------- + +func NewE2ESuite( + t *testing.T, + envSets [][]string, + runOnAnyEnv ...string, +) *e2eSuite { + RunOnAny( + t, + append( + []string{CorsoE2ETests}, + runOnAnyEnv..., + )..., + ) + + MustGetEnvSets(t, envSets...) + + return new(e2eSuite) +} + +type e2eSuite struct { + suite.Suite +} + +// --------------------------------------------------------------------------- +// Run Condition Checkers +// --------------------------------------------------------------------------- + +// RunOnAny takes in a list of env variable names and returns +// an error if all of them are zero valued. Implication being: +// if any of those env vars are truthy, you should run the +// subsequent tests. +func RunOnAny(t *testing.T, tests ...string) { + var l int + for _, test := range tests { + l += len(os.Getenv(test)) + } + + if l == 0 { + t.Skipf( + "one or more env vars must be flagged to run this test: %v", + strings.Join(tests, ", ")) + } +} + +// MustGetEnvVars retrieves the provided env vars from the os. +// Retrieved values are populated into the resulting map. +// If any of the env values are zero length, the test errors. +func MustGetEnvVars(t *testing.T, evs ...string) map[string]string { + vals := map[string]string{} + + for _, ev := range evs { + ge := os.Getenv(ev) + require.NotEmpty(t, ev, ev+" env var required for test suite") + + vals[ev] = ge + } + + return vals +} + +// MustGetEnvSls retrieves the provided env vars from the os. +// Retrieved values are populated into the resulting map. +// If any of the env values are zero length, the test errors. +func MustGetEnvSets(t *testing.T, evs ...[]string) map[string]string { + vals := map[string]string{} + + for _, ev := range evs { + r := MustGetEnvVars(t, ev...) + maps.Copy(vals, r) + } + + return vals +} diff --git a/src/internal/tester/suite_test.go b/src/internal/tester/suite_test.go new file mode 100644 index 000000000..0e7b6d2f3 --- /dev/null +++ b/src/internal/tester/suite_test.go @@ -0,0 +1,60 @@ +package tester_test + +import ( + "testing" + + "github.com/alcionai/corso/src/internal/tester" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type TesterUnitSuite struct { + tester.Suite + called bool +} + +func TestTesterUnitSuite(t *testing.T) { + suite.Run(t, &TesterUnitSuite{Suite: tester.NewUnitSuite(t)}) +} + +func (suite *TesterUnitSuite) SetupSuite() { + suite.called = true +} + +func (suite *TesterUnitSuite) TestUnitSuite() { + require.True(suite.T(), suite.called) +} + +type TesterIntegrationSuite struct { + tester.Suite + called bool +} + +func TestTesterIntegrationSuite(t *testing.T) { + suite.Run(t, &TesterIntegrationSuite{Suite: tester.NewIntegrationSuite(t, nil)}) +} + +func (suite *TesterIntegrationSuite) SetupSuite() { + suite.called = true +} + +func (suite *TesterIntegrationSuite) TestIntegrationSuite() { + require.True(suite.T(), suite.called) +} + +type TesterE2ESuite struct { + tester.Suite + called bool +} + +func TestTesterE2ESuite(t *testing.T) { + suite.Run(t, &TesterE2ESuite{Suite: tester.NewE2ESuite(t, nil)}) +} + +func (suite *TesterE2ESuite) SetupSuite() { + suite.called = true +} + +func (suite *TesterE2ESuite) TestE2ESuite() { + require.True(suite.T(), suite.called) +} diff --git a/src/internal/tester/testing.go b/src/internal/tester/tester.go similarity index 56% rename from src/internal/tester/testing.go rename to src/internal/tester/tester.go index 6eedb596f..10cb070f7 100644 --- a/src/internal/tester/testing.go +++ b/src/internal/tester/tester.go @@ -4,6 +4,7 @@ import ( "reflect" "runtime" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -24,3 +25,18 @@ func AreSameFunc(t *testing.T, expect, have any) { ).Name(), ) } + +// LogTimeOfTest logs the test name and the time that it was run. +func LogTimeOfTest(t *testing.T) string { + now := time.Now().UTC().Format(time.RFC3339Nano) + name := t.Name() + + if name == "" { + t.Logf("Test run at %s.", now) + return now + } + + t.Logf("%s run at %s", name, now) + + return now +}