github.com/leowmjw/otto@v0.2.1-0.20160126165905-6400716cf085/otto/testing_acceptance.go (about) 1 package otto 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "testing" 8 "time" 9 ) 10 11 // TestEnvVar must be set to a non-empty value for acceptance tests to run. 12 const TestEnvVar = "OTTO_ACC" 13 14 // TestCase is a single set of tests to run for an app to test the dev 15 // experience. See Test for more details on how this operates. 16 type TestCase struct { 17 // Precheck, if non-nil, will be called once before the test case 18 // runs at all. This can be used for some validation prior to the 19 // test running. 20 PreCheck func() 21 22 // Core is the core to use for testing. The Test* methods such 23 // as TestCoreConfig should be used to create the test core. 24 Core *Core 25 26 // Unit, if set to true, won't require the OTTO_ACC variable to be 27 // set and will run as a normal unit test. 28 Unit bool 29 30 // Steps are the set of operations that are run for this test case. 31 Steps []TestStep 32 33 // Teardown will be called before the test case is over regardless 34 // of if the test succeeded or failed. This should return an error 35 // in the case that the test can't guarantee all resources were 36 // properly cleaned up. 37 Teardown TestTeardownFunc 38 } 39 40 // TestStep is a single step within a TestCase. 41 type TestStep interface { 42 // Run is used to run the TestStep. It should return an error if 43 // the step failed. If the step fails, then no further steps are 44 // called. The Teardown will be called on the TestCase. 45 Run(*Core) error 46 } 47 48 // TestTeardownFunc is the callback used for Teardown in TestCase. 49 type TestTeardownFunc func(*Core) error 50 51 // Test performs an acceptance test on a backend with the given test case. 52 // 53 // Tests are not run unless an environmental variable "TF_ACC" is 54 // set to some non-empty value. This is to avoid test cases surprising 55 // a user by creating real resources. 56 // 57 // Tests will fail unless the verbose flag (`go test -v`, or explicitly 58 // the "-test.v" flag) is set. Because some acceptance tests take quite 59 // long, we require the verbose flag so users are able to see progress 60 // output. 61 func Test(t TestT, c TestCase) { 62 // We only run acceptance tests if an env var is set because they're 63 // slow and generally require some outside configuration. 64 if !c.Unit && os.Getenv(TestEnvVar) == "" { 65 t.Skip(fmt.Sprintf( 66 "Acceptance tests skipped unless env '%s' set", 67 TestEnvVar)) 68 return 69 } 70 71 // We require verbose mode so that the user knows what is going on. 72 if !c.Unit && !testTesting && !testing.Verbose() { 73 t.Fatal("Acceptance tests must be run with the -v flag on tests") 74 return 75 } 76 77 // Run the PreCheck if we have it 78 if c.PreCheck != nil { 79 c.PreCheck() 80 } 81 82 // Check that the core is provided 83 if c.Core == nil { 84 t.Fatal("Must provide a core") 85 } 86 87 // Compile the app 88 log.Printf("[WARN] test: compiling appfile...") 89 if err := c.Core.Compile(); err != nil { 90 t.Fatal("error compiling: ", err) 91 } 92 93 // Run the steps 94 for i, s := range c.Steps { 95 log.Printf("[WARN] Executing test step %d", i+1) 96 if err := s.Run(c.Core); err != nil { 97 t.Error(fmt.Sprintf("Failed step %d: %s", i+1, err)) 98 break 99 } 100 } 101 102 // Cleanup 103 if c.Teardown != nil { 104 if err := c.Teardown(c.Core); err != nil { 105 t.Error(fmt.Sprintf( 106 "Teardown failed! Dangling resources may exist. Error:\n\n%s", 107 err)) 108 } 109 } 110 } 111 112 // TestStepSleep is a debugging test step that inserts a sleep. 113 // This is useful for debugging a failing acceptance test. 114 type TestStepSleep struct{ Duration time.Duration } 115 116 func (t *TestStepSleep) Run(*Core) error { 117 time.Sleep(t.Duration) 118 return nil 119 } 120 121 // TestT is the interface used to handle the test lifecycle of a test. 122 // 123 // Users should just use a *testing.T object, which implements this. 124 type TestT interface { 125 Error(args ...interface{}) 126 Fatal(args ...interface{}) 127 Skip(args ...interface{}) 128 } 129 130 var testTesting = false