nose2 vs py.test with isolated processes

2024/10/9 22:24:08

We have been using nosetest for running and collecting our unittests (which are all written as python unittests which we like). Things we like about nose:

  • uses standard python unit tests (we like the structure this imposes).
  • supports reporting coverage and test output in xml (for jenkins).

What we are missing is a good way to run tests in isolated processes while maintaining good error repoorting (we are testing C++ libraries through python so segfaults should not be catastrophic). nosepipe seems to be no longer maintained and we have some problems with it.

We are trying to figure out whether we should - fix/use nosepipe - switch to nose2 and write nosepipe2. - use pytest or some other testing framework.

We would prefer to use an approach with a good community. It seems our problem (C++ plugins requiring good isolation) might be a common problem but googling I have not found solutions that are maintained. Advice from more experienced heads appreciated.

Answer

pytest has the xdist plugin which provides the --boxed option to run each test in a controlled subprocess. Here is a basic example::

# content of test_module.pyimport pytest
import os
import time# run test function 50 times with different argument
@pytest.mark.parametrize("arg", range(50))
def test_func(arg):time.sleep(0.05) # each tests takes a whileif arg % 19 == 0: os.kill(os.getpid(), 15)

If you run this with::

$ py.test --boxed
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
collecting ... collected 50 itemstest_module.py f..................f..................f...........================================= FAILURES =================================
_______________________________ test_func[0] _______________________________
/home/hpk/tmp/doc-exec-420/test_module.py:6: running the test CRASHED with signal 15
______________________________ test_func[19] _______________________________
/home/hpk/tmp/doc-exec-420/test_module.py:6: running the test CRASHED with signal 15
______________________________ test_func[38] _______________________________
/home/hpk/tmp/doc-exec-420/test_module.py:6: running the test CRASHED with signal 15
=================== 3 failed, 47 passed in 3.41 seconds ====================

You'll see that a couple of tests are reported as crashing, indicated by lower-case f and the respective failure summary. You can also use the xdist-provided parallelization feature to speed up your testing::

$ py.test --boxed -n3
=========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
gw0 I / gw1 I / gw2 I
gw0 [50] / gw1 [50] / gw2 [50]scheduling tests via LoadScheduling
..f...............f..................f............
================================= FAILURES =================================
_______________________________ test_func[0] _______________________________
[gw0] linux2 -- Python 2.7.3 /home/hpk/venv/1/bin/python
/home/hpk/tmp/doc-exec-420/test_module.py:6: running the test CRASHED with signal 15
______________________________ test_func[19] _______________________________
[gw2] linux2 -- Python 2.7.3 /home/hpk/venv/1/bin/python
/home/hpk/tmp/doc-exec-420/test_module.py:6: running the test CRASHED with signal 15
______________________________ test_func[38] _______________________________
[gw2] linux2 -- Python 2.7.3 /home/hpk/venv/1/bin/python
/home/hpk/tmp/doc-exec-420/test_module.py:6: running the test CRASHED with signal 15
=================== 3 failed, 47 passed in 2.03 seconds ====================

In principle, just distributing to parallel subprocesses may often suffice and avoids the overhead of starting a boxed process for each test. This currently only works if you only have less crashing tests than the -n number of processes because a dying testing process is not restarted. This limitation could probably be removed without too much effort. Meanwhile you will have to use the safe boxing option.

https://en.xdnf.cn/q/69965.html

Related Q&A

ValueError: Attempt to reuse RNNCell with a different variable scope than its first use

The following code fragmentimport tensorflow as tf from tensorflow.contrib import rnnhidden_size = 100 batch_size = 100 num_steps = 100 num_layers = 100 is_training = True keep_prob = 0.4input_da…

Convex Hull and SciPy

Im trying to use scipy (0.10.1) for a quick hack to visualize the convex hull.I can get the convex hull using the following code:vecs = [[-0.094218, 51.478927], [-0.09348, 51.479364], [-0.094218, 51.4…

Flask Confirm Action

Im creating a site using the Flask framework, and am implementing a confirmation page for (mainly administrative) actions; i.e. deleting a user.My current method (detailed below) works, but feels quite…

Regex for accent insensitive replacement in python

In Python 3, Id like to be able to use re.sub() in an "accent-insensitive" way, as we can do with the re.I flag for case-insensitive substitution.Could be something like a re.IGNOREACCENTS fl…

Python + Flask REST API, how to convert data keys between camelcase and snakecase?

I am learning Python, and coding simple REST API using Flask micro-framework.I am using SQLAlchemy for Object-relational-mapping and Marshmallow for Object-serialization/deserialization.I am using snak…

pytest reports too much on assert failures

Is there a way for pytest to only output a single line assert errors?This problem arises when you have modules with asserts, If those asserts fails, it dumps the entire function that failed the assert…

pulp.solvers.PulpSolverError: PuLP: cannot execute glpsol.exe

I am a newbie with python and optimization. I am getting some error, please help me resolve it. I tried running the below mentioned code in PyCharm where I am running Anaconda 3from pulp import * x = L…

Django urldecode in template file

is there any way do the urldecode in Django template file? Just opposite to urlencode or escapeI want to convert app%20llc to app llc

Structure accessible by attribute name or index options

I am very new to Python, and trying to figure out how to create an object that has values that are accessible either by attribute name, or by index. For example, the way os.stat() returns a stat_resul…

Loading data from Yahoo! Finance with pandas

I am working my way through Wes McKinneys book Python For Data Analysis and on page 139 under Correlation and Covariance, I am getting an error when I try to run his code to obtain data from Yahoo! Fin…