Напишите плагин для добавления данных к результатам тестирования

В этом примере показано, как создать плагин, который добавляет данные в TestResult объекты. Плагин добавляет фактическое и ожидаемые значения в утверждении к Details свойство TestResult объект. Расширение TestRunnerплагин переопределяет методы выбора matlab.unittest.plugins.TestRunnerPlugin класс.

Создайте класс плагина

В файле в текущей папке создайте пользовательский класс плагина DetailsRecordingPlugin, который наследует от TestRunnerPlugin класс. Полный код для DetailsRecordingPlugin, см. DetailsRecordingPlugin Класса Определения Сводных данных.

Хранение фактических и ожидаемых значений в TestResult объекты, задайте два постоянных свойства, ActField и ExpField, в пределах properties блок. Установите значение ActField к имени поля Details структура, содержащая фактическое значение. Установите значение ExpField имени поля, содержащего ожидаемое значение.

properties (Constant,Access = private)
    ActField = 'ActualValue';
    ExpField = 'ExpectedValue';
end

Добавить поля в свойство Details

Как добавить новые поля в Details свойство всех TestResult объекты, принадлежащие тестовому сеансу, переопределяют runSession метод TestRunnerPlugin в methods блок с protected доступ. runSession добавляет два пустых поля в Details структура TestResult Объекты и вызывают метод суперкласса, чтобы запустить весь тестовый запуск.

methods (Access = protected)
    function runSession(plugin,pluginData)
        resultDetails = pluginData.ResultDetails;
        resultDetails.append(plugin.ActField,{})
        resultDetails.append(plugin.ExpField,{})
        runSession@matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData);
    end
end

Чтобы добавить поля, реализация runSession содержит вызовы на append метод matlab.unittest.plugins.plugindata.ResultDetails класс. Каждый вызов добавляет пустое поле к Details структура.

Расширение создания общих испытательных стендов и образцов TestCase

Добавьте прослушиватели для AssertionPassed и AssertionFailed события путем расширения методов, используемых средой тестирования для создания содержания теста. Содержание теста включает TestCase образцы для каждого Test элемент, уровень классов TestCase образцы для TestClassSetup и TestClassTeardown блоки методов и Fixture образцы, используемые в TestCase класс имеет SharedTestFixtures атрибут.

Активируйте соответствующий метод суперкласса, когда вы переопределяете методы создания. Прослушиватели, которые вы добавляете к возвращенной Fixture или TestCase образцы вызывают reactToAssertion вспомогательный метод для выполнения всякий раз, когда выполняется подтверждение. Чтобы добавить данные проверки к результатам, передайте образец модификатора результатов вместе с данными прослушивателя события проверки в вспомогательный метод.

Добавьте эти методы создания к methods блок с protected доступ.

methods (Access = protected)
    function fixture = createSharedTestFixture(plugin, pluginData)
        fixture = createSharedTestFixture@...            
            matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);
        resultDetails = pluginData.ResultDetails;
        fixture.addlistener('AssertionPassed',...
            @(~,evd)plugin.reactToAssertion(evd,resultDetails));
        fixture.addlistener('AssertionFailed',...
            @(~,evd)plugin.reactToAssertion(evd,resultDetails));
    end
        
    function testCase = createTestClassInstance(plugin,pluginData)
        testCase = createTestClassInstance@...
            matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData);
        resultDetails = pluginData.ResultDetails;
        testCase.addlistener('AssertionPassed',...
            @(~,evd)plugin.reactToAssertion(evd,resultDetails));
        testCase.addlistener('AssertionFailed',...
            @(~,evd)plugin.reactToAssertion(evd,resultDetails));
    end
        
    function testCase = createTestMethodInstance(plugin,pluginData)
        testCase = createTestMethodInstance@...
            matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData);
        resultDetails = pluginData.ResultDetails;
        testCase.addlistener('AssertionPassed',...
            @(~,evd)plugin.reactToAssertion(evd,resultDetails));
        testCase.addlistener('AssertionFailed',...
            @(~,evd)plugin.reactToAssertion(evd,resultDetails));
    end
end

Определите метод помощника

В methods блок с private access, задайте метод helper reactToAssertion. Этот метод использует QualificationEventData образец для извлечения фактических и ожидаемых значений в утверждениях на основе IsEqualTo ограничение, преобразует извлеченные значения в массивы ячеек и добавляет массивы ячеек к полям соответствующей TestResult объект.

methods (Access = private)
    function reactToAssertion(plugin,evd,resultDetails)
        if ~isa(evd.Constraint,'matlab.unittest.constraints.IsEqualTo')
            return
        end
        resultDetails.append(plugin.ActField,{evd.ActualValue})
        resultDetails.append(plugin.ExpField,{evd.Constraint.Expected})
    end
end

Определение класса DetailsRecordingPlugin Сводных данных

Этот код предоставляет полное содержимое DetailsRecordingPlugin.

classdef DetailsRecordingPlugin < matlab.unittest.plugins.TestRunnerPlugin
    properties (Constant, Access = private)
        ActField = 'ActualValue';
        ExpField = 'ExpectedValue';
    end
    
    methods (Access = protected)
        function runSession(plugin,pluginData)
            resultDetails = pluginData.ResultDetails;
            resultDetails.append(plugin.ActField,{})
            resultDetails.append(plugin.ExpField,{})
            runSession@matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData);
        end
        
        function fixture = createSharedTestFixture(plugin, pluginData)
            fixture = createSharedTestFixture@...
                matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);
            resultDetails = pluginData.ResultDetails;
            fixture.addlistener('AssertionPassed',...
                @(~,evd)plugin.reactToAssertion(evd,resultDetails));
            fixture.addlistener('AssertionFailed',...
                @(~,evd)plugin.reactToAssertion(evd,resultDetails));
        end
        
        function testCase = createTestClassInstance(plugin,pluginData)
            testCase = createTestClassInstance@...
                matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData);
            resultDetails = pluginData.ResultDetails;
            testCase.addlistener('AssertionPassed',...
                @(~,evd)plugin.reactToAssertion(evd,resultDetails));
            testCase.addlistener('AssertionFailed',...
                @(~,evd)plugin.reactToAssertion(evd,resultDetails));
        end
        
        function testCase = createTestMethodInstance(plugin,pluginData)
            testCase = createTestMethodInstance@...
                matlab.unittest.plugins.TestRunnerPlugin(plugin,pluginData);
            resultDetails = pluginData.ResultDetails;
            testCase.addlistener('AssertionPassed',...
                @(~,evd)plugin.reactToAssertion(evd,resultDetails));
            testCase.addlistener('AssertionFailed',...
                @(~,evd)plugin.reactToAssertion(evd,resultDetails));
        end
    end
    
    methods (Access = private)
        function reactToAssertion(plugin,evd,resultDetails)
            if ~isa(evd.Constraint,'matlab.unittest.constraints.IsEqualTo')
                return
            end
            resultDetails.append(plugin.ActField,{evd.ActualValue})
            resultDetails.append(plugin.ExpField,{evd.Constraint.Expected})
        end
    end
end

Создайте пример тестового класса

В текущей папке создайте файл с именем ExampleTest.m содержит следующий параметризованный класс теста. Класс результатов в тестовый набор с 25 элементами, каждый из которых соответствует эксперименту, выполненному с использованием другого seed для генератора случайных чисел. В каждом эксперименте среда тестирования создает вектор 1 на 100 нормально распределенных случайных чисел и утверждает, что величина различия между фактическим и ожидаемым средствами выборки находится в пределах 0,1.

classdef ExampleTest < matlab.unittest.TestCase
    properties
        SampleSize = 100;
    end

    properties (TestParameter) 
        seed = num2cell(randi(10^6,1,25));
    end
        
    methods(Test)
        function testMean(testCase,seed)
            import matlab.unittest.constraints.IsEqualTo
            import matlab.unittest.constraints.AbsoluteTolerance
            rng(seed)
            testCase.assertThat(mean(randn(1,testCase.SampleSize)),...
                IsEqualTo(0,'Within',AbsoluteTolerance(0.1)));
        end
    end
end

Добавьте плагин к TestRunner и запустите тесты

В командной строке создайте тестовый набор из ExampleTest класс.

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

suite = TestSuite.fromClass(?ExampleTest);

Создайте TestRunner образец без плагинов. Этот код создает бесшумный раннер и дает вам контроль над установленными плагинами.

runner = TestRunner.withNoPlugins;

Добавить DetailsRecordingPlugin и запустите тесты.

runner.addPlugin(DetailsRecordingPlugin)
result = runner.run(suite)
result = 

  1×25 TestResult array with properties:

    Name
    Passed
    Failed
    Incomplete
    Duration
    Details

Totals:
   18 Passed, 7 Failed (rerun), 7 Incomplete.
   0.12529 seconds testing time.

Чтобы получить дополнительные сведения о поведении генерации случайных чисел, создайте массив структур из Details структуры результатов испытаний.

details = [result.Details]
details = 

  1×25 struct array with fields:

    ActualValue
    ExpectedValue

Создайте массив, содержащий различие между фактическим и ожидаемым значениями в каждом тесте, а затем отобразите значения ошибок в гистограмме. Семь баров с длиной более 0,1 соответствуют неудачным тестам.

errorInMean = cell2mat([details.ExpectedValue]) - cell2mat([details.ActualValue]);

bar(errorInMean)
xlabel('Experiment')
ylabel('Error')

Bar graph depicting error versus experiment

См. также

| | | | | |

Похожие темы