published on
by
tags: CubicWeb python tests

Node, 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):

import unittest
save_testrunner = unittest.TextTestRunner

import logilab.common.pytest  # noqa
unittest.TextTestRunner = save_testrunner

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:

  1. I could not get it working
  2. 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:

def noop(): pass

import cubicweb.devtools.testlib

cubicweb.devtools.testlib.pause_tracing = noop
cubicweb.devtools.testlib.resume_tracing = noop

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.