开发区域

先进与MATLAB软件开发

不要嘲笑我!

嗨,伙计们,这是很长一段时间!谢谢你的耐心,我们有很多伟大的在博客上孵化的话题讨论。今天我激动大卫·赫鲁斯卡对此介绍谁是一个令人兴奋的新开发的模拟框架,是R2017b MATLAB的一部分,他在这里与你探讨一下。享受吧!

你编写代码时模拟吗?不,我不是在说什么嘲笑。我说的是用模拟对象代替被测系统的依赖性驱动系统行为的特定方式,或验证如何与它的合作者。MATLAB释放2017包括一个嘲笑框架这一目的。让我们来看一个例子在行动在实践中这意味着什么。这里的接口迭代器我们将使用的类。

classdef迭代器<处理属性(抽象,SetAccess =私人)值;结束方法(抽象)bool = hasNext (iter);推进(iter);结束结束

这就是我们想要测试一个算法。它决定了如果一个值是在迭代器。

函数bool = hasValue (iter) validateattributes (iter, {迭代器的},{“标量”},“hasValue”);validateattributes(价值,{“数字”},{“非空的”},“hasValue”);bool = false;iter。hasNext iter.advance;如果iter。bool值= =价值= true;结束结束结束

构建一个模拟

构建一个模拟,调用createMock的方法matlab.mock.TestCase类。通常这将是内部使用的测试方法来源于一个类matlab.mock.TestCase。然而,对于互动实验在命令行中,我们将首先使用forInteractiveUse静态方法获得TestCase实例。调用createMock方法是创建一个模拟对象所需的。实现必要的抽象的框架创建一个类的属性和方法的接口,并构造一个实例。createMock还返回一个相关行为控制模拟的对象。

testCase = matlab.mock.TestCase.forInteractiveUse;[mockIterator、行为]= testCase.createMock迭代器(?);

模拟做一些有用的东西,我们需要定义其行为。行为规范读起来像是一个句子:

进口matlab.mock.actions.AssignOutputs;当((behavior.Value),然后(AssignOutputs(1),然后(AssignOutputs(2),然后(AssignOutputs (3)))));

这是什么这段代码:当价值属性访问,第一次返回一个值1。下次访问属性时,返回一个值2。最后,返回3对于任何后续属性访问。

我们也建立了hasNext方法返回真正的第一个是调用的三倍之后。使用withAnyInputs指定此行为应该执行无论任何额外的输入传递给方法。

当(withAnyInputs (behavior.hasNext),然后(重复(3,AssignOutputs(真正的)),然后(AssignOutputs(假))));

定义了一些基本的行为后,我们现在可以使用模拟测试算法。

结果= hasValue (mockIterator 2);testCase.verifyTrue(结果,“预计hasValue找到2。”);
交互式验证通过。

模拟迭代器返回成立1,然后2,然后3;的hasValue函数找到了2;我们已经验证了这一结果。太棒了!

上面的示例使用一个方法有时被称为存根:我们已经建立了一个模拟返回驱动系统在一个特定的预定义的反应方式。我们也可以间谍如何系统与它的依赖性。让我们建立一个新的模拟行为并将其传递给略有不同hasValue

[mockIterator、行为]= testCase.createMock迭代器(?);当((behavior.Value),然后(AssignOutputs (1)));当(withAnyInputs (behavior.hasNext),然后(重复(10,AssignOutputs(真正的)),然后(AssignOutputs(假))));结果= hasValue (mockIterator, 1);testCase.assertTrue(结果,“预计hasValue找到1。”);
通过交互式的断言。

我们已经定义了模拟总是返回值1当它价值属性访问。的hasNext方法返回真正的第一个10倍,表明有10迭代器中的值。这将是合理的期望的有效实现hasValue“短路”一旦发现第一个值,停止检查剩下的元素的迭代器。这是发生了什么,看看。模拟时,它会自动开始录音信息交互。除了定义模拟应该如何行动,行为还提供了访问这个间谍信息。让我们使用这个信息来验证价值是完全访问一次,作为一个有效的实现。

进口matlab.mock.constraints.WasAccessed;testCase.verifyThat(行为。价值,WasAccessed (“WithCount”1),“期望值”只被访问一次。);
交互式验证失败。- - - - - - - - - - - - - - - - -测试诊断:- - - - - - - - - - - - - - - - -期望值只访问一次。- - - - - - - - - - - - - - - - - - - - - - - -框架诊断:- - - - - - - - - - - - - - - - - - - - - - - - WasAccessed失败了。- - >属性“价值”不是预期的访问次数。实际属性访问数:10预期属性访问数:1指定属性访问:PropertyGetBehavior < IteratorMock_1 > value

资格的失败是因为算法访问属性10次了。这可能是解决由函数立即返回后发现第一个实例所需的值。

函数bool = efficientHasValue (iter) validateattributes (iter, {迭代器的},{“标量”},“efficientHasValue”);validateattributes(价值,{“数字”},{“非空的”},“efficientHasValue”);bool = false;iter。hasNext iter.advance;如果iter。bool值= =价值= true;%完成了!我们发现价值。返回;结束结束结束

回到原来的算法,让我们编写一个测试。这一次让我们写一个负面测试,以确保适当的错误检查的执行价值输入hasValue,拒绝空值。对于这个测试,我们甚至不打算使用一个迭代器,但我们确实需要提供一个有效的实例也因为函数验证迭代器的输入。因此,我们可以简单地构建一个模拟但没有定义行为。然后传递给函数模拟测试。

dummyIterator = testCase.createMock迭代器(?);testCase.verifyError (@ () hasValue (dummyIterator []),MATLAB: hasValue: expectedNonempty);
交互式验证通过。

与手工模拟

上面的测试可以使用手写执行模拟的子类迭代器接口。之一,然而,这可能导致两件事:许多不同的库存模拟(存根、间谍、假货等)或一个非常复杂的模拟类,甚至可能更复杂,你要测试的代码!例如,我们可能想重用的手写存根或间谍负面测试上面可能导致不良的耦合。通过使用模拟框架,我们实现每个测试的独立性。

同时,随着设计的发展,可能会改变你的接口:可以添加新的抽象的属性或方法。或者访问权限可能会改变。这尤其可能在开发过程的早期。手写的模拟需要单独relect更改界面更新。模拟框架,另一方面,自动实现所需的所有抽象成员接口使用正确的访问权限createMock被称为。

总之,手工模拟相比,嘲笑框架提供了

  • 隔离和独立不同的测试
  • 用更少的附加文件清晰可见性测试

成本是什么?便利为代价的性能:如果你经常重用相同的模拟类,手动将导致更快的测试执行时间。然而,模拟框架开销可能小到可以在大多数测试场景无关紧要。

还有很多框架可以做,所以检查文档。你嘲笑用于测试工作流?在下面的评论中让我们知道。




发表与MATLAB®R2017a

|
  • 打印

评论

要发表评论,请点击此处登录到您的MathWorks帐户或创建一个新帐户。