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  }