How to set the go timeout flag on "Go test"
Solution 1:
Use a valid time.ParseDuration
input. For example,
$ go test -timeout 300ms
$ go test -timeout 99999s
Command go
Testing flags
-timeout t
If a test runs longer than
t
,panic
.Package flag
Duration flags accept any input valid for
time.ParseDuration
.Package time
func ParseDuration
func ParseDuration(s string) (Duration, error)
ParseDuration parses a duration string. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "
300ms
", "-1.5h
" or "2h45m
". Valid time units are "ns
", "us
" (or "µs
"), "ms
", "s
", "m
", "h
".
Solution 2:
If you need this for just one test that you want to easily fail when it times out there is a neat way of just using timeout channels.
If I suspect a test will time out and I still want it to fail is to work with a timeout channel.
So imagine you have code where you suspect that some goroutines will deadlock and you want to make sure your test fails on that.
For that I run the actual test in a goroutine and the main goroutine then sits around waiting for either the done
channel to finish or the timeout
to finish.
func TestWithTimeOut(t *testing.T) {
timeout := time.After(3 * time.Second)
done := make(chan bool)
go func() {
// do your testing
time.Sleep(5 * time.Second)
done <- true
}()
select {
case <-timeout:
t.Fatal("Test didn't finish in time")
case <-done:
}
}
Solution 3:
To add/update to Tigraine's answer:
If you need this for just one test that you want to easily fail when it times out there is a neat way of just using timeout channels.
Actually... proposal/issue 48157 "cmd/go
: add per-test timeouts", accepted and possibly released with Go 1.18 (Q1 2022) will change that.
Tests have an overall timeout for the entire binary but no timeout for a specific test case.
You often want to limit any particular test case to a time much shorter than the overall binary.I propose to add the concept of per-test (function) timeouts to the go command user experience as follows.
Each test gets a per-test timeout.
The timer for a given test only ticks down when the test is running. It does not tick down when the test is blocked int.Parallel
, nor when it is blocked int.Run
running a subtest.The default per-test case timeout is 1m (one minute).
If the new-testtimeout
flag is specified explicitly, then that sets a different default.
If the-testtimeout
flag is omitted but-timeout
is specified explicitly, then that sets the default too. This way, if you have one really long test and usego test -timeout=30m
, the per-case timeout doesn't kick in after 1 minute and kill it anyway.There is a new
testing.TB
methodSetTimeout(d time.Duration)
that allows a test to set its own timeout.
CallingSetTimeout
does not reset the timer. If a test runs for 30 seconds and then callst.SetTimeout(1*time.Second)
, it gets killed for having timed out. A timeout set this way is inherited by subtests. (They each have their own timer.)When a test timeout happens, the whole process still gets killed. There's nothing we can really do about that. But the failure does say which test function timed out.
And so you now (Nov. 2021) have CL 363134, as an illulstration:
internal/fuzz
: set timeout for each exec of fuzz targetThis change sets a timeout of 10 seconds on each execution of the fuzz target, both during fuzzing and during minimization.