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

创建高级自定义脚手架

此示例演示如何创建设置环境变量的自定义脚手架。在测试之前,该脚手架将保存当前 UserName 变量。

创建 UserNameEnvironmentVariableFixture 类定义

在您的工作文件夹下的文件中,创建一个从 matlab.unittest.fixtures.Fixture 类继承的新类 UserNameEnvironmentVariableFixture。因为您希望向该脚手架传递用户名,所以创建一个 UserName 属性来在不同方法之间传递数据。

classdef UserNameEnvironmentVariableFixture < ...
        matlab.unittest.fixtures.Fixture
    
    properties (SetAccess=private)
        UserName
    end

定义脚手架构造函数

UserNameEnvironmentVariableFixture.m 文件的 methods 块中,创建一个构造函数方法来验证输入并定义 SetupDescription。让构造函数接受字符向量并设置该脚手架的 UserName 属性。

    methods
        function fixture = UserNameEnvironmentVariableFixture(name)
            validateattributes(name, {'char'}, {'row'}, '','UserName')
            fixture.UserName = name;
            fixture.SetupDescription = sprintf( ...
                'Set the UserName environment variable to "%s".',...
                fixture.UserName);
        end

实现设置方法

Fixture 类的子类必须实现 setup 方法。使用此方法保存原始 UserName 变量。此方法还定义 TeardownDescription 并注册拆解任务:测试后将 UserName 设置为原始状态。

UserNameEnvironmentVariableFixture.m 文件的 methods 块中定义 setup 方法。

        function setup(fixture)
            originalUserName = getenv('UserName');
            fixture.assertNotEmpty(originalUserName, ...
                'An existing UserName environment variable must be defined.')
            fixture.addTeardown(@setenv, 'UserName', originalUserName)
            fixture.TeardownDescription = sprintf(...
                'Restored the UserName environment variable to "%s".',...
                originalUserName);
            setenv('UserName', fixture.UserName)
        end
    end

实现 isCompatible 方法

如果构造函数可配置,派生自 Fixture 的类必须实现 isCompatible 方法。因为您可以通过构造函数配置 UserName 属性,所以 UserNameEnvironmentVariableFixture 必须实现 isCompatible

isCompatible 方法是通过同一类的两个实例调用的。本例中,它是通过 UserNameEnvironmentVariableFixture 的两个实例调用的。如果这两个实例的 UserName 属性相等,则测试框架将这两个实例视为是兼容的。

UserNameEnvironmentVariableFixture.m 内的新 methods 块中,定义一个返回逻辑值 1 (true) 或逻辑值 0 (false) 的 isCompatible 方法。

    methods (Access=protected)
        function bool = isCompatible(fixture, other)
            bool = strcmp(fixture.UserName, other.UserName);
        end
    end

脚手架类定义总结

以下是 UserNameEnvironmentVariableFixture.m 的完整内容。

classdef UserNameEnvironmentVariableFixture < ...
        matlab.unittest.fixtures.Fixture
    
    properties (SetAccess=private)
        UserName
    end
    
    methods
        function fixture = UserNameEnvironmentVariableFixture(name)
            validateattributes(name, {'char'}, {'row'}, '','UserName')
            fixture.UserName = name;
            fixture.SetupDescription = sprintf( ...
                'Set the UserName environment variable to "%s".',...
                fixture.UserName);
        end
        
        function setup(fixture)
            originalUserName = getenv('UserName');
            fixture.assertNotEmpty(originalUserName, ...
                'An existing UserName environment variable must be defined.')
            fixture.addTeardown(@setenv, 'UserName', originalUserName)
            fixture.TeardownDescription = sprintf(...
                'Restored the UserName environment variable to "%s".',...
                originalUserName);
            setenv('UserName', fixture.UserName)
        end
    end
    
    methods (Access=protected)
        function bool = isCompatible(fixture, other)
            bool = strcmp(fixture.UserName, other.UserName);
        end
    end
end

将自定义脚手架应用于单个测试类

在您的工作文件夹下的文件中,创建以下测试类 ExampleTest.m

classdef ExampleTest < matlab.unittest.TestCase
    methods(TestMethodSetup)
        function mySetup(testCase)
            testCase.applyFixture(...
                UserNameEnvironmentVariableFixture('David'));
        end
    end
    
    methods (Test)
        function t1(~)
            fprintf(1, 'Current UserName: "%s"', getenv('UserName'))
        end
    end
end

该测试对 ExampleTest 类中的每个测试使用 UserNameEnvironmentVariableFixture

在命令提示符下运行测试。

run(ExampleTest);
Running ExampleTest
Current UserName: "David".
Done ExampleTest
__________

将自定义脚手架应用为共享脚手架

在您的工作文件夹中,使用共享脚手架创建三个测试类。使用共享脚手架允许跨类共享 UserNameEnvironmentVariableFixture

按如下所示创建 testA.m

classdef (SharedTestFixtures={...
        UserNameEnvironmentVariableFixture('David')}) ...
        testA < matlab.unittest.TestCase
    methods (Test)
        function t1(~)
            fprintf(1, 'Current UserName: "%s"', getenv('UserName'))
        end
    end
end

按如下所示创建 testB.m

classdef (SharedTestFixtures={...
        UserNameEnvironmentVariableFixture('Andy')}) ...
        testB < matlab.unittest.TestCase
    methods (Test)
        function t1(~)
            fprintf(1, 'Current UserName: "%s"', getenv('UserName'))
        end
    end
end

按如下所示创建 testC.m

classdef (SharedTestFixtures={...
        UserNameEnvironmentVariableFixture('Andy')}) ...
        testC < matlab.unittest.TestCase
    methods (Test)
        function t1(~)
            fprintf(1, 'Current UserName: "%s"', getenv('UserName'))
        end
    end
end

在命令提示符下运行这些测试。

runtests({'testA','testB','testC'});
Setting up UserNameEnvironmentVariableFixture
Done setting up UserNameEnvironmentVariableFixture: Set the UserName environment variable to "David".
__________

Running testA
Current UserName: "David".
Done testA
__________

Tearing down UserNameEnvironmentVariableFixture
Done tearing down UserNameEnvironmentVariableFixture: Restored the UserName environment variable to "Kim".
__________

Setting up UserNameEnvironmentVariableFixture
Done setting up UserNameEnvironmentVariableFixture: Set the UserName environment variable to "Andy".
__________

Running testB
Current UserName: "Andy".
Done testB
__________

Running testC
Current UserName: "Andy".
Done testC
__________

Tearing down UserNameEnvironmentVariableFixture
Done tearing down UserNameEnvironmentVariableFixture: Restored the UserName environment variable to "Kim".
__________

请记住,如果脚手架的 UserName 属性匹配,则它们是兼容的。testAtestB 中的测试使用了不兼容的共享脚手架,因为 'David' 不等于 'Andy'。因此,该框架在对 testAtestB 的各次调用中调用脚手架的 teardownsetup 方法。不过,testC 中的共享测试脚手架与 testB 中的脚手架兼容,因此该框架在 testC 之前不重复脚手架拆解和设置。

在设置方法中调用 addTeardown 的替代方法

setup 方法中使用 addTeardown 方法的替代方法是实现单独的 teardown 方法。实现 UserNameEnvironmentVariableFixture.m 中的以下 setupteardown 方法,而不是上述的 setup 方法。

 替代 UserNameEnvironmentVariableFixture 类定义

setup 方法不包含对 addTeardown 的调用或 TeardownDescription 的定义。这些任务转移到了 teardown 方法。替代类定义包含一个额外属性 OriginalUser,该属性允许在各方法之间传递信息。

另请参阅

相关主题