本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

创建自定义插件

此示例演示如何创建一个自定义插件,以便统计在 TestRunner 运行测试套件时的通过和失败断言数。该插件在测试结束时输出简短摘要。为了扩展 TestRunner,该插件会创建 matlab.unittest.plugins.TestRunnerPlugin 类的子类并覆盖所选方法。

创建 AssertionCountingPlugin 类

在当前文件夹中的文件中,创建自定义插件类 AssertionCountingPlugin,该类继承自 TestRunnerPlugin 类。有关 AssertionCountingPlugin 的完整代码,请参阅 AssertionCountingPlugin 类定义总结

要跟踪通过和失败断言数,请编写 properties 代码块以定义两个只读属性 NumPassingAssertionsNumFailingAssertions

properties (SetAccess = private)
    NumPassingAssertions
    NumFailingAssertions
end

扩展 TestSuite 的运行

编写具有 protected 访问权限的 methods 代码块以实现 runTestSuite 方法。

methods (Access = protected)
    function runTestSuite(plugin, pluginData)
        suiteSize = numel(pluginData.TestSuite);
        fprintf('## Running a total of %d tests\n', suiteSize)

        plugin.NumPassingAssertions = 0;
        plugin.NumFailingAssertions = 0;

        runTestSuite@matlab.unittest.plugins.TestRunnerPlugin(...
            plugin, pluginData);

        fprintf('## Done running tests\n')
        plugin.printAssertionSummary()
    end
end

测试框架对此方法进行一次计算。它显示关于测试总数的信息,初始化插件用于生成文本输出的属性,并调用超类方法。在框架完成对超类方法的计算后,runTestSuite 方法通过调用辅助函数方法 printAssertionSummary(请参阅定义辅助函数方法)来显示断言计数摘要。

扩展共享测试脚手架和 TestCase 实例的创建

将侦听程序添加到 AssertionPassedAssertionFailed 事件以统计断言数。要添加这些侦听程序,请扩展测试框架用于创建测试内容的方法。测试内容包括每个 Test 元素的 TestCase 实例,TestClassSetupTestClassTeardown 方法的类级别 TestCase 实例,以及在 TestCase 类具有 SharedTestFixtures 属性时使用的 Fixture 实例。

在覆盖创建方法时调用相应的超类方法。这些创建方法返回测试框架针对其各自上下文创建的内容。当使用 incrementPassingAssertionsCountincrementFailingAssertionsCount 辅助函数方法实现上述方法时,将插件所需的侦听程序添加到返回的 FixtureTestCase 实例。

将这些创建方法添加到具有 protected 访问权限的 methods 代码块。

methods (Access = protected)
    function fixture = createSharedTestFixture(plugin, pluginData)
        fixture = createSharedTestFixture@...
            matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);

        fixture.addlistener('AssertionPassed', ...
            @(~,~)plugin.incrementPassingAssertionsCount);
        fixture.addlistener('AssertionFailed', ...
            @(~,~)plugin.incrementFailingAssertionsCount);
    end

    function testCase = createTestClassInstance(plugin, pluginData)
        testCase = createTestClassInstance@...
            matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);

        testCase.addlistener('AssertionPassed', ...
            @(~,~)plugin.incrementPassingAssertionsCount);
        testCase.addlistener('AssertionFailed', ...
            @(~,~)plugin.incrementFailingAssertionsCount);
    end

    function testCase = createTestMethodInstance(plugin, pluginData)
        testCase = createTestMethodInstance@...
            matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);

        testCase.addlistener('AssertionPassed', ...
            @(~,~)plugin.incrementPassingAssertionsCount);
        testCase.addlistener('AssertionFailed', ...
            @(~,~)plugin.incrementFailingAssertionsCount);
    end
end

扩展单个测试套件元素的运行

扩展 runTest 以在运行时显示每个测试的名称。将此方法添加到具有 protected 访问权限的 methods 代码块。像所有插件方法一样,runTest 方法要求您调用对应的超类方法。

methods (Access = protected)
    function runTest(plugin, pluginData)
        fprintf('### Running test: %s\n', pluginData.Name)

        runTest@matlab.unittest.plugins.TestRunnerPlugin(...
            plugin, pluginData);
    end
end

定义辅助函数方法

在具有 private 访问权限的 methods 块中,定义三个辅助函数方法。这些方法累加通过或失败断言数,并输出断言计数摘要。

methods (Access = private)
    function incrementPassingAssertionsCount(plugin)
        plugin.NumPassingAssertions = plugin.NumPassingAssertions + 1;
    end

    function incrementFailingAssertionsCount(plugin)
        plugin.NumFailingAssertions = plugin.NumFailingAssertions + 1;
    end

    function printAssertionSummary(plugin)
        fprintf('%s\n', repmat('_', 1, 30))
        fprintf('Total Assertions: %d\n', ...
            plugin.NumPassingAssertions + plugin.NumFailingAssertions)
        fprintf('\t%d Passed, %d Failed\n', ...
            plugin.NumPassingAssertions, plugin.NumFailingAssertions)
    end
end

AssertionCountingPlugin 类定义总结

以下代码提供 AssertionCountingPlugin 的完整内容。

classdef AssertionCountingPlugin < ...
        matlab.unittest.plugins.TestRunnerPlugin
    
    properties (SetAccess = private)
        NumPassingAssertions
        NumFailingAssertions
    end
    
    methods (Access = protected)
        function runTestSuite(plugin, pluginData)
            suiteSize = numel(pluginData.TestSuite);
            fprintf('## Running a total of %d tests\n', suiteSize)
            
            plugin.NumPassingAssertions = 0;
            plugin.NumFailingAssertions = 0;
            
            runTestSuite@matlab.unittest.plugins.TestRunnerPlugin(...
                plugin, pluginData);
            
            fprintf('## Done running tests\n')
            plugin.printAssertionSummary()
        end
        
        function fixture = createSharedTestFixture(plugin, pluginData)
            fixture = createSharedTestFixture@...
                matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);
            
            fixture.addlistener('AssertionPassed', ...
                @(~,~)plugin.incrementPassingAssertionsCount);
            fixture.addlistener('AssertionFailed', ...
                @(~,~)plugin.incrementFailingAssertionsCount);
        end
        
        function testCase = createTestClassInstance(plugin, pluginData)
            testCase = createTestClassInstance@...
                matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);
            
            testCase.addlistener('AssertionPassed', ...
                @(~,~)plugin.incrementPassingAssertionsCount);
            testCase.addlistener('AssertionFailed', ...
                @(~,~)plugin.incrementFailingAssertionsCount);
        end
        
        function testCase = createTestMethodInstance(plugin, pluginData)
            testCase = createTestMethodInstance@...
                matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);
            
            testCase.addlistener('AssertionPassed', ...
                @(~,~)plugin.incrementPassingAssertionsCount);
            testCase.addlistener('AssertionFailed', ...
                @(~,~)plugin.incrementFailingAssertionsCount);
        end
        
        function runTest(plugin, pluginData)
            fprintf('### Running test: %s\n', pluginData.Name)
            
            runTest@matlab.unittest.plugins.TestRunnerPlugin(...
                plugin, pluginData);
        end 
    end
    
    methods (Access = private)
        function incrementPassingAssertionsCount(plugin)
            plugin.NumPassingAssertions = plugin.NumPassingAssertions + 1;
        end
        
        function incrementFailingAssertionsCount(plugin)
            plugin.NumFailingAssertions = plugin.NumFailingAssertions + 1;
        end
        
        function printAssertionSummary(plugin)
            fprintf('%s\n', repmat('_', 1, 30))
            fprintf('Total Assertions: %d\n', ...
                plugin.NumPassingAssertions + plugin.NumFailingAssertions)
            fprintf('\t%d Passed, %d Failed\n', ...
                plugin.NumPassingAssertions, plugin.NumFailingAssertions)
        end
    end
end

创建示例测试类

在当前文件夹中,创建一个名为 ExampleTest.m 的文件,其中包含以下测试类。

classdef ExampleTest < matlab.unittest.TestCase
    methods(Test)
        function testOne(testCase)  % Test fails
            testCase.assertEqual(5, 4)
        end
        function testTwo(testCase)  % Test passes
            testCase.verifyEqual(5, 5)
        end
        function testThree(testCase)  % Test passes
            testCase.assertEqual(7*2, 14)
        end
    end
end

将插件添加到 TestRunner 并运行测试

在命令提示符下,基于 ExampleTest 类创建测试套件。

import matlab.unittest.TestSuite
import matlab.unittest.TestRunner

suite = TestSuite.fromClass(?ExampleTest);

创建一个不含插件的 TestRunner 实例。此代码创建一个静默运行程序,以便您控制安装的插件。

runner = TestRunner.withNoPlugins;

运行测试。

result = runner.run(suite);

AssertionCountingPlugin 添加到运行程序并运行测试。

runner.addPlugin(AssertionCountingPlugin)
result = runner.run(suite);
## Running a total of 3 tests
### Running test: ExampleTest/testOne
### Running test: ExampleTest/testTwo
### Running test: ExampleTest/testThree
## Done running tests
______________________________
Total Assertions: 2
	1 Passed, 1 Failed

另请参阅

| | | | |

相关主题