1 / 35

Designing For Testability Testable designs in the real world

Designing For Testability Testable designs in the real world. Roy Osherove Principal, Team Agile Blog : ISerializable.com. Why Should I Care?. Maintainable System Extensible System Code Quality. Automated Unit/FIT Testing Is Important. Leads to better design Extensible System

ralph
Télécharger la présentation

Designing For Testability Testable designs in the real world

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Designing For TestabilityTestable designs in the real world Roy Osherove Principal, Team Agile Blog: ISerializable.com

  2. Why Should I Care? Maintainable System Extensible System Code Quality

  3. Automated Unit/FIT Testing Is Important • Leads to better design • Extensible System • Helps with Regression Testing • Maintainable System • Finds bugs early • Code Quality • Better understanding of the requirements • API Documentation • “Executable” Requirements

  4. Testing in Context • Engineering methodologies (waterfall for example..) • Agile methodologies • XP • Automated Unit Testing • Test Driven Development • Customer Testing (FIT) • The Crystal family • MSF-Agile • Highsmith's ASD (Adaptive Software Development) • Scrum • Feature Driven Development • DSDM (Dynamic Systems Development Method) • Rational Unified Process? (dX) • …

  5. So what’s a unit test?

  6. A Unit Test is a testof a small functional piece of code Public bool IsLoginOK(string user, string password) { //………………………… }

  7. Have you done unit testing?

  8. What’s an automated unit test? • Runs without intervention • Anyone can run it • Can run as part of a daily build process

  9. The xUnit Frameworks • Original was for SmallTalk • Kent Beck and Erich Gamma • Ported to Various languages and platforms • JUnit, CppUnit, DUnit, VBUnit, RUnit, PyUnit, Sunit, HtmlUnit, … • Good list at www.xprogramming.com • Standard test architecture • Introducing NUnit

  10. Implementing a test caseNUnit [Test] Public void Add_2Numbers_ReturnsSum() { Calculator c = new Calculator(); int result = c.Add(1,2); Assert.AreEqual(3,result,”Sum of 1 and 2 was wrong”) }

  11. The FIT Framework • Customer Testing • Uses HTML Tables • Allows testing “flows” • Requires “Adapter” classes to execute the system under test

  12. Unit Level Testing Requires Testability • Testable Code Design • Allows Unit Testing • FIT Testing • Test Driven Development • Creates Testable code • Design Up front • ?

  13. What is a Unit-Testable System • For each piece of coded logic in the system, a unit test can be written easily enough to verify it works as expected while keeping the PC-COF rules • Partial runs are possible • Configuration is not needed • Consistent pass/fail result • Order does not matter • Fast

  14. Logic: Throw if Bad validation Return true/false based on … bool CanPurchase(Person p) { If(Validator.IsNotValid(p) { throw new Exception(“…”); } return p. SSID !=null&& p.SubscriptionType!=null && p.CreditOnFile>0; } Consistent pass/fail result for each test Problems: Validator has a bug How do you control Validator to validate or not?

  15. Possible solution: Extract Interface for Validator Send in a “fake” validator IValidator validator; bool CanPurchase(Person p) { If(this.validator.IsNotValid(p) { throw new Exception(“…”); } return p. SSID !=null&& p.SubscriptionType!=null && p.CreditOnFile>0; } Testable designs use Interfaces

  16. Demo Interface based design & testing

  17. Logic: Throw if Bad validation Return true/false based on … bool CanPurchase(Person p) { If(Validator.IsNotValid(p) { throw new Exception(“…”); } return p. SSID !=null&& p.SubscriptionType!=null && p.CreditOnFile>0; } Fast run times Problems: Validator takes a long time

  18. Config file is needed String[] Foo(Person p) { String connectionString= Settings.ConnectionString; … } No Configuration needed

  19. Extract dependency into virtual method Override method in derived class Used derived class in tests String[] Foo(Person p) { String connectionString= getConnectionString(); … } Protected virtual string getConnectionString() { … } Solving Configuration with override

  20. Demo Inherit & Override

  21. Verify insert works Verify Delete Order: Insert has to come before delete test? Delete Before Insert test? Rollback database state between each test to make order irrelevant. Is that easy? Is it a unit test? bool Insert(Person p) { //insert person to database } bool Delete(Person p) { //Delete person from database } Test Order does not matterfor consistent results

  22. Verify only Delete Works Order: Will is work just the same as running all tests? Rollback database state between each test to make order irrelevant. Is that easy? Is it a unit test? bool Insert(Person p) { //insert person to database } bool Delete(Person p) { //Delete person from database } Partial runs of tests produce consistent results

  23. Are Singletons Evil? • Single Responsibility • Global Variables • Tight Coupling • State that lasts forever • Threading?

  24. Refactoring Singletons Demo

  25. The GOD Method • One huge do-it-all method • Lots of little private ones perhaps • The design smell • Should you test private methods? • TDD evolves into private tested methods

  26. Singletons & statics Hard coded dependencies Configuration based objects Constructors that use external dependencies Private Stateless Methods Convert static to instance Extract Interface Use Fake Inherit & override Use TestableXXX Extract hard coded dependency to different class Extract to helper class or static helper method Pitfalls and traps

  27. Demos Hard coded dependencies statics Private Helper Methods Constructors that use external dependencies

  28. Test Driven Dev/Design • Tests have to use a testable class • Test-first means testable-design-first • Decoupled design and architecture • More control on state simulations

  29. BDUF • Design just enough to have something to build • Note that it will likely change in the future • Design as you go and change the master plan if needed

  30. Decoupled Design • Maintainable • Extensible • Testable • Replaceable parts • More Agile – Dealing with design changes becomes easier

  31. Service Oriented Design • Decoupled Services • Independently Testable • External Dependencies easily replaceable

  32. Approaching legacy code & design • Step 1 – write integration tests • Step 2- Refactor into testability • Step 3 – Write unit tests • Design evolves • Book: “Working effectively with legacy code” Michael Feathers

  33. Design Guidelines • Interface based Designs • Try to avoid Singletons • Avoid GOD Methods – Use Polymorphism instead • Virtual by default • Use Factory methods or classes instead of hard coded initializations • Single Responsibility for class and method

  34. Key points • Design for testability leads to Agility • Common patterns • Recognizing test challenges in the design • Refactoring the design for testability • Test Driven Development leads to a testable design • Testable code == Well designed, decoupled design

  35. Thank you! Roy@TeamAgile.com TeamAgile.com ISerializable.com (blog)

More Related