summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.coveragerc1
-rwxr-xr-xtest/runner/injector/injector.py1
-rw-r--r--test/runner/lib/executor.py1
-rw-r--r--test/runner/requirements/units.txt1
-rw-r--r--test/units/conftest.py33
5 files changed, 36 insertions, 1 deletions
diff --git a/.coveragerc b/.coveragerc
index 1fc35b047d..698302a7a1 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -9,6 +9,7 @@ branch = True
# results from multiple tests simultaneously, as well as supporting multiple
# test runs, such as from integration tests.
concurrency = multiprocessing
+parallel = True
# When running tests through ansible-test, this option is overridden by
# the COVERAGE_FILE environment variable. This option is present for
diff --git a/test/runner/injector/injector.py b/test/runner/injector/injector.py
index a2d22ab284..57241c9557 100755
--- a/test/runner/injector/injector.py
+++ b/test/runner/injector/injector.py
@@ -144,7 +144,6 @@ def coverage_command(self_dir, version):
args = [
find_executable(executable),
'run',
- '--append',
'--rcfile',
os.path.join(self_dir, '.coveragerc'),
]
diff --git a/test/runner/lib/executor.py b/test/runner/lib/executor.py
index 9304933db0..82e41b7822 100644
--- a/test/runner/lib/executor.py
+++ b/test/runner/lib/executor.py
@@ -624,6 +624,7 @@ def command_units(args):
cmd = [
'pytest',
+ '--boxed',
'-r', 'a',
'--color',
'yes' if args.color else 'no',
diff --git a/test/runner/requirements/units.txt b/test/runner/requirements/units.txt
index 3d7f91211f..a61fc9ce7f 100644
--- a/test/runner/requirements/units.txt
+++ b/test/runner/requirements/units.txt
@@ -6,6 +6,7 @@ passlib
pycrypto
pytest
pytest-mock
+pytest-xdist
python-memcached
pyyaml
redis
diff --git a/test/units/conftest.py b/test/units/conftest.py
new file mode 100644
index 0000000000..387fa77b87
--- /dev/null
+++ b/test/units/conftest.py
@@ -0,0 +1,33 @@
+"""Monkey patch os._exit when running under coverage so we don't lose coverage data in forks, such as with `pytest --boxed`."""
+import gc
+import os
+
+try:
+ import coverage
+except ImportError:
+ coverage = None
+
+
+def pytest_configure():
+ if not coverage:
+ return
+
+ coverage_instances = []
+
+ for obj in gc.get_objects():
+ if isinstance(obj, coverage.Coverage):
+ coverage_instances.append(obj)
+
+ if not coverage_instances:
+ return
+
+ os_exit = os._exit
+
+ def coverage_exit(*args, **kwargs):
+ for instance in coverage_instances:
+ instance.stop()
+ instance.save()
+
+ os_exit(*args, **kwargs)
+
+ os._exit = coverage_exit