Unit Testing Anti-Pattern: Prefixing Test names With “test”

This series goes through anti-patterns when writing tests. Yes, there are and will be many. 
TDD without refactoringLogic in testsMisleading testsNot asserting
Code matchingData transformationAsserting on not nullPrefixing test names with "test"

History teaches us that old habits are hard to break. Much like the proverbial monkeys who haven’t been there for the first electric shock, but still wouldn’t get near the banana, the habits are even harder to break because “that’s what we do here, we can’t explain why”.

People are still writing tests that contain “test” in the name, and you know why? Because that’s how they do it here. And it makes sense, right? It’s a test!

Which begs the question: we know it’s a test, but how does a test framework know it’s a test? What makes a test different than any other method?

The olden days

In Java, when JUnit started to take shape, and later in .net and other reflection supporting languages, before annotations were supported yet, the test framework needed to identify a test in some way, and until JUnit 3, that way was to start the test method with “test”. Convention over configuration. Beautiful.

Since JUnit 4 that took advantage of Java annotations (@Test), the requirement for a test to start with “test” was no longer needed. In NUnit, and other .net framework, attributes played that part.

In other languages that didn’t identify tests using reflection, things got more interesting.

Identifying the tests using reflection, saved the need for test registration. If you look at many C/C++ older frameworks, you’ll see the registration part, for example in CppUnit:

We manually need to register each test in the test suite.

There was no way the framework could diffrentiate between a test and another function automatically. In more modern frameworks, the registration takes place by macro implementation for you, so there’s no need to go find tests, and tag them properly.

By the way, another advantage of prefixing the test with “test”, helped with collecting and identifying the tests for registration. That’s not needed anymore either, due to the automatic registration done by macros.

To summarize, with modern frameworks there is no need for the identification of tests by prefixing them.

Furthermore, if locating tests is your issue, modern project conventions help with that more than a name can. Maven projects, for exmple, tell you where to place and find the tests. The project file architecture has much more to do with identifying and running test than anything else.

And so ends our history lesson, and you probably want to ask, again: Then why don’t people stop doing that?

Apart from the “that’s what we do here” part, I mean. They don’t have a good explanation.

Still there’s a good explanation to why you should drop the “test” prefix.

Visual noise

Code is complex enough already. Adding more code simply distracts us from understanding it. It’s true with big classes and methods, and it is also true with tests.

I always encourage to write descriptive test names (and with regular methods too). That means they get long names. Which is ok if they contain the information for better description of what the test checks, and at what context.

Obviously, having the word “test” doesn’t help me understand it better. It’s just noise, a distraction from the important bits.

This is just low noise. Annoying, but bearable.

But when you look at a CI report, and everything starts with “test”, it’s no longer low volume. It takes up a very big portion of the screen and information. Again, Everything on the test part of the CI report is obviously tests. The noise was amplified and distracts us further from identifying sibling tests and their results, looking for specific tests, etc.

In a nutshell: Prefixing tests with “test” doesn’t help anyone (unless maybe dealing with legacy test frameworks), and can even cause delays when looking to solve problems with failed tests.

Just don’t do it.

Leave a Reply

Your email address will not be published. Required fields are marked *