Запустите тесты параллельно с пользовательским плагином

В этом примере показано, как создать пользовательский плагин, который поддерживает запускающие тесты параллельно. Пользовательский плагин считает количество передачи и провальных утверждений для тестового набора. Расширять TestRunner, плагин заменяет избранные методы matlab.unittest.plugins.TestRunnerPlugin класс. Кроме того, чтобы поддержать запускающие тесты параллельно, плагин разделяет на подклассы matlab.unittest.plugins.Parallelizable интерфейс. Чтобы запустить тесты параллельно, вам нужен Parallel Computing Toolbox™.

Создайте сменный класс

В файле в вашей текущей папке создайте parallelizable сменный класс AssertionCountingPlugin, который наследовал от обоих TestRunnerPlugin и Parallelizable классы. Для полного кода для AssertionCountingPlugin, см. Сменные Сводные данные Определения класса.

Чтобы отслеживать количество передачи и провальных утверждений, задайте четыре свойства только для чтения в properties блок. Каждый рабочий MATLAB® на текущем параллельном пуле использует NumPassingAssertions и NumFailingAssertions отслеживать количество передачи и провальных утверждений при выполнении фрагмента TestSuite массив. Клиент MATLAB использует FinalizedNumPassingAssertions и FinalizedNumFailingAssertions агрегировать результаты различных рабочих и сообщить об общем количестве передачи и провальных утверждений в конце сеанса тестирования.

properties (SetAccess = private)
    NumPassingAssertions
    NumFailingAssertions
    FinalizedNumPassingAssertions
    FinalizedNumFailingAssertions
end

Расширенная работа сеанса тестирования

Расширять выполнение целого TestSuite массив, замените runSession метод TestRunnerPlugin в methods блокируйтесь с protected доступ. Среда тестирования оценивает этот метод одно время на клиенте.

methods (Access = protected)
    function runSession(plugin, pluginData)
        suiteSize = numel(pluginData.TestSuite);
        fprintf('## Running a total of %d tests\n\n', suiteSize);
        plugin.FinalizedNumPassingAssertions = 0;
        plugin.FinalizedNumFailingAssertions = 0;
            
        runSession@matlab.unittest.plugins.TestRunnerPlugin(plugin, pluginData);
            
        fprintf('## Done running tests\n')
        plugin.printAssertionSummary()
    end
end

runSession информация об отображениях об общем количестве Test элементы, инициализирует свойства, используемые плагином, чтобы сгенерировать вывод текста, и вызывает метод суперкласса инициировать целый тестовый прогон. После того, как среда завершает оценку метода суперкласса, runSession отображается утверждение считают сводные данные путем вызова вспомогательного метода printAssertionSummary (см., задают вспомогательные методы).

Расширение создания разделяемых испытательных стендов и экземпляров TestCase

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

Вызовите соответствующий метод суперкласса, когда вы замените методы создания. Методы создания возвращают содержимое, которое среда тестирования создает для каждого из их соответствующих контекстов. При реализации одного из этих методов с помощью incrementPassingAssertionsCount и incrementFailingAssertionsCount вспомогательные методы, добавляют прослушиватели, требуемые плагином к возвращенному Fixture или TestCase экземпляр.

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

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

Расширенная работа фрагмента тестового набора

Среда тестирования делит целый TestSuite массив в различные группы и присваивает их рабочим для обработки. Каждый рабочий может запустить один или несколько фрагментов тестового набора. Чтобы настроить поведение рабочих, замените runTestSuite метод TestRunnerPlugin в methods блокируйтесь с protected доступ.

Расширьте TestRunner отобразить идентификатор каждой тестовой группы, которую рабочий запускает наряду с количеством Test элементы в группе. Кроме того, сохраните количество передачи и провальных утверждений в буфере так, чтобы клиент мог получить эти значения, чтобы привести к завершенным результатам. Как все сменные методы, runTestSuite метод требует, чтобы вы вызвали соответствующий метод суперкласса в соответствующей точке. В этом случае вызовите метод суперкласса после инициализации свойств и прежде, чем хранить данные рабочего. Среда тестирования оценивает runTestSuite на рабочих так же много раз как количество фрагментов тестового набора.

methods (Access = protected)
    function runTestSuite(plugin, pluginData)
        suiteSize = numel(pluginData.TestSuite);
        groupNumber = pluginData.Group;
        fprintf('### Running a total of %d tests in group %d\n', ...
            suiteSize, groupNumber);
        plugin.NumPassingAssertions = 0;
        plugin.NumFailingAssertions = 0;
            
        runTestSuite@matlab.unittest.plugins.TestRunnerPlugin(...
            plugin, pluginData);
            
        assertionStruct = struct('Passing', plugin.NumPassingAssertions, ...
            'Failing', plugin.NumFailingAssertions);
        plugin.storeIn(pluginData.CommunicationBuffer, assertionStruct);
    end
end

Хранить специфичные для теста данные, реализацию runTestSuite содержит вызов storeIn метод Parallelizable интерфейс. Используйте storeIn наряду с retrieveFrom когда рабочие должны сообщить клиенту. В этом примере, после возврата из метода суперкласса, NumPassingAssertions и NumFailingAssertions содержите количество передачи и провальных утверждений, соответствующих группе тестов. Поскольку storeIn принимает данные рабочего как только один входной параметр, assertionStruct группирует количества утверждения с помощью двух полей.

Расширьте создание отчетов завершенного фрагмента тестового набора

Расширьте reportFinalizedSuite агрегировать количества утверждения путем получения тестовых данных для каждого завершенного фрагмента тестового набора. Получать сохраненный assertionStruct для фрагмента тестового набора вызовите retrieveFrom метод в рамках reportFinalizedSuite. Добавьте значения полей в соответствующие свойства класса и вызовите метод суперкласса. Среда тестирования оценивает этот метод на клиенте так же много раз как количество фрагментов тестового набора.

methods (Access = protected)
    function reportFinalizedSuite(plugin, pluginData)
        assertionStruct = plugin.retrieveFrom(pluginData.CommunicationBuffer);
        plugin.FinalizedNumPassingAssertions = ...
            plugin.FinalizedNumPassingAssertions + assertionStruct.Passing;
        plugin.FinalizedNumFailingAssertions = ...
            plugin.FinalizedNumFailingAssertions + assertionStruct.Failing;
            
        reportFinalizedSuite@matlab.unittest.plugins.TestRunnerPlugin(...
            plugin, pluginData);
    end
end

Задайте вспомогательные методы

В methods блокируйтесь с private доступ, задайте три вспомогательных метода. Эти методы постепенно увеличивают количество передачи или провальных утверждений в каждом рабочем фрагменте тестового набора, и распечатывают сводные данные количества утверждения.

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.FinalizedNumPassingAssertions + ...
            plugin.FinalizedNumFailingAssertions)
        fprintf('\t%d Passed, %d Failed\n', plugin.FinalizedNumPassingAssertions, ...
            plugin.FinalizedNumFailingAssertions)
    end
end

Сменные сводные данные определения класса

Следующий код предоставляет полное содержимое AssertionCountingPlugin.

classdef AssertionCountingPlugin < ...
        matlab.unittest.plugins.TestRunnerPlugin & ...
        matlab.unittest.plugins.Parallelizable
    
    properties (SetAccess = private)
        NumPassingAssertions
        NumFailingAssertions
        FinalizedNumPassingAssertions
        FinalizedNumFailingAssertions
    end
    
    methods (Access = protected)
        function runSession(plugin, pluginData)
            suiteSize = numel(pluginData.TestSuite);
            fprintf('## Running a total of %d tests\n\n', suiteSize);
            plugin.FinalizedNumPassingAssertions = 0;
            plugin.FinalizedNumFailingAssertions = 0;
            
            runSession@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 runTestSuite(plugin, pluginData)
            suiteSize = numel(pluginData.TestSuite);
            groupNumber = pluginData.Group;
            fprintf('### Running a total of %d tests in group %d\n', ...
                suiteSize, groupNumber);
            plugin.NumPassingAssertions = 0;
            plugin.NumFailingAssertions = 0;
            
            runTestSuite@matlab.unittest.plugins.TestRunnerPlugin(...
                plugin, pluginData);
            
            assertionStruct = struct('Passing', plugin.NumPassingAssertions, ...
                'Failing', plugin.NumFailingAssertions);
            plugin.storeIn(pluginData.CommunicationBuffer, assertionStruct);
        end
        
        
        function reportFinalizedSuite(plugin, pluginData)
            assertionStruct = plugin.retrieveFrom(pluginData.CommunicationBuffer);
            plugin.FinalizedNumPassingAssertions = ...
                plugin.FinalizedNumPassingAssertions + assertionStruct.Passing;
            plugin.FinalizedNumFailingAssertions = ...
                plugin.FinalizedNumFailingAssertions + assertionStruct.Failing;
            
            reportFinalizedSuite@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.FinalizedNumPassingAssertions + ...
                plugin.FinalizedNumFailingAssertions)
            fprintf('\t%d Passed, %d Failed\n', plugin.FinalizedNumPassingAssertions, ...
                plugin.FinalizedNumFailingAssertions)
        end
    end
end

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

В вашей текущей папке создайте файл с именем ExampleTest.m содержа следующий параметрированный тестовый класс. Этот класс приводит к 300 Test элементы, 100 из которых являются тестами утверждения, которые сравнивают псевдослучайные целые числа между 1 и 10.

classdef ExampleTest < matlab.unittest.TestCase
    
    properties (TestParameter)
        num1 = repmat({@()randi(10)}, 1, 10);
        num2 = repmat({@()randi(10)}, 1, 10);
    end
    
    methods(Test)
        function testAssert(testCase, num1, num2)
            testCase.assertNotEqual(num1(), num2())
        end
        function testVerify(testCase, num1, num2)
            testCase.verifyNotEqual(num1(), num2())
        end
        function testAssume(testCase, num1, num2)
            testCase.assumeNotEqual(num1(), num2())
        end
    end
end

Добавление плагина к исполнителю тестов и запущенным тестам

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

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

suite = TestSuite.fromClass(?ExampleTest);

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

runner = TestRunner.withNoPlugins;

Добавьте AssertionCountingPlugin бегуну и запущенный тесты параллельно. Можно также запустить те же тесты в последовательном режиме, если вы вызываете run метод на бегуне.

runner.addPlugin(AssertionCountingPlugin)
result = runner.runInParallel(suite);
Starting parallel pool (parpool) using the 'local' profile ...
Connected to the parallel pool (number of workers: 6).
## Running a total of 300 tests

Split tests into 18 groups and running them on 6 workers.
----------------
Finished Group 6
----------------
### Running a total of 18 tests in group 6

----------------
Finished Group 1
----------------
### Running a total of 20 tests in group 1

----------------
Finished Group 2
----------------
### Running a total of 20 tests in group 2

----------------
Finished Group 3
----------------
### Running a total of 19 tests in group 3

----------------
Finished Group 4
----------------
### Running a total of 19 tests in group 4

----------------
Finished Group 5
----------------
### Running a total of 18 tests in group 5

----------------
Finished Group 7
----------------
### Running a total of 18 tests in group 7

----------------
Finished Group 8
----------------
### Running a total of 17 tests in group 8

----------------
Finished Group 9
----------------
### Running a total of 17 tests in group 9

-----------------
Finished Group 10
-----------------
### Running a total of 17 tests in group 10

-----------------
Finished Group 11
-----------------
### Running a total of 16 tests in group 11

-----------------
Finished Group 12
-----------------
### Running a total of 16 tests in group 12

-----------------
Finished Group 15
-----------------
### Running a total of 15 tests in group 15

-----------------
Finished Group 14
-----------------
### Running a total of 15 tests in group 14

-----------------
Finished Group 17
-----------------
### Running a total of 14 tests in group 17

-----------------
Finished Group 16
-----------------
### Running a total of 14 tests in group 16

-----------------
Finished Group 13
-----------------
### Running a total of 15 tests in group 13

-----------------
Finished Group 18
-----------------
### Running a total of 12 tests in group 18

## Done running tests
______________________________
Total Assertions: 100
	88 Passed, 12 Failed

Смотрите также

| | | | | | | |

Похожие темы