Stateless Functions for Unit tests
Writing stateless tests in Cypress
Tests should not sequencally depend on each other, use beforeEach
instead.
- Unit tests have one assert per test.
- Avoid if-statements in a unit test.
- Unit tests only “new()” the unit under test.
- Unit tests do not contain hard-coded values unless they have a specific meaning.
- Unit tests are stateless.
I believe this is a practice called writing stateless code - and the benefits start from: easier readability, less bugs, easier to write test (as this example).
In general I see a pattern that makes it hard to test this:
you are used to making functions that heavily use this
. What you do is:
class WorkerClass {
public function abc(){
// do calculate accessing $this->something
return "some value, depending on internal state"
}
...
}
These functions are a pain to test, as each time you have to consturct new WorkerClass
that has all kinds of extra steps, like mocking everything that the constructor uses with dependency injection.
Converting a mindset into a more "utility" based coding style would look something like this:
class WorkerClass {
function iUseAbc(){
$price = WorkerClass.abc(this->paramAbcNeeds, ...) // <- deterministic export
}
// STATIC!
public static function abc( paramsINeedForACorrectResult:int, ... ){
// only use the parameters provided in the function statement
return "some value INDEPENDENT of this"
}
...
}
This is using the STATIC field of a Class, but exporting these into plain utility functions can totally work too.
Clean, stateless functions using only parameters they need is the way to make meaningful unit-tests possible.
It's quite a mind shift though, but once you bought into it, the code quality/readability increases significantly.
tech stateless unit test coding paradigm