How long is too long (for unit test method names)?

As I ws working on some new development in our codebase this morning, I started updating some
unit tests to match. I was looking through the code for one of them and came across a test name that was easily 50 characters long and
it got me wondering – what was the popular opinion on naming conventions and commenting in unit tests. Obviously, there’s some things
(like annotations) that have to be in comments, but do you sacrifice clarity of a comment for a method name that you can basically read
like a novel?

I mentioned something on Twitter about it and here’s some of the responses I got:

——————————–

Rafael Dohms (rdohms)
@enygma @elazar @bdeshong taking into consideration PHPUnit and its use of method names (like testdox) i would focus more on name not doc
2 hours ago

weierophinney (weierophinney)
@enygma I don’t document my tests; the test name and test content *are* documentation. /cc @elazar @bdeshong
2 hours ago

weierophinney (weierophinney)
@enygma I do those all the time. For use with #PHPUnit’s testdox output. 🙂
2 hours ago

Ralph Schindler (ralphschindler)
@bdeshong @elazar @enygma if you are using PHPUnit, run the tests with –testdox, you’ll see the benefit of long test names 🙂
2 hours ago

Chris Cornutt (enygma)
@mwillbanks ah, good point…I can see how that’d be handy heh

Mike Willbanks (mwillbanks)
@enygma putting it in a docblock is nice, however, when running it on a CI server it is nice to see what broke by method name and test name
2 hours ago

Mike Willbanks (mwillbanks)
@enygma I think we have one that is almost 100 characters 🙂 here is 1 example: testEditActionRedirectWhenJournalEntryNotFound
2 hours ago

Brian DeShong (bdeshong)
@enygma @elazar 120 characters? 🙂
2 hours ago

Michael Maclean (mgdm)
@enygma around the 100 character mark? 🙂

2 hours ago

Chris Cornutt (enygma)
@elazar @bdeshong ah, but where should method names end and docblocks begin? 😉

Brian DeShong (bdeshong)
@enygma If the method name is long, but descriptive, then that’s good. Descriptive test method names are better than short ones.
2 hours ago

Matthew Turland (elazar)
@enygma Better to be verbose and accurately descriptive than overly concise and obscure? 😛
2 hours ago

jcarouth (jcarouth)
@enygma Hey, I’ll take that over testApp1() and testApp2() any day.
3 hours ago

Chris Cornutt (enygma)
well hello entirelyTooLongUnitTestMethodName, nice to meet you
3 hours ago

——————————–

That last one was my not-so-innocent comment that started the whole thing off. I’m still interested, though, in what developers
out there think is a good point to switch from documenting via the test functions name and moving it up to a docblock comment. Seems
like there’s arguments for both sides and I’m not sure if there’s a “winner”, but it’s always fun to get opinions.

What are your preferences in unit test naming versus commenting?

10 comments

  1. I have also thought about this problem, but overall I think that comments in unit testings are usually unnecessary if the tests are laid out well. Then the unit tests also serve as an in-use documentation of your code. Another developer could easily look at your tests to determine how and what a piece of code does. Long test names therefore become a requirement.

    As an added benefit, most unit testing frameworks will display the test name when said test fails, so a descriptive test name makes the failure more obvious.

    Last, as a practical thought, writing descriptive comments for unit tests can severely increase development time with arguably little benefit.

    Liked by 1 person

  2. I subscribe to the “use descriptive test method names” camp — heck, you quoted two of my tweet replies to you above. 🙂

    My rationale hinges on several points:

    * The test name helps describe the behavior I’m testing. This solves a few problems. First, I can be fairly certain that I have unique method names this way, without having to resort to non-semantic names like testSomeMethod1(), etc. Second, if a failure or error occurs while testing, I can easily cut and paste the name. Third, on same failure, I have an idea of what behavior is failing. During initial development, this is less useful, but later, when I apply a new feature or fix another bug, I can easily grok what I broke in the process.
    * PHPUnit offers “testdox” output. This takes the CamelCasedText of the method name, and spits it out as sentences. This can serve as a nice indication of capabilities that have been explicitly tested.
    * There are enough barriers to testing as it is: you have to understand how to create a test case, how to create test methods, potentially how to scaffold, and more. Why would I require adding docblocks to something that will never even be compiled into API docs? If the methods are well named and describe the behavior under test, what more documentation do I really need?

    Sure, this can lead to some tremendously long names on occasion, but the benefits are very much worth it, in my opinion.

    Like

  3. My view is that the need for a comment is a failure of my code to not be explicit enough (not clear enough in its intentions and/or naming). In other words, what about the code is unclear such that it requires a comment? Is it doing too much? Is it not granular enough? Why is it not clear from the name what the test does? These are the questions I ask myself when I find myself needing to add a comment to a unit test (or elsewhere, for that matter).

    I tend to adopt a BDD-ish approach for my unit tests (in that I regard them as specifying behavior rather than testing). With that approach, the name is the most important thing about the test. I think the name should be easily understandable to anyone reading it (because it is a specification for the behavior), so length can be an asset rather than a problem there. Of course, if the name is too long, then the test is probably trying to do do more than one thing, but that’s a problem with the test, not with the name. The goal is to have the test be an ‘executable specification’ for the unit (and hence the test names serve ares the’ documentation’ for the unit since they are a complete description of the unit’s behavior).

    PHPUnit’s testdox is a useful check. It’s helpful to just read the testdox output for a class and see if you can understand what the class does. And if the purpose of a particular test isn’t clear from reading its testdox output, then the test probably isn’t very well-focused and is probably just testing what’s there (or testing an implementation) rather than specifying behavior. Just my two cents. Thanks for starting an interesting discussion.

    Like

  4. Ups, again

    What the Fuck? So all the “code mus comment it self” people just go to someone doing the same style and try working through her/his codebase. And then tell me they not wanted to have some comments at one point.
    It’s not about us Pro-People reading this code. Leaving comments might be a nice hint for the inexperienced people reading it or the next generation! How many lines of code (for example cobol) got thrown away just for the reason of beeing undocumented? Respect the others that might not be as badass as you and me and knowing the latest trick on the latest fuction call. There are lots of examples of technical achievements in the history of mankind that are simply left undocumented, for example the pyramids, stonehenge etc. To build something that lasts means making it feasable for usage for a long time. We havent realised this, but what’s happening now is a very fragile revolution. Knowhow (and this is what code basically is) is very temporary now. We are doing things that could run forever (if nicely migrated to new boxes all five years) and we should behave so, the longlivety of our products depends on it. There is no gurantee that the person looking at the piece of code has knowledge or all the docs we have.

    Some stuff that comes up with tests.

    – The Name must be descriptive
    – The name, the function keyword and name should be readable in one shot. What does that mean?
    – You have the Obligation to leave a comment here and there

    Very simple. There is a really different level of literacy around the world and even among us programmers. I am a bad reader, easily distracted often doing more than one thing. So before I am at the last letter of myVeryLongFunctionNameJustBecauseIcanDoItandItsDoingLotOfThings I probably have tried it.

    And then there is this special setup you might have that might not apply to the poor guy sitting in a Web Cafe in a 3rd world country starring at this nice piece of self documenting code on a 12 inch greenscreen with some pixels dead, and he is required to read through: myVeryLongFunctionNameJustBecauseIcanDoItandItsDoingLotOfThings?

    I think now 😉 KISS guys 😉

    p.s. I have patented all the spelling errors 😉

    Like

  5. I tend to write unit test method names that run parallel to what it is testing:

    testSomeFunction might be the normal case for someFunction
    testSomeFunctionWithBadXCausesException saying that I am passing something bad and expect an exception
    testSomeFunctionForRegressionBug3456 saying that this test is for a specific bug report

    and so on . . .

    Like

  6. Thanks for the post Chris… Now to address some more things that would not fit into 140 characters 🙂

    PHPUnit does use some docblocks to handle certain conditions and more (see the annotations section): http://www.phpunit.de/manual/current/en/appendixes.annotations.html

    Creating actual docblocks for writing out the test may be nice in terms of creating PHPDoc but it may be a bit of extra overhead that will not add too much value since the structure of your tests should match the structure of your application. With this – it is easy to know what failed then by the method name you should have an extremely good idea of what had failed.

    From there, it is really the job of a CI server to take all of the different types of output and aggregate them for you. For instance we run the following:
    * PHPMD (Mess Detector)
    * PHPCPD (Copy Paste Detector)
    * PHP Depend (Quality of Design)
    * PHPUnit w/ Clover Output

    A bunch of other misc items as well. The test names are more or less descriptive of what broke where as I don’t need to look through 500 things to figure it out.

    Like

  7. I have not read the comments here very thoroughly, but here is an approach I tend to like:

    The tests are namespaced, the name is generalized and then given a sequence number to group related tests. For example:

    Mail.Transport.Send_001
    Mail.Transport.Send_002
    Mail.Transport.Receive_001

    ..and so on. Whenever I can, I incorporate symbolic names from specifications if any.

    The test code must documented in a clear and concise manner (important!), and I then use phpdoc, javadoc, SandCastle or whatever is at hand to generate test code documentation *before* I execute the tests.

    I then place my test harness on one monitor, and test code documentation on the other, and press play. If anything fails, I only need to glance at the documentation to know who’s ass I need to whip (usually my own).

    The reasons for doing this:
    * I am absolutely no fan of the “myVeryLongFunctionNameJustBecauseIcanDoItandItsDoingLotOfThings” — it’s hard to read, hard to remember, and the “form” is difficult to recognize by a glance
    * The short names with sequence numbers are surprisingly simple to learn and remember, much more so than long and very descriptive names
    * It looks neat and professional in a test report, or when correlated in a specification

    Just my two cents, there are lots of other good advices here!

    Like

  8. Just want to share of what I currently used to name my unit test methods.

    My formula/template for naming unit test method is “WHEN_[condition]_SHOULD_[behave]”. This formula suit my needs cause it’s describe the behavior of unit under test. I got these formula after watching Roy Osherove presentation video. This naming strategy can produce a very long but descriptive name. I don’t use the “test” prefix cause it’ll make my already long name longer. And, PHPUnit provide annotation substitute with “@test”. Here is an example of what’s on my unit testing.

    /** @test */
    function WHEN_checking_validity_of_attribute_that_have_invalid_value_SHOULD_return_false() { }

    I use underscore instead of camel case cause i feel it’s more easy to read and PHPUnit testdox can also substitute underscore with space just like it can spits out CamelCaseText into sentences. Some added bonus is, I can use CamelCaseText to describe something else like “WHEN_checking_validity_of_undefined_attribute_SHOULD_throw_RuntimeException” and testdox will write RuntimeException as is just like i need it ?.

    Previously, I prefix this formula with the actual tested method name like so “validate_WHEN_checking_on_undefined_attribute_SHOULD_throw_RuntimeException”. But i found that these isn’t practical as in early development stage I often found my self changing a method’s name for more descriptive name. And so, I have to change all the test method for it. It’s also makes me aware that what I’m testing is not the behavior of a method on the unit but the behavior of the unit as a whole. And by these, it makes me more alert when I violate SRP.

    I am not a native english speaker, so I apologize if this comment even makes you confused.

    Like

Leave a comment