This post has several examples, and covers fixtures, test discovery, asserts, running options, and running unittests and doctests.

Nose’s tagline is “nose extends unittest to make testing easier”.

It’s is a fairly well known python unit test framework, and can run doctests, unittests, and “no boilerplate” tests.

It is a good candidate for a go-to test framework.

I think a smart developer should get familiar doctest, unittest, pytest, and nose. Then decide if one of those makes the most sense for them, or if they want to keep looking for features only found in other frameworks.

That’s of course the reason why I’m writing this series. So I guess that last bit goes without saying.

Contents

No boilerplate, some api

A basic test file for nose is pretty simple, without any boilerplate code, without required classes to drive from, without unnecessary imports, and without any extra api.

Note:

The module unnecessary_math is non-standard and can be found here: The module unnecessary_math is non-standard and can be found here: implementation of unnecessary_math.py

from unnecessary_math import multiply def test_numbers_3_4(): assert multiply(3,4) == 12

This is identical to the simple test shown in my pytest intro.

There are differences between how you have to write your tests for the two frameworks once you get into extra features of the frameworks, like fixtures, plugins, assert mechanisms, etc.

I’m going to leave a full comparison of pytest and nose to a future post.

Why do I say ‘some api’? Well, when you get into fixtures (like setup/teardown, etc), there is some nose api that is needed in the tests. I’ll get into that in the fixture section.

Nose example

For completeness in following the styles of previous framework introductions, here is the full basic test.

This only differs from above that I’ve added another test function.

from unnecessary_math import multiply def test_numbers_3_4(): assert multiply(3,4) == 12 def test_strings_a_3(): assert multiply('a',3) == 'aaa'

Running nose

To run nose, use the nosetests command that comes with nose.

nosetests test_um_nose.py

And with verbose:

nosetests -v test_um_nose.py

Here’s an example run both with and without verbose:

> nosetests test_um_nose.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK > nosetests -v test_um_nose.py simple_example.test_um_nose.test_numbers_3_4 ... ok simple_example.test_um_nose.test_strings_a_3 ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK

Nose fixtures

Nose extends the unittest fixture model of setup/teardown.

We can add specific code to run:

at the beginning and end of a module of test code (setup_module/teardown_module)

To get this to work, you just have to use the right naming rules.

To get this to work, you just have to use the right naming rules. at the beginning and end of a class of test methods (setup_class/teardown_class)

To get this to work, you have to use the right naming rules, and include the ‘@classmethod’ decorator.

before and after a test function call (setup_function/teardown_function)

You can use any name. You have to apply them with the ‘@with_setup’ decorator imported from nose.

You can also use direct assignment, which I’ll show in the example.

before and after a test method call (setup/teardown)

To get this to work, you have to use the right name.

The easiest fixtures to add are:

setup_module() function: runs before anything else in the file

function: runs before anything else in the file teardown_module() function: runs after everything else in the file

And if you use a class to define some tests:

setup() method: runs before every test method

method: runs before every test method teardown() method: runs after every test method

You can also set non-class based test functions to have setup/teardown

functions, but you have to import the ‘with_setup’ decorator from nose, like so:

from nose import with_setup # optional

def my_setup_function(): pass def my_teardown_function(): pass @with_setup(my_setup_function, my_teardown_function) def test_numbers_3_4(): assert multiply(3,4) == 12

If you don’t like to use decorators, you can also assign the setup and teardown attributes like this:

test_numbers_3_4.setup = my_setup_function test_numbers_3_4.teardown = my_teardown_function

However, I think that’s a bit awkward.

With classes, you can set a setup/teardown for the class, but you do it differently.

You need to make sure the methods are class methods using the ‘classmethod’ decorator, and name them correctly, like so:

class TestUM: @classmethod def setup_class(cls): print ("setup_class() before any methods in this class") @classmethod def teardown_class(cls): print ("teardown_class() after any methods in this class")

It works, it’s just that you have to keep the syntax straight for all the different rules for different fixtures.

Here they are all together.

from nose import with_setup # optional from unnecessary_math import multiply def setup_module(module): print ("") # this is to get a newline after the dots print ("setup_module before anything in this file") def teardown_module(module): print ("teardown_module after everything in this file") def my_setup_function(): print ("my_setup_function") def my_teardown_function(): print ("my_teardown_function") @with_setup(my_setup_function, my_teardown_function) def test_numbers_3_4(): print 'test_numbers_3_4 <============================ actual test code' assert multiply(3,4) == 12 @with_setup(my_setup_function, my_teardown_function) def test_strings_a_3(): print 'test_strings_a_3 <============================ actual test code' assert multiply('a',3) == 'aaa' class TestUM: def setup(self): print ("TestUM:setup() before each test method") def teardown(self): print ("TestUM:teardown() after each test method") @classmethod def setup_class(cls): print ("setup_class() before any methods in this class") @classmethod def teardown_class(cls): print ("teardown_class() after any methods in this class") def test_numbers_5_6(self): print 'test_numbers_5_6() <============================ actual test code' assert multiply(5,6) == 30 def test_strings_b_2(self): print 'test_strings_b_2() <============================ actual test code' assert multiply('b',2) == 'bb'

To see it in action, I'll use the -s option, which turns off output capture.

This will show the order of the different fixture calls.

> nosetests -s test_um_nose_fixtures.py .... setup_module before anything in this file setup_class() before any methods in this class TestUM:setup() before each test method test_numbers_5_6() <============================ actual test code TestUM:teardown() after each test method TestUM:setup() before each test method test_strings_b_2() <============================ actual test code TestUM:teardown() after each test method teardown_class() after any methods in this class my_setup_function test_numbers_3_4 <============================ actual test code my_teardown_function my_setup_function test_strings_a_3 <============================ actual test code my_teardown_function teardown_module after everything in this file ---------------------------------------------------------------------- Ran 4 tests in 0.001s OK

Testing markdown.py

This is also identical to code that can be run from py.test.

It's similar to unittest code, but without boilerplate, and with simple assert calls instead of assertEquals.

Again, I'm using the API adapter to cleanly call markdown functionality.

Here's the code to use nose to test markdown.py:

from markdown_adapter import run_markdown def test_non_marked_lines(): print ('in test_non_marked_lines') assert run_markdown('this line has no special handling') \ == 'this line has no special handling' def test_em(): print ('in test_em') assert run_markdown('*this should be wrapped in em tags*') \ == ' this should be wrapped in em tags ' def test_strong(): print ('in test_strong') assert run_markdown('**this should be wrapped in strong tags**') \ == ' this should be wrapped in strong tags '

And here's the output:

> nosetests test_markdown_nose.py FFF ====================================================================== FAIL: test_markdown_nose.test_non_marked_lines ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\python27\lib\site-packages

ose-1.2.1-py2.7.egg

ose\case.py", line 197, in runTest self.test(*self.arg) File "E:\python_notes\repo\markdown.py-dev\test_markdown_nose.py", line 13, in test_non_marked_lines == 'this line has no special handling' AssertionError: -------------------- >> begin captured stdout << --------------------- in test_non_marked_lines --------------------- >> end captured stdout << ---------------------- ====================================================================== FAIL: test_markdown_nose.test_em ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\python27\lib\site-packages

ose-1.2.1-py2.7.egg

ose\case.py", line 197, in runTest self.test(*self.arg) File "E:\python_notes\repo\markdown.py-dev\test_markdown_nose.py", line 18, in test_em == ' this should be wrapped in em tags ' AssertionError: -------------------- >> begin captured stdout << --------------------- in test_em --------------------- >> end captured stdout << ---------------------- ====================================================================== FAIL: test_markdown_nose.test_strong ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\python27\lib\site-packages

ose-1.2.1-py2.7.egg

ose\case.py", line 197, in runTest self.test(*self.arg) File "E:\python_notes\repo\markdown.py-dev\test_markdown_nose.py", line 23, in test_strong == ' this should be wrapped in strong tags ' AssertionError: -------------------- >> begin captured stdout << --------------------- in test_strong --------------------- >> end captured stdout << ---------------------- ---------------------------------------------------------------------- Ran 3 tests in 0.137s FAILED (failures=3)

All of the tests are failing.

Although the line numbers of the failures, along with the test function names, are printed, it's not real obvious from the report what's wrong.

Nose assert_equals

If we are using lots of assert something == somethingElse type tests, and we are committed to using nose for testing, we can use nose tools to make the report a bit obvious about what the failure is.

I'm going to rewrite the tests from above using nose.tools.assert_equals:

from nose.tools import assert_equals from markdown_adapter import run_markdown def test_non_marked_lines(): print ('in test_non_marked_lines') assert_equals(run_markdown('this line has no special handling'), 'this line has no special handling') def test_em(): print ('in test_em') assert_equals( run_markdown('*this should be wrapped in em tags*'), ' this should be wrapped in em tags ') def test_strong(): print ('in test_strong') assert_equals( run_markdown('**this should be wrapped in strong tags**'), ' this should be wrapped in strong tags ')

Nose's assert_equals works a lot like unittest's assertEquals.

Now lets look at the output:

> nosetests test_markdown_nose_assert_equals.py FFF ====================================================================== FAIL: test_markdown_nose_assert_equals.test_non_marked_lines ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\python27\lib\site-packages

ose-1.2.1-py2.7.egg

ose\case.py", line 197, in runTest self.test(*self.arg) File "E:\python_notes\repo\markdown.py-dev\test_markdown_nose_assert_equals.py", line 14, in test_non_marked_lines 'this line has no special handling') AssertionError: 'this line has no special handling' != ' this line has no special handling ' -------------------- >> begin captured stdout << --------------------- in test_non_marked_lines --------------------- >> end captured stdout << ---------------------- ====================================================================== FAIL: test_markdown_nose_assert_equals.test_em ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\python27\lib\site-packages

ose-1.2.1-py2.7.egg

ose\case.py", line 197, in runTest self.test(*self.arg) File "E:\python_notes\repo\markdown.py-dev\test_markdown_nose_assert_equals.py", line 19, in test_em ' this should be wrapped in em tags ') AssertionError: '*this should be wrapped in em tags*' != ' this should be wrapped in em tags ' -------------------- >> begin captured stdout << --------------------- in test_em --------------------- >> end captured stdout << ---------------------- ====================================================================== FAIL: test_markdown_nose_assert_equals.test_strong ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\python27\lib\site-packages

ose-1.2.1-py2.7.egg

ose\case.py", line 197, in runTest self.test(*self.arg) File "E:\python_notes\repo\markdown.py-dev\test_markdown_nose_assert_equals.py", line 24, in test_strong ' this should be wrapped in strong tags ') AssertionError: '**this should be wrapped in strong tags**' != ' this should be wrapped in strong tags ' -------------------- >> begin captured stdout << --------------------- in test_strong --------------------- >> end captured stdout << ---------------------- ---------------------------------------------------------------------- Ran 3 tests in 0.139s FAILED (failures=3)

Now the output makes it more obvious what's wrong.

Test discovery

I use the same naming conventions for nose as I do for py.test.

Name my test modules/files starting with 'test_'.

Name my test functions starting with 'test_'.

Name my test classes starting with 'Test'.

Name my test methods starting with 'test_'.

Make sure all packages with test code have an 'init.py' file.

These rules work just fine for me.

This isn't the complete list of rules. If you want to do something different, look at the nose documentation for finding tests

Running unittests from nose

Nose finds and runs unittests with no problem, and with no extra steps.

Here I'll run the tests from the unittest intro:

> nosetests test_um_unittest.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK > nosetests -v test_um_unittest.py test_numbers_3_4 (simple_example.test_um_unittest.TestUM) ... ok test_strings_a_3 (simple_example.test_um_unittest.TestUM) ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.001s OK

Running doctests from nose

Nose can run doctests, supposedly.

However, I couldn't get it to work on doctests in a separate file method, using test_unnecessary_math.txt.

I tried several of the options, with no luck.

If you know what I'm doing wrong, please let me know.

More nose info (links)

nose.readthedocs - nose official documentation (I think)

pypi - download links and multiple versions

nose-dev - google group on nose

Examples on github

All of the examples here are available in the markdown.py project on github.