DEV Community

Cover image for Bad Test, Bad

Bad Test, Bad

bob.ts on July 30, 2019

These tests should never have been written. They provide no or little value. Testing code as been described as an "art form." It is, but it shou...
Collapse
 
afcjunior profile image
Adalberto Camacho Jr.

Very well written. I loved how you gave bad examples and proceeded to correct them.

And you raise some good points too. I found many testing patterns I learned from experience that I wish someone had told me about when I was just getting started with TDD. Especially the one about not giving too much thought to the DRY principle during tests.

Collapse
 
jamesthomson profile image
James Thomson

One of the hardest parts I found about TDD was knowing exactly what to test.

You start off thinking you must test every little bit of code, but this just creates major overhead and often quite brittle tests. I've come to the conclusion that it's better to think about it as input/output.

Only testing for what's coming in and what's going out. The internals of how we get that expected output aren't necessary to test. This has helped greatly when writing tests and hopefully is correct.

Other than that, TDD has really helped to encourage keeping functions simple and modular. When something becomes (or looks like it's becoming) difficult to test, it often means the function is becoming too verbose and should be split up into smaller more manageable/testable pieces.

Collapse
 
rfornal profile image
bob.ts

Very well stated!

Thread Thread
 
jamesthomson profile image
James Thomson

Thanks! That's reaffirming :)

Collapse
 
rfornal profile image
bob.ts

I was in the same boat and recently have been mentoring an organization on testing ... prompting this article. Thanks!

Collapse
 
peerreynders profile image
peerreynders • Edited

re: Bad Test Double
Actually your GOOD PATTERN is a potential anti-pattern in itself.

You've taken a fast, well isolated (decoupled) test and slowed it down and made more it difficult to set up and run - you've created an "integrated test" (not to be confused with an integration test).

Integrated Tests Are A Scam (2009)
Clearing Up the Integrated Tests Scam (2015)

The accepted solution to the conundrum you present is contract testing (2011!)

As ridiculous as it may initially sound a contract test shows that the service implementation behaves correctly in the way the client expects - i.e. it verifies that the test double's behaviour is in alignment with the actual service.

The idea is to maintain the isolation and speed of the original microtests in order to remain viable to be executed quickly and frequently.

Contract tests are run regularly but much less frequently as they require more resources and are more complicated. When the test double's implementation becomes stale the contract test will fail. It is at this point that the test double is updated to make the contract test pass - then the updated test double is deployed to the collection of microtests.

re: Promises

reject('fail');

MDN: Promise.reject()

For debugging purposes and selective error catching, it is useful to make reason an instanceof Error.

Collapse
 
dwwhalen profile image
Dennis Whalen

Good stuff Bob!

Collapse
 
eekayonline profile image
Edwin Klesman

Great set of examples! Love this read

Collapse
 
rfornal profile image
bob.ts

Thank you!