将设置函数与子类中的测试一起使用

San*_*ios 5 matlab unit-testing

我正在为处理时间序列数据的MATLAB软件包编写测试套件。程序包使用用户编写的函数格式化来自各种提供程序的数据,这些函数将标准输入解析为正确的样式,然后使用“数据提要”工具箱来请求数据。例如,Bloomberg history调用的输入与Haver fetch调用的输入不同,但是我可以对任一调用使用标准语法,因为我将用户编写的函数中的输入解析为正确的语法。

因为我的每个用户编写函数都必须具有相似的行为,所以在设计测试套件时,我编写了myparentclass.m(继承自matlab.unittest.TestCase)来测试所有函数的常规行为。此外,由于某些用户编写的函数需要特殊输入,因此我mychilclass*.m为继承myparentclass.m并执行更具体测试的每个提供程序编写了一组子类。也就是说,当我执行时runtests('mychildclass1'),我同时在mychildclass1.m和中都运行了方法myparentclass.m。我利用其中的setupOnce函数mychildclass1.m来设置用户编写的特定于函数的行为,这些行为是的初始化属性myparentclass.m

mychildclass2.m遇到的问题是我的测试之一需要初始化目录,然后将随机数据存储在该目录中。当前,setupOncein mychildclass2.m如下所示:

testDir = fullfile(pwd(), 'testdir');
if isequal(exist(testDir, 'dir'), 7)
    rmdir(testDir, 's')
end
mkdir(testDir);

startDate = datetime('01-Jan-2018');
endDate = datetime('today');
myDates = transpose(startDate:calmonths(1):endDate);
numDates = length(myDates);
mySeries = randi(10, numDates, 1);
myTable = table(myDates, mySeries);

fname = fullfile(testDir, 'myTable.csv')
writetable(myTable, fname)
Run Code Online (Sandbox Code Playgroud)

我注意到的是,相反的是我认为,该setupOnce功能实际上是在开始时执行通过所谓的测试mychildclass2.m(即包括在myparentclass.m),而不是只有一次。我相信这可能是类继承的结果,或者是MATALB执行功能的顺序的结果,但是我不确定。请注意,由于mychildclass1.m不需要此文件夹包含数据,因此我不想在中初始化文件夹myparentclass.m

问题是,如何正确地在其中编写一个setup函数,mychildclass2.m以便在所有测试之前仅将数据写入一次?类似的问题是teardown在所有测试结束后如何编写函数以删除文件夹。

sti*_*ke4 3

我认为这里的问题是您使用的是 TestMethodSetup 而不是 TestClassSetup。请参阅 Mathworks 文档:使用类编写安装和拆卸代码

相关部分是

  • TestMethodSetup 和 TestMethodTeardown 方法在每个测试方法之前和之后运行。
  • TestClassSetup 和 TestClassTeardown 方法在测试用例中的所有测试方法之前和之后运行。

编辑以充实答案

以下是如何编写此内容的示例:

classdef mychildclass2 < myparentclass

  properties
    fname
  end

  methods (TestClassSetup)
    function createTestTable(testCase)
      startDate = datetime('01-Jan-2018');
      endDate = datetime('today');
      myDates = transpose(startDate:calmonths(1):endDate);
      numDates = length(myDates);
      mySeries = randi(10, numDates, 1);
      myTable = table(myDates, mySeries);

      testCase.fname = tempname;
      writetable(myTable, testCase.fname);
      testCase.addTeardown(@delete, testCase.fname);
    end
  end

  methods (Test)

    function unitTest1(testCase)
      % Do test 1 here
    end

    function unitTest2(testCase)
      % Do test 2 here
    end

  end

end

Run Code Online (Sandbox Code Playgroud)

请注意以下几点:

  1. 您不需要TestClassSetup使用关键字setup或来命名方法块中的函数setupOnce。这些似乎仅在您使用基于函数的单元测试框架时才使用,请参见1

  2. TestClassTeardown我没有使用该方法,而是使用了该addTeardown方法。这是上面链接的文档所建议的。请参阅2的示例。

  3. 我已经删除了目录的创建,testdir因为它没有多大作用。相反,您可以仅使用该tempname函数为此数据创建临时文件。如果您绝对需要一个目录,请使用tempname函数的结果作为目录并将您的目录放入myTable.csv其中。

testDir = tempname;
mkdir(testDir);
testCase.addTeardown(@rmdir, testCase.fname);
testCase.fname = fullfile(testDir, 'myTable.csv');
writetable(myTable, testCase.fname);
testCase.addTeardown(@delete, testCase.fname);
Run Code Online (Sandbox Code Playgroud)

  • Excellent answer. Couple quick suggestions: 1) For the benefits of addTeardown, which I also like, read this: https://blogs.mathworks.com/developer/2015/07/27/addteardown/ 2) For creating the temporary folder, consider using TemporaryFolderFixture: https://www.mathworks.com/help/matlab/ref/matlab.unittest.fixtures.temporaryfolderfixture-class.html (3认同)