我应该对不应该在函数中传递的数据(无效输入)进行单元测试吗?

时间:2011-09-07 17:55:27

标签: unit-testing testing tdd

我正在尝试使用TDD进行编码练习。我想问一下,我应该测试一个不应该在函数中发生的数据,但这些数据可能会破坏你的程序。

这是一个简单的例子来说明我的要求:

具有一个INT参数的ROBOT函数。在这个函数中我知道有效范围只有0-100。如果使用-1,101,则该函数将被中断。

function ROBOT (int num){
...
...
...
return result;
}

所以我为这个函数决定了一些自动测试用例......

1. function ROBOT with input argument 0
2. function ROBOT with input argument 1
3. function ROBOT with input argument 10
4. function ROBOT with input argument 100

但是我应该为这个ROBOT函数编写输入参数为-1或101的测试用例,如果我在我的其他函数中保护那个调用函数ROBOT ???

5. function ROBOT with input argument -1
6. function ROBOT with input argument 101

我不知道是否有必要因为我认为测试-1和101是冗余的。如果确实需要覆盖所有情况,我必须编写更多代码来保护-1和101。

所以在TDD的常规实践中,你会在-1和101上编写测试用例吗?

7 个答案:

答案 0 :(得分:10)

是的,你应该测试那些无效的输入。但是,如果您的语言具有辅助功能修饰符且ROBOT()是私有的,则您不应该对其进行测试;你应该只测试公共函数/方法。


功能测试技术称为边界值分析

如果你的范围是0-100,你的边界值是0和100.你应该测试,至少

  • 低于边界值
  • 边界值
  • 高于边界值

在这种情况下:

  

-1,0,1,
  99100101

您假设-1到-infinity以下的所有内容都表现相同,1-99之间的所有内容都表现相同,而101以上的所有内容都表现相同。这称为等效分区。边界值之外和之间的范围称为分区,您可以假设它们具有相同的行为。

您应该始终考虑使用-1作为测试用例,以确保在没有强类型的情况下,如果参数不是强类型,则使用负数和文本字符串不会发生任何有趣的事情。

答案 1 :(得分:7)

如果预期的结果是抛出了带有无效输入值的异常,则适当抛出异常的测试将是合适的。

编辑:

正如我在下面的评论中所指出的,如果这些案例会破坏您的申请,您应该抛出异常。如果这些情况在逻辑上确实不可能发生,那么我会说不,你不需要抛出异常,而且你不需要测试用例来覆盖它。

请注意,如果你的系统组件化很好,并且这个功能是一个组件,那么它在逻辑上不可能现在并不意味着它在逻辑上总是不可能的。它可能会在不同的路上使用。

答案 2 :(得分:5)

您说如果参数无效,您的方法将引发异常。

所以,是的,你应该,因为你应该测试是否会引发异常。

答案 3 :(得分:5)

简而言之,如果它可以破解,那么你应该测试它。也尽可能早地验证数据。

答案取决于您是否控制传递给Robot的输入。如果Robot是内部类(C#);值只从RobotClientX流入,这是一个公共类型。然后我将看守检查放在RobotClientX中,为它编写测试。我不会为Robot编写测试,因为无效值无法实现。 例如如果我将我的验证放在GUI中,以便在源处过滤掉所有无效值,那么我不会在GUI下面的所有类中检查无效值(除非我还公开了绕过GUI的公共API)

另一方面,如果机器人是公开可见的,即任何人都可以使用他们喜欢的任何值调用机器人,那么我需要测试来记录给定特定类型输入的行为。无效是其中之一。例如如果你传递一个超出范围的值,它会抛出一个ArgumentException。

答案 4 :(得分:2)

如果其他代码不能正确地调用该方法,并且没有其他人会编写代码来调用该方法,那么我就没有理由用无效值进行测试。对我来说,这似乎是浪费时间。

答案 5 :(得分:1)

按合同设计和实现的方式编程注意到这样一个事实,即单个函数(方法)应该只对某些事情负责,而不是对所有事情负责。它调用的其他函数(委托给它)以及调用它的其他函数也有责任。这种责任划分是将编程任务划分为可以单独执行的较小任务的核心。合同编程的合同部分是函数的规范说明函数必须做什么当且仅当函数的调用者履行对调用者的职责时按照那个规范。输入整数在[0,100]范围内的要求就是那种要求。

现在,单元测试不应该测试实现细节。他们应该测试该函数是否符合其规范。这使得实现可以在不破坏测试的情况下进行更改。它使重构成为可能。

结合这两个想法,我们如何为一个特定无效输入的函数编写测试?我们应该检查函数是否符合规范*。但是规范没有说明在这种情况下函数必须做什么。因此在无效函数调用之后我们不能写任何程序状态的检查;行为是 undefined 。所以我们根本不能写这样的测试。

答案 6 :(得分:0)

我的回答是,不,你不想要例外,你不希望ROBOT()检查超出范围的输入。客户端应该表现良好,不会传递垃圾值。

您可能想要记录这一点 - 只要说客户必须小心他们传递的值。

除了你从哪里获得无效值?好吧,用户输入或通过将字符串转换为数字。但在这些情况下,它应该是执行检查的转换例程,并提供有关值是否有效的反馈。这些值应该保证在它们到达ROBOT()附近的任何地方之前有效!