1 / 27

Test Driven Lasse Koskela Chapter 4: Concepts and Patterns for TDD

Test Driven Lasse Koskela Chapter 4: Concepts and Patterns for TDD. Paul Ammann http://cs.gmu.edu/~pammann/. Overview. How to Write Tests and Make Them Pass Essential Testing Concepts Closer Look into Test Doubles Guidelines for Testable Designs Unit-Testing Patterns

jace
Download Presentation

Test Driven Lasse Koskela Chapter 4: Concepts and Patterns for TDD

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. Test DrivenLasseKoskelaChapter 4: Concepts and Patterns for TDD Paul Ammann http://cs.gmu.edu/~pammann/

  2. Overview • How to Write Tests and Make Them Pass • Essential Testing Concepts • Closer Look into Test Doubles • Guidelines for Testable Designs • Unit-Testing Patterns • Working With Legacy Code Lots of Stuff in This Chapter

  3. How to Write Tests And Make Them Pass • Test Selection Strategies • Details-First vs. Big-Picture • Details-First Offers Concrete Progress, but • Big-Picture Fleshes Out Overall Design • Judgment Call In Any Given Situation • Uncertain vs. Familiar • Attacking Uncertainty Can Reduce Risk • Familiar Code May Have Large Payoff • High Value vs. Low Hanging Fruit • Usually, High Value is Better • Happy Path vs. Error Situations • Happy Path First – Mostly for Value • Sometimes Error Situations Help Define Remainder as Happy Path Keep Your Options in Mind; Avoid a Rut

  4. How to Write Tests And Make Them Pass(2) • Implementation Strategies • Faking It • Useful Strategy For Handling Big Steps • Incurs Later Obligations To Squeeze Out Fakes • Triangulation • Strategy For Evolving Towards More General Implementation • Use To Drive Out Hard Coded Solutions • Obvious Implementation • Sometimes The Correct Solution Really Is Simple • Try It And See • If Tests Fail, Back It Out Goal Is To Get To Green Fast

  5. How to Write Tests And Make Them Pass(3) • Prime Guidelines for Test Driving • Do. Not. Skip. Refactoring. • The Design Cycle for TDD is Crucial • Skipping This Step Leads to Code/Test Bloat • Result Is Unmaintainable Software • Get To Green Fast • Write Code That Passes The Tests First • Then Worry About Refactoring • Slow Down After a Mistake • Mistakes Indicate That Your Reach Exceeds Your Grasp • Back Off and Try Smaller Steps • The Tests Are The Oracle That Keeps You On Track The First Rule Is The Most Important

  6. Essential Testing Concepts • Fixtures are the Context for Tests • Holistic View of State • Fixtures Remove Duplication • Bloated Tests Are Hard to Read and Hard to Maintain • Fixtures Allow For Focused Tests • Test Doubles Stand In for Dependencies • Example: java.sql.ResultSet • Details Depend on Database Used • More on Doubles in Later Slides Real-World JUnit Tests Can’t Avoid Some Complexities

  7. Essential Testing Concepts(2) • State and Interaction-Based Testing • State-Based Testing • Idea Is To Look At Variable State To Verifying Result @Test public void notEmpty() { Collection<String> c = new ArrayList<String>(); assertTrue (c.isEmpty()); c.add(“Bob”); assertFalse(c.isEmpty()); } • Testing For Interactions • Goal: Did The Expected Methods Calls Happen In The Right Order? • Usually Requires Some Sort of Double We lean on interaction-based testing to verify how an object talks to its collaborators; we lean on state-based testing to verify how well the object listens.

  8. Closer Look Into Test Doubles • Replace Object with Double If Real Object is • Too Slow • It’s Not Available • It Depends on Something That’s Not Available • Its Too Difficult To Instantiate Or Configure For a Test • Examples • How to test exceptions, such as • “Dead”code? • An unplugged network cable? • How to interact with something that’s nondeterministic? Doubles Are Key To Unit Testing

  9. Closer Look Into Test Doubles(2) • Example of a Test Double • Next Slide • Stubs, Fakes, and Mocks • Stub: Simplest Possible Implementation • Fake: Still Hand Coded, But A Degree More Sophisticated • Mock: Usually Generated By Tools • Mock Objects in Action • Next slide Checking Correct Behavior is Complicated!

  10. Test Double Example: State Testing

  11. Test Double Example: Interaction Testing

  12. Guidelines for Testable Designs • Choose Composition Over Inheritance • General Advice For Normal Coding And Testing • More Verbose, But Worth It • Avoid Static and Singleton • These Are Hard To Double • Static class names are hardcoded. How to replace at test time? • This Can Conflict With Normal Coding Advice • Consider Factories! Test Requirements Impact Code!

  13. 4.4. Code smell: methods obtaining dependencies through static method calls Dependency Example: Static Method

  14. Exploiting a Seam

  15. Injecting Dependencies: Easy Test! public class OrderProcessorTest { @Test public void testOrderProcessorWithDependencyInjection() throws Exception { OrderProcessor p = new OrderProcessor(); p.setPricingService(new FakePricingService()); ... }}

  16. Unit Testing Patterns • Assertion Patterns • Resulting State Assertion • Most Common Usage • Guard Assertion • Test Both Before and After The Action (precondition testing) • Delta Assertion • Verify Part of the State – Eg, List is One Bigger Than Before • Custom Assertion • Encodes Complex Verification Rules • Interaction Assertion • Verification For Interaction Tests Choose and Use Standard Patterns

  17. Example Interaction Assertion

  18. 4.4. Code smell: methods obtaining dependencies through static method calls Fowler: Conventional JUnit Example

  19. 4.4. Code smell: methods obtaining dependencies through static method calls Fowler: jMock Version

  20. 4.4. Code smell: methods obtaining dependencies through static method calls Fowler: EasyMock Example

  21. Fowler/Meszaros “Double” Definitions • A Test Double is anything that stands in for a real object • Dummy • Used to fill parameter lists • Fake • Actual working implementations, but take shortcuts • Example: In Memory Database • Stub • Canned answers to calls made during tests, but useless elsewhere • Mock • Objects preprogrammed with expectations that form a specification of the calls they expect to receive Various Levels of Complexity

  22. 4.4. Code smell: methods obtaining dependencies through static method calls Fowler: Stub Example

  23. 4.4. Code smell: methods obtaining dependencies through static method calls Fowler: Mock Version

  24. Unit Testing Patterns (2) • Fixture Patterns • Parameterized Creation Method • Populating Complex Set Of Objects • Object Mother • Aggregate of Creation Methods • Automated TearDown • More Important For Integration Testing Than Unit Testing Fixtures Need Attention Too

  25. Unit Testing Patterns (3) • Test Patterns • Parameterized Test (see next slide) • Self Shunt • The Double Is The Test Class • Intimate Inner Class • Sharing Between Test Class and Test Double Classes • Privileged Access • Reflection-Based Injection Approaches For Legacy Code (Careful) • Extra Constructor • Compensates For Classes Not Designed For Testing Tests Need To Accommodate A Variety of Real Code

  26. Parameterized JUnit Example

  27. Working With Legacy Code • Test-Driven Legacy Development • Analyzing the Change • Change Points and Inflection Points • Change Code at Change Points • See Effects At Inflection Points • Hopefully, The Points Are Close Together… • Preparing for the Change • Install Tests To Capture Current Behavior of Inflection Point • Test-Driving the Change • Add Tests To Capture New Behavior, Also At Inflection Point Turning Legacy Code Into TDD Code

More Related