变异测试示例:执行测试

使用本系列到目前为止创建的逻辑来实现可运行的代码,然后使用故障和单元测试使其更好。
134 位读者喜欢这篇文章。
Unleashed: Open source tech for pets and animals

Jeff Macharyas, CC BY-SA 4.0。唐纳德,这只猫。

本系列第二篇文章演示了如何在家庭自动化系统 (HAS) 应用程序中实现用于确定白天或夜间的逻辑,该应用程序控制猫门的锁定和解锁。 这第三篇文章解释了如何编写代码以在应用程序中使用该逻辑,该应用程序在夜间锁定门并在白天解锁门。

提醒一下,请按照此处的说明进行设置,以便使用 .NET xUnit.net 测试框架进行后续操作。

在夜间禁用猫活板门

假设猫门是一个复杂的物联网 (IoT) 产品,它具有 IP 地址,可以通过向其 API 发送请求来访问。为了简洁起见,本系列不介绍如何对 IoT 设备进行编程;相反,它模拟了该服务,以将重点放在测试驱动开发 (TDD) 和变异测试上。

首先编写一个失败的单元测试

[Fact]
public void GivenNighttimeDisableTrapDoor() {
   var expected = "Cat trap door disabled";
   var timeOfDay = dayOrNightUtility.GetDayOrNight(nightHour);
   var actual = catTrapDoor.Control(timeOfDay);
   Assert.Equal(expected, actual);
}

这描述了一个全新的组件或服务 (catTrapDoor)。该组件(或服务)具有根据当前时间控制活板门的能力。现在是时候实现 catTrapDoor 了。

要模拟此服务,您必须首先使用接口描述其功能。在 app 文件夹中创建一个新文件,并将其命名为 ICatTrapDoor.cs(按照惯例,接口名称以大写字母 I 开头)。将以下代码添加到该文件

namespace app{
   public interface ICatTrapDoor {
       string Control(string dayOrNight);
   }
}

此接口不具备运行能力。它仅仅描述了您在构建 CatTrapDoor 服务时的意图。接口是创建您正在使用的服务的抽象的好方法。在某种程度上,您可以将此接口视为 CatTrapDoor 服务的 API。

要实现 API,请在 app 文件夹中创建一个新文件,并将其命名为 FakeCatTrapDoor.cs。将以下代码输入到类文件中

namespace app{
   public class FakeCatTrapDoor : ICatTrapDoor {
       public string Control(string dayOrNight) {
           string trapDoorStatus = "Undetermined";
           if(dayOrNight == "Nighttime") {
               trapDoorStatus = "Cat trap door disabled";
           }

           return trapDoorStatus;
       }
   }
}

这个新的 FakeCatTrapDoor 类实现了接口 ICatTrapDoor。它的 Control 方法接受字符串值 dayOrNight,并检查传入的值是否为“Nighttime”。如果是,它会将 trapDoorStatus 从“Undetermined”修改为“Cat trap door disabled”,并将该值返回给调用客户端。

为什么称之为 FakeCatTrapDoor?因为它不是真实猫活板门的表示。这个“fake”只是帮助您理清处理逻辑。一旦您的逻辑严密,fake 服务就会被真实服务取代(此主题保留给集成测试学科)。

完成所有实现后,所有单元测试在运行时都会通过

Starting test execution, please wait...

Total tests; 3. Passed: 3. failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 1.3913 Seconds

在白天启用猫活板门

现在是时候看看我们用户故事中的下一个场景了

场景 #2:在白天启用猫活板门

  • 假设时钟检测到白天
  • 当时钟通知 HAS 时
  • 然后 HAS 启用猫活板门

这应该很容易,只是第一个场景的反面。首先,编写失败的测试。将以下单元测试添加到 unittest 文件夹中的 UnitTest1.cs 文件中

[Fact]
public void GivenDaylightEnableTrapDoor() {
   var expected = "Cat trap door enabled";
   var timeOfDay = dayOrNightUtility.GetDayOrNight(dayHour);
   var actual = catTrapDoor.Control(timeOfDay);
   Assert.Equal(expected, actual);
}

当将“Daylight”状态发送到 catTrapDoor 服务时,您可以期望收到“Cat trap door enabled”通知。当您运行单元测试时,您会看到您期望的结果,即按预期失败

Starting test execution, please wait...
[Xunit unittest.UnitTest1.UnitTest1.GivenDaylightEnableTrapDoor [FAIL]
Failed unittest.UnitTest1.UnitTest1.GivenDaylightEnableTrapDoor
[...]

单元测试期望收到“Cat trap door enabled”通知,但实际上收到的通知是猫活板门状态为“Undetermined”。太棒了;现在是时候解决这个小故障了。

FakeCatTrapDoor 添加三行代码即可解决问题

if(dayOrNight == "Daylight") {
   trapDoorStatus = "Cat trap door enabled";
}

再次运行单元测试,所有测试都通过

Starting test execution, please wait...

Total tests: 4. Passed: 4. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 2.4888 Seconds

太棒了!一切看起来都不错,所有单元测试都呈绿色,您拥有一个坚如磐石的解决方案。谢谢你,TDD!

别高兴得太早!

经验丰富的工程师不会相信该解决方案坚如磐石。为什么?因为该解决方案尚未经过变异。要深入了解什么是变异以及为什么它很重要,请务必阅读本系列的最后一篇文章。

标签
User profile image.
Alex 自 1990 年以来一直从事软件开发。他目前的热情是如何将“软性”带回软件中。他坚信,我们的行业已经达到了可以完全实现这一崇高目标(即将“软性”带回软件中)的成熟度。

评论已关闭。

Creative Commons License本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.