测试驱动开发 测试前移

有关如何更有效地应用TDD的技巧,以及为什么它是一种有价值的技术 (Tips on how to apply TDD more efficiently, and why it's a valuable technique)

There's a common pattern we follow when we start a project using TDD. We describe the specifications of what we expect the system to do in the form of a special test. This "special test" can be an end-to-end with the front-end or an integration test that executes an HTTP request to test the back-end.

当使用TDD启动项目时,我们遵循一种常见的模式。 我们以特殊测试的形式描述了我们期望系统执行的操作的规范。 此“特殊测试”可以是前端的端到端,也可以是执行HTTP请求以测试后端的集成测试。

It's the first test we write. We do it before a single line of code is written. That special test will serve as a guideline to make sure we don't break anything that prevents the regular flow from working. If we don't do that and rely solely on unit tests, there's a chance that, eventually, we will have all tests passing but the server will not be starting or the user won’t be able to do anything on the screen.

这是我们编写的第一个测试。 我们在编写一行代码之前就完成了。 该特殊测试将作为准则,以确保我们不会破坏任何阻止常规流程正常运行的内容。 如果我们不这样做,而仅依靠单元测试,则最终有机会通过所有测试,但服务器将无法启动,否则用户将无法在屏幕上执行任何操作。

When starting a project using TDD, there's a common pattern to create a special test to make sure we don’t break anything that prevents the regular flow from working.

使用TDD启动项目时,通常会使用一种模式来创建特殊测试,以确保我们不会破坏任何妨碍正常流程正常工作的内容。

After we make that special test pass with a naive implementation (or we can keep it failing if we are using ATDD to drive the application internals), we start building the units of the system using a similar pattern on a micro level, never breaking any test we created earlier. We describe each unit of the system through a failing test and make it pass with a naive implementation first. Then, we identify smells and refactor it if necessary so that we can keep the cycle going over and over again.

在通过幼稚的实现使特殊测试通过之后(或者如果我们使用ATDD来驱动应用程序内部,我们可以使其保持失败),我们开始在微观级别上使用类似的模式来构建系统的单元,而不会破坏任何单元我们之前创建的测试。 我们通过失败的测试描述系统的每个单元,并使其首先通过幼稚的实现。 然后,我们识别气味并在必要时对其进行重构 ,以便使循环不断进行。

That’s called the Red/Green/Refactor cycle of TDD.

这称为TDD的红色/绿色/重构周期 。

This cycle will drive us to build all the pieces of our application with enough confidence that it will be robust and maintainable. It will also expose problems early if we were to get stuck due to the wrong assumption of how the API is supposed to behave.

这个周期将驱使我们以足够的信心来构建应用程序的所有部分,以确保其健壮和可维护。 如果由于错误地假设API的行为而使我们陷入困境,它也会尽早暴露出问题。

There's one important thing we should be careful about: we should avoid refactoring code or adding a new test while another test is failing. If we do that, there's a high chance we will get stuck because of the unnecessary cognitive load of worrying about another rule we have already covered. To prevent that, we need to fix the failing test before starting anything else.

我们应该注意一件事: 在另一个测试失败时,我们应该避免重构代码或添加新测试。 如果这样做,很有可能由于担心我们已经涵盖的另一条规则而不必要的认知负担而陷入困境。 为防止这种情况,我们需要在开始任何其他操作之前先修复失败的测试。

In TDD, we should avoid refactoring code or adding a new test while another test is failing.

在TDD中,我们应该避免在另一个测试失败时重构代码或添加新测试。

There are circumstances where one would prefer writing tests after writing the code. However, there are some negative effects that come with that approach:

在某些情况下,人们更愿意在编写代码后编写测试。 但是,这种方法会带来一些负面影响:

  • We can miss important functionality because it’s harder to know if the coverage matches our expectation.我们可能会错过重要的功能,因为很难知道覆盖范围是否符合我们的期望。
  • It can create false positives because we won’t see a failing test first.

    它会产生误报,因为我们不会首先看到失败的测试。

  • It can make us over-engineer the architecture because we won’t have any guidelines to force us to write the minimum amount of code that fits in our most basic requirements.

    它可能使我们对架构进行过度设计 ,因为我们没有任何准则可以迫使我们编写满足我们最基本要求的最少代码量。

  • It's harder to validate if the message for the failing test is clear and pointing to the cause of that failure or not.很难验证失败测试的消息是否清晰并指出失败的原因。

One thing to keep in mind is that TDD can be posed as a discipline, but there's no way to create a discipline for writing tests after the production code.

要记住的一件事是,可以将TDD视为一门学科,但是无法创建一种在生产代码之后编写测试的学科 。

There are cases when there's no value in applying TDD or automated testing at all. It's when we're testing some IO layers, support functions for the tests, or things built using a declarative language like HTML or CSS (we can test the visual in CSS, but not the CSS code). However, testing is a fundamental part of the process that ensures a complex piece of functionality satisfies a set of expectations. That alone allows us to be confident enough that each part of the system works as expected.

在某些情况下,应用TDD或自动测试根本没有价值 。 是在测试某些IO层,测试的支持功能或使用声明性语言(如HTML或CSS)构建的东西的时候(我们可以在CSS中测试外观,但不能测试CSS代码)。 但是,测试是该过程的基本部分,可确保复杂的功能满足一系列期望。 仅凭这一点,我们就足以确信系统的每个部分都能按预期工作。

There are cases when there's no value in applying TDD or automated testing at all, like when testing IO layers, support functions for the tests, or code written with a declarative language.

在某些情况下,应用TDD或自动测试根本没有价值,例如在测试IO层,测试的支持功能或使用声明性语言编写的代码时。

There's a concept called The Transformation Priority Premise. The TL;DR is that there are some transformations we can apply when making the code more generic in the "green" phase of the TDD cycle.

有一个概念称为“转换优先级前提” 。 TL; DR是在使代码在TDD周期的“绿色”阶段更加通用时可以应用一些转换。

"Refactor" is when we change the structure of the code without changing its behavior. The Transformations are not called "refactoring" because they change the structure and the behavior of the code to make it more generic.

“ 重构 ”是指我们在不更改代码结构的情况下更改其结构。 转换不称为“ 重构 ”,因为它们会更改代码的结构和行为以使其更通用。

An example of using the Transformation Priority is when we make a test that forces us from returning a single constant to returning an argument that will contain more than one value. In this case, it's the constant->scalar priority transformation.

使用转换优先级的一个示例是,当我们进行测试以迫使我们从返回单个常量到返回将包含多个值的参数时。 在这种情况下,这是常量->标量优先级转换。

So what are these transformations? Perhaps we can make a list of them:

那么这些转换是什么? 也许我们可以列出它们:

So what are these transformations? Perhaps we can make a list of them:

那么这些转换是什么? 也许我们可以列出它们:

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)根本没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件->如果)分割执行路径 *(标量->数组) *(数组->容器)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(数组->容器) *(语句->递归)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件->如果)分割执行路径 *(标量->数组) *(数组->容器) *(语句->递归)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数)用以下表达式替换表达式函数或算法

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数)用函数或算法

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm* (variable->assignment) replacing the value of a variable.

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数) 替换变量值的 函数或算法 *(变量->赋值)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm* (variable->assignment) replacing the value of a variable.

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数)用以下表达式替换表达式 替换变量值的 函数或算法 *(变量->赋值)

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm* (variable->assignment) replacing the value of a variable.There are likely others.

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数) 替换变量值的 函数或算法 *(变量->赋值) 可能还有其他人。

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm* (variable->assignment) replacing the value of a variable.There are likely others.

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)根本没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)用变量或参数替换常量 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数)用以下表达式替换表达式 替换变量值的 函数或算法 *(变量->赋值) 可能还有其他人。

So what are these transformations? Perhaps we can make a list of them:* ({}–>nil) no code at all -> code that employs nil* (nil->constant)* (constant->constant+) a simple constant to a more complex constant* (constant->scalar) replacing a constant with a variable or an argument* (statement->statements) adding more unconditional statements.* (unconditional->if) splitting the execution path* (scalar->array)* (array->container)* (statement->recursion)* (if->while)* (expression->function) replacing an expression with a function or algorithm* (variable->assignment) replacing the value of a variable.There are likely others.— Excerpt from The Transformation Priority Premise article

那么这些转换是什么? 也许我们可以列出它们: *({} –> nil)完全没有代码->使用nil的代码 *(nil-> constant) *(constant-> constant +)从简单常量到更复杂的常量 * (constant-> scalar)将常量替换为变量或参数 *(statement-> statements)添加更多无条件语句。 *(无条件-> if)分割执行路径 *(标量->数组) *(array->容器) *(语句->递归) *(if-> while) *(表达式->函数)用以下表达式替换表达式 替换变量值的 函数或算法 *(变量->赋值) 可能还有其他人。 —摘自《转型优先前提》一文

In TDD, The Transformation Priority Premise can give us a guideline for the "green" phase.

在TDD中,“转换优先级前提”可以为我们提供“绿色”阶段的指导。

Writing correct software is hard. TDD is a common pattern where we use the tests to help driving the implementation of our system while retaining a huge percentage of test coverage. However, it's not a Silver Bullet.

编写正确的软件非常困难 。 TDD是一种常见的模式,在这种模式下,我们使用测试来帮助推动系统的实施,同时保留很大比例的测试覆盖率。 但是,它不是Silver Bullet 。

If we are using TDD, we should avoid refactoring the code when the tests are failing. To make it pass in the "green" phase, we use the Transformation Priority Premise to guide us in the most naive implementation approach we can take before refactoring.

如果使用的是TDD,则应在测试失败时避免重构代码。 为了使其通过“绿色”阶段,我们使用“转换优先级前提”来指导我们采用重构之前可以采取的最幼稚的实施方法。

In comparison with other ways of writing tests, TDD can take more time in the beginning. However, as with every new skill, with enough practice we will reach a plateau, and the time it takes to apply TDD will be no different than the time it would take to write tests in a traditional way.

与其他编写测试的方式相比,TDD在开始时可能会花费更多时间。 但是,与每一项新技能一样,如果有足够的实践,我们将达到一个平稳阶段,并且应用TDD所花费的时间与以传统方式编写测试所花费的时间没有什么不同。

The difference now is that your software will be less likely to behave in a way you didn't expect.

现在的区别是您的软件将不太可能以您未曾期望的方式运行。

And for all practical means, that's no different than 100% test coverage.

对于所有实际方法,这与100%的测试覆盖率没有什么不同。

Thanks for reading. If you have some feedback, reach out to me on Twitter, Facebook or Github.

谢谢阅读。 如果您有任何反馈意见,请通过Twitter , Facebook或Github与我联系。

翻译自: https://www.freecodecamp.org/news/why-test-driven-development-4fb92d56487c/

测试驱动开发 测试前移

测试驱动开发 测试前移_为什么测试驱动的开发有用?相关推荐

  1. 测试驱动开发 测试前移_测试驱动的开发可能看起来是工作的两倍-但无论如何您都应该这样做...

    测试驱动开发 测试前移 by Navdeep Singh 通过Navdeep Singh 测试驱动的开发可能看起来是工作的两倍-但无论如何您都应该这样做 (Test-driven developmen ...

  2. 测试驱动开发 测试前移_测试驱动陷阱,第2部分

    测试驱动开发 测试前移 单元测试中单元的故事 在本文的上半部分 ,您可能会看到一些不好但很受欢迎的测试示例. 但是我不是一个专业的批评家(也被称为"巨魔"或"仇恨者&qu ...

  3. 测试驱动开发 测试前移_测试驱动开发:它是什么,什么不是。

    测试驱动开发 测试前移 by Andrea Koutifaris 由Andrea Koutifaris Test driven development has become popular over ...

  4. 测试驱动开发 测试前移_测试驱动开发简介

    测试驱动开发 测试前移 I've been programming for five years and, honestly, I have avoided test-driven developme ...

  5. 测试驱动开发 测试前移_测试驱动开发–双赢策略

    测试驱动开发 测试前移 敏捷从业人员谈论测试驱动开发 (TDD),所以许多关心代码质量和可操作性的开发人员也是如此. 我曾几何时,不久前设法阅读了有关TDD的文章. 据我了解,TDD的关键是: 编写测 ...

  6. 测试驱动开发 测试前移_我如何以及为什么认为测试驱动开发值得我花时间

    测试驱动开发 测试前移 by Ronauli Silva 通过罗纳利·席尔瓦(Ronauli Silva) I first read about test driven development (TD ...

  7. 测试驱动开发_DevOps之浅谈测试驱动开发

    "测试驱动开发(Test-Driven Development, TDD),以测试作为开发过程的中心,它要求在编写任何产品代码之前,先编写用于定义产品代码行为的测试,而编写的产品代码又要以使 ...

  8. tdd测试驱动开发课程介绍_测试驱动开发的实用介绍

    tdd测试驱动开发课程介绍 by Luca Piccinelli 通过卢卡·皮奇内利 测试驱动开发很难! 这是不为人知的事实. (Test Driven Development is hard! Th ...

  9. mysql不能做端点测试吗_端点测试的分步介绍

    mysql不能做端点测试吗 I've been playing around with testing lately. One thing I tried to do was to test the ...

最新文章

  1. phpmyadmin另类拿shell
  2. 如何在 Fedora 上使用 Podman
  3. 联想e480笔记本如何拆屏幕_如何评价 2020 年 10 月 20 日联想发布的小新 Pro14 笔记本?有哪些亮点和槽点?...
  4. Redis进阶之主从复制
  5. 新手坐高铁怎么找车厢_一个新手怎么做直播卖衣服?找对货源供应商成功一半...
  6. delphi 通过句柄获取exe文本框内容_实战经验:通过NotifyAddrChange侦测网络变化
  7. CactiEZ的使用
  8. WIN32:参考文章
  9. [20170623]利用传输表空间恢复数据库2.txt
  10. 学前端需要什么基础知识(前端需要掌握什么 )
  11. 14届数独-真题标准数独-Day 3-20220118
  12. 7-9 幂集(回溯法) (20 分)(C语言版)
  13. BOMAPI和DOMAPI
  14. Cadence: 各软件业务
  15. 解决:Connections could not be acquired from the unde
  16. 假如孔子看见《孔子》――兼谈我们需要怎样的国学
  17. python实现软件自动点击_鼠标自动点击、键盘自动输入?几行Python代码搞定
  18. 流密码(一)同步流密码、自同步流密码以及线性反馈移位寄存器
  19. 【烈日炎炎战后端】Linux(0.3万字)
  20. 数据帧、数据包、数据报三者区分

热门文章

  1. 温故而知新!微信小程序的事件处理,吊打面试官系列!
  2. iOS 证书与签名 解惑详解
  3. tcp http socket
  4. JAVASCRIPT 等比例缩放图片 限定最大宽度和最大高度
  5. arcgis server for .NET学习转载5
  6. centos7安装oracle12c 一
  7. 3.10 十进制转换为二进制
  8. redis终端简单命令
  9. ebtables之BROUTING和PREROUTING的redirect的区别
  10. 谢烟客---------Linux之DNS服务系统的基础知识