There's _a lot_ of useful advice in there. But what I wanted to mention specifically is this:
One of the things he's saying is that you can sometimes test against a simpler (let's say brute force) implementation that is easier to verify than what you want to test.
There's a deeper wisdom implied in there:
The usefulness of tests is dependent on the simplicity of their implementation relative to the simplicity of the implementation of what they are testing.
Or said more strongly, tests are only useful if they are simpler than what they test. No matter how many tests are written, in the end we need to reason about code. Something being a "test", doesn't necessarily imply anything useful by itself.
This is why I think a lot of programmers are wary of:
- Splitting up functions into pieces, which don't represent a useful interface, just so the tests are easier to write.
- Testing simple/trivial functions (helpers, small queries etc.) just for coverage. The tests are not any simpler than these functions.
- Dependency inversion and mocking, especially if they introduce abstractions just in order to write those tests.
I don't think of those things in absolute terms though, one can have reasons for each. The point is to not lose the plot.
https://www.youtube.com/watch?v=X4rxi9jStLo
There's _a lot_ of useful advice in there. But what I wanted to mention specifically is this:
One of the things he's saying is that you can sometimes test against a simpler (let's say brute force) implementation that is easier to verify than what you want to test.
There's a deeper wisdom implied in there:
The usefulness of tests is dependent on the simplicity of their implementation relative to the simplicity of the implementation of what they are testing.
Or said more strongly, tests are only useful if they are simpler than what they test. No matter how many tests are written, in the end we need to reason about code. Something being a "test", doesn't necessarily imply anything useful by itself.
This is why I think a lot of programmers are wary of:
- Splitting up functions into pieces, which don't represent a useful interface, just so the tests are easier to write.
- Testing simple/trivial functions (helpers, small queries etc.) just for coverage. The tests are not any simpler than these functions.
- Dependency inversion and mocking, especially if they introduce abstractions just in order to write those tests.
I don't think of those things in absolute terms though, one can have reasons for each. The point is to not lose the plot.