Создание усовершенствованного параметризованного теста

Этот пример показывает, как создать тест, который параметризован в TestClassSetup, TestMethodSetup и Test блоки methods. Тестовый класс в качестве примера тестирует генератор случайных чисел.

Тестирование обзора

Тестовый класс TestRand параметризован на трех разных уровнях.

Уровень параметризацииОпределение параметризацииAccessible Parameterization Properties
Атрибут методаАтрибут свойства
Протестируйте уровеньТестTestParameterTestParameter, MethodSetupParameter и ClassSetupParameter
Уровень настройки методаTestMethodSetupMethodSetupParameterMethodSetupParameter и ClassSetupParameter
Уровень настройки классаTestClassSetupClassSetupParameterClassSetupParameter

На каждом тестовом уровне можно использовать атрибут метода ParameterCombination, чтобы задать тестовую параметризацию.

Атрибут ParameterCombinationВызов метода
'exhaustive' (значение по умолчанию)Методы вызываются для всех комбинаций параметров. Среда тестирования использует эту комбинацию по умолчанию, если вы не задаете атрибут ParameterCombination.
'sequential'Методы вызываются с соответствующими значениями от каждого параметра. Каждый параметр должен содержать то же количество значений.
'pairwise'Методы вызываются для каждой пары значений параметров, по крайней мере, однажды. В то время как среда тестирования гарантирует, что тесты создаются для каждой пары значений, по крайней мере, однажды, вы не должны полагаться на тот размер, упорядоченное расположение или определенный набор элементов тестового набора.

Например, используйте объединенный атрибут методов TestMethodSetup, ParameterCombination='sequential', чтобы задать последовательную комбинацию параметров уровня настройки метода, заданных в блоке свойств MethodSetupParameter.

Для этого примера параметризация уровня настройки класса задает тип генератора случайных чисел. Параметризация уровня настройки метода задает seed для генератора случайных чисел, и параметризация тестового уровня задает тип данных и размер случайного числа вывод.

Создание тестового класса TestRand

В файле в вашей рабочей папке создайте класс, который наследовался matlab.unittest.TestCase. Этот класс тестирует различные аспекты генерации случайных чисел.

classdef TestRand < matlab.unittest.TestCase

Определение свойств Blocks

Задайте свойства, используемые для параметризованного тестирования. Каждый блок properties соответствует параметризации на конкретном уровне.

    properties (ClassSetupParameter)
        generator = {'twister','combRecursive','multFibonacci'};
    end
    
    properties (MethodSetupParameter)
        seed = {0, 123, 4294967295};
    end
    
    properties (TestParameter)
        dim1 = struct('small', 1,'medium', 2, 'large', 3);
        dim2 = struct('small', 2,'medium', 3, 'large', 4);
        dim3 = struct('small', 3,'medium', 4, 'large', 5);
        type = {'single','double'};
    end

Определение тестовых методов Setup метода класса и метода тестирования

Задайте методы настройки на тестовом уровне метода класса и метода тестирования. Эти методы указывают начальное состояние генератора случайных чисел. После того, как среда запускает тесты, методы восстанавливают исходное состояние. Метод ClassSetup задает тип генератора случайных чисел, и TestMethodSetup отбирает генератор.

    methods (TestClassSetup)
        function ClassSetup(testCase, generator)
            orig = rng;
            testCase.addTeardown(@rng, orig)
            rng(0, generator)
        end
    end
    
    methods (TestMethodSetup)
        function MethodSetup(testCase, seed)
            orig = rng;
            testCase.addTeardown(@rng, orig)
            rng(seed)
        end
    end

Определение последовательных параметризованных методов тестирования

Задайте блок methods с атрибутами ParameterCombination='sequential' и Test. Среда тестирования вызывает эти методы однажды для каждого соответствующего значения свойства.

    methods (Test, ParameterCombination='sequential')
        function testSize(testCase,dim1,dim2,dim3)
            testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3])
        end 
    end

Метод тестирует размер вывода для каждого соответствующего параметра в dim1, dim2 и dim3. Например, чтобы протестировать все использование значений 'medium': testCase.verifySize(rand(2,3,4),[2 3 4]);. Для данного TestClassSetup и параметризации TestMethodSetup, среда вызывает метод testSize три раза — однажды каждый для 'small', 'medium' и значений 'large'.

Определение попарно параметризованных методов тестирования

Задайте блок methods с атрибутами ParameterCombination='pairwise' и Test. Среда тестирования вызывает эти методы, по крайней мере, однажды для каждой пары значений свойств.

    methods (Test, ParameterCombination='pairwise')
        function testRepeatable(testCase,dim1,dim2,dim3)
            state = rng;
            firstRun = rand(dim1,dim2,dim3);
            rng(state)
            secondRun = rand(dim1,dim2,dim3);
            testCase.verifyEqual(firstRun,secondRun)
        end
    end

Метод тестирования проверяет, что результаты генератора случайных чисел повторяемы. Для данного TestClassSetup и параметризации TestMethodSetup, среда вызывает метод testRepeatble 10 раз, чтобы гарантировать тестирование каждой пары dim1, dim2 и dim3. Однако, если атрибут комбинации параметра является исчерпывающим, среда вызывает метод времена 3^3=27.

Определение исчерпывающих параметризованных методов тестирования

Задайте блок methods с атрибутом Test или никакой заданной комбинацией параметра. Комбинация параметра является исчерпывающей по умолчанию. Среда тестирования вызывает эти методы однажды для каждой комбинации значений свойств.

    methods (Test)
        function testClass(testCase,dim1,dim2,type)
            testCase.verifyClass(rand(dim1,dim2,type), type)
        end
    end

Метод тестирования проверяет, что класс вывода от rand совпадает с ожидаемым классом. Для данного TestClassSetup и параметризации TestMethodSetup, среда вызывает метод testClass времена 3*3*2=18, чтобы гарантировать тестирование каждой комбинации dim1, dim2 и type.

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

classdef TestRand < matlab.unittest.TestCase
    properties (ClassSetupParameter)
        generator = {'twister','combRecursive','multFibonacci'};
    end
    
    properties (MethodSetupParameter)
        seed = {0, 123, 4294967295};
    end
    
    properties (TestParameter)
        dim1 = struct('small', 1,'medium', 2, 'large', 3);
        dim2 = struct('small', 2,'medium', 3, 'large', 4);
        dim3 = struct('small', 3,'medium', 4, 'large', 5);
        type = {'single','double'};
    end
    
    methods (TestClassSetup)
        function ClassSetup(testCase, generator)
            orig = rng;
            testCase.addTeardown(@rng, orig)
            rng(0, generator)
        end
    end
    
    methods (TestMethodSetup)
        function MethodSetup(testCase, seed)
            orig = rng;
            testCase.addTeardown(@rng, orig)
            rng(seed)
        end
    end
    
    methods (Test, ParameterCombination='sequential')
        function testSize(testCase,dim1,dim2,dim3)
            testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3])
        end 
    end
    
    methods (Test, ParameterCombination='pairwise')
        function testRepeatable(testCase,dim1,dim2,dim3)
            state = rng;
            firstRun = rand(dim1,dim2,dim3);
            rng(state)
            secondRun = rand(dim1,dim2,dim3);
            testCase.verifyEqual(firstRun,secondRun);
        end
    end
    
    methods (Test)
        function testClass(testCase,dim1,dim2,type)
            testCase.verifyClass(rand(dim1,dim2,type), type)
        end
    end
end

Создание комплекта из всех тестов

В командной строке создайте комплект из класса TestRand.m.

suite = matlab.unittest.TestSuite.fromClass(?TestRand)
suite = 

  1×279 Test array with properties:

    Name
    ProcedureName
    TestClass
    BaseFolder
    Parameterization
    SharedTestFixtures
    Tags

Tests Include:
   17 Unique Parameterizations, 0 Shared Test Fixture Classes, 0 Tags.

Тестовый набор содержит 279 тестовых элементов. Для данного TestClassSetup и параметризации TestMethodSetup, среда создает тестовые элементы 3+10+18=31. Этот 31 элемент называется три раза — однажды для каждой параметризации TestMethodSetup, приводящей к тестовым элементам 3*31=93 для каждой параметризации TestClassSetup. Существует три параметризации TestClassSetup, приводящая к в общей сложности тестовым элементам 3*93=279.

Исследуйте имена первого тестового элемента.

suite(1).Name
ans =

    'TestRand[generator=twister]/[seed=value1]testClass(dim1=small,dim2=small,type=single)'

Имя каждого элемента создается из комбинации следующего:

  • Тестирование класса: TestRand

  • Свойство настройки класса и имя свойства: [generator=twister]

  • Свойство настройки метода и имя свойства: [seed=value1]

  • Имя метода тестирования: тестирование класса

  • Свойства метода тестирования и имена свойства: (dim1=small,dim2=small,type=single)

Имя для свойства seed не особенно значимо (value1). Среда тестирования обеспечила это имя, потому что значения свойств seed являются числами. Для большего количества понятного имени задайте свойство seed как struct с более описательными именами полей.

Выполнение комплекта от класса Используя селектор

В командной строке создайте селектор, чтобы выбрать тестовые элементы, которые тестируют генератор 'twister' на точность 'single'. Не используйте тестовые элементы, которые используют свойства с именем 'large'.

import matlab.unittest.selectors.HasParameter
s = HasParameter('Property','generator', 'Name','twister') & ...
    HasParameter('Property','type', 'Name','single') & ...
    ~HasParameter('Name','large');

suite2 = matlab.unittest.TestSuite.fromClass(?TestRand,s)
suite2 = 

  1×12 Test array with properties:

    Name
    ProcedureName
    TestClass
    BaseFolder
    Parameterization
    SharedTestFixtures
    Tags

Tests Include:
   9 Unique Parameterizations, 0 Shared Test Fixture Classes, 0 Tags.

Если вы сначала генерируете полный комплект, создайте тот же тестовый набор как выше использования метода selectIf.

suite = matlab.unittest.TestSuite.fromClass(?TestRand);
suite2 = selectIf(suite,s);

Запустите тестовый набор.

suite2.run;
Running TestRand
..........
..
Done TestRand
__________

Выполнение комплекта из метода Используя селектор

В командной строке создайте селектор, который не использует тестовые элементы, которые используют свойства с именем 'medium' или 'large'. Ограничьте результаты протестировать элементы из метода testRepeatable.

import matlab.unittest.selectors.HasParameter
s =  ~(HasParameter('Name','large') | HasParameter('Name','medium'));

suite3 = matlab.unittest.TestSuite.fromMethod(?TestRand,'testRepeatable',s);
{suite3.Name}'
ans =

  9×1 cell array

    'TestRand[generator=twister]/[seed=value1]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=twister]/[seed=value2]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=twister]/[seed=value3]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=combRecursive]/[seed=value1]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=combRecursive]/[seed=value2]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=combRecursive]/[seed=value3]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=multFibonacci]/[seed=value1]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=multFibonacci]/[seed=value2]testRepeatable(dim1=small,dim2=small,dim3=small)'
    'TestRand[generator=multFibonacci]/[seed=value3]testRepeatable(dim1=small,dim2=small,dim3=small)'

Запустите тестовый набор.

suite3.run;
Running TestRand
.........
Done TestRand
__________

Запущение всех тестов двойной точности

В командной строке запустите все тестовые элементы от TestRand.m, которые используют название параметра 'double'.

runtests('TestRand','ParameterName','double');
Running TestRand
..........
..........
..........
..........
..........
..........
..........
..........
.
Done TestRand
__________

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

| |

Похожие темы

Была ли эта тема полезной?