В этом примере показано, как создать пользовательский плагин, который поддерживает параллельные тесты. Пользовательский плагин подсчитывает количество проходящих и неудачных утверждений для тестового набора. Расширение TestRunner
плагин переопределяет методы выбора matlab.unittest.plugins.TestRunnerPlugin
класс. Кроме того, чтобы поддержать параллельные тесты, плагин подклассифицирует matlab.unittest.plugins.Parallelizable
интерфейс. Чтобы запустить тесты параллельно, вам нужен Parallel Computing Toolbox™.
В файле в текущей папке создайте класс параллелизируемого плагина AssertionCountingPlugin
, который наследует от обоих TestRunnerPlugin
и Parallelizable
классы. Полный код для AssertionCountingPlugin
, см. «Класс плагина Определения Сводных данных».
Чтобы отслеживать количество проходящих и неудачных утверждений, задайте четыре свойства только для чтения в properties
блок. Каждый MATLAB® worker в текущем параллельном пуле использует 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
(см. «Определение вспомогательных методов»).
Добавить прослушивателей в AssertionPassed
и AssertionFailed
события для подсчета утверждений. Чтобы добавить эти прослушиватели, расширьте методы, используемые средой тестирования, чтобы создать содержание теста. Содержание теста включает TestCase
образцы для каждого Test
элемент, уровень классов TestCase
образцы для TestClassSetup
и TestClassTeardown
блоки методов и Fixture
образцы, используемые в TestCase
класс имеет SharedTestFixtures
атрибут.
Активируйте соответствующий метод суперкласса, когда вы переопределяете методы создания. Методы создания возвращают содержимое, которое создает среда тестирования для каждого из соответствующих контекстов. При реализации одного из этих методов используйте incrementPassingAssertionsCount
и incrementFailingAssertionsCount
helper methods, добавьте прослушиватели, необходимую для плагина, к возвращенной 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
access, задайте три вспомогательных метода. Эти методы увеличивают количество проходящих или неудачных утверждений в каждом текущем фрагменте тестового набора и печатают сводные данные количества утверждений.
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
addlistener
| matlab.unittest.fixtures.Fixture
| matlab.unittest.plugins.Parallelizable
| matlab.unittest.plugins.TestRunnerPlugin
| matlab.unittest.TestCase
| matlab.unittest.TestResult
| matlab.unittest.TestRunner
| matlab.unittest.TestSuite
| runInParallel