Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wolfram mathematica 寻找类似JUnit';在MUnit中的s@Before/@After_Wolfram Mathematica - Fatal编程技术网

Wolfram mathematica 寻找类似JUnit';在MUnit中的s@Before/@After

Wolfram mathematica 寻找类似JUnit';在MUnit中的s@Before/@After,wolfram-mathematica,Wolfram Mathematica,我在一个.mt文件中编写了许多测试用例,它们共享公共设置(和拆卸)过程。我希望看到像JUnit的@之前/@之后这样的东西,但MUnit软件包中没有任何东西能让我想到这一点。老实说,MUnit包文档比wolframworkbench的MUnit文档要好一点,但它也远远不够完整 所以,在我重新发明轮子之前,我想我应该检查一下,看看我是否遗漏了MUnit中的一些东西,或者是否有人有一种模式可以很好地工作 所以根据Leonid Shifrin最初的答案(他更新了他的答案,而我把它放在一起),这就是我现在

我在一个.mt文件中编写了许多测试用例,它们共享公共设置(和拆卸)过程。我希望看到像JUnit的
@之前
/
@之后
这样的东西,但MUnit软件包中没有任何东西能让我想到这一点。老实说,MUnit包文档比wolframworkbench的MUnit文档要好一点,但它也远远不够完整

所以,在我重新发明轮子之前,我想我应该检查一下,看看我是否遗漏了MUnit中的一些东西,或者是否有人有一种模式可以很好地工作

所以根据Leonid Shifrin最初的答案(他更新了他的答案,而我把它放在一起),这就是我现在的位置

TestPlus.mt

(* Mathematica Test File *)

(* x is a global value *)
x=0;

SetUp[] := Module[{}, x=1;];
TearDown[] := Module[{}, x=0;];

(* test SetUp[] *)
SetUp[];       
Test[x, 1, TestID->"SetUp-20120103-F2U9V6"]

(* test TearDown[] *)
TearDown[];
Test[x, 0, TestID->"TearDown-20120103-O4R6M7"]

(* test plus --contrived tests-- *)
SetUp[];
Test[x+0, 1, TestID->"Plus-20120103-S5D9X6"]
TearDown[];

SetUp[];
Test[x+1, 2, TestID->"Plus-20120103-D7Q3E0"]
TearDown[];

SetUp[];
Test[x+2, 3, TestID->"Plus-20120103-F0S4P9"]
TearDown[];

MUnit
文件是普通的包文件,它们是按顺序读取和执行的——至少这是我对它们的经验。您只需在测试之前和之后添加带有公共代码的行,它们将分别在所有测试之前和之后执行

如果您想单独调用每个测试的设置和teardown过程,那么可以在每次测试之前和之后添加相应的行(调用)。然后,您可能会发现编写一个预处理器很方便,它将把您的测试作为一个包加载(例如,通过使用
Import[“tests.tm”,“HeldExpressions”]
——在本例中,您的测试位于
tests.tm
),插入相应的行,然后再次保存文件。这将需要熟练地使用保留的代码进行操作,但是可以很快地掌握,并且如果您有许多测试,这是非常方便的

编辑

作为更轻量级的替代方案,您可以定义类似宏的快捷方式。以下是测试文件内容的示例:

(* Mathematica Test File *)

before[]:= (Print["Before Test: ",f[2]];f[x_]:=x^3);
after[] := (ClearAll[f];Print["After Test: ",f[2]]);

SetAttributes[withCodeAfter,HoldRest];
withCodeAfter[before_,after_]:=(after;before)

SetAttributes[{wrapTest,wrapTest1},HoldAll]
wrapTest[code_]:= withCodeAfter[before[];code,after[]]  
wrapTest1[code_]:=Block[{f},f[x_]:=x^3;code];

wrapTest@
Test[f[2],
  8,
  TestID -> "MyTest1"
]

wrapTest1@
Test[f[2],
  8,
  TestID -> "MyTest2"
]

和后
功能模拟您的设置/拆卸功能。函数
withCodeAfter
是一个帮助宏,它首先在
之前执行code
,然后在
之后执行code
,但结果返回
之前的结果。函数
wrapTest
wrapTest1
说明了两种可能性:您可以定义单独的“before”和“after”函数并将代码与它们夹在一起,或者可以使用
Block
并定义“around”宏,这有时可能更方便。测试将以任何方式工作。您还可以混合使用这些方法。在这两种情况下,样板代码的数量都是最小的-只需在每次测试之前添加
wrapTest@
行。

我无法在注释中获得正确的格式,因此我这样做是为了回答

好的,我想我已经在你的答案中解析了代码,请让我知道我是否正确


定义在评估“测试用例”之前和之后评估的内容。旁注,您在
之前的
中定义
f
,在
之后的
中取消定义
f

(* Mathematica Test File *)

before[]:= (Print["Before Test: ",f[2]];f[x_]:=x^3);
after[] := (ClearAll[f];Print["After Test: ",f[2]]);
SetAttributes[withCodeAfter,HoldRest];
withCodeAfter[before_,after_]:=(after;before)

使用CODEAFTER定义函数
。它需要两个表达式,第一个表达式是
之前的
,传入时进行计算。第二个表达式,
after
,在未计算的情况下传递,是在
withcodefter
中要计算的第一个表达式。计算出的第一个表达式
before
,由
withcodefeater
返回

(* Mathematica Test File *)

before[]:= (Print["Before Test: ",f[2]];f[x_]:=x^3);
after[] := (ClearAll[f];Print["After Test: ",f[2]]);
SetAttributes[withCodeAfter,HoldRest];
withCodeAfter[before_,after_]:=(after;before)

定义函数
wrapTest
。它采用一个表达式,
code
,该表达式未经计算而传入。该表达式,
code
,是复合表达式的第二个表达式,
在[]之前;代码
,作为第一个表达式在
之前传递到
之后的
。复合表达式,
在[]之前;代码
,在通过CodeAfter传递到
时进行计算。被求值表达式的值,
code
,由被求值的
之后的
withcodefeater
返回。
withCodeAfter
返回的值由
wrapTest
返回

SetAttributes[{wrapTest},HoldAll]
wrapTest[code_]:= withCodeAfter[before[];code,after[]]

这与调用
wrapTest[Test[f[2],8,TestID->“MyTest1”是一样的


好吧,我用一个蹩脚的例子更新了我的问题,我以为你在说什么。现在,我明白你在说什么了。Thanks@mmorris谢谢你的接受。你的更新确实是我最初回答中的意思。我的更新只是为了展示如何以相对最小的努力减少样板代码的数量。请参见下面的答案。谢谢MikeYes,你完全正确-这正是正在发生的事情。函数
withCodeAfter
只是一个方便的函数,它不是必需的-只是保存一个辅助变量的引入,以保存
之前的结果。它实际上是一个宏,也许是我所知道的有用宏中较小的一个。对不起,如果我的回答不是很清楚。