如何测试具有N个不同路径的函数?

时间:2017-06-05 05:23:47

标签: unit-testing testing

我有一个验证模型类的函数,它必须在类的情况下检查类的每个成员是非空的还是非空的。

这个is_complete函数的逻辑是这样的:

def is_complete(profile):
    if profile.first_name in (None, ''):
        return False
    elif profile.last_name in (None, ''):
        return False
    elif profile.dob is None:
        return False
    .
    .
    .# and checks so on for all members of the profile instance
    .
    .

    return True

我的问题,因为执行可能采用的路径数量非常大,并且与要检查的profile成员变量的数量成比例增加,如何可靠地为所有可能路径编写测试?

现在,我有两个简单的测试用例:

  1. 其中只设置某些成员并检查assertFalse(is_complete(foo))
  2. 其中 all 成员已设置并检查assertTrue(is_complete(foo))
  3. 但我觉得这可能还不够。

2 个答案:

答案 0 :(得分:1)

我不确定拥有MxN路径的含义。在发布的代码中,您拥有与字段+ 1一样多的路径。

创建一个帮助方法,创建一个完整的profile并传递is_complete

为完整的is_complete(profile)添加一个测试方法,以验证Trueprofile

为每个字段添加一个测试方法,步骤如下:

  • 调用帮助器方法以创建我们知道将通过is_complete
  • 的完整配置文件
  • 打破测试中的字段
  • 确认is_complete返回False

您将拥有与字段+ 1一样多的测试方法。

顺便说一下,而不是这个:

if profile.first_name in (None, ''):

你可以更简单地写作:

if not profile.first_name:

答案 1 :(得分:1)

您可以使用随机化进行测试:

  • 编写一个函数,创建一个随机的Profile对象,填充所有字段(可以是随机的,但有效)。
  • 将一个或多个字段随机更改为“无”或“空”
  • 将对象传递给is_complete()函数。

我只能在Qala Datagen的Java中显示这一点。我假设你对负面路径感兴趣,所以看起来像这样:

@Test void profileIsNotComplete_ifAtLeastOneFieldIsBlank() {
    Profile p = Profile.random();
    callOneOrMore(
        () -> profile.setName(nullOrEmpty()),
        () -> profile.setLastName(nullOrEmpty()),
        ...);
    assertFalse(profile.isComplete();
}

注意,此代码实际上测试更多 - 它还检查设置为null / empty的字段组合。如果在Python中没有这样的库,你可以为自己编写一些实用程序方法。

NB :每次执行只会测试一条路径。你可以运行它多次(一千?),以确保所有路径都通过。然后在CI中,如果这不是关键任务功能,您只能运行一次,并且您不会担心它会经常中断。

否则,如果您真的希望每次调用 100%覆盖,您可以违反一些良好做法并将所有这些测试合并为一个(否则将会有太多使阅读变得复杂的测试):

@Test void profileIsNotComplete_ifOneFieldIsBlank() {
    assertFalse(Profile.random().setName(null).isComplete());
    assertFalse(Profile.random().setName("").isComplete());

    assertFalse(Profile.random().setLastName(null).isComplete());
    assertFalse(Profile.random().setLastName("").isComplete());
    ...
}

虽然这并没有测试组合,但您可以将这两种方法结合起来。在两种方法中,积极的情况都很容易:

@Test void profileIsComplete_ifAllFieldsAreFilled() {
    assertTrue(Profile.random());
}

有关随机化测试的更多信息是here