How we can run unit tests in parallel mode with failpoint injection taking effect and without injection race

This is a simple demo to show how we can run unit tests in parallel mode with failpoint injection taking effect and without injection race.

The basic premise is once a failpoint is enabled, its injection terms will take effect until we disable the injection explicitly.

A injection race example

Taking bad_work.go and bad_work_test.go as an example:

bad_work.go defines a function badWork, which has two failpoint injections. In bad_work_test.go we have three test cases, TestBadWorkPath1 and TestBadWorkPath2 enable a failpoint respectively, parallel mode is enabled in each test case. When we enable failpoint and run test cases, we will find the injection race. Pay attention to the output of bad work path..., the injection cf/bad-path1 will always work after its first injection.

➜  failpoint-ctl enable .
➜  go test -count=2 -v -run TestBadWork .
=== RUN   TestBadWorkNormal
=== PAUSE TestBadWorkNormal
=== RUN   TestBadWorkPath1
=== PAUSE TestBadWorkPath1
=== RUN   TestBadWorkPath2
=== PAUSE TestBadWorkPath2
=== CONT  TestBadWorkNormal
=== CONT  TestBadWorkPath2
bad work path2
--- PASS: TestBadWorkPath2 (0.00s)
=== CONT  TestBadWorkPath1
bad work path1
--- PASS: TestBadWorkPath1 (0.00s)
bad work path normal
--- PASS: TestBadWorkNormal (0.00s)
=== RUN   TestBadWorkNormal
=== PAUSE TestBadWorkNormal
=== RUN   TestBadWorkPath1
=== PAUSE TestBadWorkPath1
=== RUN   TestBadWorkPath2
=== PAUSE TestBadWorkPath2
=== CONT  TestBadWorkNormal
bad work path1
--- PASS: TestBadWorkNormal (0.00s)
=== CONT  TestBadWorkPath2
=== CONT  TestBadWorkPath1
bad work path1
--- PASS: TestBadWorkPath2 (0.00s)
bad work path1
--- PASS: TestBadWorkPath1 (0.00s)
PASS
ok      cf      0.023s

A workaround for parallel failpoint injection

In work.go, the failpoint injection path is encoded with a dynamic function name, which is the entrypoint of test case, where we have enabled a failpoint. This time the failpoint injection will only take effect when the matching test case is running.

We can use InjectContext and failpoint.WithHook to pass a test independent context key value to achieve running parallel test cases without injection race.

➜  failpoint-ctl enable .
➜  go test -count=2 -v -run TestWork
=== RUN   TestWorkNormal
=== PAUSE TestWorkNormal
=== RUN   TestWorkPath1
=== PAUSE TestWorkPath1
=== RUN   TestWorkPath2
=== PAUSE TestWorkPath2
=== RUN   TestWorkPathPanic
=== PAUSE TestWorkPathPanic
=== CONT  TestWorkNormal
work path normal
--- PASS: TestWorkNormal (0.00s)
=== CONT  TestWorkPathPanic
--- PASS: TestWorkPathPanic (0.00s)
=== CONT  TestWorkPath2
work path2
--- PASS: TestWorkPath2 (0.00s)
=== CONT  TestWorkPath1
work path1
--- PASS: TestWorkPath1 (0.00s)
=== RUN   TestWorkNormal
=== PAUSE TestWorkNormal
=== RUN   TestWorkPath1
=== PAUSE TestWorkPath1
=== RUN   TestWorkPath2
=== PAUSE TestWorkPath2
=== RUN   TestWorkPathPanic
=== PAUSE TestWorkPathPanic
=== CONT  TestWorkNormal
work path normal
--- PASS: TestWorkNormal (0.00s)
=== CONT  TestWorkPathPanic
--- PASS: TestWorkPathPanic (0.00s)
=== CONT  TestWorkPath2
work path2
--- PASS: TestWorkPath2 (0.00s)
=== CONT  TestWorkPath1
work path1
--- PASS: TestWorkPath1 (0.00s)
PASS
ok      cf      0.005s

The basic code is as follows

// business code with failpoint injection
func work(ctx context.Context) {
	failpoint.InjectContext(ctx, "path1", func() {
		// do something
	})
	// ...
}

// test case entrypoint, with failpoint enable
func TestWorkPath1(t *testing.T) {
	failpoint.Enable("cf/path1", "return(true)")
	ctx := failpoint.WithHook(context.Background(), func(ctx context.Context, fpname string) bool {
		// only the code is running from this test case contains the context key of `fpname`
		return ctx.Value(fpname) != nil
	})
	ctx = context.WithValue(ctx, "cf/path1", struct{}{})
	work(ctx)
}
Similar Resources

Belajar golang unit test

perintah eksekusi di root folder : go test -v ./... assertion ambil dari framewo

Feb 3, 2022

Record and replay your HTTP interactions for fast, deterministic and accurate tests

go-vcr go-vcr simplifies testing by recording your HTTP interactions and replaying them in future runs in order to provide fast, deterministic and acc

Dec 25, 2022

Testing framework for Go. Allows writing self-documenting tests/specifications, and executes them concurrently and safely isolated. [UNMAINTAINED]

GoSpec GoSpec is a BDD-style testing framework for the Go programming language. It allows writing self-documenting tests/specs, and executes them in p

Nov 28, 2022

Extremely flexible golang deep comparison, extends the go testing package and tests HTTP APIs

Extremely flexible golang deep comparison, extends the go testing package and tests HTTP APIs

go-testdeep Extremely flexible golang deep comparison, extends the go testing package. Latest news Synopsis Description Installation Functions Availab

Dec 22, 2022

A next-generation testing tool. Orion provides a powerful DSL to write and automate your acceptance tests

Orion is born to change the way we implement our acceptance tests. It takes advantage of HCL from Hashicorp t o provide a simple DSL to write the acceptance tests.

Aug 31, 2022

Robust framework for running complex workload scenarios in isolation, using Go; for integration, e2e tests, benchmarks and more! 💪

e2e Go Module providing robust framework for running complex workload scenarios in isolation, using Go and Docker. For integration, e2e tests, benchma

Jan 5, 2023

A simple and expressive HTTP server mocking library for end-to-end tests in Go.

mockhttp A simple and expressive HTTP server mocking library for end-to-end tests in Go. Installation go get -d github.com/americanas-go/mockhttp Exa

Dec 19, 2021

Snapshot - snapshot provides a set of utility functions for creating and loading snapshot files for using snapshot tests.

Snapshot - snapshot provides a set of utility functions for creating and loading snapshot files for using snapshot tests.

Jan 27, 2022

Package for comparing Go values in tests

Package for equality of Go values This package is intended to be a more powerful and safer alternative to reflect.DeepEqual for comparing whether two

Dec 29, 2022
gomonkey is a library to make monkey patching in unit tests easy

gomonkey is a library to make monkey patching in unit tests easy, and the core idea of monkey patching comes from Bouke, you can read this blogpost for an explanation on how it works.

Jan 4, 2023
Rr-e2e-tests - Roadrunner end-to-end tests repository
Rr-e2e-tests - Roadrunner end-to-end tests repository

RoadRunner end-to-end plugins tests License: The MIT License (MIT). Please see L

Dec 15, 2022
Benchmarking deferent Fibonacci functions and algorithms with running unit test

GoFibonacciBench Benchmarking deferent Fibonacci functions and algorithms with running unit test ... Introduction: Fibonacci numbers are special kinds

Feb 27, 2022
This repository includes consumer driven contract test for provider, unit test and counter api.

This repository includes consumer driven contract test for provider, unit test and counter api.

Feb 1, 2022
go websocket client for unit testing of a websocket handler

wstest A websocket client for unit-testing a websocket server The gorilla organization provides full featured websocket implementation that the standa

Dec 21, 2022
Easier way to unit test terraform

Unit testing terraform (WIP) Disclaimer Currently, the only way to compare values is using JSON query path and all types are strings. want := terraf

Aug 16, 2022
A mock of Go's net package for unit/integration testing

netmock: Simulate Go network connections netmock is a Go package for simulating net connections, including delays and disconnects. This is work in pro

Oct 27, 2021
Go Unit Testing Clean Arch

Golang Unit Testing Tutorial melakukan unit testing di Golang yang sudah menerapkan clean architecture Menjalankan Service PSQL_HOST=<IP Database Serv

Feb 12, 2022
A simple yet intuitive golang unit test framework.

gotest Intuitive and simple golang testing framework which helps in writing unit tests in a way which improves the readability of the test. Here is an

Jan 1, 2022
Vault mock - Mock of Hashicorp Vault used for unit testing

vault_mock Mock of Hashicorp Vault used for unit testing Notice This is a person

Jan 19, 2022