github.com/whamcloud/lemur@v0.0.0-20190827193804-4655df8a52af/uat/uat_test.go (about) 1 // Copyright (c) 2018 DDN. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package uat 6 7 import ( 8 "os" 9 10 "github.com/DATA-DOG/godog" 11 "github.com/DATA-DOG/godog/gherkin" 12 "github.com/pkg/errors" 13 14 "github.com/intel-hpdd/lemur/cmd/lhsmd/config" 15 "github.com/intel-hpdd/lemur/uat/harness" 16 "github.com/intel-hpdd/lemur/uat/steps" 17 "github.com/intel-hpdd/logging/alert" 18 ) 19 20 // This is the entry point for godog tests. The godog CLI cmd automatically 21 // identifies it via the *godog.Suite parameter and generates a test 22 // binary based on this function. 23 // 24 // The test binary then scans through features/ to load and execute the 25 // feature tests it finds there. 26 // 27 // Implementation of the feature tests is done in the steps package. 28 // 29 // These tests are intended to automate acceptance testing as might 30 // be manually performed by an end-user (i.e. a filesystem admin and 31 // their users), or by developers prior to delivery. 32 // 33 // These tests SHOULD NOT be seen as a replacement for proper unit 34 // tests. 35 // 36 // Scenarios should always be isolated from one another as much as 37 // possible. Setting up and tearing down a whole Lustre filesystem 38 // is not practical, but a scenario should NEVER depend on or be 39 // affected by the outcome of a prior scenario. Trust me, that way 40 // ends in tears. 41 // 42 // Steps within a scenario may depend on each other, but this should 43 // be done very judiciously. Troubleshooting scenario failures gets 44 // complicated very quickly when there is a rat's nest of step 45 // interdependencies. 46 func ConfigureSuite(s *godog.Suite) { 47 cfg, err := harness.LoadConfig() 48 if err != nil { 49 alert.Abort(errors.Wrap(err, "Failed to load test config")) 50 } 51 52 // Create socket dir so that tests don't fail mysteriously. This 53 // is handled by the RPM when things are installed that way, but 54 // it should work when run via Makefile, too. 55 if err := os.MkdirAll(config.DefaultTransportSocketDir, 0700); err != nil { 56 alert.Abort(errors.Wrap(err, "Failed to create agent socket dir")) 57 } 58 59 // This is a pretty awkward solution, but it should keep us 60 // moving forward. We need some place to stash state during 61 // a scenario execution. The godog examples hang the step 62 // implementations off of a single *suiteContext which gets 63 // reset on every scenario, but then we'd lose the ability to 64 // define step implementations independently. 65 var ctx *harness.ScenarioContext 66 67 // Reset the scenario context before each scenario. 68 s.BeforeScenario(func(interface{}) { 69 ctx = harness.NewScenarioContext(cfg) 70 steps.RegisterContext(ctx) 71 }) 72 73 // If a step fails, we need to mark the context as failed so 74 // that cleanup does the right thing. 75 s.AfterStep(func(step *gherkin.Step, err error) { 76 if err != nil { 77 ctx.Fail() 78 } 79 }) 80 81 // Clean up after the scenario. Anything which needs to be cleaned up 82 // should have been registered as a cleanup handler. 83 s.AfterScenario(func(i interface{}, err error) { 84 // The agent should always be stopped. 85 if err := harness.StopAgent(ctx); err != nil { 86 alert.Warnf("Failed to stop agent after scenario: %s", err) 87 ctx.Fail() 88 } 89 90 if ctx.Failed() && !cfg.CleanupOnFailure { 91 alert.Warnf("Scenario failed and CleanupOnFailure is not set. Not cleaning up %s and other temporary files.", ctx.Workdir()) 92 return 93 } 94 95 if err := ctx.Cleanup(); err != nil { 96 alert.Warnf("Error during post-scenario cleanup: %s", err) 97 } 98 }) 99 100 // Register steps with the suite runner. 101 for matcher, step := range steps.WithMatchers { 102 s.Step(matcher, step) 103 } 104 }