Unit Testing - Understanding the Automation Testing Pyramid
The Automation Testing Pyramid is something we use to describe the most effective and efficient way for just about any business wanting to use Test Automation for quality assurance. You can read more about the Pyramid and why we use it here.
What is Unit Testing?
If you Google ‘Unit Testing’ you’ll find a hundred different definitions, but I like the one coined by the Microsoft Developer Network best: Unit Testing is about taking the smallest piece of testable software in application, isolating it from the code base and external services, and determining if it works like you expect it to. That way you can determine with certainty if that particular piece of code or microcode works correctly.
What are the biggest benefits of Unit Testing?
- Unit Testing is done early on in the Software Development Life Cycle (SDLC). If we were to consider a defect being discovered by a Unit Test versus a defect discovered by a Tester at the UI layer there is a cost saving. For a defect found by the tester to be resolved it must be developed, deployed, tested, analysed, redeveloped, redeployed and re-tested. This all costs time and money. If it were picked up at a Unit Testing level it would not even be deployed.
- Unit Tests are run very quickly. At one client we have more than 8,000 tests that run in 29 seconds, for example. This means we know a lot about the application – and can give confidence on its high-risk areas – in less than half a minute. As a developer this is useful because you know exactly where an error occurs, since you’re testing a unit that is one of the smallest pieces of testable software and there are very few places for problems to hide. A developer therefore knows where the failure occurs, the conditions of the failure, and jump in to resolve the issue as fast as possible.
- Unit Tests highlight code quality. Unit Tests show whether a Unit of code works in various scenarios. This also encourages developers to think about what could potentially go wrong in each given piece of code and therefore create code of a higher standard. Code quality can also be improved by bringing in external testers, having a fresh set of eyes on a piece of code, that do not feel attached to the original solution, can also highlight bad code practices in your project.
- Unit Tests reduce costs. UI Testing is expensive and time consuming. Unit Testing stops critical issues from getting to the point where they are only uncovered through UI Testing, thereby reducing the number of UI Tests required to sign off on a deployment.
- Unit Tests fit into a DevOps approach. Because Unit Tests are so quick and efficient it means that they can be used in a DevOps pipeline without impacting on the Deployment time. Having Tests kickoff when a Developer commits code demonstrates the health of your application quickly, and with less admin then setting up a testing cycle.
How to do Unit Testing
- Choose your framework. There are a number of different Unit Testing frameworks available. Every language has a few Unit Testing frameworks, so it’s a case of choosing the framework that works for your style or is already used in house.
- Use Mocking Libraries. I mentioned previously that Unit Tests isolate a piece of code from its environment. We don’t want to test the code in its natural environment because then it could be affected by the rest of the code base or external sources. To isolate a unit of code use a concept called mocking that allows us to set a context for the testing. For example, if the Unit Test is testing a function that implements a bunch of interfaces or a function that calls a database, we can ‘mock out’ those dependencies to use a pre-set piece of information, and tell the test to use those interfaces/functions rather than what it would normally use. That way we have full control of all the variables.
- Test one thing at a time. Unit Tests should test for single variables, so we typically end up with thousands of Unit Tests to cover an application. You might have a relatively small code base but an exponentially greater number of tests because there are multiple potential outcomes for each function and you have many functions to test.
- Write testable code. Unit Testing requires code that can be tested, which can highlight poor code quality, but also forces your Developers to work to a better standard. If a piece of code is not deemed ‘testable’ it should be seen as an opportunity to improve the quality of the product, and not a failure in Development – Testing is part of Development.
When do you need Unit Testing?
- Unit Testing is not something you implicitly expect. Many clients either assume that Unit Testing is being done, or actively prevent their Developers from writing Unit Tests in favour of developing new items. If you run or own a project you should start asking questions about the level and quality of Unit Testing currently being done.
- Your developers don’t have time. Companies often feel they’d like to do Unit Testing but that their developers don’t have time because the business prioritises the development of new items over testing existing ones. This is where partnering with a company that can implement Unit Testing and leaving developers to develop makes sense.
- It’s not a silver bullet. Unit Tests protect you from certain risks to different parts of an application. You have the UI, which is always a risk because that’s what your clients are using. You have the data, which is always a risk because it changes everything about how your code works. And then you have the operational logic of your code. Unit Testing won’t guarantee you won’t have issues with your UI, and won’t protect you from bad data being in your application. But, if you have Unit Testing in place, you can say with a high degree of certainty that your business logic is going to work.
Unit Testing is critical, it should be part of every project. There are parts of the application that are more complex or aren’t covered by the strengths of Unit Testing, and that’s when we move up the Automation Testing Pyramid to API or Integration Testing and UI Testing.