如何简化Java中无副作用的方法的测试?

use*_*558 1 java junit unit-testing functional-testing

函数(无副作用)是一个基本的构建块,但我不知道用Java测试它们的令人满意的方法.

我正在寻找能够更轻松地测试它们的技巧.这是我想要的一个例子:

public void setUp() {
   myObj = new MyObject(...);
}

// This is sooo 2009 and not what I want to write:
public void testThatSomeInputGivesExpectedOutput () {
   assertEquals(expectedOutput, myObj.myFunction(someInput);
   assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
   // I don't want to repeat/write the following checks to see
   // that myFunction is behaving functionally.
   assertEquals(expectedOutput, myObj.myFunction(someInput);
   assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);

}


// The following two tests are more in spirit of what I'd like 
// to write, but they don't test that myFunction is functional:
public void testThatSomeInputGivesExpectedOutput () {
   assertEquals(expectedOutput, myObj.myFunction(someInput);
}

public void testThatSomeOtherInputGivesExpectedOutput () {
   assertEquals(expectedOtherOutput, myObj.myFunction(someOtherInput);
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找一些我可以放在测试,MyObject或myFunction上的注释,以使测试框架在我给出的给定输入/输出组合的所有可能的排列中自动重复调用myFunction,或者某些子集可能的排列,以证明该功能是功能性的.

例如,在(仅)两个可能的排列之上是:

  • myObj = new MyObject();
  • myObj.myFunction(someInput);
  • myObj.myFunction(someOtherInput);

和:

  • myObj = new MyObject();
  • myObj.myFunction(someOtherInput);
  • myObj.myFunction(someInput);

我应该只能提供输入/输出对(someInput,expectedOutput)和(someOtherInput,someOtherOutput),框架应该完成剩下的工作.

我没有使用过QuickCheck,但它看起来像是一个非解决方案.它被记录为发电机.我不是在寻找一种方法来为我的函数生成输入,而是一个框架,它允许我声明性地指定我的对象的哪个部分是无副作用的,并使用基于该声明的一些排列来调用我的输入/输出规范.

更新:我不打算验证对象没有任何变化,memoizing函数是这种测试的典型用例,而memoizer实际上改变了它的内部状态.但是,给定输入的输出始终保持不变.

Ste*_*n C 7

如果你试图测试这些函数无副作用的,那么用随机参数调用并不会真正削减它.这同样适用于具有已知参数的随机调用序列.或伪随机,随机或固定种子.很有可能只有在随机发生器选择的任何调用序列中才会发生(有害的)副作用.

无论输入是什么,也有可能在您正在进行的任何调用的输出中实际上看不到副作用.它们的副作用可能是你想不到的其他一些相关对象.

如果你想测试这种东西,你真的需要实现一个"白盒"测试,你可以看一下代码并试着找出可能导致(不需要的)副作用的原因并根据这些知识创建测试用例.但我认为更好的方法是仔细的手动代码检查,或使用自动静态代码分析器......如果你能找到一个能为你完成工作的人.

OTOH,如果您已经知道这些功能是无副作用的,那么实施随机测试"以防万一"有点浪费时间,IMO.