A Given is the context in which a feature is used
When we write code, we want to know that it works. As developer, I want to know how to tell this before I even start coding, so that I can do as little work as possible.
This isn’t laziness – it’s simplicity! It just happens that it also lets me head for the pub sooner (“Beer Driven Development”).
In order to know whether my code is working or not, I’ll run the same kind of manual tests as the QAs will. I’ll also try to automate these.
I start by thinking about how I’m going to use the feature I’m checking, and the outcomes that I’m expecting. That then leads me to think about the things I need to do first, before I can use my feature.
For instance, I think about successfully paying a bill through my online banking system. That reminds me that I need to have sufficient credit with the bank, either a positive balance or perhaps an overdraft facility.
We can use the application to set up a Given
I could pretend to be an admin at the bank, and use the application to create a new account. I could then deposit some money in the account. That would allow me to try and pay a bill and check that the bill payment code worked.
We can set up the state directly
Let’s suppose that all bank account and balance details are stored in a database. I could set up the data in the database to make it look like an admin had created an account. That’s OK, because it’s not the account creation functionality we’re worried about – we probably have another scenario that covers that.
We can use existing data
Let’s say that we’ve copied a production database, or that we have some test data with which all environments are initialised. Maybe I have an account for a “Mr. Test”, with £2000 in.
I could use this account for my scenario!
But what happens if someone changes the data? Suppose that someone else writes a scenario that withdraws all the money, and it runs before mine? The first I will know about it is when my outcome – that I paid a bill successfully – fails.
So, it’s useful for me to check that the state I need really does exist, either by checking the contents of the database, or by using the application to log in as Mr. Test and verify that my balance is sufficient. Either way, my Given contains assertions, just like my Then. It will fail if it can’t find the right data. This will help me differentiate between the wrong setup, and a genuine bug.
We could use state if it does exist, and create it if it doesn’t
If I wanted to, I could look to see if Mr. Test’s account existed, and if he had enough money, then create his account or add more money if he didn’t. This might be useful if, say, setting up an account was very expensive, but checking its existence and balance wasn’t. In that case, we’d have an assertion which performed the setup if it failed.
I’ve never had reason to do this. Let me know if you do!