Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallel tests (UNIX) #1709

Merged
merged 59 commits into from Apr 26, 2020
Merged

Parallel tests (UNIX) #1709

merged 59 commits into from Apr 26, 2020

Conversation

giampaolo
Copy link
Owner

@giampaolo giampaolo commented Mar 3, 2020

OK, this is big. We are now able to run tests in parallel on UNIX (and we keep using unittest module). On my Linux box with 8 logical cores all 551 unit-tests complete in half the time: around 6 seconds instead of 12. Same on FreeBSD. This is great news also because hopefully the CI builds should complete sooner. Currently we have 10 builds running on each commit:

  • Travis (8 builds: 5 Linux, 2 OSX, 1 for PYPY on Linux)
  • Cirrus-CI (2 builds for FreeBSD)

We now depend on the super cute concurrencytest lib which takes care of the internal fork/parallelization details.

The tricky part though was the fact that some tests needed to be run serially. In order to achieve that I added a @serialrun decorator which can be used to mark TestCase classes. On start, the test runner will split the test suite in 2 based on that, and finally run parallel and serial suites separately but as a single test run.

Prior to this I also had to refactor quite a lot of stuff and get rid of TESTFN global variable (#1734), since a global test file name doesn't play nice when accessed by multiple tests at the same time (and no, including os.getpid() as part of the file name wasn't enough).

We now have:

make test
make test-parallel

And here's the test output (an actual one):

$ make test-parallel
>>> starting parallel tests using 8 workers <<<
test_testutils.TestNetUtils.test_unix_socketpair (subunit.RemotedTestCase)
test_testutils.TestNetUtils.test_unix_socketpair ... OK
test_testutils.TestRetryDecorator.test_retries_arg (subunit.RemotedTestCase)
test_testutils.TestRetryDecorator.test_retries_arg ... OK
test_system.TestCpuAPIs.test_cpu_count_logical (subunit.RemotedTestCase)
test_system.TestCpuAPIs.test_cpu_count_logical ... OK
test_system.TestCpuAPIs.test_cpu_times_percent (subunit.RemotedTestCase)
test_system.TestCpuAPIs.test_cpu_times_percent ... OK
[...]
----------------------------------------------------------------------
Ran 510 tests in 3.683s

FAILED (failures=1, skipped=146)

>>> starting serial tests <<<
psutil.tests.test_unicode.TestFSAPIsWithInvalidPath.test_proc_cwd ... OK
psutil.tests.test_unicode.TestFSAPIsWithInvalidPath.test_proc_exe ... OK
psutil.tests.test_unicode.TestFSAPIsWithInvalidPath.test_proc_name ... OK
psutil.tests.test_unicode.TestFSAPIsWithInvalidPath.test_proc_open_files ... OK
[...]
----------------------------------------------------------------------
Ran 41 tests in 2.790s

OK
----------------------------------------------------------------------

+----------+----------+----------+----------+----------+----------+
|          |    total | failures |   errors |  skipped |     time |
+----------+----------+----------+----------+----------+----------+
| parallel |      510 |        1 |        0 |      146 |    3.68s |
+----------+----------+----------+----------+----------+----------+
| serial   |       41 |        0 |        0 |        0 |    2.79s |
+----------+----------+----------+----------+----------+----------+

Ran 551 tests in 6.474s using 8 workers

@giampaolo giampaolo merged commit 420c9e8 into master Apr 26, 2020
@giampaolo giampaolo deleted the parallel-tests branch April 26, 2020 00:02
@giampaolo
Copy link
Owner Author

giampaolo commented Apr 30, 2020

It turns out on CI we save just a bunch of secs but there are occasional false positives.
Since the majority of the time is spent waiting for the CI to start, install etc, it's not worth the instability so CI services will run the test serially (done in #1741 where I added parallelization to build/install).
While developing though, parallel tests are still a game changer.

giampaolo added a commit that referenced this pull request Apr 30, 2020
Refactor test runner.py with a saner unittest-based class hierarchy so
that --parallel args affects all test suites (all, by-name, failed).
Also change Makefile which now can be used like this:

make test-process ARGS=--parallel
giampaolo added a commit that referenced this pull request May 2, 2020
Despite I recently implemented parallel tests on UNIX (#1709), TestFetchAllProcesses class is the slowest one to run because it gets all possible info for all processes in one go. In fact it's a singe unit-test, so it's not parallelized by the test runner. In here I used multiprocessing.Pool to do the trick.

On my main linux box (8 cores):

Before:
----------------------------------------------------------------------
Ran 1 test in 2.511s

After:
----------------------------------------------------------------------
Ran 1 test in 0.931s

On Windows (virtualized, 4 cores):

Before:
----------------------------------------------------------------------
Ran 1 test in 13.752s

After:
----------------------------------------------------------------------
Ran 1 test in 3.951s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant