Why do assertions in unittest use TestCase.assertEqual not the assert keyword?
PythonUnit TestingPython Problem Overview
Python's built-in unittest module makes assertions with TestCase.assert*
methods:
class FooTest(TestCase):
def test_foo(self):
self.assertEqual(1,1)
self.assertNotEqual(1,2)
self.assertTrue(True)
I have generally used a testrunner such as nose or py.test which allow use of the built-in assert
keyword when making assertions:
assert 1 == 1
assert 1 != 2
assert True
What is the motivation for unittest's TestCase.assert*
approach and what are the strengths and weaknesses of this vs asserting with the built-in assert keyword? Are there reasons why unittest's syntax should be favoured?
Python Solutions
Solution 1 - Python
The problem with the assert
keyword is that it is optimized out, and thus ignored, when Python is run in 'optimized' mode (with the -O
argument or with the PYTHONOPTIMIZE
environment variable set.) If tests were to use assert
then testing with -O
would be impossible.
Additionally, the use of the assert methods makes it trivial to report about what the values involved actually were, without having to dig into the stack and the source and figure out what they were supposed to be (which, I believe, is the technique nose
and py.test
use for this.)
Solution 2 - Python
I don't see a concrete design decision for this. Looking at the unittest docs it states that
> the type specific equality function will be called in order to generate a more useful default error message
So I would say it is an implementation decision to help produce more meaningful errors etc.
Solution 3 - Python
The main strength of this approach is providing several built in tests that are commonly performed so that one doesn't have to write them over and over again. Additionally, assertRaises lets you customize the exact behavior of the assert by throwing an exception.
Solution 4 - Python
The unittest syntax is a workaround for a weakness in how Python has implemented assert
. Pytest has another workaround with assertion rewriting that largely fixes this problem in a much better way. It's also BETTER at giving nice error messages for asserts than the assertFoo
style asserts.
Use pytest and live a happier and more productive life :P