Why are my Minitest tests running in parallel?

I recently realized that my Minitest tests can run in parallel. All I had to do was

require "minitest/hell"


and so I did. Unfortunately, my tests run exactly the same as before. Everything passes, and it takes just as long as usual. I checked htop

while running my test suite and only one core is used.

I set a breakpoint in a random test to check if the tests were actually running in parallel:

(byebug) Minitest :: Test.test_order
: parallel

So what's going on?

My first guess was that Minitest counts the number of processor cores when choosing the number of processes to spawn. I had multiple physical processors (in a virtual machine) but only 1 core per processor. I changed my VPS to have two physical processors, each with 4 cores, and my tests are still not running in parallel.

$ lscpu
Architecture: x86_64
CPU op-mode (s): 32-bit, 64-bit
Byte Order: Little Endian
CPU (s): 8
On-line CPU (s) list: 0-7
Thread (s) per core: 1
Core (s) per socket: 4
Socket (s): 2
NUMA node (s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 62
Stepping: 4
CPU MHz: 2600.000
BogoMIPS: 5200.00
Hypervisor vendor: VMware
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 20480K
NUMA node0 CPU (s): 0-7

source to share

3 answers

Minitest uses threads, not processes, to run the test in parallel.

Since the MRI (Standard Ruby Interpreter) has a global interpreter lock, only one thread can execute at a time. Therefore your tests do not run in parallel when using an MRI.

You can run tests in parallel using a Ruby interpreter that supports parallel threads like JRuby or Rubinius.

Read more in this article.



severin's answer that MRI cannot be performed in parallel due to GIL. (Disclaimer: I wrote the article he links to.) The language is a little vague in many emails, but you can read this article for a very simple description.

If you're still interested in running tests in parallel and can't change Ruby interpreters, look at the parallel_tests gem for an alternative, albeit with some limitations.



For tests to run in parallel, you need a Ruby version that allows parallel execution (like JRuby), or you can use simple shell commands to run a few minimal runs.

For example, use gnu parallel:

find test -type f | parallel --dry-run  bundle exec rake test TEST={}


(The flag dry-run

so you can see what happens before it runs, omit the flag dry-run

, when you're satisfied, the commands will do what you want.)

The exec and rake overhead is very high. The main benefit of parallel execution is to make sure your tests run correctly - that is, the main benefit is not speed. If you are using parallel, you probably want to try spork

which one the finished application supports.



All Articles