Main Content

Generate Code Coverage Report in HTML Format

When you generate an HTML code coverage report using the CoverageReport class, the report displays coverage metrics that let you perform a detailed analysis of the source code covered by your tests. This topic provides an overview of the supported types of code coverage, as well as an example of how to generate and analyze a coverage report.

Statement Coverage for MATLAB Source Code

Statement coverage identifies the source code statements that are executed when the tests run. Use this type of coverage to see whether every statement in your source code is executed at least once.

To report statement coverage metrics, MATLAB® divides the source code into statements that are separated by a comma, semicolon, or newline character. For example, this code has three statements that are terminated by a comma, semicolon, and newline character, respectively.

b = 1, a = 2 * (b + 10);
x = (b ~= 0) && (a/b > 18.5)

MATLAB divides control flow statements into smaller units for code coverage reporting. For example, MATLAB reports coverage for five units in the following code: if x > 0, elseif x < 0, and three calls to the disp function. To achieve 100% statement coverage, you need tests that execute each unit.

if x > 0
    disp("x is positive.")
elseif x < 0
    disp("x is negative.")
else
    disp("x is either zero or NaN.")
end

A keyword followed by an expression forms a unit for which MATLAB reports coverage. Among keywords that do not require an expression, MATLAB reports coverage for break, catch, continue, return, and try, and ignores keywords such as else, end, and otherwise.

In general, MATLAB reports coverage for statements that perform some action on program data or affect the flow of the program. It ignores code that defines functions, classes, or class members (such as function [y1,...,yN] = myfun(x1,...,xM) or classdef MyClass).

Function Coverage for MATLAB Source Code

Function coverage identifies the functions defined in the source code that are executed when the tests run. Use this type of coverage to see whether every function in your source code is called at least once.

For example, the following code contains three defined functions: f, root, and square. To achieve 100% function coverage, you need tests that result in each of these functions being called.

function f(x)
if x >= 0
    root
else
    square
end
disp(x)

    function root
        x = sqrt(x);
    end
    function square
        x = x.^2;
    end
end

Generate and Analyze HTML Coverage Report

This example shows how to generate and analyze an HTML code coverage report for the QuadraticPolynomial class definition file. The class represents quadratic polynomials. Its constructor first validates that the coefficients of the polynomial are numeric values and then uses those values to initialize the class properties. The class includes the solve method to return the roots of the specified quadratic polynomial, and the plot method to plot the polynomial around its axis of symmetry. To view the complete code for QuadraticPolynomial, see QuadraticPolynomial Class Definition.

In your current folder, save the QuadraticPolynomial class definition in a file named QuadraticPolynomial.m. Then, create the QuadraticPolynomialTest test class in your current folder. Add two Test methods to the class that test the solve method against real and imaginary solutions.

classdef QuadraticPolynomialTest < matlab.unittest.TestCase
    methods(Test)
        function realSolution(testCase)
            p = QuadraticPolynomial(1,-3,2);
            actSolution = p.solve();
            expSolution = [1 2];
            testCase.verifyEqual(actSolution,expSolution)
        end
        function imaginarySolution(testCase)
            p = QuadraticPolynomial(1,2,10);
            actSolution = p.solve();
            expSolution = [-1-3i -1+3i];
            testCase.verifyEqual(actSolution,expSolution)
        end
    end
end

At the command prompt, create a test suite from the QuadraticPolynomialTest class.

suite = testsuite("QuadraticPolynomialTest");

Create a test runner with a plugin that outputs an HTML code coverage report for the source code in the file QuadraticPolynomial.m.

import matlab.unittest.plugins.CodeCoveragePlugin
runner = testrunner("textoutput");
runner.addPlugin(CodeCoveragePlugin.forFile("QuadraticPolynomial.m"))

Run the tests. The plugin generates a code coverage report in a temporary folder.

results = runner.run(suite);
Running QuadraticPolynomialTest
..
Done QuadraticPolynomialTest
__________

Code coverage report has been saved to:
 C:\TEMP\tp16c9a437_b675_4739_a5de_338f0063ddb5\index.html

Open the report, which displays statement and function coverage metrics, and uses different colors to highlight the executed or missed statements and functions. In this example, the function coverage is 75% because the tests miss one of the four methods in the class (plot). Additionally, the statement coverage is low because the tests miss the code that throws an error and the code within the plot method.

Code coverage report for the QuadraticPolynomial class

You can achieve 100% statement and function coverage by adding a Test method that tests against nonnumeric inputs and another Test method that tests properties of a plotted polynomial.

classdef QuadraticPolynomialTest < matlab.unittest.TestCase
    methods(Test)
        function realSolution(testCase)
            p = QuadraticPolynomial(1,-3,2);
            actSolution = p.solve();
            expSolution = [1 2];
            testCase.verifyEqual(actSolution,expSolution)
        end
        function imaginarySolution(testCase)
            p = QuadraticPolynomial(1,2,10);
            actSolution = p.solve();
            expSolution = [-1-3i -1+3i];
            testCase.verifyEqual(actSolution,expSolution)
        end
        function nonnumericInput(testCase)
            testCase.verifyError(@()QuadraticPolynomial(1,"-3",2), ...
                "QuadraticPolynomial:InputMustBeNumeric")
        end
        function plotPolynomial(testCase)
            p = QuadraticPolynomial(1,-3,2);
            fig = figure;
            testCase.addTeardown(@close,fig)
            ax = axes(fig);
            p.plot(ax)
            actYLabelText = ax.YLabel.String;
            expYLabelText = '1.00x^2-3.00x+2.00';
            testCase.verifyEqual(actYLabelText,expYLabelText)
        end
    end
end

QuadraticPolynomial Class Definition

This code provides the complete contents of the QuadraticPolynomial class.

classdef QuadraticPolynomial
    properties
        A,B,C   % Coefficients of a*x^2 + b*x + c
    end

    methods
        function obj = QuadraticPolynomial(a,b,c)
            if ~isa(a,"numeric") || ~isa(b,"numeric") || ~isa(c,"numeric")
                error("QuadraticPolynomial:InputMustBeNumeric", ...
                    "Coefficients must be numeric.")
            else
                obj.A = a; obj.B = b; obj.C = c;
            end
        end

        function roots = solve(obj)
            % Return solutions to a*x^2 + b*x + c = 0
            delta = calculateDelta(obj);
            roots(1) = (-obj.B - sqrt(delta)) / (2*obj.A);
            roots(2) = (-obj.B + sqrt(delta)) / (2*obj.A);
        end

        function plot(obj,ax)
            % Plot a*x^2 + b*x + c around its axis of symmetry
            delta = calculateDelta(obj);
            x0 = -obj.B/(2*obj.A);
            x1 = abs(sqrt(delta))/obj.A;
            x = x0 + linspace(-x1,x1);
            y = obj.A*x.^2 + obj.B*x + obj.C;
            plot(ax,x,y)
            xlabel("x")
            ylabel(sprintf("%.2fx^2%+.2fx%+.2f",obj.A,obj.B,obj.C))
        end
    end

    methods (Access = private)
        function delta = calculateDelta(obj)
            delta = obj.B^2 - 4*obj.A*obj.C;
        end
    end
end

See Also

| |

Related Topics