Wolfram mathematica 寻找类似JUnit';在MUnit中的s@Before/@After
我在一个.mt文件中编写了许多测试用例,它们共享公共设置(和拆卸)过程。我希望看到像JUnit的Wolfram mathematica 寻找类似JUnit';在MUnit中的s@Before/@After,wolfram-mathematica,Wolfram Mathematica,我在一个.mt文件中编写了许多测试用例,它们共享公共设置(和拆卸)过程。我希望看到像JUnit的@之前/@之后这样的东西,但MUnit软件包中没有任何东西能让我想到这一点。老实说,MUnit包文档比wolframworkbench的MUnit文档要好一点,但它也远远不够完整 所以,在我重新发明轮子之前,我想我应该检查一下,看看我是否遗漏了MUnit中的一些东西,或者是否有人有一种模式可以很好地工作 所以根据Leonid Shifrin最初的答案(他更新了他的答案,而我把它放在一起),这就是我现在
@之前
/@之后
这样的东西,但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
只是一个方便的函数,它不是必需的-只是保存一个辅助变量的引入,以保存之前的结果。它实际上是一个宏,也许是我所知道的有用宏中较小的一个。对不起,如果我的回答不是很清楚。