Trikalabs
  • Home
  • Best online TDD videos
  • Book Suggestions
  • About Me
  • Contact
Trikalabs
No Result
View All Result

Test Coverage

by fragi
July 19, 2019
in Unit Testing
Share on FacebookShare on Twitter

As our project gets bigger and bigger, we want to be certain that all our production codes have executed during tests.  Thus, we need to look for automated metrics that can help us evaluate our goal.  One of these metrics is the Code Coverage.  There are many types of code coverage but let’s focus on one of the most popular, the Branch Code Coverage.  Consider the following implementation of the FizzBuzz program (You can find the implementation in this link: https://github.com/Fragki/FizzBuzz) :

Swift
1
2
3
4
5
6
7
8
9
10
func fizzBuzz(number: Int) -> String {
    if isDivisibleBy(numerator: number, denominator: 3) &&  isDivisibleBy(numerator: number, denominator: 5) {
        return "FizzBuzz"
    } else if isDivisibleBy(numerator: number, denominator: 5) {
        return "Fuzz"
    } else if isDivisibleBy(numerator: number, denominator: 3) {
        return "Fizz"
    }
    return "\(number)"
}

How many branches can we spot?  Each if counts as 1, so if we have 3 branches from the if clause plus one from the return line,  the total is 4.  Branch code coverage evaluates if the branch is executed by tests at least once.  This means that we will need at least 4 tests in order to get 100% code coverage for this method.  We can see that branch code coverage is correlated to the Cyclomatic complexity.

How to enable Code Coverage in Xcode

Enabling code coverage in Xcode is easy.  All we have to do is select the Target and edit the scheme:

 

Then select Test and enable the Code Coverage:

Press CMD + U to run all the tests.

If we go to a file, we can now see some numbers on the right side of the executable lines.  These numbers show how many times this line has been executed during the tests.

And if we want to see the test report for all classes in our project, we should visit the Report Navigator:

Let’s say that in our FizzBuzz implementation we have forgotten to write the test for Number 15.  By running the tests, we immediately see a red rectangle to the right of our code.  This  tells us that this logic has not been tested:

Does 100% code coverage mean that our code has been fully tested?

Absolutely not!  Code coverage is an indication of the tests’ quality, not an absolute metric.  It can, however, tell us which part of the code has not been tested. Let’s look at some examples where the code coverage is 100% but the code has not been fully tested.

We will once again use the FizzBuzz implementation as an example. Let’s assume now that the requirements have changed and the business requires the FizzBuzz to return “FizzBuzz” only if the number is a multiple of 3 and 5 but not the number 30.  Our implementation will look like this:

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct FizzBuzzCalculator {
    
    func fizzBuzz(number: Int) -> String {
        if isDivisibleBy(numerator: number, denominator: 3) &&
            isDivisibleBy(numerator: number, denominator: 5) &&
            number != 30 {
            return "FizzBuzz"
        } else if isDivisibleBy(numerator: number, denominator: 3) {
            return "Fizz"
        } else if isDivisibleBy(numerator: number, denominator: 5) {
            return "Buzz"
        }
        return "\(number)"
    }
    
    func isDivisibleBy(numerator: Int, denominator: Int) -> Bool {
        return numerator % denominator == 0
    }
}

After running the tests, we get a 100% test coverage, but we know that a test is missing.  We know that the input for number 30 has not been tested.  So, the code coverage does not guarantee that all the necessary tests are in place, it is just a good indicator.  We should be very careful when testing code with complex if statements or methods with many arguments.

fragi

fragi

Related Posts

What is TDD?
Unit Testing

Write better Unit tests with XCTUnwrap

January 27, 2022

Testing optionals can require boilerplate code to unwrap it. It can also affect the readability of the test. Let's look...

Test static method on collaborator
Unit Testing

Test static method on collaborator

May 13, 2021

One of the main issues we are facing when we try to make an old piece of code testable is...

Dependency injection – UIViewController in Storyboard (iOS 13)
Unit Testing

Dependency injection – UIViewController in Storyboard (iOS 13)

May 13, 2021

Finally Apple (iOS 13 +) has added constructor dependency injection to Storyboards! No excuses anymore for not using DI properly...

Unit testing code with DispatchQueue
Unit Testing

Unit testing code with DispatchQueue

May 13, 2021

One way of testing code with DispatchQueue is by using expectations (https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations) but in most of the cases it's more...

Unit testing UIViewController LifeCycle
Unit Testing

Unit testing UIViewController LifeCycle

May 13, 2021

Unit testing UIViewController life cycle events are not a straightforward process. Let's have a look on the following view controller:...

Dependency Injection – UIViewController with a Nib file
Unit Testing

Dependency Injection – UIViewController with a Nib file

May 13, 2021

UIViewControllers are among the most used UIKit objects. As the name implies UIViewControllers are controller objects and their purpose should...

Next Post
Arrange Act Assert

Arrange Act Assert

Code Kata

Code Kata

Improve Pull Requests with Sequence Diagrams

Improve Pull Requests with Sequence Diagrams

  • Advertise
  • Privacy & Policy
  • Contact

© 2019 Trikalabs Ltd. All rights reserved.

No Result
View All Result
  • Home
  • About Me
  • A curated list with the best free online TDD videos
  • Book Suggestions
  • Pinner Code Club

© 2019 Trikalabs Ltd. All rights reserved.