Leaders Logo

Strategies to Determine the Ideal Code Coverage Percentage in Web Applications

Importance of Code Coverage

Code coverage is an essential metric that allows developers to evaluate the quality of their automated tests. In web applications developed in C#, this metric helps identify which parts of the code are being tested and which are not, ensuring that the software functions as expected and minimizing the likelihood of bugs in production. However, it is important to maintain a balance: undercoverage can leave critical areas of the code untested, compromising reliability, while overcoverage can generate high costs without necessarily providing proportional benefits to the effort invested (ATLASSIAN, 2025).

When discussing code coverage, it is important to understand that this metric is not just a number, but represents the confidence that the development team can have in their code. High coverage can indicate that developers have done a good job implementing tests, but it is also crucial to consider the quality of those tests. As the code evolves, it is also essential that unit tests are updated. Outdated or faulty tests can be more harmful than the absence of tests, as they provide a false sense of security and can conceal real problems in the code (NORMANDO, 2025).

Defining Coverage Percentages

The ideal percentage of code coverage can vary depending on the type of application, team, and project context. However, many experts suggest that a coverage around 80% is a good starting point (ATLASSIAN, 2025). This percentage ensures that most of the code is tested while still allowing room for innovation and the addition of new features. It is important to emphasize that this range should not be viewed as a rigid goal, but rather as a guideline that can be adjusted according to the project's needs.

In critical projects, where failure can result in significant consequences, such as financial or health applications, it may be more appropriate to seek coverage of 90% or more. On the other hand, in experimental projects or prototypes, lower coverage may be acceptable, as long as the main workflows are tested. The key is to always evaluate the context and the specific needs of the project.

Below is a flowchart with steps to determine the coverage percentage:


+--------------------------------+
| Understand the Project Context |
+--------------------------------+
              |
              v
+--------------------------------+
| Define Quality Objectives      |
+--------------------------------+
              |
              v
+--------------------------------+
| Choose Measurement Tools       |
+--------------------------------+
              |
              v
+--------------------------------+
| Implement Tests Progressively  |
+--------------------------------+
              |
              v
+--------------------------------+
| Monitor and Reassess           |
+--------------------------------+

Process Steps to Define Coverage Percentages

  1. Understand the Project Context: Analyze the type of application, the risks involved, and the business priorities.
  2. Define Quality Objectives: Set clear goals for code coverage based on the project's needs and expectations.
  3. Choose Measurement Tools: Select coverage analysis tools that are compatible with your technology and workflow.
  4. Implement Tests Progressively: Start with critical flows and expand coverage to other areas of the code.
  5. Monitor and Reassess: Regularly track coverage percentages and adjust goals as the project evolves.

Choosing Measurement Tools

To measure code coverage in a C# application, it is common to use tools like dotCover or Coverlet. These tools allow generating detailed reports on which parts of the code were executed during tests, thereby identifying areas that may need more attention. Additionally, these tools can be integrated into your development environment, facilitating report generation whenever new tests are run.

Coverlet, for example, is a code coverage tool that works well with .NET Core and is easy to use. It can be quickly configured in an existing project and provides results in various formats, including JSON, XML, and HTML, making result analysis easier. On the other hand, dotCover is a JetBrains tool that integrates with Rider and Visual Studio, providing a rich interface and additional functionalities, such as the ability to view coverage directly in the IDE.

Practical Example of an Application with Unit Tests

Let's consider an example in C# using the XUnit library for tests. First, we will create a simple class that performs some mathematical operations. Below is the implementation of the Calculator class.

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public int Subtract(int a, int b)
    {
        return a - b;
    }

    public int Multiply(int a, int b)
    {
        return a * b;
    }

    public int Divide(int a, int b)
    {
        if (b == 0) throw new DivideByZeroException("Division by zero is not allowed.");
            return a / b;
    }
}
    

Now, let's create tests for this class using XUnit, to subsequently measure the coverage.

        
        using Xunit;

        public class CalculatorTests
        {
            private readonly Calculator _calculator;

            public CalculatorTests()
            {
                _calculator = new Calculator();
            }

            [Fact]
            public void Add_ShouldReturnCorrectSum()
            {
                var result = _calculator.Add(2, 3);
                Assert.Equal(5, result);
            }

            [Fact]
            public void Subtract_ShouldReturnCorrectDifference()
            {
                var result = _calculator.Subtract(5, 3);
                Assert.Equal(2, result);
            }

            [Fact]
            public void Multiply_ShouldReturnCorrectProduct()
            {
                var result = _calculator.Multiply(3, 4);
                Assert.Equal(12, result);
            }

            [Fact]
            public void Divide_ShouldReturnCorrectQuotient()
            {
                var result = _calculator.Divide(10, 2);
                Assert.Equal(5, result);
            }

            [Fact]
            public void Divide_ShouldThrowExceptionWhenDividingByZero()
            {
                Assert.Throws(() => _calculator.Divide(10, 0));
            }
        }
        
    

After running the tests, you can use Coverlet to generate a code coverage report that will show which methods were tested and which were not. This report is a valuable tool for identifying areas of code that need more attention and where new tests can be added.

Balancing Code Coverage

Although a coverage percentage of 80% is generally acceptable, it is important to remember that the quality of tests is more important than the quantity. Well-tested code should cover not only happy paths but also error scenarios and exceptions. Thus, it is essential to periodically review the tests and add new ones as the code evolves. Code coverage should not be seen merely as a metric to be achieved, but as part of a quality culture that should permeate the entire development team.

Moreover, it is essential to consider the complexity of the code when evaluating coverage. More complex code may require a higher coverage, not only in terms of percentages but also regarding the variety of scenarios tested. When reviewing tests, teams should ask themselves: "Are we testing all possible paths?" and "Are we covering all exceptions?".

Considerations on Code Maintenance

Code maintenance is a critical aspect of any software project. As the code is altered, new tests should be added, and old ones should be reviewed. A good practice is to integrate code coverage into the CI/CD pipeline, ensuring that new commits do not reduce overall coverage. This not only helps maintain code quality but also allows the entire team to have visibility into the health of the project.

Additionally, documenting tests and code coverage can be very helpful for the team. Keeping a record of the areas that have been tested and those that still need attention can assist in prioritizing future tests and identifying patterns of recurring problems.

Strategies to Increase Coverage

There are several strategies that can be employed to increase code coverage in a C# application:

  • Integration Tests: In addition to unit tests, implementing integration tests can help ensure that different parts of the system work correctly together. Integration tests are essential for validating interactions between modules and ensuring that the application as a whole is functioning as expected.
  • Behavior Tests: Use behavior tests to validate complete user flows, which can significantly increase code coverage. These tests help ensure that the end-user experience is consistent and that all functionalities are operating as they should.
  • Code Reviews: Conducting code reviews can help identify areas that lack tests. During reviews, the team can discuss which parts of the code are well covered and which are not, promoting a culture of shared responsibility for code quality.
  • Adopt TDD: Test-driven development (TDD) can be an effective approach to ensure that new functionalities are tested from the start. By writing tests before the code, developers are forced to think about use cases and error scenarios from the design phase.

Avoiding Common Pitfalls

When focusing on code coverage, it is easy to fall into some common pitfalls, such as:

  • Focusing Only on Quantity: Having 100% coverage does not guarantee that the code is well tested. It is vital that tests are meaningful and validate business logic comprehensively. Superficial tests that only check if the code executes are not sufficient.
  • Ignoring Error Case Tests: Not testing error scenarios can lead to failures in production. Developers must ensure that their solutions are prepared to handle invalid inputs and other exceptional conditions.
  • Leaving Code Coverage Aside: Code coverage should be an ongoing part of the development process, not a final check. Integrating it into daily discussions and development practices can help maintain code quality over time.

Conclusion

Determining the ideal percentage of code coverage in web applications is a task that involves careful consideration. A balance between quantity and quality, coupled with good development practices, can lead to more robust and reliable software. By integrating coverage tools into the workflow and continuously reviewing tests, teams can ensure that their applications meet user needs and are easy to maintain in the long run.

Finally, it is crucial to remember that code coverage is just one of several metrics that can be used to evaluate software quality. Other metrics, such as cyclomatic complexity, defect density, and customer satisfaction, should also be considered. By adopting a holistic approach to software quality, teams will be better equipped to deliver high-value products that meet user expectations.

References

  • ATLASSIAN. Code coverage. Available at: https://www.atlassian.com/es/continuous-delivery/software-testing/code-coverage. Accessed on: Jan 9, 2025.
  • NORMANDO, Celio. Unit tests. Medium. Available at: https://medium.com/@celionormando/testes-unitários-5bb55a9b4e83. Accessed on: January 9, 2025.
About the author