TDD用于随机算法

时间:2012-08-28 14:10:03

标签: java unit-testing testing tdd

我的测试有问题。有一种算法用于一些奇特的程序。该算法从一个范围[-999,999; +999,999],将其视为表中的id号,并在数据库中执行一些随机操作。这意味着我需要多次调用该方法以确保随机数分布正确。

我想使用TDD制作所有代码(只是为了更多地学习它)。

问题是我不知道如何用TDD原理测试算法。

根据TDD,如果不首先编写测试,则不应运行代码。

我想到的解决方案之一是在主类中有一个名为debug(text)的虚方法。此方法在生产代码中不执行任何操作。然而,我会使这个方法的子类重载,这次它会存储一些有趣的信息。以后可以通过测试使用此信息来确定函数是否正常工作。数据库连接将被模拟,不会做任何事情。

另一个解决方案是创建一个模拟的数据库连接,该连接将存储稍后在测试中使用的有趣信息。然而,创建这样的连接将是如此巨大的工作,我认为不值得花时间在它上面。

稍后将进行集成测试以检查数据库是否正确更改。但集成测试不是TDD的一部分。

我是否进入过TDD失败且无用或难以使用的地方?

3 个答案:

答案 0 :(得分:8)

你的随机数函数吗?

它是:随机数生成器应该在使用它的任何东西之外进行测试。

它不是:你根本不应该测试它,除非你真的需要验证它是多么随机。 IMO不是很好的投资回报率,但它完全取决于您的实际需求。

数据库功能应该假设RNG实际上是R,并且应该从RNG单独测试 - 在测试期间您可能不想使用RNG。至少,您可能想要使RNG播种以使测试可重复 - 这可能使正确性更难以验证。

答案 1 :(得分:1)

你应该再考虑一下你的设计。单元测试(通过TDD或稍后添加测试)应该完全隔离测试每个类。

在您的情况下,您有一些不同的功能:

  • 随机数生成器
  • 数据库中的查找
  • 针对数据库运行的一些代码

通过使用Dependency InjectionMocking等设计模式,可以完全隔离彼此中的每一个。

单元测试不应该依赖于随机行为。这样他们就会变得脆弱,难以维持。

因此,在您的情况下,您将通过运行大量次数并检查结果是否在预期范围内来测试随机数生成器。无论何时何地,该测试每次运行都应该成功。

对于数据库部分,我将创建一个隐藏数据库代码的界面(查看Repository pattern)。在单元测试中,您可以模拟此接口并检查是否使用正确的参数调用了正确的函数。在集成测试中,您可以使用真正的Repository实现。

然后第二个测试检查您的数据库查找是否正常工作。检查传递的“随机数”是否正确用于在数据库模拟上调用正确的方法。

第三个测试将检查是否对数据库mock执行了正确的代码。

几个月前,我为.NET杂志撰写了一篇关于单元测试和一些最佳实践的文章。也许它可以提供帮助:Unit Testing, hell or heaven?

答案 2 :(得分:1)

以下是您的代码库的一些假设:

1)对存储过程的调用是数据访问代码。

2)数据访问代码实现了一个接口。

3)您想用TDD编写的业务逻辑可以将数据访问代码注入其构造函数。

如果是这种情况,您可以使用模拟框架来模拟数据访问代码。实际的存储过程没有被调用。

可以使用TDD开发新代码。