Test smarter, not harder (2020)
lukeplant.me.uk
lukeplant.me.uk
I'll take tests any day over the luck of getting an individual to pick up flaws in the code review.
It should read: "Don't code review for things that can be more effectively tested in other ways, and lean on other correctness methodologies as much as possible."
+1
In general, I've learned to listen to people who actually do something rather than people writing books and giving shows about that something.
Exceprt from "Music Poetry" written by Chick Corea
A big side effect of writing tests extensively is that the code is often more thoughtfully written and in smaller chunks. No one wants code that is hard to test or large enough that it requires extensive mocking and faking.
Gut feel is that the code quality could be better on more deeply tested code.
There are cases when testability shouldn't be a concern. If you're writing code iteratively or in an agile way, for instance. Nothing is worse than CI/CD rejecting your experimental PR for lack of unit test coverage.
Definitely. Ensuring that basic functionality works and that no awful regressions are introduced, using high-level tests (e2e, integration, based on realistic test data) is great. Such tests allow to refactor refactor with sufficient confidence.
Having hundreds of tests for trivial functions that might not even be relevant in day to day use for most customers which need to be rewritten or thrown away when refactoring - not so much.
> no awful regressions are introduced
What are those?
> with sufficient confidence
How much?
> Having hundreds of tests for trivial functions
If you can have _hundreds_ of tests for trivial functions, either the tests are redundant or the functions are not trivial. So which is it?
How do you communicate what you think you know to neophytes on the team other than very lossy generalizations?
I'd love to have some very clear rules and metrics as an answer, but I doubt that there are any.
"I spent a lot of time worrying about edge cases. That’s something I learned from Trenchard More and his array theory for APL. His contention was that if you took care fo the edge cases then the stuff in the middle usually took care of itself."
The real value lies in testing something you would have forgotten and saving your butt. So the question is . . . where is your butt hanging out? Can you define that in a way that translates convincingly into metrics for someone who doesn't know your code?
At this point, most of our tests are much higher level by default - setup 3 nodes, run the config management against it, check if the cluster formed. If the cluster formed, the setup from the config management can't be that wrong.
From there, we're adding tests in an outage/bug-driven way. If it doesn't deploy and load a config correctly into the application, that's a test to write. Or, we recently almost ran into an outage because some failure earlier on caused the config management to start tearing the cluster apart because of missing metadata. So we added a test that it cancels the rollout in such a case.
Those tests are valuable, because we can rely on these issues not cropping up again. Some test breaking on yaml formatting isn't as much.
By now, we mostly do a quick syntax check of the config and the rest is usually handled by smoke-testing the application. The config files are usually only parsed if they contain some non-trivial degree of dynamic computation.
I tend to use test harnesses. I write about my approach, here: https://littlegreenviper.com/miscellany/testing-harness-vs-u...
That said, my testing code generally dwarfs my implementation code; whether harness or unit. Part of the reason is that I spent 27 years at a company, where Quality was a religion, and it was very important, not to faceplant in public.
I learned to write very effective tests, very quickly. Most of my test harnesses are "full-fat" applications, that many people would want to ship. I'll often throw them together in a day or so. It helps me to practice for The Rilly Big Shoo.
I use almost every line of code I write, in shipping software, so it is a very practical approach.
>the time taken to write them.
>the time they add to the test suite on every run.
>the time to maintain them - understand them, debug them, change them when other things change.
To me these are not unit tests in the first place. A unit test is by definition (at least the venerated M. Feathers one):
simple
fast
used either to help understand code behaviour or flag when this changes.
If you're complaining about unit tests and your unit tests arent unit tests in the first place, then no wonder you won't like TDD as a design approach.