在这种情况下,如何确保单元测试保持正确?

时间:2015-02-23 21:49:01

标签: java unit-testing integration-testing

我真的不知道如何简明扼要地解释我的情况,因此我将不得不描述这种情况。

我有一个进程A,它接受一个输入X并产生一个输出Y.我有一个单独的进程B,它接受输入Y(来自进程A)并产生一个输出Z.

流程A和B都很复杂,因此可以从单元测试中受益。进程A和B也可能会发生变化,因此“中间”格式Y会发生变化。

如果我只是对B进行了具有输入Y的单元测试,那么如果进程A发生变化,如何确保它们保持相关性和正确性?例如,进程A将输入“foo”变为“bar”。 B的单元测试将“bar”作为输入并将其转换为“溢出”。如果进程A发生变化并且现在将“foo”变为“fish”,那么我对B的单元测试仍然会通过但是他们的价值是值得怀疑的,因为他们不再测试预期的输入。

解决这种情况的最佳做法是什么?这种情况有名吗?

另外(为了增加复杂性),进程B是Java,但进程A是Visual Basic。

我知道“超越”单元测试和执行集成测试将是一种确保输入X可以成为输出Z的方法,但由于我们对流程B进行了大量测试,我们如何才能确保它们保持相关性? (当一个是Visual Basic而另一个是Java时,这也不容易。)

3 个答案:

答案 0 :(得分:1)

我认为您已经知道答案:集成(端到端)测试。如果设置不可行,您可以做的最好是分别测试X / Y和Y / Z,并确保每当中断(由于代码更改),您更新另一个以保持测试数据相关。

在我看来,投资建立一个合适的集成测试套件会更安全,特别是如果端到端流程符合您用户的期望。最后,他们不会关心你的任何好的单元测试,他们只是想看到你的软件为他们的特定输入做特定的事情。因此,编写端到端行为测试更具有前瞻性,并且可以很好地记录您的软件所做的事情。

答案 1 :(得分:1)

拥有彼此交流的不同系统是一个非常普遍的问题,并且没有一个正确的解决方案。但是,在这个问题的每个例子中,有两种方法可以解决它,你的解决方案将是两者的平衡。

  1. 测试互动

    正如您所建议的,端到端集成测试对于您的应用程序的成功至关重要。它们比单元测试更复杂,更容易出现故障,但它们更加必要。如果您没有进行适当的集成测试(无论什么"适当的"适用于您的应用程序),您根本无法知道您的应用程序是否正常工作 - 您的单元测试将在真空中通过。

    如何执行此操作取决于您的应用程序及其依赖项的业务关键程度。如果您的整个生计依赖于信用卡交易的成功和安全处理,您最好通过某种形式的测试来验证这一点;否则,有一天,你会在愤怒的传呼机上醒来,数百万美元的交易丢失,或者更糟糕的是关于丢失或暴露数据的诉讼。另一方面,您只想以这种方式选择要测试的最重要的东西,因为这样做既昂贵又耗时。

  2. 接受易失性输入

    另一种方法是让你的第二个程序接受尽可能多的输入,并妥善处理它们。您可以对此进行单元测试。设计过程B尽可能容错,并为您希望处理的尽可能多的故障情况编写测试。如果它应该处理foo并将其转换为bar,它应该如何处理FoO?还是f o o?如果它根本没有收到任何输入,它应该如何回应?这种容错是loose coupling的一种类型。

    一般来说,快速和艰难的失败是可取的(即接受一组固定的输入,并在遇到意外情况时引发明显的异常)。但是,当您无法可靠地定义这些输入时,您必须处理所有请求而不会失败。例如,如果您是一个用户可见的网络服务器,那么您无法测试所有输入,因此您必须处理可能会被抛出的任何内容。

  3. 根据您的需求,您希望更多地依赖选项1或选项2.如果没有更多的背景,很难说您应该倾向于多少,但希望这是足以让你思考它。

答案 2 :(得分:0)

如果您还没有准备好采用集成测试,那么一个权宜之计就是使用数据驱动的单元测试。有很多方法可以完成这项工作;当我读到这个问题时,让我印象深刻的是:

  1. 为每个进程使用单独的测试输入和测试验证文件,然后
  2. 将进程A的测试验证文件用作进程B的测试输入文件
  3. 因此,当您更新流程A的验证文件时,流程B的测试将立即失败,提醒您更新流程B的验证文件。当然,当您更新流程B的测试输入文件时,进程A的测试将立即失败,提醒您更新进程A的测试。