Scaling Code Coverage

I’m going to do one more (I think) post on this subject. Markus asked the following about my latest post:

But how do I answer the question for “what’s the coverage of your testing?” for a multiple component-based application, consisting of a C/C++ major component, an application server, and customized business logic?

The answer is sort of in this post, but it’s worth elaboration.

First and foremost, if someone asks “what’s the coverage of your testing”, you can answer in multiple ways. You can say “we’ve tested the requirements”, or “we have an average of 70% line coverage throughout the product”, or “we’ve covered all of the key customer scenarios”. But what you probablyshould ask is, “What do you really want to know?” Explain that “testing coverage” probably isn’t the best way to think about it, and “identifying missing tests” is a better train of thought.

The sample I used was a simple command line app, but we usually test much larger systems, so let me also explain how you could scale code coverage from my previous example to a larger application. The solution I prefer isn’t complex – you just start at a high level, then drill down until you get to something actionable. Let’s say my overall product code coverage is 60%. That tells me that 40% of my code is untested. For the sake of easy math, let’s say the application has a million lines of code. That’s 400,000 untested lines of code. Which ones do we look at first?

Let’s drill down into the four main feature areas of the (fictitious) app.

Feature Area Priority Lines of Code Code Coverage
UI Controls 3 100,000 60%
Engine 1 400,000 60%
Web Server 2 400,000 70%
Utilities 4 100,000 50%

OK – I notice that the Utilities only have 50% code coverage, but it’s the lowest priority, so I won’t start there. Instead, I’m going to look for testing holes in our pri 1 area (Engine). Let’s dig in again.

Engine Drill Down Lines of Code Code Coverage
Core 200000 60%
File Access 75000 75%
Protocols 50000 53%
Filters 75000 56%

Protocols are the worst (although we’ll definitely need to look at Filters as well at some point). Digging in further tells us …

Protocols Drill Down Lines of Code Code Coverage
XML Transform 20000 80%
Format Codes 10000 55%
Models 20000 40%

Looking like I’m missing test cases for Models…

Models Drill Down Lines of Code Code Coverage
File1.cpp 1000 5%
File2.cpp 1000 70%
File3.cpp 2000 70%
File4.cpp 500 60%
File5.cpp 500 60%

oh wow – I’ve barely tested the functionality in one of the files (File1.cpp). One step deeper confirms the story.

File1.cpp Drill Down Code Coverage
SomeFunc 10%
SomeOtherFunc 0%
SomePeculiarFunc 0%
ImportantFunc 3%

From here, I’d look at each of the functions in this file and see what testing I’m missing that may help me hit this code. Once again, all I’ve done is used the code coverage data to guide my testing. Once I’ve looked at what I may be missing in File1.cpp, I may back out and look at Format Codes, or I may back all the way back to looking at Filters. I still use my knowledge of risk and priority to tell me where to investigate, then use the coverage data as a tool to help guide me in the right direction.

An important thing to reiterate, is that I’m still not concerned with improving the code coverage number – I just want to use the data to see what I’m missing. Sure, the number will go up anyway, but it’s not the point. The point is reducing risk by identifying missing test areas.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.