Clean Code and most importantly DRY does not stop at unit test code! -.-
Clean Code and most importantly DRY does not stop at unit test code! -.-
I just refactored a unit test that had the same bunch of lines (that contained a bug) in like 2 dozen test methods and moved them to the SetUp method.
The benefits are obvious:
- need to fix the bug only once
- test methods are not cluttered with boilerplate but only contain the arrange, assert, act code for the specific test
I just refactored a unit test that had the same bunch of lines (that contained a bug) in like 2 dozen test methods and moved them to the SetUp method.
The benefits are obvious:
- need to fix the bug only once
- test methods are not cluttered with boilerplate but only contain the arrange, assert, act code for the specific test
Bugs in test suites raise "the" interesting question: are they bugs or undocumented features?
ReplyDeleteWhen they are caught before release, they're unambiguously bugs, but if they are caught months/years later, and do not lead to outright crashes or security issue, but just to unexpected behaviors... then fixing them can break stuff in the wild that relied on them.... ah, joy :)
Eric Grange Well in this case it was actually a memory leak within the unit tests environment where test instances were not properly freed which popped up after I recently enabled leak checking in our unit tests.
ReplyDeleteBut having to review quite a lot of them (in almost all cases it boiled down to not cleaning up things created during SetUp) reveals some horrid code that manifested over the years.
But my point still stands regardless: test code should also be clean.
Parameterized tests can help a lot with this too.
ReplyDeleteSimple : http://blog.8thlight.com/uncle-bob/2013/09/23/Test-first.html
ReplyDeleteJo Claes "test first" and "test as specs" is a path fraught with peril in practice.
ReplyDeleteWhile it can be fine for isolated functions or internal/technical layers, expressing specs as code makes the specs opaque, for two reasons:
- even if the test code "reads nice" to developers, it is still code, with particular grammars, syntax, conventions etc. the example given in the article is very telling, what he proudly calls "now that's a spec" is actually just gibberish Java code.
- it is code, and as such can have bugs, on the same magnitude of complexity as what it tests.
Finally a problem with tests as specs is that it if the tests are thorough, they will be beyond human readability, as in "there are millions of them!".
While tests can be part of a spec, and a spec can be part of the tests, both tests and specs are quite fundamentally different concepts.
Eric Grange I have to say I disagree to an extent. While xUnit style tests may be unreadable to a non programmer they are not the only way to write automated tests. BDD style tests tend to be far more readable, both the code and the generated output. Frameworks such as Fitnesse make it even more approachable by turning tests into tables of inputs and expected outputs that can be written by anyone with knowledge of the problem domain.
ReplyDeleteI've had a good deal of success with using the test first approach to drive the design of the production code. I find it tends to help me focus on the usability of the public interfaces of my classes and poorly designed code makes testing painful so I tend to notice things like tight coupling or violations of SOLID principles a lot sooner when I write tests first.
The "too many tests" argument doesn't really hold up. If a project was specified using a written document at the same level of detail it would be just as difficult to read. I've dealt with government specs that were far more difficult to read than the unit tests we derived from them.
I do agree that tests can never fully capture everything that a specification can. Things like usability and UI aesthetic don't lend themselves to automated testing.
Tests as specifications has a lot of potential. It see it like double entry accounting. For every scenario you write the production code (debits) and the tests (credits). While there is always the potential for errors on either side, it becomes far less likely. Only way an error can slip through the cracks is if you happened to make the same error on both sides of the ledger.