如何干净地进行单元测试控制流方法

时间:2019-05-04 10:58:44

标签: ruby unit-testing minitest

我有一个验证方法,如果保存记录后应跳过回调,则返回true,否则返回false。

如果窗帘条件为true,则该方法很复杂,包含多个return语句。我不知道如何彻底测试该方法并确认每个测试都在测试不同的条件。

我正在使用Rails和Minitest,但是相信这是关于单元测试的普遍问题,可以应用于其他语言和/或测试框架。

我尝试测试该方法,结果一团糟。

  • 如果未更改感兴趣的字段且未更改bulk_association,则返回true
  • 如果批量关联但没有关联的用户,则返回true
  • 如果批量关联以及关联的用户但未激活,则返回true
  • 如果批量关联和关联的活动用户返回false
  • 如果attribute_a已更改并关联了活动用户,则返回false
  • 如果attribute_b已更改并关联了活动用户,则返回false
  • 如果attribute_c已更改并关联了活动用户,则返回false

每个测试都需要更多的设置,而我没有办法证明它们并非都在同一行中返回true。

var date = new Date(); //Time of the clock in-game
var hours;
var minutes;
var seconds;

var display_hours; // Displayers for the time
var display_minutes;
var display_seconds;

window.onload = function() {
    display_hours = document.getElementById("hour");
    display_minutes = document.getElementById("minute");
    display_seconds = document.getElementById("second");
};

function time_on() {
    hours = date.getHours();
    if (hours < 10) {
        hours = "0" + hours;
    };
    minutes = date.getMinutes();
    if (minutes < 10) {
        minutes = "0" + minutes;
    };
    seconds = date.getSeconds();
    if (seconds < 10) {
        seconds = "0" + seconds;
    };

    display_hours.textContent = hours;
    display_minutes.textContent = minutes;
    display_seconds.textContent = seconds;
};

var go_time = setInterval(time_on, 1000); // Display time on the clock every seconds

应该如何测试这种方法?我正在尝试编写具有可读性,独立性和真实性的良好单元测试,因此,如果我评论退货,则正确的测试应该会失败。

2 个答案:

答案 0 :(得分:0)

一种选择可能是使用模拟库来确保每种情况的条件:

https://github.com/freerange/mocha

您的测试将被写成这样:

your_test_object.expects(:attribute_a_changed?).returns(true)

请注意,这种方法并非没有缺点,但无论如何还是值得研究的。

答案 1 :(得分:0)

在您的代码示例中,我看到了两种可以解决您的测试问题的方法,这些方法也可以结合使用。

首先,您可以使用MC / DC(修改后的条件/决策范围)设计测试用例。其背后的思想如下:对于代码中的每个布尔输入b,请确定两个具有以下属性的测试用例:a)其中一个测试用例具有预期的true结果,而另一个则具有预期的结果。预期的false结果。 b)除b以外,两个测试用例都具有相同的输入,在一个测试用例中,其值为true,而在另一个测试用例中,其值为false。换句话说,在这两个测试用例之间,只有b会更改和控制输出。

示例:要使输入self.attribute_a_changed?控制输出,其他输入必须具有以下值:

  • self.attribute_b_changed?必须为false
  • self.attribute_c_changed?必须为false
  • self.bulk_association必须不同于true
  • self.user.blank?必须为false
  • self.user.active必须为true

然后,将所有上述输入值与self.attribute_a_changed?组合为true的一个测试用例将为false产生skip_callback的预期输出。第二个测试用例将上述输入值与self.attribute_a_changed?组合为false并导致true的预期输出skip_callback。进行这两个测试可以使您确定您确实检查过self.attribute_a_changed?对输出有影响。

在此Wikipedia page中描述了

MC / DC,该MC / DC也具有与此tutorial from NASA的链接。 SO上也有一些示例,例如here

第二,您可以通过针对代码的修改版本(突变)运行测试用例来检查它们。这称为变异测试,用于判断测试套件的质量。要查看您的测试是否确实发现了一个特殊的错误(例如self.attribute_a_changed?对结果没有理想的影响),只需插入该错误并查看测试是否失败。例如,您可以简单地从代码中删除self.attribute_a_changed?并查看测试是否注意到。或者,您可以将其转换为self.attribute_a_changed? == false,然后查看测试是否发现了该错误。