As software continues to dominate every facet of our lives, developers are faced with an ever-increasing pressure to produce bug free code. The responsibility of clean quality software falls upon everyone that is involved in the process of designing, creating, testing, and releasing an application. To have the highest confidence that users will love your application, each member of the team needs to be conscious of the need for a high-quality product. If each member of the team, not just QA, takes ownership for quality then bugs can be caught and fixed long before users ever use your application.
As a developer, unit tests are the primary mechanism to promote quality. Unit tests ensure that a piece of an application behaves as intended. Code coverage increasing means that more pieces are covered, ensuring application behavior on a wider scale. The minute you begin to talk about code coverage people begin to ask how much code coverage I should have in my application. Without spending an entire post on proper code coverage, a simple and dirty answer is 80% or more. A better answer is 100% functionality coverage, by focusing on functionality coverage it takes away from the semantics of individual lines and focuses on the behavior of the application.
I will primarily focus on unit testing in this blog but it is important to be aware that there are a few different types of tests. This is not an all-inclusive list and it is important that each type of test is used to get complete test coverage of a system:
1. Unit Tests
Unit Testing is used to ensure correct functionality for pieces of an application i.e. a method. Unit tests are run in isolation so they should not be calling any outside dependencies and that is done by utilizing mocking frameworks.
2. Integration Tests
Integration Testing is the testing of different pieces of an application and how they work together. In these types of tests, you would hit the external dependencies that are not hit by unit tests.
3. Regression/UI Tests
Regression testing is the execution of previously written tests to ensure that current code has not broken any existing functionality. Such tests are typically run when promoting code to a higher environment.
4. System/UI Tests
System testing is the execution of the software in its final configuration, including integration with other software and systems. It tests for security, performance, resource loss, timing problems, and other issues that can’t be tested at lower levels of integration. As with regression testing, automated tools such as selenium can be used for this process.
There are many reasons why unit tests are important, starting with:
1. Write Fewer Bugs
I’ve had discussions with developers who do not write tests and they say it’s because developers should check their work anyway and that there are QA that will catch any issues; therefore, the tests are not needed and are seen as additional effort and lines of code. A study by Glenford Myers in 1978 had a group of developers test a program with 15 defects. The average developer only found 5 of the bugs. In the study the main source of the errors that went unnoticed was erroneous output. Humans are error prone and this study makes that very obvious. Though the study may have been done 40 years ago there are still things that are unchanged in today’s development world. To mention a few first, software needs to function properly and bugs indicate it is not. Second, humans will always be flawed and as long as they are involved there will always be the chance bugs will be introduced. Finally having tests for written code can reduce the errors that humans introduce into applications.
It’s important to see that writing tests does not guarantee an application with no bugs. There is still plenty that can go wrong such as database problems, mistakes with functionality and so on, so there will always be a need for QA.
2. Decrease Manual Testing
The process of testing code after making changes can be very time consuming, and as we’ve established, is prone to human error. The book ‘Code Complete’ indicates that developer testing takes 8 to 25 percent of the total project time dependent on project size and complexity. That’s 16.5% on average, or around an hour per 8 hour working day. This means that developers will spend a lot of time testing the code they write, so any approach to streamline this process is worth serious consideration.
3. Get a Faster Feedback Loop
A feedback loop is the cycle of adding some code, getting feedback on the code and knowing whether it needs to be changed or if it’s ready to be released.
4. Increased Confidence when Changing Code
A frequent sign of low code coverage is when developers see areas of improvement in the code but shy away due to fear of breaking the system. Automated test coverage provides confidence to the team when changing pieces of an application, making developers more willing to touch the code. The net effect of this is a better code base for the entire team.
Tests by themselves do not improve software quality. The process of writing code that is testable, and the safety net of being able to refactor code and (almost) be sure that it does not result in a regression, is where the improvements occur, for more reading on this topic, see S.O.L.I.D: The First 5 Principles of Object Oriented Design
Unit testing has many frameworks to choose from and in my opinion, C# has 3 main frameworks to choose from; NUnit, XUnit, and MSTest. Which one you choose is completely up to you, but I prefer to use NUnit. It executes tests quickly, is easy to use, and simple to quickly increase unit test coverage.
Developers who write unit tests know that it increases the amount of work that needs to be done before marking that work as “done” but it is time that cannot be skipped to move on to the next piece of functionality.
I am advocating that you take the extra time and develop a strong unit test suite to increase the integrity of data, create a better user experience, and increase confidence when adding new functionality.