cubicweb
Nose, Coverage and CubicWeb
This post was part of the now dead Unlish blog.
Writing unittests in CubicWeb cubes requires to use pytest, a test runner provided by logilab-devtools. Trying to use an other test runner is problematic, if not doomed to fail, as well as doing code coverage.
Fortunately, we can do something about it.
nose
Using nosetests to run the tests immediately fails with an obscure:
TypeError: unbound method __init__() must be called
with SkipAwareTextTestRunner instance as first
argument (got TextTestRunner instance instead)
After some digging, I discovered that CubicWebTC, from which we inherit all the test cases, ultimately depends on logilab pytest… which is meant to be a test runner, or so it should.
Logilab pytest, as a runner, introduce features missing from the early versions of unittests. To do so, it monkey-patch unittests itself. And I have a feeling that nose is doing something similar… which leads to the ugly error we have.
The solution is to un-monkey-patch unittests, by including these few lines somewhere loaded before any of the test (we do that in test/init.py):
|
|
After that, we can happily use nose to run the cube unittests!
coverage
The Logilab pytest tool is supposed to do code coverage measurement. Thing is:
- I could not get it working
- we want to use another test runner
The naïve approach, using directly coverage or the cover extension of nose (or py.test), unfortunately fails because pytest is still messing with the trace function. The result will invariably be a coverage of 0%.
To avoid CubicWebTC to call any of the tracing-related functions of pytest, we simply inject noop() operations where they are used:
|
|
And voilà!
In the end, we can use the test runner we want and get coverage to work properly. It remains a hackish workaround though, I think we ultimately need to cut the dependency from CubicWebTC to logilab.devtools.pytest.