pytest support for unittest style fixtures

As with nose, I ran pytest on the tests written to demonstrate unittest fixtures.
Some surprises.
There are some differences, which I’ll list out in this post.

Before we get started, I’d like to express that I’m a huge fan of pytest.
The cool stuff in pytest far outweighs any invonvenience that it doesn’t behave exactly like unittest.

However, it’s good to know what the differences are, so you can be informed about how your unittests will run under pytest.

This testing is using pytest 2.3.5.

Update: As of pytest 2.4, these issues have all been fixed. pytest now fully supports unittest fixtures
  • module: setUpModule()/tearDownModule() NOT supported (use setup_module()/teardown_module() instead)
  • class: setUpClass()/tearDownClass() supported
  • around methods: setUp()/tearDown() supported
  • add cleanup functions: addCleanup() called from setUp() and from a test supported
  • skipping tests dynamically: testSkip() called from setUp() supported
  • error conditions: handled differently than unittest

Missing support for setUpModule()/tearDownModule()

In my opinion, this is just an oversight.
The current head of the development branch of pytest DOES support these functions.
I know, because I just changed the code and submitted a pull request. And it’s been excepted.

However, 2.3.5 doesn’t support these functions.

Differences with error conditions

In unittest, the matching tearDown function is NOT run if the setUp function fails.

  • If setUpModule() throws an exception, tearDownModule() is NOT run.
  • If setUpClass() throws an exception, tearDownClass() is NOT run.
  • If setUp() throws an exception, tearDown() is NOT run.
  • If setUp() trhows an exception AFTER adding a cleanup function with addCleanup(), the cleanup function IS run.

What does pytest do?

Well, setUpModule() isn’t supported yet. But let’s look at setup_module() instead.

  • If setup_module() throws an exception, teardown_module() IS run.
  • If setUpClass() throws an exception, tearDownClass() IS run.
  • If setUp() throws an exception, tearDown() is NOT run.
  • If setUp() trhows an exception AFTER adding a cleanup function with addCleanup(), the cleanup function IS run.

So, for pytest, the only tearDown that doesn’t run in setUp failure cases.
All of the other tearDown like functions ARE run regardless of the state of the matching setUp function.


Whew… Still with me?

Update: As of pytest 2.4, these issues have all been fixed. pytest now fully supports unittest fixtures.
But… I gave up on strike-throughs, I just need to rewrite this post…
In the meantime, suffice it to say that you can use pytest to run unittest without fear of fixtures doing anything different.

They just work.

Good thing or bad thing?

  • All tests that pass with unittest will pass with pytest.
  • All tests that fail with unittest will fail with pytest.
  • All tests that error with unittest will error with pytest.

However, if you are relying on a tearDown like function NOT running, you have to watch out.
That seems like a small population though.

I’m not really even sure what the behaviour SHOULD be.

When could it be a good thing?

If you have several resources that you are opening, allocating, etc, in setUpClass(), then…
For unittest and nose, you need to make sure you clean up everything in setUpClass() if anything fails.
For pytest, you could only clean up in tearDownClass().

However, I wouldn’t rely on this behavior.

It’s extremely possible that a future release of pytest will match the unittest/nose behavior regarding this bit.

Code output TL;DR

You can look at my evidence if your bored.

Leave a Reply