This presentation challenges the "norm" for TDD. Testing should be an integral part of your daily programming practice. But you don’t always need to derive your code via many test-code-revise-retest cycles to be test-driven. Some find it more natural to outline a related set of tests first, and use those test scenarios to guide them as they write code. Once they’ve completed a “good enough” implementation that supports the test scenarios, they then write those tests and incrementally fix any bugs as they go. As long as you don’t write hundreds of lines of code without any testing, there isn’t a single best way to be Test Driven. There’s a lot to becoming proficient at TDD. Developing automated test suites, refactoring and reworking tests to eliminate duplication, and testing for exceptional conditions, are just a few. Additionally, acceptance tests, smoke tests, integration, performance and load tests support incremental development as well. If all this testing sounds like too much work, well…let’s be practical. Testing shouldn’t be done just for testing’s sake. Instead, the tests you write should give you leverage to confidently change and evolve your code base and validate the requirements of the system. That’s why it is important to know what to test, what not to test, and when to stop testing.
Pragmatic Not Dogmatic TDD Agile2012 by Joseph Yoder and Rebecca Wirfs-Brock
Pragmatic, Not Dogmatic TDD:Rethinking How We Test Joseph W. Yoder The Refactory, Inc. Rebecca Wirfs-Brock Wirfs-Brock Associates Copyright 2012 Joseph Yoder, Rebecca Wirfs-Brock, The Refactory, Inc. and Wirfs-Brock Associates
Introducing JosephFounder and Architect, The Refactory, Inc.Pattern enthusiast, author and Hillside Board PresidentAuthor of the Big Ball of Mud PatternAdaptive systems expert (programs adaptive software, consults on adaptive architectures, author of adaptive architecture patterns, metatdata maven, website: adaptiveobjectmodel.com)Agile enthusiast and practitionerBusiness owner (leads a world class development company)Consults and trains top companies on design, refactoring, pragmatic testingAmateur photographer, motorcycle enthusiast, enjoys dancing samba!!!
Introducing RebeccaPresident, Wirfs-Brock AssociatesAgile enthusiast (involved with experience reports since 1st agile conference, board president Agile Open Northwest, past Agile Alliance Board member)Pattern enthusiast, author, and Hillside Board TreasurerOld design geek (author of two object design books, inventor of Responsibility- Driven Design, advocate of CRC cards, hot spot cards, & other low-tech design tools, IEEE Software design columnist)Consults and trains top companies on agile architecture, responsibility-driven design, enterprise app design, agile use cases, design storytelling, pragmatic testingRuns marathons!!!
Some Agile Myths Simple solutions are always best. We can easily adapt to changing requirements (new requirements). Because I’m following TDD, I can reliably change the system fast!!! TDD will ensure good Design. “www.agilemyths.com”
First Classic Test-Driven DevelopmentStart Write test fails Re(Write) Check if production a test test fails code 1 or more tests fail test succeeds all tests Clean up code succeed Check all tests (Refactor) succeed Ship Ready to it!!! Release? Short Cycles
TDD Promises1 Tests help you build the right thing2 Tests guide development3 Tests keep you focused4 Tests allow you to change code safely and quickly5 Tests ensure what you build works6 You will end up with quality code7 You will end up with a good design
Question: Do tests help youbuild the right things?
Common Misperceptions Tests verify program correctness 3.1415926535… Tests enable and encourage well-designed code
Test Target → the thingT we are trying to test. Action → changes environment or the Test Target. Assertion → compares expected vs observable outcome of the action on the Test Target.
Test → a sequenceof at least one action and one assertion T T’
Good Test Outline1. Set up2. Declare the expected results3. Exercise the test4. Get the actual results5. Assert that the actual results match the expected results6. Teardown
Pragmatic Testing Questions What is important to test? Who should write them? Who runs them? When are they run? How are they run?
What to TestSignificant scenarios of use, notisolated methods.The difficult parts: Complex interactions,intricate algorithms, tricky business logicRequired system qualities Performance, scalability, throughput, security...How services respond to normaland exceptional invocations.
What Not to Test Tests should add value, not just be an exercise. Do not test: setters and getters (unless they have side effects or are very complex) every boundary condition; only test those with significant business value every exception; only those likely to occur or that will cause catastrophic problems.
Different Tests Can Overlap… Smoke Tests Quality Scenarios Integration Tests Acceptance Tests Unit TestsCommon to only focus on Unit Tests in TDD!!!We believe TDD is more than just Unit Tests
Question: Do tests help youbuild the right things?Answer: Yes. But …
Question: Do tests guidedevelopment and keep youfocused?
Two Faces of TestingDefining tests But you mayhelps limit be missingscope and the biggerincreases focus picture…Tests force you Might need toto implement consider howfunctionality currentinstead of functionalityjumping around affects theand tweaking rest of thestuff system
Thinking Fast vs. Slow Fast thinking: decisions based on intuition, biases, ingrained patterns, and emotions Slow thinking: Reasoning, logical thinking
Take Time For Both Slow thinking Pairing and discussion options are why you want to implement something a certain way Sketching, noodling, design spikes Fast thinking Fast turns of coding, testing and quick fixes… (Red/Green)
Question: Do tests guidedevelopment and keepyou focused?Answer: Yes…but…
Ten Tenets of Testing1. Test single complete scenarios2. Do not create dependencies between tests3. Only verify a single thing in each assertion4. Respect class encapsulation5. Test limit values and boundaries6. Test expected exceptional scenarios7. Test interactions with other objects8. When you find a bug, write a test to show it9. Do not duplicate application logic in tests10. Keep your test code clean
Question: Do I always haveto write tests first?
You are not doing TDD! Common BeliefYou must create You are not your tests first! practicing TDD correctly unless you write tests first, before writing any code that is tested.
Is it OK to write tests afteryou write production code? Is this cheating? Does this result in bad code? Does it result in a bad design? Does it reinforce “slacker” tendencies to not write tests?
Common Practice Tests don’t always get written first.Start Write test fails Re(Write) Check if production a test test fails code 1 or more tests fail test succeeds all tests Clean up code succeed Check all tests (Refactor) succeed Ship Ready to it!!! Release?
A Pragmatic Testing Cycle Code is only checked in with Valid Tests that verify that code works as expected (validate tests too)!!!Write some Check if Re(write)production test fails a testcode Clean up code (Refactor) 1 or more tests fail Check all tests succeed all tests succeed Ship Ready to it!!! Release?
Pragmatic Testing CycleAlternate between writing test code and production in small steps.Use feedback from tests to verify code (integrate often).Don’t worry whether the chicken or the egg comes first. Sometimes development guides testing.Do what yields the most value!
Question: Do I always haveto write tests first?Answer: No, as long as tests arechecked in with production code!
Question: Do tests allowyou to change code safelyand quickly?
Common WisdomWork refactoring into your daily routine… “In almost all cases, I’m opposed to setting aside time for refactoring. In my view refactoring is not an activity you set aside time to do. Refactoring is something you do all the time in little bursts.” — Martin Fowler
Two Refactoring Types* Floss Refactorings—frequent, small changes, intermingled with other programming (daily health) Root canal refactorings — infrequent, protracted refactoring, during which programmers do nothing else (major repair)* Emerson Murphy-Hill and Andrew Black in “Refactoring Tools: Fitness for Purpose”http://web.cecs.pdx.edu/~black/publications/IEEESoftwareRefact.pdf
What if the Tests are anObstacle to Refactoring?
The design of test codeneeds to evolve, just like production code!
Sometimes it is easier to throwaway tests, change the designof your production code, andthen write new tests.
Question: Do tests allowyou to change code safelyand quickly?Answer: Yes and no.
Question: Do tests help withquality code and good design?
Classic Test-DrivenDevelopment Rhythm User story-by-story: Write the simplest test Run the test and fail Write the simplest code that will pass the test Run the test and pass Repeat until a “story” is tested and implemented “Design happens between the keystrokes”
Another View ofTest-Driven Development Requirements Architecture Envisioning Envisioning Conceptual Modeling (days/weeks/...) (days/weeks/…) Iteration 0: Envisioning Iteration Modeling (hours) a little bit of modeling Model Storming then a lot of coding (minutes) Fast TDD(hours) Iteration n: Development
Spike SolutionsIf some technical difficulty threatens to hold up the systems development,Or you are not sure how to solve a particular problem… “Put a pair of developers on the problem for a week or two to reduce the potential risk”
Other Techniques forImproving QualitySteve McConnellhttp://kev.inburke.com/kevin/the-best-ways-to-find-bugs-in-your-code/
Combine and Conquer The average is 40% for any one technique… No one approach is adequate Combining techniques gives you much higher quality
Question: Do tests help withquality code and good design?Answer: They can but …you need more than tests.
Pragmatic Test-Driven Development (core process) Tests written & must pass before checking in production codeWrite some Check if Re(write)production test fails a testcode Clean up code (Refactor) 1 or more tests fail Check all tests succeed all tests succeed Ship Ready to it!!! Release? Good Tests
TDD Challenges1. Unit Tests aren’t enough… should they be the main focus?2. It is hard to know the “right” tests3. Deception that incrementally writing tests inductively proves software works… probably more deductive and example driven…4. Tests can constrain code evolution and refactoring
Be Pragmatic…Use tests to enhance your current practice!Ask how best to validate that yoursoftware meets its requirements.Develop the optimum set of tests to keepyour system working, not only Unit Tests!Make time for slow thinking too.
Keep It Focused Keep It FreshExpand your Horizons …Be Practical