Should I spend time prettifying unit tests?
If prettifying means to make the unit test more consistent and easier to understand then yes.
As I have not written a book or interviewed many people I can only pass along my personal experience in this matter. Recently I spent a week on an F# project making a several hundred unit test consistent, easier to read and more comprehensive. In the process I learned a few things and developed a philosophy.
- In making the unit test consistent, I began to see test cases that needed to be added to make the test for a function comprehensive. Because the unit test were consistent it was easy to spot the cases that needed to be added. Basically I tried to move the parameters and result for a function into an array element with all of the test cases for a function in one array one after the next. It made seeing the patterns of this input causes this output easy because you only had to look at the input and output, not all of the overhead needed for a test case. Then the mechanics of the test case followed pulling out the parameters and result and passing them through the test function.
For example:
let private butLastValues : (int list * int list)[] = [|
(
// idx 0
// lib.butLast.01
// System.Exception - butlast
[],
[] // Dummy value used as place holder
);
(
// idx 1
// lib.butLast.02
[1],
[]
);
(
// idx 2
// lib.butLast.03
[1; 2],
[1]
);
(
// idx 3
// lib.butLast.04
[1; 2; 3],
[1; 2]
);
|]
[<TestCase(0, TestName = "lib.butLast.01", ExpectedException=typeof<System.Exception>, ExpectedMessage="butlast")>]
[<TestCase(1, TestName = "lib.butLast.02")>]
[<TestCase(2, TestName = "lib.butLast.03")>]
[<TestCase(3, TestName = "lib.butLast.04")>]
[<Test>]
let ``List butlast`` idx =
let (list, _) = butLastValues.[idx]
let (_, result) = butLastValues.[idx]
butlast list
|> should equal result
In making the unit test easier to read it became obvious that they were good enough to use for learning because the comprehensiveness of the unit test for a function became better than some of the documentation; it was real working examples that not only demonstrated a case but also showed what the result would be, be it a valid result, exception, or failure to complete.
Since our project was a translation of OCaml code from "Handbook of Practical Logic and Automated Reasoning" by John Harrison, we created both a direct translation version and an optimized version. Having made the test comprehensive it was easier to additionally test the optimized code and the normal code using the same test case.
So by spending time working with the unit test by hand and in detail, I learned more about how the code worked than just by reading the code. I began to see patterns in the test data that I would not be seen in the code and leveraged that to learn more about how the code worked.
If you view unit test as something that should be created and then left in a box only to be used by automated tools then I think you are missing something significant.