diff --git a/sources/tech/20190923 Mutation testing by example- How to leverage failure.md b/sources/tech/20190923 Mutation testing by example- How to leverage failure.md deleted file mode 100644 index f86183f798..0000000000 --- a/sources/tech/20190923 Mutation testing by example- How to leverage failure.md +++ /dev/null @@ -1,195 +0,0 @@ -[#]: collector: (lujun9972) -[#]: translator: (Morisun029) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) -[#]: subject: (Mutation testing by example: How to leverage failure) -[#]: via: (https://opensource.com/article/19/9/mutation-testing-example-tdd) -[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic) - -Mutation testing by example: How to leverage failure -====== -Use planned failure to ensure your code meets expected outcomes and -follow along with the .NET xUnit.net testing framework. -![failure sign at a party, celebrating failure][1] - -In my article _[Mutation testing is the evolution of TDD][2]_, I exposed the power of iteration to guarantee a solution when a measurable test is available. In that article, an iterative approach helped to determine how to implement code that calculates the square root of a given number. - -I also demonstrated that the most effective method is to find a measurable goal or test, then start iterating with best guesses. The first guess at the correct answer will most likely fail, as expected, so the failed guess needs to be refined. The refined guess must be validated against the measurable goal or test. Based on the result, the guess is either validated or must be further refined. - -In this model, the only way to learn how to reach the solution is to fail repeatedly. It sounds counterintuitive, but amazingly, it works. - -Following in the footsteps of that analysis, this article examines the best way to use a DevOps approach when building a solution containing some dependencies. The first step is to write a test that can be expected to fail. - -### The problem with dependencies is that you can't depend on them - -The problem with dependencies, as Michael Nygard wittily expresses in _[Architecture without an end state][3]_, is a huge topic better left for another article. Here, you'll look into potential pitfalls that dependencies tend to bring to a project and how to leverage test-driven development (TDD) to avoid those pitfalls. - -First, pose a real-life challenge, then see how it can be solved using TDD. - -### Who let the cat out? - -![Cat standing on a roof][4] - -In Agile development environments, it's helpful to start building the solution by defining the desired outcomes. Typically, the desired outcomes are described in a [_user story_][5]: - -> _Using my home automation system (HAS), -> I want to control when the cat can go outside, -> because I want to keep the cat safe overnight._ - -Now that you have a user story, you need to elaborate on it by providing some functional requirements (that is, by specifying the _acceptance criteria_). Start with the simplest of scenarios described in pseudo-code: - -> _Scenario #1: Disable cat trap door during nighttime_ -> -> * Given that the clock detects that it is nighttime -> * When the clock notifies the HAS -> * Then HAS disables the Internet of Things (IoT)-capable cat trap door -> - - -### Decompose the system - -The system you are building (the HAS) needs to be _decomposed_–broken down to its dependencies–before you can start working on it. The first thing you must do is identify any dependencies (if you're lucky, your system has no dependencies, which would make it easy to build, but then it arguably wouldn't be a very useful system). - -From the simple scenario above, you can see that the desired business outcome (automatically controlling a cat door) depends on detecting nighttime. This dependency hinges upon the clock. But the clock is not capable of determining whether it is daylight or nighttime. It's up to you to supply that logic. - -Another dependency in the system you're building is the ability to automatically access the cat door and enable or disable it. That dependency most likely hinges upon an API provided by the IoT-capable cat door. - -### Fail fast toward dependency management - -To satisfy one dependency, we will build the logic that determines whether the current time is daylight or nighttime. In the spirit of TDD, we will start with a small failure. - -Refer to my [previous article][2] for detailed instructions on how to set the development environment and scaffolds required for this exercise. We will be reusing the same NET environment and relying on the [xUnit.net][6] framework. - -Next, create a new project called HAS (for "home automation system") and create a file called **UnitTest1.cs**. In this file, write the first failing unit test. In this unit test, describe your expectations. For example, when the system runs, if the time is 7pm, then the component responsible for deciding whether it's daylight or nighttime returns the value "Nighttime." - -Here is the unit test that describes that expectation: - - -``` -using System; -using Xunit; - -namespace unittest -{ -   public class UnitTest1 -   { -       DayOrNightUtility dayOrNightUtility = [new][7] DayOrNightUtility(); - -       [Fact] -       public void Given7pmReturnNighttime() -       { -           var expected = "Nighttime"; -           var actual = dayOrNightUtility.GetDayOrNight(); -           Assert.Equal(expected, actual); -       } -   } -} -``` - -By this point, you may be familiar with the shape and form of a unit test. A quick refresher: describe the expectation by giving the unit test a descriptive name, **Given7pmReturnNighttime**, in this example. Then in the body of the unit test, a variable named **expected** is created, and it is assigned the expected value (in this case, the value "Nighttime"). Following that, a variable named **actual** is assigned the actual value (available after the component or service processes the time of day). - -Finally, it checks whether the expectation has been met by asserting that the expected and actual values are equal: **Assert.Equal(expected, actual)**. - -You can also see in the above listing a component or service called **dayOrNightUtility**. This module is capable of receiving the message **GetDayOrNight** and is supposed to return the value of the type **string**. - -Again, in the spirit of TDD, the component or service being described hasn't been built yet (it is merely being described with the intention to prescribe it later). Building it is driven by the described expectations. - -Create a new file in the **app** folder and give it the name **DayOrNightUtility.cs**. Add the following C# code to that file and save it: - - -``` -using System; - -namespace app { -   public class DayOrNightUtility { -       public string GetDayOrNight() { -           string dayOrNight = "Undetermined"; -           return dayOrNight; -       } -   } -} -``` - -Now go to the command line, change directory to the **unittests** folder, and run the test: - - -``` -[Xunit.net 00:00:02.33] unittest.UnitTest1.Given7pmReturnNighttime [FAIL] -Failed unittest.UnitTest1.Given7pmReturnNighttime -[...] -``` - -Congratulations, you have written the first failing unit test. The unit test was expecting **DayOrNightUtility** to return string value "Nighttime" but instead, it received the string value "Undetermined." - -### Fix the failing unit test - -A quick and dirty way to fix the failing test is to replace the value "Undetermined" with the value "Nighttime" and save the change: - - -``` -using System; - -namespace app { -   public class DayOrNightUtility { -       public string GetDayOrNight() { -           string dayOrNight = "Nighttime"; -           return dayOrNight; -       } -   } -} -``` - -Now when we run the test, it passes: - - -``` -Starting test execution, please wait... - -Total tests: 1. Passed: 1. Failed: 0. Skipped: 0. -Test Run Successful. -Test execution time: 2.6470 Seconds -``` - -However, hardcoding the values is basically cheating, so it's better to endow **DayOrNightUtility** with some intelligence. Modify the **GetDayOrNight** method to include some time-calculation logic: - - -``` -public string GetDayOrNight() { -    string dayOrNight = "Daylight"; -    DateTime time = new DateTime(); -    if(time.Hour < 7) { -        dayOrNight = "Nighttime"; -    } -    return dayOrNight; -} -``` - -The method now gets the current time from the system and compares the **Hour** value to see if it is less than 7am. If it is, the logic transforms the **dayOrNight** string value from "Daylight" to "Nighttime." The unit test now passes. - -### The start of a test-driven solution - -We now have the beginnings of a base case unit test and a viable solution for our time dependency. There are more than a few more cases to work through.  - -In the next article, I'll demonstrate how to test for daylight hours and how to leverage failure along the way. - --------------------------------------------------------------------------------- - -via: https://opensource.com/article/19/9/mutation-testing-example-tdd - -作者:[Alex Bunardzic][a] -选题:[lujun9972][b] -译者:[译者ID](https://github.com/译者ID) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]: https://opensource.com/users/alex-bunardzic -[b]: https://github.com/lujun9972 -[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/fail_failure_celebrate.png?itok=LbvDAEZF (failure sign at a party, celebrating failure) -[2]: https://opensource.com/article/19/8/mutation-testing-evolution-tdd -[3]: https://www.infoq.com/presentations/Architecture-Without-an-End-State/ -[4]: https://opensource.com/sites/default/files/uploads/cat.png (Cat standing on a roof) -[5]: https://www.agilealliance.org/glossary/user-stories -[6]: https://xunit.net/ -[7]: http://www.google.com/search?q=new+msdn.microsoft.com diff --git a/translated/tech/20190923 Mutation testing by example- How to leverage failure.md b/translated/tech/20190923 Mutation testing by example- How to leverage failure.md new file mode 100644 index 0000000000..115b7f05bf --- /dev/null +++ b/translated/tech/20190923 Mutation testing by example- How to leverage failure.md @@ -0,0 +1,205 @@ +[#]: collector: (lujun9972) +[#]: translator: (Morisun029) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) +[#]: subject: (Mutation testing by example: How to leverage failure) +[#]: via: (https://opensource.com/article/19/9/mutation-testing-example-tdd) +[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic) + +变异测试:如何利用故障? +====== +使用事先设计好的故障以确保你的代码达到预期的结果,并遵循 .NET xUnit.net 测试框架来进行测试。 +![failure sign at a party, celebrating failure][1] + +[在变异测试是TDD的演变][2]一文中, 我谈到了迭代的力量。在可度量的测试中,迭代能够保证找到问题的解决方案。 在那篇文章中,我们讨论了迭代法帮助确定实现计算给定数字平方根的代码。 + +我还演示了最有效的方法是找到可衡量的目标或测试,然后以最佳猜测值开始迭代。 正如所预期的,第一次测试通常会失败。因此,必须根据可衡量的目标或测试对失败的代码进行完善。 根据运行结果,对测试值进行验证或进一步加以完善。 +在此模型中,学习获得解决方案的唯一方法是反复失败。 这听起来有悖常理,但它确实有效。 + +按照这种分析,本文探讨了在构建包含某些依赖项的解决方案时使用 DevOps 的最佳方法。 第一步是编写一个预期结果失败的用例。 + + +### 依赖性问题是你不能依赖它们 + +正如迈克尔•尼加德(Michael Nygard)在_[Architecture without an end state][3]_,表达的那样,依赖问题是一个很大的话题,最好留到另一篇文章中讨论。 在这里,你将会看到依赖项给项目带来的一些潜在问题,以及 +如何利用测试驱动开发(TDD)来避免这些陷阱。 + +首先,找到现实生活中的一个挑战,然后看看如何使用TDD解决它。 + +### 谁让猫出来? + +![一只猫站在屋顶][4] + + +在敏捷开发环境中,通过定义期望结果开始构建解决方案会很有帮助。 通常,在 [用户故事][5]中描述期望结果: + + +>我想使用我家的自动化系统(HAS)来控制猫何时可以出门,因为我想保证它在夜间的安全。 + + +现在你已经有了一个用户故事,你需要通过提供一些功能要求(即指定验收标准)来对其进行详细说明。 从伪代码中描述的最简单的场景开始: + +> 场景1:在夜间关闭猫门 +> +> * 用时钟监测到晚上时间 +> * 时钟通知 HAS 系统 +> * HAS 关闭支持物联网(IoT)的猫门 +> + + +### 分解系统 + + +开始构建之前,你需要将正在构建的系统(HAS)进行分解(分解为依赖项)。 你必须要做的第一件事是识别任何依赖项(如果幸运的话,你的系统没有依赖项,这将会更容易,但是,这样的系统可以说不是非常有用)。 + +从上面的简单场景中,你可以看到所需的业务成果(自动控制猫门)取决于对夜间情况监测。 这种依赖性取决于时钟。 但是时钟是无法区分白天和夜晚的。 需要你来提供这种逻辑。 + +正在构建的系统中的另一个依赖项是能够自动访问猫门并启用或关闭它。 该依赖项很可能取决于具有 IoT 功能的猫门提供的API。 + + + +### 依赖管理面临快速失败 + +为了满足一个依赖项,我们将构建确定当前时间是白天还是晚上的逻辑。 本着TDD的精神,我们将从一个小小的失败开始。 + + +有关如何设置此练习所需的开发环境和脚手架的详细说明,请参阅我的[上一篇文章][2]。 我们将重用相同的 NET 环境和 [xUnit.net][6] 框架。 + + +接下来,创建一个名为 HAS(“家庭自动化系统”)的新项目,创建一个名为**UnitTest1.cs**的文件。 在该文件中,编写第一个失败的单元测试。 在此单元测试中,描述你的期望结果。 例如,当系统运行时,如果时间是晚上7点,负责确定是白天还是夜晚的组件将返回值“ Nighttime”。 + +这是描述期望值的单元测试: + + +``` +using System; +using Xunit; + +namespace unittest +{ + public class UnitTest1 + { + DayOrNightUtility dayOrNightUtility = [new][7] DayOrNightUtility(); + + [Fact] + public void Given7pmReturnNighttime() + { + var expected = "Nighttime"; + var actual = dayOrNightUtility.GetDayOrNight(); + Assert.Equal(expected, actual); + } + } +} +``` + + +至此,你可能已经熟悉了单元测试的结构。 快速复习:在此示例中,通过给单元测试一个描述性名称**Given7pmReturnNighttime** 来描述期望结果。 然后,在单元测试的主体中,创建一个名为**expected** 的变量,并为该变量指定期望值(在该示例中,值为“ Nighttime”)。 然后,为实际变量指定一个 **actual**(在组件或服务处理一天中的时间之后可用)。 + +最后,通过断言期望值和实际值是否相等来检查是否满足期望结果:**Assert.Equal(expected, actual)**。 + + +你还可以在上面的列表中看到名为**dayOrNightUtility** 的组件或服务。 该模块能够接收消息**GetDayOrNight**,并且返回**string** 类型的值。 + + +同样,本着TDD的精神,描述的组件或服务还尚未构建(仅为了后面说明在此进行描述)。 构建这些是由所描述的期望结果来驱动的。 + +在 **app** 文件夹中创建一个新文件,并将其命名为**DayOrNightUtility.cs**。 将以下 C# 代码添加到该文件中并保存: + + +``` +using System; + +namespace app { + public class DayOrNightUtility { + public string GetDayOrNight() { + string dayOrNight = "Undetermined"; + return dayOrNight; + } + } +} +``` + + +现在转到命令行,将目录更改为**unittests**文件夹,然后运行: + +``` +[Xunit.net 00:00:02.33] unittest.UnitTest1.Given7pmReturnNighttime [FAIL] +Failed unittest.UnitTest1.Given7pmReturnNighttime +[...] +``` + +恭喜,你已经完成了第一个失败的单元测试。 单元测试的期望结果是**DayOrNightUtility**方法返回字符串“ Nighttime”,但相反,它返回是“ Undetermined”。 + +### 修复失败的单元测试 + + +修复失败的测试的一种快速而粗略的方法是将值“ Undetermined”替换为值“ Nighttime”并保存更改: + +``` +using System; + +namespace app { + public class DayOrNightUtility { + public string GetDayOrNight() { + string dayOrNight = "Nighttime"; + return dayOrNight; + } + } +} +``` + +现在运行时,成功了。 + +``` +Starting test execution, please wait... + +Total tests: 1. Passed: 1. Failed: 0. Skipped: 0. +Test Run Successful. +Test execution time: 2.6470 Seconds +``` + +但是,对值进行硬编码基本上是在作弊,最好为**DayOrNightUtility** 方法赋予一些智能。 修改**GetDayOrNight**方法以包括一些时间计算逻辑: + + +``` +public string GetDayOrNight() { + string dayOrNight = "Daylight"; + DateTime time = new DateTime(); + if(time.Hour < 7) { + dayOrNight = "Nighttime"; + } + return dayOrNight; +} +``` + + +该方法现在从系统获取当前时间,并与 **Hour**比较,查看其是否小于上午7点。 如果小于,则处理逻辑将 **dayOrNight**字符串值从“ Daylight”转换为“ Nighttime”。 现在,单元测试通过。 + + +### 测试驱动解决方案的开始 + +现在,我们已经开始了基本的单元测试,并为我们的时间依赖项提供了可行的解决方案。 后面还有更多的测试案例需要执行。 + +在下一篇文章中,我将演示如何对白天时间进行测试以及如何在整个过程中利用故障。 + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/19/9/mutation-testing-example-tdd + +作者:[Alex Bunardzic][a] +选题:[lujun9972][b] +译者:[Morisun029](https://github.com/译者ID) +校对:[校对者ID](https://github.com/校对者ID) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]: https://opensource.com/users/alex-bunardzic +[b]: https://github.com/lujun9972 +[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/fail_failure_celebrate.png?itok=LbvDAEZF (failure sign at a party, celebrating failure) +[2]: https://opensource.com/article/19/8/mutation-testing-evolution-tdd +[3]: https://www.infoq.com/presentations/Architecture-Without-an-End-State/ +[4]: https://opensource.com/sites/default/files/uploads/cat.png (Cat standing on a roof) +[5]: https://www.agilealliance.org/glossary/user-stories +[6]: https://xunit.net/ +[7]: http://www.google.com/search?q=new+msdn.microsoft.com