github.com/hernad/nomad@v1.6.112/e2e/framework/doc.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  /*
     5  Package framework implements a model for developing end-to-end test suites. The
     6  model includes a top level Framework which TestSuites can be added to. TestSuites
     7  include conditions under which the suite will run and a list of TestCase
     8  implementations to run. TestCases can be implemented with methods that run
     9  before/after each and all tests.
    10  
    11  # Writing Tests
    12  
    13  Tests follow a similar patterns as go tests. They are functions that must start
    14  with 'Test' and instead of a *testing.T argument, a *framework.F is passed and
    15  they must have a receiver that implements the TestCase interface.
    16  A crude example as follows:
    17  
    18  	// foo_test.go
    19  	type MyTestCase struct {
    20  		framework.TC
    21  	}
    22  
    23  	func (tc *MyTestCase) TestMyFoo(f *framework.F) {
    24  		f.T().Log("bar")
    25  	}
    26  
    27  	func TestCalledFromGoTest(t *testing.T){
    28  		framework.New().AddSuites(&framework.TestSuite{
    29  			Component:   "foo",
    30  			Cases: []framework.TestCase{
    31  				new(MyTestCase),
    32  			},
    33  		}).Run(t)
    34  	}
    35  
    36  Test cases should embed the TC struct which satisfies the TestCase interface.
    37  Optionally a TestCase can also implement the Name() function which returns
    38  a string to name the test case. By default the name is the name of the struct
    39  type, which in the above example would be "MyTestCase"
    40  
    41  Test cases may also optionally implement additional interfaces to define setup
    42  and teardown logic:
    43  
    44  	BeforeEachTest
    45  	AfterEachTest
    46  	BeforeAllTests
    47  	AfterAllTests
    48  
    49  The test case struct allows you to setup and teardown state in the struct that
    50  can be consumed by the tests. For example:
    51  
    52  	type ComplexNomadTC struct {
    53  		framework.TC
    54  		jobID string
    55  	}
    56  
    57  	func (tc *ComplexNomadTC) BeforeEach(f *framework.F){
    58  		// Do some complex job setup with a unique prefix string
    59  		jobID, err := doSomeComplexSetup(tc.Nomad(), f.ID())
    60  		f.NoError(err)
    61  		f.Set("jobID", jobID)
    62  	}
    63  
    64  	func (tc *ComplexNomadTC) TestSomeScenario(f *framework.F){
    65  		jobID := f.Value("jobID").(string)
    66  		doTestThingWithJob(f, tc.Nomad(), jobID)
    67  	}
    68  
    69  	func (tc *ComplexNomadTC) TestOtherScenario(f *framework.F){
    70  		jobID := f.Value("jobID").(string)
    71  		doOtherTestThingWithJob(f, tc.Nomad(), jobID)
    72  	}
    73  
    74  	func (tc *ComplexNomadTC) AfterEach(f *framework.F){
    75  		jobID := f.Value("jobID").(string)
    76  		_, _, err := tc.Nomad().Jobs().Deregister(jobID, true, nil)
    77  		f.NoError(err)
    78  	}
    79  
    80  As demonstrated in the previous example, TC also exposes functions that return
    81  configured api clients including Nomad, Consul and Vault. If Consul or Vault
    82  are not provisioned their respective getter functions will return nil.
    83  
    84  # Testify Integration
    85  
    86  Test cases expose a T() function to fetch the current *testing.T context.
    87  While this means the author is able to most other testing libraries,
    88  github.com/stretch/testify is recommended and integrated into the framework.
    89  The TC struct also embeds testify assertions that are preconfigured with the
    90  current testing context. Additionally TC comes with a Require() method that
    91  yields a testify Require if that flavor is desired.
    92  
    93  	func (tc *MyTestCase) TestWithTestify() {
    94  		err := someErrFunc()
    95  		tc.NoError(err)
    96  		// Or tc.Require().NoError(err)
    97  	}
    98  
    99  # Parallelism
   100  
   101  The test framework honors go test's parallel feature under certain conditions.
   102  A TestSuite can be created with the Parallel field set to true to enable
   103  parallel execution of the test cases of the suite. Tests within a test case
   104  will be executed sequentially unless f.T().Parallel() is called. Note that if
   105  multiple tests are to be executed in parallel, access to TC is not syncronized.
   106  The *framework.F offers a way to store state between before/after each method if
   107  desired.
   108  
   109  	func (tc *MyTestCase) BeforeEach(f *framework.F){
   110  		jobID, _ := doSomeComplexSetup(tc.Nomad(), f.ID())
   111  		f.Set("jobID", jobID)
   112  	}
   113  
   114  	func (tc *MyTestCase) TestParallel(f *framework.F){
   115  		f.T().Parallel()
   116  		jobID := f.Value("jobID").(string)
   117  	}
   118  
   119  Since test cases have the potential to work with a shared Nomad cluster in parallel
   120  any resources created or destroyed must be prefixed with a unique identifier for
   121  each test case. The framework.F struct exposes an ID() function that will return a
   122  string that is unique with in a test. Therefore, multiple tests with in the case
   123  can reliably create unique IDs between tests and setup/teardown. The string
   124  returned is 8 alpha numeric characters.
   125  */
   126  
   127  // Deprecated: no longer use e2e/framework for new tests; see TestExample for new e2e test structure.
   128  package framework