If you read my previous post What have I been doing? you know I have been busy working on a team building an Online Banking application. I have done unit testing in the past but this was the first time where it was done on a large (for me) project. When we started we had a few goals in regards to unit testing.
- Write unit tests in C# to cover business logic for our API
- Write unit tests for our AngularJs application
Why it is important
Unit testing is extremely important in any application of significant scale. I can not stress this enough as unit testing helps identify potential problems early on and forces you to think how your application is structured. If your class/method is difficult to test chances are you need to reevaluate your implementation.
With any application bugs are going to exist from either coding defects or undefined results from your business rule given a unexpected data. I can not tell you how mentally satisfying it is for me to write up a failing test after a bug report.
- We receive a bug report
- We recreate the bug with a failed unit test
- We fix the bug which makes my failed unit test pass
- We now know with some reasonable assurance that the bug is now fixed
Changing business rules
We all know that even with the best requirements and specifications changes occur to business rules. Month one we are told do not allow that person to register and then on month ten we are told that person can now register.
- Method has adequate code coverage via unit testing
- Business rule changes
- We write failing unit test for the new business rule
- We make our alterations until the new rule passes
- We run our existing tests to verify that our old rules still pass
This allows us to have some assurance that our new change to the business rule did not inadvertently break existing rules.
With any type of unit testing you are going to use some sort of test runner to run your unit tests. Knowing your toolset greatly increases your chances of succeeding in creating valid unit tests for your project. If your tests are difficult to run or the results are not known they most likely will be forgotten and broken.
The tool we used or our C# code was NCrunch. NCrunch changed the way we viewed unit testing. We had it configured to constantly monitor all of our MSTests and run them in parallel giving us immediate results for any possible failures. NCover also places small dots on each line of code that is covered by our unit tests. This visual feedback and instantaneous results for passing and failing unit tests allowed us to reach our goal of incorporating C# unit testing from the start of the project.
Learn when to use Mocks, Stubs, and Fakes
You need to learn what is the difference is between Mocks, Stubs, and Fakes when writing your tests. Creating a mock to test a method where a fake is appropriate can help reduce the complexity of your code and make your tests easier to maintain. Another thing we learned is that just because you can use a framework like Moq does not mean you always should. We had experiences where we used moq which resulted in a few lines of setup and configuration in each test that could have been simplified with a Stub.
Your tests are important and need maintained
Early on when creating our tests we suffered for a lot of code duplication where we would copy and paste similar arrangements and build ups for our tests. For some reason we would tend to let this practice slide. We would think, "These are just tests! They are not production code! They don't have to be maintained" We were wrong! Do not get lazy when it comes to writing your tests as they need to be maintained almost as much as your production code base. Write helper methods, base classes, custom asserts, and reducing code duplication allows your test to be easier to understand and when changes come in (and they will) you do not spend 10 minutes making a change and 2 hours cleaning up your tests.
Do it from the start
I can say I learned quite a lot about unit testing in our project. I hope you will be were able to learn from some of my experiences so unit testing succeeds in your project.