Skip to content

Instantly share code, notes, and snippets.

@ojplg
Last active December 15, 2020 13:50
Show Gist options
  • Save ojplg/6d3de5a034a1c89726c124afb5f4b0e4 to your computer and use it in GitHub Desktop.
Save ojplg/6d3de5a034a1c89726c124afb5f4b0e4 to your computer and use it in GitHub Desktop.
testing thoughts

I think there are seven reasons why writing tests during software development is a good practice for me. Here they are. (There is some overlap in the reasons, and some might agree with all the points, but still find a different classification made better sense.)

  1. Correctness. Writing tests means that the code that I write is more correct. There are fewer errors, bugs, or unwanted behaviors. I think this is fairly universally accepted, so I will not belabor the point.
  2. Shortened feedback loop. Writing tests creates a much improved feedback loop compared to running an application and inspecting its outputs. Writing a test is almost like being in a REPL, except I am in an editor and so everything I do can easily be saved. (I know more advanced programmers know how to run REPLs within their editors. Wizards.) I think that Jane Street's Jenga/Emacs integration is particularly shiny and sweet in this regard.
  3. It's a free client. Suppose I'm writing a module to provide frobulation. It's likely that I have only one place that I'm working on that uses it. It can be difficult to decide what are the boundaries between the frobulator interface and the calling code. In practice, I find that once I get three or more clients, I will have a much cleaner, better interface design than when I started. When there is only one client, my tendency is to make the idiosyncrasies of the demands of that client over-influence the interface design. By adding tests, I get another client right away, to I'm up to two clients right off the bat. Not as good as three, but much better than one.
  4. Improves the usability of the code. In general I hold to the dictum: Hard to test means hard to use. Forcing myself to write tests means that I add helper methods, provide useful constructors, and think carefully about adding a dependency on a particular service or interface if that thing is hard to create. By writing tests, I ensure that I will be able to use my code in different contexts without too much trouble.
  5. Writing tests generally leads to a number of good design characteristics (these are perhaps just a bunch of ways of saying the same thing):
    • Isolation. In order to test a thing, I must be able to remove it from its surroundings.
    • Single purpose. I am less likely to complect the thing I am writing by adding multiple capabilities to it, since that will make my testing more difficult.
    • Promotes loose coupling. Very similar to the point about isolation. Each thing I want to test will need to have clear ways to join with other things that are not overly prescriptive.
    • Promotes programming to interfaces over implementation.
  6. Documentation. Tests are one of the best forms of documentation for the code. When I am reading a new piece of code, or doing a code review, I often start with the tests. It's a great way to not just see what the code actually does, but hints as to the author's intention of how it is to be used. If there are hidden tricks to using the code (something non-obvious has to be done to prime the system), it will be easy to see in the tests, since they will all do it. Moreover, I can immediately modify the tests to check out how changes in inputs change the outputs and whether those things conform to my mental model. When I am doing code review, I often start by making random modifications to the tests, just to see what happens
  7. Finally, and not least important, writing tests now proves I will be able to write tests later. When I am thinking clearly about some problem, even a difficult one, it can seem easy at that moment. But later, if I have to modify some behavior, or find some subtle bug, I would prefer to be able to work on that without first re-writing the code in question, which might introduce problems or bugs of its own. The best way to assure that I will be able to add the needed tests when bugs arise, or when I have to revisit something months or years later, is to write tests today.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment