集成测试失败所有单元测试成功,结论是什么?

时间:2014-06-13 14:56:52

标签: unit-testing integration-testing

我有一个普遍的问题 我为一堆连接类编写了几个单元测试,所有的单元测试都在成功。

然而,在实现我的第一次集成测试后,我遇到了一些错误,因为我没有考虑类之间的某些共享行为。

我的问题是: 我是否应该修复我的单元测试,因为他们找不到错误?单元测试是不是应该考虑其他类,我只是修改我的生产代码,因为集成测试足以覆盖这些东西。

编辑:

由于回复,似乎有必要进一步指出我的问题。我仍然不确定哪个测试对什么负责。

让我们假设我有一个类(让我们称之为ListClass),它包含一个对象列表,一个索引,一个getCurrentValue和一个incrementIndex函数。我想功能名称不言自明。

索引以-1开头,如果用-1调用getCurrentValue,则返回null

我还有一个重置功能,它将起始索引设置回-1。

好的,我的测试有100%的代码覆盖率,我创建了我的测试检测到的突变体,所以看起来很好。

我的第二个类是一个处理程序,负责在每次调用Handler.Next()时设置所有Permutations。

// listContainer1.index = -1, listContainer2.index = -1,

handler.add(listContainer1) //has 2 values
handler.add(listContainer2) //has 2 values

handler.next() // listContainer1.index = 0, listContainer2.index = 0
handler.next() // listContainer1.index = 0, listContainer2.index = 1
handler.next() // listContainer1.index = 1, listContainer2.index = 0
handler.next() // listContainer1.index = 1, listContainer2.index = 1

再次100%代码覆盖率,检测到突变体(我使用mocking来定义listContainer的行为)

这是破坏代码的集成测试: 在几个handler.next()调用之后,在listContainer上调用reset 因为容器索引是-1,所以下一个handler.next()调用导致了一个不期望的状态。

如何在我的处理程序中预测单元测试中的这种结果而不依赖于我的ListClass?或者正如我在原帖中所说的那样..如果集成测试捕获错误就足够了。

对我而言,单元测试课程似乎都涵盖了自己的责任......

3 个答案:

答案 0 :(得分:3)

首先,您必须确定问题所在。

您的单元测试是否相关?这包括:

  • 他们是否有有意义的断言?
  • 单元测试涵盖了多少代码?
  • 您是否测试它是否在有效条件下工作并且无效?

如果实际出现问题,您只能修复单元测试。通常情况下,您构建测试的方式应该能够依赖它们。考虑到你觉得你不能,你应该把它作为你的第一要务(如果你不能信任它们,那么它们基本上没有价值)。

考虑到开始集成测试时出现的问题,您的第一思路(假设有足够的单元测试)应该是验证集成是否正常。如果外部依赖在某处出错,那么它不一定是程序错误,但可能是一个未正确设置的配置(如数据库连接)。

由于您的情况似乎涉及中断每个人行为的课程,我相信您必须重新审视您的测试设计,因为您可能在那里犯了一些错误。即使单元测试自己的工作,你必须确保它们是孤立的,但你也应该知道一个单元可能不仅仅是一个方法或类(更多关于here)。

你应该注意的一个例子是状态变化,通常是void方法的结果,但肯定可能是任何类型的动作的副作用。这可能会干扰您在其他测试中所做的假设。

由于问题的一般性质,我保持答案非常普遍,但如果你分享一些细节,那么我可以提供更具体的答案。

简而言之:坏的单元测试是不可靠的,因此无用的单元测试;确保它们与您的申请充分相关。

答案 1 :(得分:1)

单元测试检查每个部件是否正常工作。集成测试检查零件是否适合。如果他们中的任何一个能够涵盖你不需要另一个的一切。

仍然 - 最终你需要更改你的单元测试,不是因为它们错了,而是因为如果你的程序组件不适合你,你需要改变界面行为(或代码 - 其中一些是使用其他接口的,这意味着你需要改变一些单元测试。

例如,如果Foo依赖于Bar,则两者都通过单元测试,但是检查它们的集成测试都会失败,这意味着Foo使用的方式有问题Bar。这意味着要么(或两者都有):

  • 您必须更改Bar的行为。这意味着一些Bar单元测试不再有效(因为它们会检查旧行为),您也需要更改它们。

  • 您需要更改Foo使用Bar的方式。这可以打破一些Foo单元测试,您可以将Foo模拟Bar发送给Foo。该模拟是使用旧方法Bar创建的,正在使用{{1}} - 您需要更改它以匹配新的,正确的方式。

仍然 - 这并不意味着新的单元测试能够解决集成问题!

答案 2 :(得分:0)

你打电话给#34;重置"在listContainer上,那么处理程序处于不期望的状态?

当你说"不是预期的状态"这可能意味着你的测试是错误的(状态只是通过测试外部改变,但测试需要其他东西,所以这显然是一个糟糕的测试)。

如果处理程序被外部代码更改其数据而损坏,使其与处理程序维护的另一个内部索引不同步,则集成测试违反了封装。如果它们不是单位,则不能进行单元测试。

如果处理程序是访问listContainer的许多类之一,那么它必须使用listContainer的接口。如果它只是询问listContainer它的状态是什么,它就不会有坏状态。在这种情况下,处理程序完全出错,您需要向处理程序添加新的单元测试。你无法预料到一切,但是当你发现问题时,你可以添加一个检测它的单元测试,然后修复代码以便测试通过。