Better Testing Through Behaviour

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    1 Favorite & 1 Group

    Better Testing Through Behaviour - Presentation Transcript

    1. Better Testing Through Behaviour Open Source Developers’ Conference November 2007 Tom Adams Workingmouse
    2. “The act of writing a unit test is more an act of design than of verification. It’s also more an act of documentation than of verification. The act of writing a unit test closes a remarkable number of feedback loops, the least of which is the one pertaining to verification of function.” Robert C. Martin
    3. Why do I care? I. Better process •Workflow is easier, IDE-a-bility, simpler •Supporting infrastructure & language that guides you down the correct path II. Better results •Splitting of state into separate contexts means understanding •Nicer syntax, less code to mentally parse •Readable results
    4. Test driven development •Development practice, arising out of XP’s test first approach •Incremental process - test, code, refactor, test code, refactor… •Drives implementation - improved quality, low coupling, high cohesion •Comprehensive regression test suite •Focus on design? •Focus on documentation? •Focus on behaviour?
    5. Problems? •Too much time/money, optional extra •Overlapping with traditional QA testers •Developers require training •Developer resistance •Vocabulary difference
    6. Problems? •Test vocabulary affects thinking •Intent not clear •Design focus obscured •Documentation •1-1 mapping of test/production code •Tight tests coupled to code •Repetitive infrastructure setup •Where to start?
    7. BDD is just TDD •Coined by Dan North - JBehave first BDD framework •Development practice, arising out agile methodologies •Refinement of TDD that shifts the emphasis from testing to specification •Frameworks - JBehave, RSpec, Instinct, JDave, NSpec, GSpec, beanSpec, JSSpec, DSpec, MissingBDD, PHPSpec, Specs, Specipy
    8. class ACsvFileReaderWithNothingToRead { @Subject CsvFileReader csvFileReader; @Mock CsvFile csvFile; @Stub CsvLine[] noLines; @Specification void returnsNoLines() { expect.that(new Expectations() {{ one(csvFile).hasMoreLines(); will(returnValue(false)); ignoring(csvFile).close(); }}); expect.that(csvFileReader.readLines()).equalTo(noLines); } }
    9. class AnEmptyStack { @Subject Stack<Object> stack; @Dummy Object object; @Specification void isEmpty() { expect.that(stack.isEmpty()).isTrue(); } @Specification void isNoLongerBeEmptyAfterPush() { stack.push(object); expect.that(stack.isEmpty()).isFalse(); } @Specification(expectedException = IllegalStateException.class, withMessage = \"Cannot pop an empty stack\") void throwsExceptionWhenPopped() { stack.pop(); } }
    10. AnEmptyStack - isEmpty - isNoLongerBeEmptyAfterPush - throwsExceptionWhenPopped ANonEmptyStack - isNotEmpty - isNoLongerFullAfterPoppingAllElements - throwsExceptionWhenANullIsPushed - popsPushedValue - shouldPopSecondPushedValueFirst - leavesValueOnStackAfterPeek
    11. Ubiquitous language •Language has an impact on how you think about something •Known in linguistics as the Sapir-Whorf hypothesis •There is “a systematic relationship between the grammatical categories of the language a person speaks and how that person both understands the world and behaves in it” •The language used to describe software constructs has an impact on how we create those constructs, e.g. good APIs, well named variables
    12. Ubiquitous language •Getting the words right - naming of classes, methods and variables •Borrows from domain driven development (DDD) •Bridges gap between technical and business artefacts •Captures the behaviour of the domain using clear and concise syntax •Forms consensus around domain artefacts and run-time behaviour
    13. private void testRunnerSendsSpecifiationResultsToOutput() { assertTrue(\"Expected to find context name\", runnerOutput.contains(className)); } private void sendsSpecifiationResultsToOutput() { expect.that(runnerOutput).containsString(className); }
    14. assertEquals(1, map.size()); assertTrue(map.containsKey(1000)); assertEquals(fileNames, map.get(1000)); expect.that(map).hasSize(1); expect.that(map).containsKey(1000); expect.that(map).containsEntry(1000, fileNames);
    15. public void testMethodIsAnnotated() { checkIsAnnotated(WithRuntimeAnnotations.class, Context.class, true);   checkIsAnnotated(WithoutRuntimeAnnotations.class, Context.class, false); } private void checkIsAnnotated(AnnotatedElement element, Class<?> expectedAnnotation, boolean expectingAnnotation) { AnnotationChecker annotationChecker = new AnnotationCheckerImpl();   assertEquals(expectingAnnotation, annotationChecker.isAnnotated(element, expectedAnnotation)); }
    16. public void testClassIsAnnotated() { expect.that(annotationChecker.isAnnotated( WithRuntimeAnnotations.class, Context.class)).isTrue(); expect.that(annotationChecker.isAnnotated( WithoutRuntimeAnnotations.class, Context.class)).isFalse(); }
    17. Design focus •Design is one of the most important aspect of TDD •TDD’d code is (usually of) higher quality that non-TDD’d code •Bugs, coupling, cohesion, maintainability, understandable, smaller, etc. •Emphasis on testing limits TDD’s uptake & effectiveness •Organisational, technical, process •Encourages you to think about design •Design is documented through ubiquitous language, contexts
    18. Behaviour focus •Focused specifications •One context per “state” of subject •Minimal expectations per specification method
    19. Behaviour focus •1-to-1 test-to-prod code mapping broken •“Units” gone, what’s important is the behaviour •Specification code is less coupled to production code •Easier refactoring •M-to-N mapping encouraged
    20. class AnEmptyStack { void isEmpty() {} void isNoLongerBeEmptyAfterPush() {} void throwsExceptionWhenPopped() {} } class ANonEmptyStack { void isNotEmpty() {} void throwsExceptionWhenANullIsPushed() {} void popsPushedValue() {} void shouldPopSecondPushedValueFirst() {} void leavesValueOnStackAfterPeek() {} }
    21. Process •Works best top-down/outside-in •Specify at the highest level first •Use top-level objects to discover the services needed from the next level down •Rinse, repeat
    22. Levels •Story-level •Code-level •Mostly historical, frameworks are now adopting both approaches •Both levels are legitimate, use one or the other depending on audience
    23. Scenario \"transfer from savings account to cheque acount\" do Given \"my savings account balance is\", 100 do |balance| @savings_account = Accounts::AccountFactory.create(:savings) @savings_account.add(balance) end And \"my cheque account balance is\", 50 do |balance| @cheque_account = Accounts::AccountFactory.create(:cheque) @cheque_account.add(balance) end When \"I transfer\", 20 do |amount| @savings_account.transfer(amount.to_i).to(@cheque_account) end Then \"my savings account balance should be\", 80 do |balance| @savings_account.balance.should == balance end And \"my cheque account balance should be\", 70 do |balance| @cheque_account.balance.should == balance end end
    24. describe \"non-empty Stack\" do it \"should return the top item when sent #peek\" do @stack.peek.should == @last_item_added end end class ANonEmptyStack { void shouldReturnTheTopItemWhenSentPeek() { expect.that(stack.peek()).equalTo(lastItemAdded); } }
    25. Instinct •Goals - explicitness, simplicity and flexibility •Code-level (currently) framework •Unified state and behaviour (mocking) expectation API (c.f. xUnit Assert) •Built in infrastructure - mocks, stubs, dummies, subjects •Formalised nomenclature •Integration - JUnit, Ant, Clover, IntelliJ IDEA
    26. Instinct examples
    27. Summary •Shifts the emphasis from testing to specification •Provides a ubiquitous language •Strong focus on design •Emphasises system behaviour, independent of where the behaviour resides
    28. Take home I. Better process •Workflow is easier, IDE-a-bility, simpler •Supporting infrastructure & language that guides you down the correct path II. Better results •Splitting of state into separate contexts means understanding •Nicer syntax, less code to mentally parse •Readable results
    29. References •http://en.wikipedia.org/wiki/Behavior_driven_development •http://blog.daveastels.com/2005/07/05/a-new-look-at-test-driven-development •http://blog.davidchelimsky.net/files/BDDWithRspec.RubyConf.2007.pdf •http://code.google.com/p/instinct/ •http://rspec.rubyforge.org/

    + Tom AdamsTom Adams, 2 years ago

    custom

    1583 views, 1 favs, 3 embeds more stats

    Test Driven Development (TDD) is a well established more

    More info about this document

    CC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike License

    Go to text version

    • Total Views 1583
      • 1562 on SlideShare
      • 21 from embeds
    • Comments 0
    • Favorites 1
    • Downloads 147
    Most viewed embeds
    • 19 views on http://www.jroller.com
    • 1 views on http://jroller.com
    • 1 views on http://64.233.167.104

    more

    All embeds
    • 19 views on http://www.jroller.com
    • 1 views on http://jroller.com
    • 1 views on http://64.233.167.104

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories

    Groups / Events