Upload
noah-patterson
View
213
Download
0
Embed Size (px)
Citation preview
Growing softwarefrom examples
Seb Rose, Claysnow Limited
Twitter: @sebrose
Blog: www.claysnow.co.uk
E-mail: [email protected]
Heavily influenced by GOOS book:
They’re called different thingsThe difference is that one is called Behaviour Driven Development – and some people find that wording useful – and one (or two) is called (Acceptance) Test Driven Development – and some people find that wording useful in a different way.
And that’s it. Liz Keogh, 2011http://lizkeogh.com/2011/06/27/atdd-vs-bdd-and-a-potted-history-of-some-related-stuff/
Test Driven
Development
Acceptance Test
Driven
DevelopmentBehaviour
Driven Development
Domain Driven DesignSpecification by Example
Example
Driven
Development
Customer Test
Pattern Generally good for Generally bad for
Given/When/Then
Tests that require•a lot of setup OR•easily forgotten setupTests that have a non-obvious triggerTests with few expected outputs
•Tests that have unimportant/simple/obvious preconditions
•Tests where there are multiple different inputs and multiple different outputs
•Tests where a single Given/When/Then only describes one of numerous very similar test scenarios
Specification By Example - Conceptual or Concrete
Tests that have numerous:Inputs that affect output behaviorOutputs/expected behaviorsTests where it’s important to test a lot of different data scenariosTests where the trigger event is somewhat obviousAny test where it seems like a table would be useful to:describe the test better, orhelp explore all of the possible inputs and outputs for a test.
•Simple tests•Tests that are more about
verifying simple UI behavior
For instance – “Test that an error message is displayed when the user enters an incorrect password.”
•Test where there is really only one input or precondition
http://www.scrumcrazy.com/file/view/ScrumCrazy.com_StoryTestingPatternsSummary3.pdf/391066838/ScrumCrazy.com_StoryTestingPatternsSummary3.pdf
http://exampler.com
UnderstandableMaintainableNecessaryGranularReliable
Understandable
http://plus.maths.org/latestnews/sep-dec08/proof/proof.jpg
Maintainable
Necessary
Granular
Reliable
Declarative - makes a statement (.)
Prefer declarative examples
Exclamatory - shows excitement (!)
Interrogative - asks a question (?)
Imperative - makes a command (.)
Imperative vs Declarative Style
Feature: Sign up Scenario: New user redirected to their own page Given I am not logged in And I visit the homepage And I follow "Sign up" And I fill in "Username" with "Seb" And I fill in "Password" with "password" And I fill in "Confirm password" with "password" When I press "Sign up" Then I should be on my feeds page And I should see "Hello, Seb"
Imperative vs Declarative Style
Feature: Sign up Scenario: New user redirected to their own page When I sign up for a new account
Then I should be taken to my feeds pageAnd I should see a greeting message
Imperative vs Declarative Style
Feature: The entire system This feature illustrates what can happen when you take the declarative style too far.
Scenario: It works When I use the system Then it should work perfectly
Remember your audience
Who should be able to read the examples?
Keep things clear.
What is their interest in them?
Don’t hide the context
[Test] public void asterisk_should_format_to_em() {String expected = "This is <em>em</em> text";String actual = f.Format("This is *em* text");
Assert.AreEqual(expected, actual); }
Don’t hide the context
Scenario: Increased delivery charges for zip codeGiven my delivery zip code is in AlaskaWhen I go to the checkoutThen I will have to pay the higher delivery charges
Don’t hide the context
@Test public void smoker_requires_manual_referral() {Referral referral = underwriting.process(smoker);
Assert.assertEquals(Referral.Manual, referral); }
Make data explicit
@Test public void smoker_requires_manual_referral() {Customer customer = new Customer(“Joe”, “Smith”,
“12/12/1980”, “Accountant”, “$300,000”, “Yes”, “No”);
Referral referral = underwriting.process(customer);
Assert.assertEquals(Referral.Manual, referral); }
Emphasise interesting details
@Test public void smoker_requires_manual_referral() {CustomerBuilder builder = new CustomerBuilder();Customer customer = builder
.withSmokerFlag()
.build();
Referral referral = underwriting.process(customer);
Assert.assertEquals(Referral.Manual, referral); }
Work collaboratively
Create a ubiquitous language.
Use examples to discover the domain.
Decompose ruthlessly.
Online subscriptionsIn order to increase subscriptions
visitors should be able to
subscribe online with a VISA card
User / Stakeholder Story
VISA subscriptionsIn order to increase subscriptions
visitors should be able to
subscribe online with a VISA card
User / Stakeholder Story
VISA subscriptionsIn order to increase subscriptions
visitors should be able to
subscribe online with a VISA card
Acceptance Criteria
•Must support VISA•Does not need to support MasterCard, Switch•...•Customers should be prevented from entering invalid credit card details• ...
Credit Card ProcessingAcceptance criteria:
Really? So tell me...
"Customers should be prevented from entering invalid
credit card details"
•What exactly makes someone's credit card details invalid?
•Can they use spaces?
•Should we checksum the digits?
•How do we feed back that the details are invalid?
Avoid workflow style
Every journey is made from single steps.
Workflows are more brittle.
A few workflows go a long way.
https://www.ibm.com/developerworks/library/j-aopwork11/TestingPyramid.jpg
Exploratory and
manual
Workflow style
Scenario: Happy path for registration and purchaseGiven I am on the homepageAnd I register for an account in AlaskaAnd I go to the most popular item pageAnd I add the most popular item to my basketAnd I go to checkoutAnd I select my delivery addressAnd I give valid payment detailsWhen I confirm acceptance of terms and conditionsThen my purchase will be confirmed
Workflow style
Scenario: Correct postage price for AlaskaGiven I am on the homepageAnd I register for an account in “Alaska”And I go to the most popular item pageAnd I add the most popular item to my basketAnd I go to checkoutWhen I select delivery to my home addressThen I have to pay the higher delivery charge
Focus on a single step
Scenario: Correct postage price for AlaskaGiven I am on the checkout pageWhen I select delivery to “Alaska”Then I have to pay the higher delivery charge
Consider costs and benefits
Remove unnecessary examples
Exercise the thinnest slice possible
Automate when viable
Cost
Risk
Manual
Automate
Don’t let example dictate mechanism
Visibility depends on interest not layer.
Insulate examples from technical details.
Acceptance tests not always end-to-end.
Make technical tests visible
Scenario: High Risk rates for Test PilotsGiven an applicant with occupation “Test Pilot”When the underwriting engine is invokedThen we will use the “High Risk” rates table
Scenario: Applicant with high risk occupationGiven a standard, single-life, male applicantBut with a high risk occupationWhen the application is processedThen it will be referred for manual underwriting
Is this end to end?
@domain_model@stubbed_underwriting
Categorise in multiple dimensions
Faster feedback is better.
Other dimensions are also useful.
Take advantage of partitioning.
Summary
Example-based methods are very similar.
Minor variations by target audience.
Skills are transferable.
Nomenclature
Check
Example
Specification
Test
Backup
Drive out traceability
-
-
-
Verify dependencies
-
-
-