Do not rely only on comments to provide information about test objectives. Comments do not appear when tests are executed from your favorite IDE, nor do they appear in reports generated by the CI or build tools.
不要仅仅依靠注释来提供有关测试目标的信息。 从您喜欢的 IDE 执行测试时不会出现注释,也不会出现在 CI 或构建工具生成的报告中。
除了编写测试,您还需要运行它们。由于我们使用的是 Gradle,因此可以从命令提示符下运行它们:
...
...
@@ -240,7 +240,7 @@ public class TicTacToeSpec {
}
```
When a piece is placed anywhere outside the *x*-axis, then `RuntimeException` is thrown.
Write the test before writing the implementation code .
在编写实现代码之前编写测试。
The benefits of doing this are as follows—it ensures that testable code is written and ensures that every line of code gets tests written for it.
这样做的好处如下——它确保编写了可测试的代码,并确保每一行代码都为它编写了测试。
By writing or modifying the test first, the developer is focused on requirements before starting to work on a code. This is the main difference when compared to writing tests after the implementation is done. An additional benefit is that with tests first, we are avoiding the danger that the tests work as quality checking instead of quality assurance.
Rerun all the tests every time the implementation code changes.
每次实现代码更改时重新运行所有测试。
This ensures that there is no unexpected side-effect caused by code changes.
这可确保不会因代码更改而导致意外的副作用。
Every time any part of the implementation code changes, all tests should be run. Ideally, tests are fast to execute and can be run by a developer locally. Once code is submitted to the version control, all tests should be run again to ensure that there was no problem due to code merges. This is especially important when more than one developer is working on the code. CI tools, such as Jenkins, Hudson, Travind, Bamboo, and Go-CD should be used to pull the code from the repository, compile it, and run tests.
每次实现代码的任何部分更改时,都应该运行所有测试。 理想情况下,测试可以快速执行并且可以由开发人员在本地运行。 一旦代码提交给版本控制,所有的测试都应该重新运行,以确保没有由于代码合并引起的问题。 当有多个开发人员在处理代码时,这一点尤其重要。 应该使用 CI 工具,例如 Jenkins、Hudson、Travind、Bamboo 和 Go-CD,从存储库中提取代码、编译它并运行测试。
@@ -464,9 +464,9 @@ public void whenReceiveCommandsFThenForward() {
我们已经谈到了编写通过规范的最简单的代码的重要性。
Write the simplest code to pass the test. This ensures a cleaner and clearer design and avoids unnecessary features
编写最简单的代码来通过测试。 这确保了更清晰、更清晰的设计,并避免了不必要的功能
The idea is that the simpler the implementation, the better and easier it is to maintain the product. The idea adheres to the KISS principle. It states that most systems work best if they are kept simple rather than made complex; therefore, simplicity should be a key goal in design and unnecessary complexity should be avoided.
这个想法是实施越简单,维护产品就越好、越容易。 这个想法遵循 KISS 原则。 它指出,大多数系统如果保持简单而不是变得复杂,则效果最佳; 因此,简单应该是设计的一个关键目标,应该避免不必要的复杂性。
这是一个应用此规则的好机会。您可能倾向于编写类似以下内容的代码:
...
...
@@ -535,11 +535,11 @@ public void receiveCommands(String commands) {
If all the implementation code that can be affected has tests and if they are all passing, it is relatively safe to refactor. In most cases, there is no need for new tests; small modifications to existing tests should be enough. The expected outcome of refactoring is to have all the tests passing both before and after the code is modified.
Implement surface detection before each move to a new position. If a command encounters a surface, the ship aborts the move, stays on the current position, and reports the obstacle.
Connect 4 is a two-player connection game in which the players first choose a color and then take turns dropping colored discs from the top into a seven column, six row, vertically suspended grid. The pieces fall straight down, occupying the next available space within the column. The objective of the game is to connect four of your own discs of the same color next to one another vertically, horizontally, or diagonally, before your opponent connects four of theirs.
Players introduce discs on the top of the columns. The introduced disc drops down the board if the column is empty. Future discs introduced in the same column will stack over the previous ones.
The benefits of using mocks include reduced code dependency and faster text execution.
使用模拟的好处包括减少代码依赖性和更快的文本执行。
Mocks are prerequisites for the fast execution of tests and the ability to concentrate on a single unit of functionality. By mocking dependencies external to the method that is being tested, the developer is able to focus on the task at hand without spending time setting them up. In a case of bigger or multiple teams working together, those dependencies may not even be developed. Also, the execution of tests without mocks tends to be slow. Good candidates for mocks are databases, other products, services, and so on.
@@ -240,9 +240,9 @@ public void whenInstantiatedThenMongoHasNameGame() {
}
```
Use setup and teardown methods. The benefits of these allow preparation or setup and disposal or teardown code to be executed before and after the class or each test method.
使用设置和拆卸方法。 这些的好处允许在类或每个测试方法之前和之后执行准备或设置和处置或拆卸代码。
In many cases, some code needs to be executed before the test class or each method in a class. For this purpose, JUnit has the `@BeforeClass` and `@Before` annotations that should be used in the setup phase. The `@BeforeClass` executes the associated method before the class is loaded (before the first test method is run). `@Before` executes the associated method before each test is run. Both should be used when there are certain preconditions required by tests. The most common example is setting up test data in the (hopefully in-memory) database. On the opposite end are the `@After` and `@AfterClass` annotations, which should be used as the teardown phase. Their main purpose is to destroy the data or state created during the setup phase or by tests themselves. Each test should be independent from others. Moreover, no test should be affected by the others. The teardown phase helps maintain the system as if no test were previously executed.
Tests should run quickly. The benefits are that the tests are used often.
测试应该快速运行。 好处是经常使用这些测试。
If it takes a lot of time to run tests, developers will stop using them or run only a small subset related to the changes they are making. One benefit of fast tests, besides fostering their usage, is fast feedback. The sooner the problem is detected, the easier it is to fix it. Knowledge about the code that produced the problem is still fresh. If a developer has already started working on the next feature while waiting for the completion of the execution of tests, they might decide to postpone fixing the problem until that new feature is developed. On the other hand, if they drops their current work to fix the bug, time is lost in context switching.
All tests should pass before a new test is written. The benefits of this are that the focus is maintained on a small unit of work, and implementation code is (almost) always in a working condition.
It is sometimes tempting to write multiple tests before the actual implementation. In other cases, developers ignore problems detected by the existing tests and move towards new features. This should be avoided whenever possible. In most cases, breaking this rule will only introduce technical debt that will need to be paid with interest. One of the goals of TDD is ensuring that the implementation code is (almost) always working as expected. Some projects, due to pressures to reach the delivery date or maintain the budget, break this rule and dedicate time to new features, leaving the fixing of the code associated with failed tests for later. Those projects usually end up postponing the inevitable.
我们如何检测遗留代码?虽然传统代码通常等同于糟糕的代码,但 Michael Feathers 在他的书《有效地处理传统代码》*(Dorling Kindsley(印度)私人有限公司)(1993 年)中透露了一些气味。*
***Code smell**.
Smells are certain structures in the code that indicate violation of fundamental design principles and negatively impact design quality.
***代码气味**。
Code smells are usually not bugs—they are not technically incorrect and do not currently prevent the program from functioning. Instead, they indicate weaknesses in design that may be slowing down development or increasing the risk of bugs or failures in the future.
Black-box testing is a method of software testing that examines the functionality of an application without peering into its internal structures or workings. This type of test can be applied to virtually every level of software testing: unit, integration, system, and acceptance. It typically most if not all higher-level testing, but can dominate unit testing as well.
curl is a command-line tool and library for transferring data with URL syntax, supporting `[...] HTTP`, `HTTPS, [...]`, `HTTP POST`, `HTTP PUT`, and `[...]`.
Each and every single test that we perform is not automated. In this case, the tests from the Postman interface are much faster to write than the automated ones. Also, the experience is far more representative of what production use would be like. The test client (thankfully, in this case) could introduce some problems with the production one, and therefore not return trusted results.
In this particular case, we have found that the Postman tests are a better investment because, even after writing them, we will throw them away. They give very rapid feedback on the API and results. We also use this tool for prototyping the REST APIs, as its tools are both effective and useful.
在这种特殊情况下,我们发现 Postman 测试是更好的投资,因为即使在编写它们之后,我们也会将它们扔掉。 他们对 API 和结果提供非常快速的反馈。 我们还使用此工具为 REST API 进行原型设计,因为它的工具既有效又实用。
The general idea here is this: depending on whether you want to save those tests for the future or not, use one tool or another. This also depends on how often you want to execute them, and in which environment.
The smell: Primitive obsession involves using primitive data types to represent domain ideas. For example, we use a string to represent a message, an integer to represent an amount of money, or a struct/dictionary/hash to represent a specific object.