pt

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2022 License: MIT Imports: 2 Imported by: 0

README

Logo
CI Codecov Codebeat Maintainability Go Report Card License Go Reference

This is a go (golang) package with functions to run Parallel Tests. You don't have to call t.Parallel() anymore.

Installation

go get github.com/maratori/pt

Usage

You can use pt.PackageParallel, pt.Parallel, pt.Group, pt.Test in standard go test function to run tests in parallel.

See example_test.go

...

func TestSum(t *testing.T) {
	pt.PackageParallel(t,
		pt.Test("should be 0 without values", func(t *testing.T) {
			if sum() != 0 {
				t.Fail()
			}
		}),
		pt.Group("should be equal to single value",
			pt.Test("0", testSumSingleValue(0)),
			pt.Test("1", testSumSingleValue(1)),
			pt.Test("-1", testSumSingleValue(-1)),
			pt.Test("123", testSumSingleValue(123)),
			pt.Test("-123", testSumSingleValue(-123)),
		),
		pt.Group("should be sum of two values",
			pt.Test("0+0 = 0", testSumTwoValues(0, 0, 0)),
			pt.Test("0+1 = 1", testSumTwoValues(0, 1, 1)),
			pt.Test("1+0 = 1", testSumTwoValues(1, 0, 1)),
			pt.Test("5+6 = 11", testSumTwoValues(5, 6, 11)),
		),
		pt.Test("1+2+3+4+5 = 15", func(t *testing.T) {
			if sum(1, 2, 3, 4, 5) != 15 {
				t.Fail()
			}
		}),
	)
}

func TestFibonacci(t *testing.T) {
	pt.PackageParallel(t,
		pt.Test("0 -> 0", testFibonacci(0, 0)),
		pt.Test("1 -> 1", testFibonacci(1, 1)),
		pt.Test("2 -> 1", testFibonacci(2, 1)),
		pt.Test("3 -> 2", testFibonacci(3, 2)),
		pt.Test("4 -> 3", testFibonacci(4, 3)),
	)
}

...

When you call go test, all these tests will run in parallel.

go test -v -p 8 -parallel 8 --tags example github.com/maratori/pt/example
Output
=== RUN   TestSum
=== PAUSE TestSum
=== RUN   TestFibonacci
=== PAUSE TestFibonacci
=== CONT  TestSum
=== RUN   TestSum/should_be_0_without_values
=== PAUSE TestSum/should_be_0_without_values
=== RUN   TestSum/should_be_equal_to_single_value
=== PAUSE TestSum/should_be_equal_to_single_value
=== CONT  TestFibonacci
=== RUN   TestFibonacci/0_->_0
=== RUN   TestSum/should_be_sum_of_two_values
=== PAUSE TestSum/should_be_sum_of_two_values
=== RUN   TestSum/1+2+3+4+5_=_15
=== PAUSE TestFibonacci/0_->_0
=== PAUSE TestSum/1+2+3+4+5_=_15
=== CONT  TestSum/should_be_0_without_values
=== RUN   TestFibonacci/1_->_1
=== PAUSE TestFibonacci/1_->_1
=== RUN   TestFibonacci/2_->_1
=== CONT  TestSum/1+2+3+4+5_=_15
=== PAUSE TestFibonacci/2_->_1
=== RUN   TestFibonacci/3_->_2
=== PAUSE TestFibonacci/3_->_2
=== CONT  TestSum/should_be_equal_to_single_value
=== RUN   TestFibonacci/4_->_3
=== PAUSE TestFibonacci/4_->_3
=== CONT  TestFibonacci/0_->_0
=== CONT  TestSum/should_be_sum_of_two_values
=== RUN   TestSum/should_be_sum_of_two_values/0+0_=_0
=== CONT  TestFibonacci/2_->_1
=== PAUSE TestSum/should_be_sum_of_two_values/0+0_=_0
=== CONT  TestFibonacci/4_->_3
=== CONT  TestFibonacci/1_->_1
=== CONT  TestFibonacci/3_->_2
=== RUN   TestSum/should_be_equal_to_single_value/0
=== PAUSE TestSum/should_be_equal_to_single_value/0
=== RUN   TestSum/should_be_sum_of_two_values/0+1_=_1
=== RUN   TestSum/should_be_equal_to_single_value/1
=== PAUSE TestSum/should_be_sum_of_two_values/0+1_=_1
=== PAUSE TestSum/should_be_equal_to_single_value/1
--- PASS: TestFibonacci (0.00s)
    --- PASS: TestFibonacci/0_->_0 (0.00s)
    --- PASS: TestFibonacci/2_->_1 (0.00s)
    --- PASS: TestFibonacci/4_->_3 (0.00s)
    --- PASS: TestFibonacci/1_->_1 (0.00s)
    --- PASS: TestFibonacci/3_->_2 (0.00s)
=== RUN   TestSum/should_be_equal_to_single_value/-1
=== PAUSE TestSum/should_be_equal_to_single_value/-1
=== RUN   TestSum/should_be_sum_of_two_values/1+0_=_1
=== RUN   TestSum/should_be_equal_to_single_value/123
=== PAUSE TestSum/should_be_sum_of_two_values/1+0_=_1
=== PAUSE TestSum/should_be_equal_to_single_value/123
=== RUN   TestSum/should_be_sum_of_two_values/5+6_=_11
=== RUN   TestSum/should_be_equal_to_single_value/-123
=== PAUSE TestSum/should_be_equal_to_single_value/-123
=== PAUSE TestSum/should_be_sum_of_two_values/5+6_=_11
=== CONT  TestSum/should_be_sum_of_two_values/0+0_=_0
=== CONT  TestSum/should_be_equal_to_single_value/0
=== CONT  TestSum/should_be_equal_to_single_value/123
=== CONT  TestSum/should_be_sum_of_two_values/1+0_=_1
=== CONT  TestSum/should_be_equal_to_single_value/-123
=== CONT  TestSum/should_be_equal_to_single_value/1
=== CONT  TestSum/should_be_sum_of_two_values/0+1_=_1
=== CONT  TestSum/should_be_sum_of_two_values/5+6_=_11
=== CONT  TestSum/should_be_equal_to_single_value/-1
--- PASS: TestSum (0.00s)
    --- PASS: TestSum/should_be_0_without_values (0.00s)
    --- PASS: TestSum/1+2+3+4+5_=_15 (0.00s)
    --- PASS: TestSum/should_be_sum_of_two_values (0.00s)
        --- PASS: TestSum/should_be_sum_of_two_values/0+0_=_0 (0.00s)
        --- PASS: TestSum/should_be_sum_of_two_values/1+0_=_1 (0.00s)
        --- PASS: TestSum/should_be_sum_of_two_values/0+1_=_1 (0.00s)
        --- PASS: TestSum/should_be_sum_of_two_values/5+6_=_11 (0.00s)
    --- PASS: TestSum/should_be_equal_to_single_value (0.00s)
        --- PASS: TestSum/should_be_equal_to_single_value/0 (0.00s)
        --- PASS: TestSum/should_be_equal_to_single_value/123 (0.00s)
        --- PASS: TestSum/should_be_equal_to_single_value/-123 (0.00s)
        --- PASS: TestSum/should_be_equal_to_single_value/1 (0.00s)
        --- PASS: TestSum/should_be_equal_to_single_value/-1 (0.00s)
PASS
ok  	github.com/maratori/pt/example	0.091s

Supported golang versions

  • 1.8
  • 1.9
  • 1.10
  • 1.11
  • 1.12
  • 1.13
  • 1.14
  • 1.15
  • 1.16
  • 1.17
  • 1.18
  • 1.19

Flags for go test

There are 2 flags for go test command related to parallel execution.

  • -parallel n

Allow parallel execution of test functions that call t.Parallel. The value of this flag is the maximum number of tests to run simultaneously; by default, it is set to the value of GOMAXPROCS. Note that -parallel only applies within a single test binary. The 'go test' command may run tests for different packages in parallel as well, according to the setting of the -p flag (see 'go help build').

  • -p n

The number of programs, such as build commands or test binaries, that can be run in parallel. The default is the number of CPUs available.

So go test -p 8 -parallel 1 runs test packages in parallel, while tests inside each package are executed sequentially.
On the other hand, go test -p 1 -parallel 8 runs different packages sequentially, but tests inside each package are executed in parallel.

Difference between pt.PackageParallel and pt.Parallel

The difference can be demonstrated with the code below. Tests will be executed in the following sequence:

  1. Tests 1-8 run in parallel
  2. After that tests 9-12 run in parallel
  3. After that tests 13-16 run in parallel

See godoc for more info.

func TestA(t *testing.T) {
	pt.PackageParallel(t, test1, test2)
	pt.PackageParallel(t, test3, test4)
}
func TestB(t *testing.T) {
	pt.PackageParallel(t, test5, test6)
	pt.Parallel(t, test7, test8)
}
func TestC(t *testing.T) {
	pt.Parallel(t, test9, test10)
	pt.Parallel(t, test11, test12)
}
func TestD(t *testing.T) {
	pt.Parallel(t, test13, test14)
	pt.Parallel(t, test15, test16)
}

Changelog

[v1.0.2] - 2022-08-28
Changed
  • Use go 1.19
  • Test all supported go versions on CI (1.8 .. 1.19)
Fixed
[v1.0.1] - 2019-09-29
Changed
  • Use go 1.13
Fixed
  • Readme and godoc slightly improved
[v1.0.0] - 2019-07-21
Added

License

MIT License

Documentation

Overview

Package pt provides functions to run tests in parallel. You don't have to call t.Parallel() anymore.

Example

func TestMyFunc(t *testing.T) {
	pt.PackageParallel(t,
		pt.Test("should do something", func(t *testing.T) {
			// test code
		}),
		pt.Test("should do something else", func(t *testing.T) {
			// test code
		}),
		pt.Group("some condition",
			pt.Test("should not do something", func(t *testing.T) {
				// test code
			}),
			pt.Test("should not do something else", func(t *testing.T) {
				// test code
			}),
		),
	)
}

You can achieve the same behavior with bare testing package:

func TestMyFunc(t *testing.T) {
	t.Parallel()
	t.Run("should do something", func(t *testing.T) {
		t.Parallel()
		// test code
	})
	t.Run("should do something else", func(t *testing.T) {
		t.Parallel()
		// test code
	})
	t.Run("some condition", func(t *testing.T) {
		t.Parallel()
		t.Run("should not do something", func(t *testing.T) {
			t.Parallel()
			// test code
		})
		t.Run("should not do something else", func(t *testing.T) {
			t.Parallel()
			// test code
		})
	})
}

Parallel vs PackageParallel

The difference can be demonstrated with the code below. Tests will be executed in the following sequence:

  1. Tests 1-8 run in parallel
  2. After that tests 9-12 run in parallel
  3. After that tests 13-16 run in parallel

Code:

func TestA(t *testing.T) {
	pt.PackageParallel(t, test1, test2)
	pt.PackageParallel(t, test3, test4)
}
func TestB(t *testing.T) {
	pt.PackageParallel(t, test5, test6)
	pt.Parallel(t, test7, test8)
}
func TestC(t *testing.T) {
	pt.Parallel(t, test9, test10)
	pt.Parallel(t, test11, test12)
}
func TestD(t *testing.T) {
	pt.Parallel(t, test13, test14)
	pt.Parallel(t, test15, test16)
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Group

func Group(name string, tests ...testing.InternalTest) testing.InternalTest

Group is a constructor of testing.InternalTest. It wraps provided tests with a single testing.InternalTest. Provided tests will run in parallel when the wrapper is executed. It is designed to be an argument of Group, Parallel and PackageParallel.

func PackageParallel

func PackageParallel(t *testing.T, tests ...testing.InternalTest)

PackageParallel is non-blocking function that runs provided tests in parallel with other tests in package. It can take Group and Test as arguments.

func TestA(t *testing.T) {
	pt.PackageParallel(t, test1, test2)
}

is equivalent to

func TestA(t *testing.T) {
	t.Parallel()
	t.Run(test1.Name, func(t *testing.T) {
		t.Parallel()
		test1.F(t)
	})
	t.Run(test2.Name, func(t *testing.T) {
		t.Parallel()
		test2.F(t)
	})
}

If you don't need to run TestA in parallel with other tests, use Parallel.

func Parallel

func Parallel(t *testing.T, tests ...testing.InternalTest)

Parallel is non-blocking function that runs provided tests in parallel. It can take Group and Test as arguments.

func TestA(t *testing.T) {
	pt.Parallel(t, test1, test2)
}

is equivalent to

func TestA(t *testing.T) {
	t.Run(test1.Name, func(t *testing.T) {
		t.Parallel()
		test1.F(t)
	})
	t.Run(test2.Name, func(t *testing.T) {
		t.Parallel()
		test2.F(t)
	})
}

Note that Parallel will not execute different TestXXX and TestYYY in parallel. For example, test3 and test4 will run in parallel and after that test5 and test6 will run in parallel.

func TestB(t *testing.T) {
	pt.Parallel(t, test3, test4)
}
func TestC(t *testing.T) {
	pt.Parallel(t, test5, test6)
}

If you need different behavior, use PackageParallel.

func Test

func Test(name string, test func(t *testing.T)) testing.InternalTest

Test is a simple constructor of testing.InternalTest. It is designed to be an argument of Group, Parallel and PackageParallel.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL