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

Integration test fails all unit tests succeed, whats the conclusion?

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

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

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

编辑:

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

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

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

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

好吧,我的测试有100%的代码覆盖率,我创建了由我的测试检测到的突变体,所以外观似乎很好。

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

1
2
3
4
5
6
7
8
9
// 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?或者正如我在原帖中所说的那样..如果集成测试捕获错误就足够了。

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


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

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

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

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

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

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

您应该注意的一个例子是状态更改,通常是由于void方法而发生的事情,但肯定可能是任何类型操作的副作用。这可能会干扰您在其他测试中所做的假设。

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

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


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

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

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

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

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

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


你在listContainer上调用了"reset",然后处理程序处于不期望的状态?

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

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

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