One of a few important lessons I learn from Java development is the importance of unit test. It is of course not a silver bullet to the software reliability/quality problem, but the consequence not adopting it can only be more dire.
I used only JUnit to implement unit tests in Java (Since JUnit is “good enough”, I never explore the alternative framework TestNG.). Actually, problems in writing unit tests usually have very little to do with the frameworks themselves, but more with:
A. The legacy code base you want to test against. For example, if the existing code base design is not modular enough, you have to go through some refactoring process to make unit testing possible. It is not the kind of luxury we can afford very often.
B. Mock objects. EasyMock has made mocking a dependency easier, but maintaining the mock object codes still requires considerable effort.
Unit testing and Python
I think unit testing is even more important for Python programmers.
Since everything happens in runtime for Python, errors in your scripts, no matter syntactical or logical, will not be caught until you actually execute the line of code where the bug lives.
On top of it, a majority of commercial/in-house software contains so many features. The sheer number of possible combination of the execution pathways means thorough manual testing is simply unattainable, if not unrealistic.
If at the end of the day, a production issue in your python software arises and it turns out to be “incorrect indentation”, the managers and users will look down on you pretty hard (“Did you really test it?”). Unit test + coverage tools can help us to avoid these kind of situation.
Besides, unit tests can be used to safeguard corner cases and exceptional conditions. For financial applications, one of those commonly-seen mistakes is that a program fails to perform properly when a certain event (e.g. rollover) happens on a public holiday. With unit testing, we can subject the relevant codes to different combination of date and instruments, so we can make sure it will, for instance, calculate accrual correctly no matter what.
Comparing Java, I find it easier to do unit testing in Python because, with Python’s “Duck Typing” capability, we do not have to worry about maintaining mock objects at all. Whenever you need to mimic a dependency’s behavior, just write a dummy class with just enough attributes/methods the testee expects. End of story.
No more record and play APIs, as in EasyMock.
Nosetests makes it easy
So, you can understand why I am so glad to find nose. Nosetests is, in a nutshell, a unit test discovery tool. It can traverse down a python source code directory and pick up classes that extends unittest.Testcase, doc test, and any classes/methods that follow the default naming convention. I can now mix any testing styles depending on the task at hand.
I usually use the following parameters with nosetests:
—verbosity=3 —with-doctest -s —exe
“—exe” is necessary because in cygwin, my primary development environment, py files are usually set to be “executable”.
Do you have any tips and idea on unit testing/software quality assurance to share? Feel free.