There appears to be a bit of a divide in the software community on what and how much you should verify in unit tests. Don't get me wrong unit tests are great and I don't think I've ever spoken to a competent developer who has disagreed with this statement. There is however a grey area as to how much to assert in each test.
So what are the options?
Test per Assert
This, at it's heart, is the restriction of what you are checking in the test. You setup (Arrange) the prerequisites for the test. These are the bare minimum you need to test the value you want. You execute (Act) on the System Under Test (SUT), and then you verify (Assert) the results.
As you can tell from that one paragraph I am a big fan of the AAA (Arrange, Act, Assert) approach to unit testing.
Using this style you are testing explicit values and can see tests failing early if something isn't quite right.
- Explicitly shows what is being tested
- Clean code as removes unrequired setup and assertion code
- Reduces the need to manipulate the result before verifying
- Can make code repetitive as testing very similar items. This can lead to duplicate code and violate the DRY principle.
Test per Function/Method
These are the types of test where you exercise the functional unit you want to test and put all the asserts into the same test. Typically you would have one 'Happy Path' test and a number of negative tests.
- Single test for the Happy Path of the functional area
- Can step through each line of asserts and check where it went wrong during debugging.
- Potentially not as much code as the "Test per Assert"
- One test can fail but it's not immediately obvious as to why it failed due to number of asserts
- You can end up verifying lots of the same values on none happy path tests
Above are what I would suggest be the extremes of unit test methodology. I have seen great benefits in combining the two approaches over the years but, like all development, you need to assess the current situtation.
What are the considerations?
So how do you know what type of unit test you should be writing? To make the right choice you will need to consider a number of factors.
Your development team, and even OSS project now a days, should have consistent Coding Standards everyone is aiming for. These can be either broad across everything or specific for different libraries, applications or framework packages.
It also depends on existing patterns which are already established as the code base needs to be consistent.
Another consideration is stablity and backwards compatiblity. Recently at work I have been extending an existing internal library that a lot of the company already are using. I have been working in a much more TDD style approach using the "Test per Assert" pattern. I did this as I wanted the tests to pass as I went. This decision was made to aid with keeping backwards compatibility and to flag issues early to make sure even the slightest changes did not break functionality.
Personally I think there is a time and a place (and this fits into the "depends" camp) as to when to use each approach but for me if you are asserting too much in a unit test then it's a potential indication that the service, or functional unit, you are trying to test is doing too much. This should lead to asking questions about the overall architecture or structure of the current functional area as it maybe violating the Single Responsibility Principle.
In this post we've reviewed the two extremes of unit test styles, how many asserts in each and reviewed the pros and cons. We've also looked at some of the considerations to take on board when deciding which approach to take.
One thing is a must though and that's to write unit tests!
Any questions/comments then please contact me on Twitter @WestDiscGolf