---
title: "Go Testing: Contexts and t.Parallel() - Blog - Coder"
description: "This blog explains a common testing bug when using <span style=\"color:red\">*t.Parallel()*</span> and test timeouts, e.g. <span style=\"color:red\">*context.WithTimeout()*</span>, and explains how to avoid it."
image: "/api/dynamic-og?title=Go+Testing%3A+Contexts+and+t.Parallel%28%29&randomBackground=true&styles=%7B%22height%22%3A162%2C%22width%22%3A302%2C%22padding%22%3A16%2C%22titleSize%22%3A24%2C%22logo%22%3A%7B%22width%22%3A80%2C%22height%22%3A12.15%7D%7D"
canonical: "https://coder.com/blog/go-testing-contexts-and-t-parallel"
---

Nov 13 20235 min read

# Go Testing: Contexts and t.Parallel()

![Spike Curtis](https://www.datocms-assets.com/19109/1667322800-spike.png?fit=crop&fm=jpg&h=3840&w=3840)

Spike Curtis

Share this article

We develop Coder on Coder which allows our engineers to do their work on big, shared infrastructure (32 cores and 256 GB of RAM in our case). With a lot of hardware, extensive use of _t.Parallel()_ in our Go backend shortens test times considerably.

We also make extensive use of _context.Context_ in our production code, so it appears in our testing. And even if the code under test doesn’t accept a context, it is a very convenient pattern for testing concurrent code.

But, there is a dangerous little sharp edge when using both _t.Parallel()_ and _context.WithTimeout()_. Tl;dr is–

> Always call _t.Parallel()_ before _context.WithTimeout()_

To understand why this is, and what kinds of gnarly test bugs you’ll find by not taking my advice, we need to dig a little bit into what _t.Parallel()_ does under the hood. But first, it’s worth some background on why we make extensive use of _context.WithTimeout()_ in our tests at Coder.

# Test Context Timeouts

Building programs that correctly handle concurrency is hard, even with Go. With concurrency comes the possibility of race conditions and deadlocks. Here we’re focused on the latter. Consider the following unit test of a hypothetical component that takes inputs and output via channels:

```

```

When the component is working fine, the test passes. But if the component is broken and deadlocks, the test also deadlocks. The default timeout on _go test_ is 10 minutes. During the initial development and any maintenance of the component, we’d expect a developer to run the tests iteratively: code, test, code, test…, and so on. If you have to wait 10 minutes to discover a broken test it kills productivity!

You can, of course, change the go test timeout, but that’s a relatively crude instrument as it sets the timeout for the entire test suite, which often grows over time, and different tests might be expected to take different times. I expect most unit tests to execute in less than 1ms, but a complex integration test could take several seconds.

Let’s set a timeout on our test case with a context.

```

```

Now, if the component deadlocks, it fails in 100ms. You’ll have to choose this number based on what the unit test is doing, choosing something that is a reasonable multiple of the usual runtime to account for testing on different systems and under load, but still quick enough to avoid dragging out the code/test iterative cycle.

You can make this pattern a lot more readable by adding some helper functions.

```

```

```

```

# Parallel Tests with Timed Contexts

Godoc for _t.Parallel()_ is very simple. Perhaps, deceptively simple:

> _Parallel signals that this test is to be run in parallel with (and only with) other parallel tests. When a test is run multiple times due to use of -test.count or -test.cpu, multiple instances of a single test never run in parallel with each other._

The mental model of parallel testing you get from this description looks like this

![](https://www.datocms-assets.com/19109/1699480697-screenshot-2023-11-08-at-1-58-07-pm.png?fit=clip&fm=webp&w=3840&q=90)

You might be tempted to think of _t.Parallel()_ as basically a little flag (or like a decorator in other programming languages). Its presence signals something, but you can just kinda throw it anywhere in your test setup code.

```

```

**If you do this, then your tests might start to mysteriously start to fail with timeouts, even if you haven’t changed the tests or the component you are testing!**

In fact, what happens is that _t.Parallel()_ sort of chops your test code into two halves. Any statements before _t.Parallel()_ run serially along with other serial test cases, and then any statements after _t.Parallel()_ run in parallel. Here is a great blog post that covers this in more detail, including how _t.Run()_ is handled.

To keep the diagram readable, I’m going to abbreviate the serial portion of Parallel Test1 (the part before _t.Parallel()_ is called) **sPT1**, and so on.

![](https://www.datocms-assets.com/19109/1699480887-screenshot-2023-11-08-at-2-01-16-pm.png?fit=clip&fm=webp&w=3840&q=90)

Consequently, if you create a timeout context in the serial portion of a parallel test, that is, before the call to _t.Parallel()_, then it may expire before or during the parallel portion.

Another way to think about this is to just look at the green boxes in the diagram.

![](https://www.datocms-assets.com/19109/1699480928-screenshot-2023-11-08-at-2-01-58-pm.png?fit=clip&fm=webp&w=3840&q=90)

A call to _t.Parallel()_ is like a _time.Sleep()_ for an indeterminate time. The time depends on how big the test suite is and how much of it is parallel. So, doing any sort of time-based computation on different sides of the _t.Parallel()_ call is fraught with danger.

Generally, the best thing to do is just put _t.Parallel()_ as the first statement of your test case.

```

```

```

```

In rare cases, you might need to do some test setup serially, and then want to execute your test cases in parallel. This is often not worth the trouble unless the parallel parts are numerous or take a long time (relative to the setup). But, if you really, really decide you need it, create a parent context without a timeout, tied to the lifetime of the test case (_defer testCancel()_ below). Then create child contexts for before and after _t.Parallel()_ as needed. As the child contexts are tied to the parent’s lifetime, they are also canceled when the test completes.

```

```

# Conclusion

We make extensive use of _t.Parallel()_ at Coder, to the extent our linters yell if you don’t use it. We care a lot about keeping developers in flow here, including our own. I hope I’ve convinced you of the value of test timeouts to avoid disrupting flow during code/test iterations. When you use context timeouts and _t.Parallel()_ in the same test, save yourself some grief and make sure _t.Parallel()_ is first!

### Subscribe to our newsletter

Want to stay up to date on all things Coder? Subscribe to our monthly newsletter for the latest articles, workshops, events, and announcements.
