🚀 55% off The Software Essentialist sale - doors open in 2 days
A lot of devs get stuck in “best practices”.
Between things like SOLID, Clean Code, microservices, single-file components, and so on — there’s a lot you can do...
But in my experience, there’s only a small set of things that really matter at this stage when it comes to making the shift from coding to crafting.
There's only a few things that really move the needle in terms of writing scalable, testable code (on any side of the stack).
That's what the Best Practice-First Phase is all about: the real best practices.
We're doing a 55% off promo of The Software Essentialist from March 31st to April 4th to celebrate the launch of The Best Practice-First phase of craftship in the Early Adopter course.
Folks have been asking me to do one of these for a while, but I wanted to wait until this valuable module dropped.
Join the waitlist for bonuses and to get early bird access (1 to 5 hours before everyone else) when the sale goes live.
Only 200 spots available. Join the waitlist here 🔗.
PS: You can track updates on the course progress & the companion book (solidbook.io) here.
Stateful Tests
About this...
Stateful tests are tests against state machines. Ask: "are we testing a transition from one state to another?" or are we just testing "input/output".
🌱 This blog post hasn't fully bloomed. It's very likely to change over the next little while.
What is this?
- Stateful tests are obviously tests that rely on state
-
What makes these different than other tests?
- You have to set up the state of the world
- You usually have to test that the new state of the world is correct
- You usually have to test that the commands that changed the state of the world were, in fact called, and were called correctly.
State changes
- What are state changes?
- A successful command-like operation is a state-change.
-
Examples:
- A successful
save
, saving auser
aggregate to auserRepo
- A successful
makePurchase
call to aStripe API
- A successful
addRole
on auser
aggregate
- A successful
State machines
- Your application is fundamentally a state machine. We move people from A to B - problem to solution. If your app had 9 different states, from beginning to end, and you wanted to test the transition from state 6 to 7, you'd need to load up the state of the world from 1-6, in order to test that transition. Or at the very least, load up what the state of the world looked like at 6.
Questions
-
Why don't you test queries?
- Because queries don't change the state of the world.
- Yes, they might return different data which informs the behaviour, sending it down different code paths, but ultimately, there's no point in testing queries for stateful tests.
-
What's the role of queries in tests then?
- Queries merely return the current state of the world.
- And depending on that state of the world, our application (a state machine), has to act upon that data in different ways.
- This is what we care about.
- "Is my feature/use case behaving the way it should based on this state of the world? Do I get a failure result when I try to do something (ie: perform a transition from one state to the next) at an invalid state? Do I get a failure when I don't provide the appropriate data to perform the transition (the behaviour)?"
-
What's the difference between stateful and stateless tests?
- State, of course.
- That is, with stateless tests, we are testing functions or objects which typically live in total isolation. They have no stateful collaborators.
- Why? Because there is no state to them. Stateless because they themselves have no state. There is no state to them.
- We are often just testing purely behaviour.
-
Data, behaviour, namespaces
- Let us remember that the essence of software is solve problems. And that is achieved by gathering data, performing behaviour against that data, and organizing the units of data and behaviour into cohesive namespaces.
- Do you see how this is much different from a stateless test?
Join 15000+ value-creating Software Essentialists getting actionable advice on how to master what matters each week. 🖖