Writing software is writing

In his book Patterns of Software Richard Gabriel devotes a whole chapter (Writing Broadside) to writing about writing. Writing software is an act of writing so to get better at writing software he suggests it is a good idea to get better at writing in general. I was reminded of the chapter when I listened to Kevlin Henney's Skillsmatter podcast Rethinking unit testing in C++.

In his talk Kevlin discusses identifiers. Names. Names are funny things. When developers choose names they have a difficult task. They have to balance two forces that are very definitely competing against each other. On the one hand longer names give more room to express intention - to create intention revealing names. A declaration is a declaration of intent, an expression is an expression of intent, a statement is a statement of intent. But on the other hand the names of our classes, our functions and our objects also participate as sub expressions in larger and larger expressions. In the context of use the pull of brevity is very powerful.

Kevlin reminds us that some names are never intended to be used at all! They never participate in expressions that we write! Brevity should not be a concern for such names. In a language that supports reflection your test framework will call the test method for you. The only time you write the name of the test method is when you define it.

Developers typically have a lot less practice at writing names when they are freed from the shackles of brevity so it's not really surprising test method names often smell so bad. They smell bad because they are too concise! Loosen up! Give yourself some space. Instead of writing a test method called test_index think about the intention deep inside your head and try to express that as a whole sentence. That's a difficult practice to develop. If I'm pair programming and as the navigator I see the driver struggling with a test method name I sometimes ask them to "put the mouse down and step away from the keyboard". We discuss, face to face, what the intention is. Freed from the code-silo mentality of the keyboard we can usually move quite rapidly from test_index to test_indexing to test_out_of_range_indexing to test_out_of_range_indexing_throws_exception.

The last additional suffix ...throws_exception is an important one. A good test name should express an expectation. This is a transformational name change. It transforms the idea of testing so that it becomes not-testing. The name becomes a proposition. And the tests inches closer towards being an executable specification.

Another example of the context of test/proposition names having a different meta-context from regular code is naming style. Kevlin suggests that even in a language with a strong camelCase or PascalCase naming convention there is a strong argument for naming test methods with underscores_as_separators. You aren't calling these methods. They aren't participating in larger expressions. The only time they appear is in a diagnostic. Experiments have shown there is a small but definite cognitive delay in reading camelCase or PascalCase identifiers once they get beyond around 30 characters.