Search This Blog

2010-05-08

Test-Driven-Development Best Practices

I recently read a very intersting conversation in StackOverflow.com about test-driven development. I found it very instersting and the principles can be summarized as follows: (not ordered by importance)

1. Write the test first, then the code. Reason: This ensures that you write testable code and that every line of code gets tests written for it. 



2. Design classes using dependency injection. Reason: You cannot mock or test what cannot be seen. 


3. Separate UI code from its behavior using Model-View-Controller or Model-View-Presenter. Reason: Allows the business logic to be tested while the parts that can't be tested (the UI) is minimized. 


4. Do not write static methods or classes. Reason: Static methods are difficult or impossible to isolate and Rhino Mocks is unable to mock them. 


5. Program off interfaces, not classes. Reason: Using interfaces clarifies the relationships between objects. An interface should define a service that an object needs from its environment. Also, interfaces can be easily mocked using Rhino Mocks and other mocking frameworks. 


6. Isolate external dependencies. Reason: Unresolved external dependencies cannot be tested. 


7. Mark as virtual the methods you intend to mock. Reason: Rhino Mocks is unable to mock non-virtual methods.

8. Use creational design patterns. This will assist with DI, but it also allows you to isolate that code and test it independently of other logic.



9. Write tests using Bill Wake's Arrange/Act/Assert technique. This technique makes it very clear what configuration is necessary, what is actually being tested, and what is expected.


10. Don't be afraid to roll your own mocks/stubs. Often, you'll find that using mock object frameworks makes your tests incredibly hard to read. By rolling your own, you'll have complete control over your mocks/stubs, and you'll be able to keep your tests readable. (Refer back to previous point.)


11. Avoid the temptation to refactor duplication out of your unit tests into abstract base classes, or setup/teardown methods. Doing so hides configuration/clean-up code from the developer trying to grok the unit test. In this case, the clarity of each individual test is more important than refactoring out duplication.


12. Implement Continuous Integration. Check-in your code on every "green bar." Build your software and run your full suite of unit tests on every check-in. (Sure, this isn't a coding practice, per se; but it is an incredible tool for keeping your software clean and fully integrated.)

Reference: http://stackoverflow.com/questions/124210/best-practices-of-test-driven-development-using-c-and-rhinomocks

No comments: