For the last 6 months I’ve been thinking and reading a lot about how best to write automated tests for applications - including data generation, structure, naming, etc. This blog series is a foray into my current thinking (which will probably change over time; for instance I’m looking back at tests I wrote 6 months ago that I thought were awesome and now thinking that I hate them :P). I’m inviting you to join me on this journey by publishing this series and I encourage thoughtful comments to provoke further thinking and discussion.
- Test Naming
- General Test Structure
- Acceptance Tests Structure
- Making Intent Clear
- Derived Values
- Anonymous Variables
- Equivalence Classes and Constrained Non-Determinism
- Unit Testing
- What should a unit be / what level should we be testing at?
- What role should mocking have in unit testing?
- UI Testing
- What should be your goal with UI Testing?
- What are the best practices for keeping UI tests robust?
I have always been a fan of the Arrange Act Assert structure within a test and started by naming my test classes like
<ThingBeingTested>Should with each test method named like
A_statement_indicating_what_the_thing_being_tested_should_do. You can see examples of this type of approach in some of my older repositories such as TestStack.FluentMVCTesting.
More recently I’ve started naming my tests with a Given, When, Then description (be it an acceptance test or a unit test). I like the Given, When, Then method naming because:
- Generally the Given will map directly to the Arrange, The When will map directly to the Act and the Then will map directly to the Assert - this provides a way of quickly cross checking that a test does what the name suggests it should by comparing the name to the implementation
- I find this really useful when reviewing pull requests to quickly understand that the author of a test didn’t make a mistake and structured their test correctly
- e.g. it’s probably wrong if there is a Given in the name, but no clear Arrange section
- It requires that you put more thought into the test name, which forces you to start by thinking about what scenario you are trying to test rather than “phoning in” an arbitrary test name and diving into the implementation and focussing on how you are testing it
- My gut feel along with anecdotal evidence from the last few projects I’ve worked on - with developers of varying skill levels - suggests this leads to better written, more understandable tests
- Side note: I really like the idea discussed by Grzegorz Gałęzowski in his TDD e-book about the order in which you should write a TDD test (from the section “Start From The End”) - he suggests you start with the Then section and then work backwards from there
- I can’t honestly say I usually do this though, but rather just that it sounds like a good idea; generally I know exactly what I want to write when writing a test (yes, it’s possible I’m just naive and/or arrogant ;))
To clarify, I still use Arrange, Act, Assert in my tests. I could write a whole blog post on how I structure the AAA sections in my tests, but luckily I don’t have to because Mark Seemann has already written a really good post that mimics my thoughts exactly.