← Back to context

Comment by lbreakjai

3 hours ago

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.

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.