Test-driven development (TDD) is an important feature of extreme programming. CodeIt not only simplifies the code, but also ensures the software quality. This article describes the advantages, principles, processes, principles, testing techniques, and tips of TDD from the perspective of developers.
Background
An efficient software development process is crucial to software developers. It determines whether development is a painful struggle or a joy of continuous progress. Chinese people despise the blue-collar software and are impatient with the tedious and lengthy traditional development process, making most developers at a loss. Some recently emerging software development process-related technologies provide some efficient and practical software process development methods. One of the basic and key technologies is test-driven development ). Although TDD is better than extreme programming, test-driven development can be applied independently. The following is an introduction from the perspective of developers, so that developers can understand, master, and apply this technology at the minimum cost. The following describes the advantages, principles, processes, principles, testing techniques, and tips.
1. Advantages
The basic idea of TDD is to promote the entire development through testing. The test-driven development technology is not just a test.
Requirements have always been the most difficult to clearly describe and change things in the software development process. The requirements mentioned here refer not only to user requirements, but also to code usage requirements. Many developers are most afraid of modifying or extending the interface of a class or function in the future. Why is this happening because the usage requirements of this Part of Code are not well described. Test-driven development is to write test cases, first consider the use requirements of the Code (including functions, processes, interfaces, etc.), and this description is unambiguous and can be executed for verification.
By writing test cases for this part of the code, the functional decomposition, use process, and interfaces are all designed. In addition, the code design from the perspective of use is generally more in line with the needs of later development. The testable requirements are very helpful for improving and reusing code cohesion. Therefore, test-driven development is also a code design process.
Developers often get bored with writing documents, but they often hope to provide guidance when using and understanding other people's code. The test case code generated during the test-driven development process is the best explanation of the Code.
The foundation of happy work is to have confidence in yourself and the fruits of your work. At present, many developers often worry: "Is the code correct ?" "Are there any serious bugs in the hard-coded code ?" "Does the modified Code affect other parts ?". This worry even causes some code to be modified but cannot be modified. The test set provided by test-driven development can serve as a source of your confidence.
Of course, the most important function of test-driven development is to ensure the correctness of the code and quickly discover and locate bugs. Quickly discovering and locating bugs is the dream of many developers. The test set for key code and continuously improved test cases provide conditions for rapid detection and locating of bugs.
My code with very complex functions was developed using TDD. Only a few bugs were found in real-world applications and were quickly resolved. After your application, you will certainly feel that you are confident in the development process, constantly adding and improving features, and rapidly discovering and locating bugs. You love this technology.
So what principles and methods are there to provide these benefits? Next we will look at the principles of TDD.
2. Principles
The basic idea of test-driven development is to compile the test code before developing the function code. That is to say, after developing a function, first think about how to test the function, write the test code, and then write the relevant code to meet these test cases. Then add other functions cyclically until all functions are developed.
Here we extend the application field of this technology from code writing to the entire development process. We should test each stage of the development process. First, we should consider how to test, verify, and assess this stage, compile relevant test documents, and start the next step, finally, verify the relevant work. Is a popular test model: V test model.
Figure V test model]
In all stages of development, including requirement analysis, outline design, detailed design, and coding, the corresponding testing work should be considered, design related test cases, test plans, and test plans. The development phase mentioned here is just an example to make adjustments based on actual development activities. Related Test documents are not necessarily very detailed and complex documents, or form, but should be developed into the habit of test-driven.
There are also X test models for the test model. In my opinion, this test model is used to model the detailed stage and the encoding stage. It should be said that the detailed design and coding stage development behavior are described in more detail. And test-driven development for a function.
Figure X test model]
The basic principle should be said to be very simple, so the detailed introduction of the development process will be given to how to perform the actual operation.
3. Process
Test-driven development in other stages of software development. Complete the corresponding test documents based on the idea of test-driven development. The following describes the detailed design and coding stages.
The basic process of test-driven development is as follows:
1) Define the functions to be completed. A todo list can be recorded.
2) quickly write test cases for this function.
3) The test code compilation fails.
4) Compile the corresponding functional code.
5) pass the test.
6) refactor the Code and ensure that the test passes.
7) develop all functions cyclically.
To ensure the entire test process is fast and convenient, you can use the testing framework to organize all test cases. A free and excellent testing framework is the xunit series, and almost all languages have corresponding testing frameworks. I once wrote an articleArticleThis article introduces cppunit (http://www.ibm.com/developerworks/cn/linux/l-cppunit/index.html ).
During the development process, the test code and function code are usually stored separately. Here we provide a simple test framework example for you to understand how to use the test framework. Below is the file list.
Project/Project main directory
Project/test project home directory
Project/test/testseq. cpp test seq_t test file. Copy the test file of other function files and modify the file.
Project/test/testseq. h
Project/test/makefile The makefile of the test project
Project/test/Main. cpp: main file of the test project, which does not need to be modified.
Project/Main. cpp main file of the project
Project/seq_t.h function code, tested File
Project/makefile project makefile
The main process is basically the same, but there are still many testing principles and technologies to consider if you want to easily test your code and perform tests in an all-round and tedious manner.
4. Principles
Test isolation. Tests of different codes should be isolated from each other. The test of a piece of code only takes into account the test of this Code, rather than the implementation details (for example, it uses the boundary conditions of other classes ).
A hat. Developers need to do different work in the development process, such as writing test code, developing function code, and refactoring code. Perform different tasks and assume different roles. When a developer completes the corresponding work, they should stay focused on the current work, rather than thinking too much about other details to ensure that there is only one hat on the head. Avoid increasing complexity by considering too many irrelevant details.
Test list. There are many features to be tested. When you want to add feature requirements at any stage, add relevant feature points to the test list and continue the work. Then, the corresponding test cases, functional code, and refactoring are continuously completed. First, avoid omissions and interfere with the current work.
Test driver. This is the core. To complete a function and a class, first write the test code and consider how to use it and test it. And then design and code it.
Write assertions first. When writing test code, you should first write the asserted statement for determining the function code, and then write the corresponding auxiliary statements.
Testability. Functional code design and development should be highly testable. In fact, the code that follows good design principles has good testing performance. For example, the high cohesion depends on interfaces as much as possible.
Timely reconstruction. Whether it is a functional code or a test code, the structure of the Code is unreasonable, repeated code, and so on, after the test is passed, timely refactoring. I will write a detailed analysis on refactoring.
Small steps forward. Software development is a complex task. Many things need to be considered during the development process, including code correctness, scalability, and performance. Many problems are caused by the complexity. Extreme Programming puts forward a very good idea that small steps forward. All the large and complex jobs are divided into small tasks. For a class, if it is too difficult to complete a function, it will be decomposed. After each function is completed, test code-function code-test-rebuild cycle is adopted. The complexity of system development is reduced through decomposition. This effect is very obvious. After several small functional codes are completed, the large functional code can be passed without debugging. The implementation of classes and methods will soon be completed. I felt that many features need to be added. Soon I will see a few. You may even be shocked by the speed. (I understand that this speed is greatly reduced by debugging and error time)
5. Testing Technology
5.1 test scope and granularity
Which functions are tested? Will it be too cumbersome? When can I stop the test? These problems are common. In Master Kent benk's words, test the code that you think should be tested. That is to say, believe in your own feelings and experience. Important functions and core code should be tested. If you are tired, stop and take a rest. If you feel that there is no need for more detailed tests, stop this round of tests.
Test-Driven Development emphasizes that testing should not be a burden, but a method to help us reduce the workload. Based on your experience, you should also compile more comprehensive and detailed test cases for codes with complex functions and core functions. Otherwise, you can simply stop writing test cases.
The test scope does not have static standards and should change over time. If you do not compile enough functional code for testing at the beginning, you can complete the relevant test cases based on the bug.
The principle of small steps forward requires that we split the large functional blocks into smaller ones for testing. For example, Class A uses class B and class C, you should compile the test code for a to use the B and C functions, and test and develop B and C. So what should I test for every small class or small function? I don't think it is necessary. You should use your experience to focus on tests on areas where problems may occur and where problems do not feel possible. Just wait for the tests to be completed when they actually have problems.
5.2 how do I write test cases?
The traditional testing technology is used to compile test cases.
- Simulate the normal operation process as much as possible.
- Full test cases should be covered by branches as much as possible, and the core code should be covered by paths as much as possible.
- Test data should include real data and boundary data as much as possible.
- Test statements and test data should be as simple as possible and easy to understand.
- To avoid too much dependency on other code, you can implement simple pile functions or mock objects ).
- If the internal status is very complex or the process should be determined rather than the status, you can record the log string
6. Tips
Many of my friends have doubts about how to ensure the correctness of the test code? Do you want to write test code or test documents ?" In this case, will it be in the cycle of "chicken, eggs, and chickens. Actually, it won't. Usually the test code is very simple. It usually involves several statements that determine the correctness of a certain situation. If it is too complicated, it should be further decomposed. Traditional development processes usually emphasize test documents. However, with the accelerated development pace and changing user requirements, maintenance of high-level (demand, outline design) testing documents is acceptable, and the cost of lower-level testing documents is indeed too high. In addition, the test code that can verify functional correctness in real time is the best documentation for the code.
In the software development process, in addition to complying with the above-mentioned principles of test-driven development, one of the issues that need to be paid attention to is to guard against over-design. When writing function code, you should focus on completing the current function point. Through testing, you can use the simplest and most direct encoding method. Excessive consideration of later extension and addition of other functions will undoubtedly increase the complexity and cause problems. You should wait until you add these features for detailed test-driven development. At that time, there will be a complete set of test cases as the basis, and it is easy to add relevant features through continuous refactoring.
// The above is from http://www.ibm.com/developerworks/cn/linux/l-tdd/index.html
As an ideal and pursuedProgramClerk, you are surrounded by various terms all day long. You are particularly interested in one of the things called agility, because it places special emphasis on the role of people, this makes you feel comfortable as a programmer. To make yourself agile as soon as possible, you have selected a test driven development (TDD) from numerous agile practices as your starting point. Because it has the lowest Requirements for the environment around you: it does not require other people to work with you like a pair, nor does it change the way your team works like story ...... All you need to do is write the test before you write the Business Code. This is completely a kind of silent practice, and there is no need to tell anyone other than you. When others are busy looking for bugs, you begin to enjoy the joy that agile brings to you. By the way, you can appear as a practitioner next time when you argue with others about agility, rather than being there.
You won't fight unprepared, So you read the thin hacker of Kent Beck. By reading this, you are more confident in TDD. Because the steps of "red-green-rebuilding" are really simple. Okay! All in all, you are confident that you are ready to begin TDD and step into the agile kangzhuang Avenue.
The ideal is beautiful, and the reality is cruel.
When you start to experience TDD in a real project, everything is not as good as it initially looks. Although you strive to adhere to the TDD principle, you often find that some things are hard to test. For example, if you encounter a database or a GUI, for example, you have encountered a timer ). Agility is not a dogma. When something cannot be done, you can simply stick to it. So, you tell yourself that something hard to test can be unexpected. In this way, at least psychologically, you feel much more comfortable. As work continues, you find that you cannot test more and more things. The unit test coverage rate is gradually decreasing as development progresses, and a bit of fear comes to your mind. Looking back, I went to read Kent Beck's book. You suddenly felt that you were cheated, because the Kent Beck example seems to be all logical. If it's just logic, of course it's a good test, but this is never the case.
Doesn't TDD look pretty good?
Obviously, if you don't want to give up and give up the secret of software development that you have learned with painstaking efforts, the TDD that the legendary experts strongly advocate must have some truth. TDD can make you feel good: the code that can be tested greatly enhances your confidence in the quality of the software, and you can find it if something goes wrong, every time you modify the code, running the green bar in the test will make you feel physically and mentally happy.
What is the problem? You are immersed in meditation.
By mistake, you opened your own code. Looking at the code you wrote, you suddenly realized that the problem you encountered was not TDD, but a unit test. As you have previously thought, the results of TDD practices make you feel happy. Yes, it must be that the unit test itself has a problem. What's wrong with unit testing? Obviously, a lot of untested parts make unit testing hard to write and reduce the coverage of unit testing. Is this an unsolved problem? You obviously don't want to give up on this, so keep moving forward with this idea.
TDD gives you peace of mind, mainly because every time you write code, a green bar appears when you run the test, telling you that the test passes. In this way, you can proceed with confidence because your code has not broken anything. What makes you feel uneasy is clearly the code that is not covered by the test. You have carefully reviewed the codes that are not covered by the test, and your ideas are all clear. The reason for this is that you are upset, because there are some logic in it besides those that are really hard to test. If the test is not covered, you may feel a little comforting. You are sure that what really upset you is the logical part of co-survival with poorly tested code.
If the test can cover the logic, it can be accepted, at least emotionally. So how can we make these parts covered by tests? You carefully observe the code that has not been tested. If you do this, you can test the Code. If you do that, you can test the code, these seemingly untestable code can be broken down into many testable parts.
Your mood is much better, because doing so can finally make the test coverage reach a psychological acceptable range. However, new problems also follow. What am I doing? Split and split. Isn't that the design? How can I get here. I am not analyzing the unit test problem? By the way, my first question was TDD. How did I go all the way to design?
TDD? Design?
You suddenly find that you have some deviations in your understanding of TDD. TDD does not mean no design is required. After reading many books, you suddenly think of Robert Martin's famous agile software development. The above is an example of database access. In that example, the difference between the two versions is exactly the result of considering the design. Generally, when testing is considered in the design, it is easy to find rigid parts in the design to make the program more flexible. Further, if you design a little before getting started, you may still be aware of these issues. You suddenly think that it is precisely because TDD itself places too much emphasis on the value of testing, so you can ignore the important part of software development: design.
The idea suddenly becomes clear, TDD is not just "red-green-reconstruction", it is still related to the design: there must be a certain design before the start, and, test issues should be considered in the design. At last, you have solved the confusion in your mind. Now you have a new understanding of TDD. Although this understanding is not necessarily the ultimate truth, it is at least obtained through your own thinking, this gives you more confidence in the truth of practice.
After clarifying your ideas, you are more confident in the value of TDD itself, and have strengthened the idea of continuing to use TDD in future development. Of course, you have been eyeing other agile practices with great vision.
// The above source http://dreamhead.blogbus.com/logs/14189175.html