/paralleltest

Linter to check if your tests have been marked as parallel correctly

Primary LanguageGoMIT LicenseMIT

paralleltest

Test

The Go linter paralleltest checks that the t.Parallel gets called for the test method and for the range of test cases within the test.

Usage

paralleltest ./...

To ignore missing calls to t.Parallel and only report incorrect uses of it, pass the flag -i.

Examples

Missing t.Parallel() in the test method

// bad
func TestFunctionMissingCallToParallel(t *testing.T) {
}

// good
func TestFunctionMissingCallToParallel(t *testing.T) {
  t.Parallel()
  // ^ call to t.Parallel()
}
// Error displayed
// Function TestFunctionMissingCallToParallel missing the call to method parallel

Missing t.Parallel() in the range method

// bad
func TestFunctionRangeMissingCallToParallel(t *testing.T) {
  t.Parallel()

  testCases := []struct {
    name string
  }{{name: "foo"}}

  for _, tc := range testCases {
    t.Run(tc.name, func(t *testing.T) {
      fmt.Println(tc.name)
    })
  }
}

// good
func TestFunctionRangeMissingCallToParallel(t *testing.T) {
  t.Parallel()

  testCases := []struct {
    name string
  }{{name: "foo"}}

  for _, tc := range testCases {
    t.Run(tc.name, func(t *testing.T) {
      t.Parallel()
      // ^ call to t.Parallel()
      fmt.Println(tc.name)
    })
  }
}
// Error displayed
// Range statement for test TestFunctionRangeMissingCallToParallel missing the call to method parallel in t.Run

t.Parallel() is called in the range method but testcase variable not being used

// bad
func TestFunctionRangeNotUsingRangeValueInTDotRun(t *testing.T) {
  t.Parallel()

  testCases := []struct {
    name string
  }{{name: "foo"}}
  for _, tc := range testCases {
    t.Run("this is a test name", func(t *testing.T) {
      // ^ call to tc.name missing
      t.Parallel()
      fmt.Println(tc.name)
    })
  }
}

// good
func TestFunctionRangeNotUsingRangeValueInTDotRun(t *testing.T) {
  t.Parallel()

  testCases := []struct {
    name string
  }{{name: "foo"}}
  for _, tc := range testCases {
    t.Run(tc.name, func(t *testing.T) {
      // ^ call to tc.name
      t.Parallel()
      fmt.Println(tc.name)
    })
  }
}
// Error displayed
// Range statement for test TestFunctionRangeNotUsingRangeValueInTDotRun does not use range value in t.Run

t.Parallel() is called in the range method and test case variable tc being used, but is not reinitialised (More Info)

// bad
func TestFunctionRangeNotReInitialisingVariable(t *testing.T) {
  t.Parallel()

  testCases := []struct {
    name string
  }{{name: "foo"}}
  for _, tc := range testCases {
    t.Run(tc.name, func(t *testing.T) {
      t.Parallel()
      fmt.Println(tc.name)
    })
  }
}

// good
func TestFunctionRangeNotReInitialisingVariable(t *testing.T) {
  t.Parallel()

  testCases := []struct {
    name string
  }{{name: "foo"}}
  for _, tc := range testCases {
    tc:=tc
    // ^ tc variable reinitialised
    t.Run(tc.name, func(t *testing.T) {
      t.Parallel()
      fmt.Println(tc.name)
    })
  }
}
// Error displayed
// Range statement for test TestFunctionRangeNotReInitialisingVariable does not reinitialise the variable tc