Why do assertions in unittest use TestCase.assertEqual not the assert keyword?

PythonUnit Testing

Python 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStephen EmslieView Question on Stackoverflow
Solution 1 - PythonThomas WoutersView Answer on Stackoverflow
Solution 2 - PythonNick MartinView Answer on Stackoverflow
Solution 3 - PythonjpmView Answer on Stackoverflow
Solution 4 - PythonboxedView Answer on Stackoverflow