Why *do* I love tiny tests?

I’m told that granularity is good, up to a point. But we don’t want to go too far. When I do go too far, I’ve been told more times than I can count that I’m being rigid or pedantic or mindlessly following rules. I don’t think that’s true, but I don’t have enough experience to defend my preferences well.

So, I thought I’d ask *you*.

I want to (remain open to learning new ways, and also) get better at explaining why I like:

  • Test names that describe a small characteristic of our system (typically called behavior). Like “a new account has a balance of zero” or “opens new accounts with a balance of zero”.
  • Asserts that match the name of the test.

I think that the tinier the test, the more likely we are to quickly know what went wrong when it breaks. I also think that tests that describe real behavior or characteristics:

  • are less likely to be stoopid tests—that is, not test for something we don’t want, like the ones I’ve seen that assert that for every new person, their name is Brian, and
  • are useful in letting us know what we have done and what we haven’t, and
  • help us find what broke, when they fail

What do you say? Should tests combine several asserts? Do we really need single-assert (single behavior, single characteristic) tests? And, are names important? How do we name tests?

GeePaw sez…

One of the reasons for me coining the term “microtest” was precisely to aim at the notion of very tiny tests.

I do occasionally have a test that contains a single behavior but multiple assertions. “One behavior” really means “One path through one function”, not “one variable changed”. I sometimes argue that we should add these two more assertions to test the two more changes made by a single path through the function. It’s not “one test per line of code”, it’s “one test per path”. Anyway, the argument is not very significant, and I yield quite easily.

Most TDD beginners envision and enact tests that test far too much in one test. If we’re to err in the size of our microtests, the error of making them too small is far less dangerous than the error of making them too big. If you can see how to write a smaller microtest, go ahead and do it.

10 thoughts on “Why *do* I love tiny tests?

  1. Angela Post author

    I am totally convinced. I write the smallest tests I can think of.

    What stumps me is what to tell my pair when they say it’s silly, unnecessary, excessive, etc.

    Reply
  2. Evan Cofsky

    What you call “microtests” I call “tests”. And if you’re not writing “tests”, you’re probably hoping that large parts of code just “work” because there are no obvious flaws. But I think if you really do write the tests along side the code you’re testing, and not one separate from the other, you end up with a certain design which is hard to really engineer up front.

    Reply
  3. Rob Conaway

    In this phase of my developer life, I focus on the design. Tests that improve the code are good; I tend to forget the ones that don’t. When I worry too much about regression, I seem to spend a lot of time worrying about the rules of TDD and don’t do as good at letting the tests drive the design.

    Now, this may be an overcompensation for my inate perfectionism. In the next phase of my developer life, the pendulum may swing back toward better regression.

    Of course, hypothetically speaking, if we were pairing on a simple introductory problem, I’d also be focused on helping you come up to speed on the environment and the project and probably make some pragmatic decisions favoring expediency.

    Reply
    1. Angela Post author

      Yeah, hypothetically ^__^

      But, also hypothetically, it’s so much easier for me to think when I’m taking tiny steps. I get a lovely flow. I mean, I’m not the sharpest egg in the carton, you know?

      Reply
  4. rdm

    Perhaps, if your partner is saying you are being silly, it is worth doing some discovery on the issue: What problem he trying to avoid? (And I do think that this sounds like a male partner.)

    If the only thing he is trying to avoid is lost time — that would be time lost testing, and that gets into the whole quality issue that testing is aimed at in the first place. As a general rule, testing saves time, and hopefully your partner agrees that this is the case?

    If he has some other thing he is trying to avoid — for example, if he is trying to avoid losing site of the goal in the noise — it might be that his thought processes are structured differently from yours, that he might be feeling lost and needs something to help hold onto the core concepts?

    Or it could be an entirely different set of issues. So I would be tempted to say “Why do you say that?” and “What problem are you trying to solve?” and “How would decreasing test modularity solve that problem?”

    And then… I am not sure that pedantry must always be a bad thing. When dealing with computers its so very often the only game in town that gets the computer behaving properly. And if pedantry is a virtue, and engaging in pedantry is silly, then silliness might sometimes be a virtue also. If this were actually the case, perhaps the best approach would be a soft laugh and a warm “thank you”. Or, if the tension is too high for that, perhaps its time to take a break, stretch your neck muscles and just relax for a couple minutes?

    Reply
    1. Angela Post author

      So I would be tempted to say “Why do you say that?” and “What problem are you trying to solve?” and “How would decreasing test modularity solve that problem?”

      I find this approach intriguing. I wonder what’d happen if I ask “what would the problems that might stem from writing my tiny tests instead?”

      Reply
  5. David Adsit

    I recently posted about mocks in testing on my blog and I was about to post a follow up about why I prefer small, simple tests and think that large tests are worse than useless, but since I see Angela has already started that conversation, I will just add my comments here:

    Small tests help guide your hands as you take small steps in crafting the software.
    Small tests help you find problems quickly and precisely.
    Small tests (with descriptive names) reveal the intent of the author.
    Large tests can tell you that a problem exists, but may not show you where or what or why.
    Large tests are often harder to read and understand than the code under test.
    Large tests are often easier to ignore than fix when something goes wrong and they fail.
    Large tests tend toward short names (Test_MyObject_ctor) that don’t express intent.

    If you care about crafting quality software with good regression tests, small tests are the way to go.
    If you care about achieving an artificial code coverage metric, large tests are your friend. In fact, take that to the limit and do want a co-worker did: write 1 test that instantiates every class and calls every method on each class. 0 -> 100% coverage in 1 day!

    Reply

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>