←back to thread

Unit tests as documentation

(www.thecoder.cafe)
174 points thunderbong | 4 comments | | HN request time: 0.754s | source
Show context
bunderbunder ◴[] No.41874483[source]
I share this ideal, but also have to gripe that "descriptive test name" is where this falls apart, every single time.

Getting all your teammates to quit giving all their tests names like "testTheThing" is darn near impossible. It's socially painful to be the one constantly nagging people about names, but it really does take constant nagging to keep the quality high. As soon as the nagging stops, someone invariably starts cutting corners on the test names, and after that everyone who isn't a pedantic weenie about these things will start to follow suit.

Which is honestly the sensible, well-adjusted decision. I'm the pedantic weenie on my team, and even I have to agree that I'd rather my team have a frustrating test suite than frustrating social dynamics.

Personally - and this absolutely echoes the article's last point - I've been increasingly moving toward Donald Knuth's literate style of programming. It helps me organize my thoughts even better than TDD does, and it's earned me far more compliments about the readability of my code than a squeaky-clean test suite ever does. So much so that I'm beginning to hold hope that if you can build enough team mass around working that way it might even develop into a stable equilibrium point as people start to see how it really does make the job more enjoyable.

replies(20): >>41874655 #>>41874662 #>>41874705 #>>41875392 #>>41875790 #>>41875904 #>>41875926 #>>41876835 #>>41876977 #>>41877265 #>>41877415 #>>41877434 #>>41877459 #>>41877538 #>>41878062 #>>41878426 #>>41878897 #>>41879455 #>>41879817 #>>41880385 #
wubrr ◴[] No.41874705[source]
> It's socially painful to be the one constantly nagging people about names, but it really does take constant nagging to keep the quality high.

What do test names have to do with quality? If you want to use it as some sort of name/key, just have a comment/annotation/parameter that succinctly defines that, along with any other metadata you want to add in readable English. Many testing frameworks support this. There's exactly zero benefit toTryToFitTheTestDescriptionIntoItsName.

replies(7): >>41874814 #>>41874867 #>>41875382 #>>41876013 #>>41876871 #>>41876888 #>>41877002 #
serial_dev ◴[] No.41876888[source]
Some languages / test tools don’t enforce testNamesLikesThisThatLookStupidForTestDescriptions, and you can use proper strings, so you can just say meaningful requirements with a readable text, like “extracts task ID from legacy staging URLs”.

It looks, feels, and reads much better.

replies(2): >>41877015 #>>41881545 #
lbreakjai ◴[] No.41877015[source]
With jest (Amonsts others), you can nest the statements. I find it really useful to describe what the tests are doing:

    describe('The foo service', () => {

      describe('When called with an array of strings', () => {

        describe('And the bar API is down', () => {

          it('pushes the values to a DLQ' () => {
            // test here
          })

          it('logs the error somewhere' () => {
            // test here
          })

          it('Returns a proper error message`, () => {
            // test here
          })
        })
      })
    })

You could throw all those assertions into one test, but they’re probably cheap enough that performance won’t really take a hit. Even if there is a slight impact, I find the reduced cognitive load of not having to decipher the purpose of 'callbackSpyMock' to be a worthwhile trade-off.
replies(1): >>41877837 #
chriswarbo ◴[] No.41877837[source]
The `describe`/`it` nesting pattern is quite common (I currently use it in Jest and HSpec); but it doesn't solve the social problem. It's common to see tests like:

    describe("foo", () => {
      describe("called with true", () => {
        it("returns 1", () => {
          assert(foo(someComplicatedThing, true) === 1)
        })
      })
      describe("called with false", () => {
        it("returns 12", () => {
          assert(foo(someOtherIndecipherableThing, false) === 12)
        })
      })
    })
It's the same problem as comments that repeat what the code says, rather than what it means, why it's being done that way, etc. It's more annoying in tests, since useless comments can just be deleted, whilst changing those tests would require discovering better names (i.e. investigating what it means, why it's being done that way, etc.). The latter is especially annoying when a new change causes such tests to fail.

Tests with such names are essentially specifying the function's behaviour as "exactly what it did when first written", which is ignoring (a) that the code may have bugs and (b) that most codebases are in flux, as new features get added, things get refactored, etc. They elevate implementation details to the level of specification, which hinders progress and improvement.

replies(2): >>41878364 #>>41881597 #
1. yakshaving_jgt ◴[] No.41878364[source]
At the end of the day, someone has to shoulder the burden of holding their colleagues to higher standards. I don’t think there’s a technical solution to this social problem.
replies(2): >>41878925 #>>41879458 #
2. chiph ◴[] No.41878925[source]
This is part of the job of being a team lead or manager. You have a standard, you need to get people to follow it (or consequences..)
3. cle ◴[] No.41879458[source]
It could also be a symptom of something else, like I’ve seen this happen when someone goes overboard on unit tests and they become so burdensome that other engineers just want to get it out of the way. They may not consciously realize it, but subconsciously they know that it’s BS and so they don’t mind BS names to just move on with actual productive work.

Not saying it’s always the case, but it could be. Higher standards are not always better, they have diminishing returns.

replies(1): >>41881073 #
4. mewpmewp2 ◴[] No.41881073[source]
It's all a spectrum of trade-offs with different people having different opinions.

There could be some sort of formula to explain this better to determine how much effort to spend on tests vs features and product quality and importance of quality compared to that.