Sunday, October 9, 2016

Test Driven Development (TDD)

  • Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test, and finally refactors the new code to acceptable standards.
  • sequence of steps
    • Add a test 
    • Run all tests and see if the new one fails
    • Write some code
    • Run tests
    • Refactor code
    • Repeat
  • TDD Best practices
    • Naming Conventions
    • Processes
    • Development practices
    • Tools 
  1. Naming conventions 
    • Naming conventions help organize tests better so that it is easier for developers to find what they’re looking for
    • Most important is that everyone on the team knows what conventions are used and is comfortable with them. Choosing “more popular” conventions has the advantage that newcomers to the team can get up to speed fast since they can leverage existing knowledge to find their way around. 
  2. Separate the implementation from the test code
    • Common practice is to have at least two source directories. Implementation code should be located in src/main/java and test code in src/test/java. In bigger projects number of source directories can increase but the separation between implementation and tests should remain.
  3. Place test classes in the same package as implementation 
    • Knowing that tests are in the same package as the code they test helps finding them faster
  4. Name test classes in a similar fashion as classes they test 
    • One commonly used practice is to name tests the same as implementation classes with suffix Test. If, for example, implementation class is StringCalculator, test class should be StringCalculatorTest.
  5. Use descriptive names for test methods
    • Using method names that describe tests is beneficial when trying to figure out why some test failed or when the coverage should be increased with more tests. It should be clear what conditions are set before the test, what actions are performed and what is the expected outcome.
    • public final void whenSemicolonDelimiterIsSpecifiedThenItIsUsedToSeparateNumbers()  
  6. Write the simplest code to pass the test
    • The idea is that the simpler the implementation the better and easier to maintain is the product. 
  7. Write assertions first, act later
    • Once assertion is written, purpose of the test is clear and developer can concentrate on the code that will accomplish that assertion and, later on, on the actual implementation.
  8. Minimize assertions in each test
    • If multiple assertions are used within one test method, it might be hard to tell which of them caused a test failure 
  9. Use mocks
    • Mocks are prerequisites for fast execution of tests and ability to concentrate on a single unit of functionality. By mocking dependencies external to the method that is being tested developer is able to focus on the task at hand without spending time to set them up 
  • Pros 
    • It can lead to simple, elegant, modular code.
    • It can help developers find defects and bugs earlier than they otherwise would and it’s a commonly held belief that a bug is cheaper to fix the earlier you find it.
    • The tests can serve as a kind of live documentation and make the code much easier to understand.
    • It can speed up development in the long term.
    • It can encourage developers to think from an end user point of view.
  • Cons
    • It necessitates a lot of time and effort up front which can make development feel slow to begin with.
    • It’s difficult to write good tests that cover the essentials and avoid the superfluous.
    • If the design is changing rapidly then you’ll need to keep changing your tests

No comments:

Post a Comment