Sunday 4 November 2018 — This is six years old. Be careful.
A cautionary tale about testing that things are unequal...
We had a test that was kind of like this:
def test_thing():
data = "I am the data"
self.assertNotEqual(
modify_another_way(change_the_thing(data)),
data
)
But someone refactored the test oh-so-slightly, like this:
def test_thing():
data = "I am the data"
modified = modify_another_way(change_the_thing(data)),
self.assertNotEqual(
modified,
data
)
Now the test isn’t testing what it should be testing, and will pass even if change_the_thing and modify_another_way both return their argument unchanged. (I’ll explain why below.)
Negative tests (asserting that two things are unequal) is really tricky, because there are infinite things unequal to your value. Your assertion could pass because you accidentally have a different one of those unequal values than you thought.
Better would be to know what unequal value you are producing, and test that you have produced that value, with an equality assertion. Then if something unexpectedly shifts out from under you, you will find out.
Why the test was broken: the refactorer left the trailing comma on the “modified =” line, so “modified” is a 1-element tuple. The comparison is now between a tuple and a string, which are always unequal, even if the first element of the tuple is the same as the string.
Comments
Asserting that an exception is thrown, without checking that the exception is the kind you expected.
Making an assertion within a callback, which is never called, or which is called by something that catches all exceptions including the one the test framework uses for "assertion failed".
Once you start doing this by habit, you will be *amazed* at how frequently you discover you accidentally create tests that pass *all the time*, no matter what the code-under-test says. Thus proving that this habit is vital.
* we should be careful with our assertions, especially the negative ones (because of the wide range of valid values)
* we should be careful when refactoring our code. Refactoring is necessary. But refactoring untested code (like the code of the test here) is always dangerous, and extra care should be taken in this case. And specifically, you need to double check anything you copy and paste.
Add a comment: