Pair progamming is a strongly recommended when learning a new practice especially TDD
So, you can have both with a compromise. Do this in an agile fashion, incrementally. Take on pair programming first. It is the easier of the two. All practices after pair programming will become much easier to learn and will be adopted by the team more quickly and with greater consistentcy. Pair programming is one of the first if not the first engineerring practice that should be adopted. Make sure it is done effectively. Below is a description of how to do pair programming.
Paired programming is one of the most potent practices a development team can practice when developing software. Pairing occurs with two developer actively develop a story card using a single computer and keyboard. Managers worry that using paired programming will double their programming costs. At first glance, it is understandable why they might think that -- after all --two developers are being asked to work together on the same task. In practice, though, Agile teams using this development technique have found that the slight increase in costs for the initial development (15% according to a University of Utah study) are more than offset by a reduction in defects, a shorter and less expensive testing cycle and reduced need for production support.
While it may seem counterintuitive that having programmers pair and work together improves productivity, there are a number of reasons why this technique really does work (Think of the old saying, "Two heads are better than one.") Here's why:
- Improved quality -- Pairing encourages code review. Many mistakes get caught as they are typed. Paired programming means continuous code review done by two people who are committed to the quality of the code and are working together to identify and fix bugs at all times. A study done by the University of Utah found that the end number of defects found in code was reduced by 15% on average for the code written by pairs.
- Less Time Spent "Stuck" -- Programming is hard. Often developers struggle to find a solution and spend more time than they should "stuck". Having a partner to brainstorm ideas with and to agree to seek help if necessary reduces the amount of unproductive time spent stuck trying to find a solution.
- Less Time Spent on Distractions -- A developer is less likely spend time on personal phone calls or surfing the web, or email vacations when he or she is working with a partner.
- Two Perspectives are Applied to the Problem -- Differing levels of experience, different problem solving styles, different auxiliary skills all increase the chances of solving a problem faster. The study done by the University of Utah also identified better overall design and shorter code length for the software written by pairs.
- Less Fear of the Unknown -- When pairing with another developer it is easier to tackle a problem or try to get a handle on new technology than it is when working alone. They also gain, over time, a much better understanding of the entire application. In the end, the project ends up with multiple people understanding each piece of the system as a result of pairing.
- Less Likely to Build in Scope -- Often developers willingly add functionality not addressed in the requirements. When working with a pair, the second developer is more likely to keep his/her partner on task.
- Improved Team Dynamics -- Because of the paired approach, people learn to work together. They talk more often and experience a better flow of information. Team dynamics improve as a result. In fact, we have found that the best team building experience around is working together to produce software your customer is excited about. Everyone loves being part of a successful team.
- Elimination of Silos of Knowledge – Domain knowledge, knowledge of the code or practices are quickly propagated through the team and developer pair with one another on a rotation basis.
Once the team is confortable with pairing, then take on TDD. A destription follows:
Test-Driven Development (TDD) is a software development engineering practice consisting of short burst of development where a new test case covering the desired improvement or new functionality is written first, then the production code necessary to pass the test is implemented, and finally the software is refactored to accommodate changes. The availability of tests before actual development ensures rapid feedback after any change. Practitioners emphasize that test-driven development is a method of designing software, not merely a method of testing. Test-driven development is a powerful practice and a major contributor to the reduction of defects found later in the life cycle. A new team is strongly encouraged to pair with an experience TDD practitioner or otherwise receive TDD coaching.e
Test-driven development requires that an automated unit test, defining requirements of the code, is written before each aspect of the code itself. These tests contain assertions that are either true or false. Running the tests gives rapid confirmation of correct behavior as the code evolves and is refactored. Testing frameworks based on the xUnit concept provide a mechanism for creating and running sets of automated test cases.
Test-Driven Development Cycle: The following sequence is based on the book Test-Driven Development by Example, which many consider to be the canonical source text on the concept in its modern form.
- Write a test. In test-driven development, each new story card begins with writing a test. This test will fail because it is written before the feature has been implemented. In order to write a test, the developer must understand the specification and the requirements of the feature clearly. This may be accomplished through Story Cards with acceptance criteria to specify when the requirements has been meet. This could also imply an invariant, or modification of an existing test. This is a differentiating feature of test-driven development versus writing unit tests after the code is written: it makes the developer focus on the requirements before writing the code, a subtle but important difference.
- Run all tests and see if the new one fails. This validates that the test harness is working correctly and that the new test does not mistakenly pass without requiring any new code. The new test should also fail for the expected reason. This step tests the test itself, in the negative: it rules out the possibility that the new test will always pass, and therefore be worthless.
- Write some code. The next step is to write some code that will cause the test to pass. The new code written at this stage will not be perfect and may, for example, pass the test in an inelegant way. That is acceptable because later steps will improve and hone it.
It is important that the code written is only designed to pass the test; no further (and therefore untested) functionality should be predicted and 'allowed for' at any stage.
- Run the automated tests and see them succeed. If all test cases now pass, the programmer can be confident that the code meets all the tested requirements. This is a good point from which to begin the final step of the cycle.
- Refactor code. Now the code can be cleaned up as necessary. By re-running the test cases, the developer can be confident that refactoring is not damaging any existing functionality. The concept of removing duplication is an important aspect of any software design. In this case, however, it also applies to removing any duplication between the test code and the production code — for example magic numbers or strings that were repeated in both, in order to make the test pass in step 3.
Repeat
Starting with another new test, the cycle is then repeated to push forward the functionality. The size of the steps can be as small as the developer likes, or get larger if s/he feels more confident. If the code written to satisfy a test does not fairly quickly do so, then the step-size may have been too big, and maybe the smaller testable steps should be used instead. When using external libraries it is important not to make increments that are so small as to be effectively merely testing the library itself, unless there is some reason to believe that the library is buggy or is not sufficiently feature complete to serve all the needs of the main program being written.
Development Style
There are various aspects to using test-driven development, for example the principles of "Keep It Simple, Stupid" (KISS) and "You Ain't Gonna Need It" (YAGNI). By focusing on writing only the code necessary to pass tests, designs can be cleaner and clearer than is often achieved by other methods.
Test-driven development requires the programmer to first fail the test cases. The idea is to ensure that the test really works and can catch an error. Once this is shown, the normal cycle will commence. This has been coined the "Test-Driven Development Mantra", known as red/green/refactor where red means fail and green is pass.
Test-driven development constantly repeats the steps of adding test cases that fail, passing them, and refactoring. Receiving the expected test results at each stage reinforces the programmer's mental model of the code, boosts confidence and increases productivity