首页 > 解决方案 > 在子类中使用带有测试的设置函数

问题描述

我正在为处理时间序列数据的 MATLAB 包编写测试套件。该包使用用户编写的函数对来自各种提供者的数据进行格式化,这些函数将标准输入解析为正确的样式,然后使用 Datafeed Toolbox 请求数据。例如,Bloomberghistory调用的输入与 Haver 调用的输入不同fetch,但我可以使用标准语法调用任何一个,因为我将用户编写的函数中的输入解析为正确的语法。

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

我遇到的问题是我的一个测试mychildclass2.m需要初始化一个目录并将随机数据存储在那里。目前,setupOnceinmychildclass2.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)

我注意到的是,与我的想法相反,该setupOnce函数实际上是在每个由(即,包括 )调用的测试开始时执行的,mychildclass2.m不是只myparentclass.m执行一次。我相信这可能是类继承或 MATALB 执行函数的顺序的结果,但我不确定。请注意,由于mychildclass1.m不需要此文件夹和数据,我不想在myparentclass.m.

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

标签: matlabunit-testing

解决方案


我认为这里的问题是您使用的是 TestMethodSetup 而不是 TestClassSetup。请参阅 Mathworks 文档:Write Setup and Teardown Code Using Classes

相关部分是

  • 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

注意几点:

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

  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);

推荐阅读