matlab 使用文件范围的变量进行单元测试,而不使用类

xienkqul  于 8个月前  发布在  Matlab
关注(0)|答案(1)|浏览(74)

假设,不管出于什么原因,我拒绝使用matlab.unittest.TestCase。我试图重现以下Python功能:

# `utils.py` is in same directory as the test file
# `test_wide_variable` gets used inside or outside of test functions
from utils import test_wide_variable

# gets used inside of test functions
file_wide_variable = [1, 2, 3]

def test_func1():
    y = (file_wide_variable, test_wide_variable)
    # ...

# ...

test_func1()
# test_func2()
test_func3()
# ...

尝试

定义reset_test_params.m

global P
P = struct;

然后,测试文件看起来像

reset_test_params

P.file_wide_variable = [1, 2, 3];
P.test_wide_variable = load('test_wide_variables.m').test_wide_variable;

test_func1()
% test_func2()
test_func3()
% ...

function test_func1(~)
    global P
    y = {P.file_wide_variable, P.test_wide_variable};
    % ...

% ...

提问

这种方法有什么明显的缺点吗?特别是,并发文件执行?使用Python,可以在同一个全局命名空间(AFAIK)中同时运行多个测试,因此全局变量是不允许的。

wmomyfyw

wmomyfyw1#

I just learned that you do use the builtin test harness runtests ..其他细节也不清楚,当我写的答案下面的休息。以下是避免使用全局变量的建议:
你需要做的就是以function <name>开始文件,并以end结束。这将把内部的所有测试函数转换为嵌套函数,如下所述。现在删除所有提到的关键字global,事情应该像你期望的那样工作,使用文件范围的变量在你的文件中的测试函数之间共享,而不是跨文件。
我仍然强烈建议不要从代码中调用脚本,下面描述了一些危险。将其转换为返回常量数据的函数并不费力。

原始答案:

你的Python脚本,我们称之为my_tests.py

from utils import test_wide_variable

# gets used inside of test functions
file_wide_variable = [1, 2, 3]

def test_func():
    y = (file_wide_variable, test_wide_variable)
    # ...

可能会被测试工具调用,

from inspect import getmembers, isfunction

import my_tests
for name, func in getmembers(my_tests, isfunction):
   func()

或者类似的东西(我甚至还没有测试过这个代码)。
你的MATLAB脚本,让我们称之为my_tests.m

reset_test_params

P.file_wide_variable = [1, 2, 3];
P.test_wide_variable = load('test_wide_variables.m').test_wide_variable;

function test_func(~)
    global P
    y = {P.file_wide_variable, P.test_wide_variable};
    # ...

当调用测试装具时,

my_tests

或等效地

run("my_tests")

将导致P在测试工具的工作区中被定义(希望不会破坏任何局部变量!)). test_func(),然而,丢失了。脚本本身不会调用它,因此它保持未使用和未定义状态。作为一个本地函数,它只能从my_tests.m内部调用。
因此,试图直接复制Python的测试脚本格式是不可能的,因为这两种语言在这些方面的工作方式根本不同。
还要注意的是,当您从另一个脚本或函数(在MATLAB中)中调用脚本时,它的所有变量都将在调用者的工作区中定义。这意味着脚本可能会覆盖调用方的任何变量。使用脚本来构建一个更复杂的软件是一个非常糟糕的主意,试图将所有脚本的变量分开是一场噩梦。这正是函数的作用所在。函数有一个局部作用域,这使得组合变得容易得多。
除了(可能)程序的入口点之外,我不会使用脚本。其他的都应该是函数。没有理由不使用函数。
这就是我如何尝试在MATLAB中重现Python格式:
test_wide_variable.m

function v = test_wide_variable
v = [5, 6, 7];

my_tests.m

function funcs = my_tests
   file_wide_variable = [1, 2, 3];
   data = test_wide_variable

   funcs = {@test_func};  % list all the test functions defined in the file

   function test_func
      y = {file_wide_variable, data};
      % ...
   end

end

现在可以从测试工具调用它,如下所示:

fail = 0
total = 0
for func = my_tests
   total = total + 1;
   try
      func()
   catch ME
      disp(ME)
      fail = fail + 1;
   end
end
disp(fail + "tests failed out of " + total " tests.")

请注意,在函数my_tests()中局部声明的变量可用于该函数中定义的嵌套函数(请注意,这些函数在my_tests()functionend语句之间声明,因此它们是嵌套函数,而不是局部函数。
my_tests()函数返回一个单元数组,其中包含嵌套函数的句柄。然后,这些可以由调用测试工具调用。当被调用时,它们仍然可以访问在my_tests中定义的变量,就像第一次获得函数句柄时一样--这些是lambda捕获。

相关问题