Creating Data with the Test DataBuilder PatternCukeUp! 2013Alan Parkinson
Create test data with the mostappropriate tools andusing a sensible DSL
Scenario AUTDatabase
Build methodSafe DefaultsChainable
public class UserBuilder {String name = “admin”;String password = “admin”;…public User build() {return new User(admin, pas...
User user = new UserBuilder() .build();User user = new UserBuilder().withName(“Alan”).withPassword(“secret”).build();
Build methodSafe DefaultsChainable
Imperative ExampleGiven a User "dave" exists with password "secret"And I am not logged inWhen I navigate to the home pageT...
Refactored to be DeclarativeGiven I am an unauthenticated UserWhen I attempt to view some restricted contentThen I am show...
private UserDescription user;@Given("^I am an … $")public void unauthenticated_user() {user = new UserBuilder().build();…}...
private UserDescription user;@Given("^ a User … $")public void a_user(String name, password) {user = new UserBuilder().wit...
private UserDescription user;private UserBuilder userBuilder = new UserBuilder();@Given("^I am an … $")public void unauthe...
public class IssueBuilder {String summary = “Default Summary”;Project project = new ProjectBuilder().build();String report...
Issue issue = new IssueBuilder().withSummary(“Icon hover bug”).build();.withReporter(new UserBuilder().withName(“Alan”).bu...
public class IssueBuilder {…Project project = null;…public IssueDescription build() {if (project == null) {project = new P...
Unique
Factories
Create test data with the mostappropriate tools andusing a sensible DSL
QuestionsAlan ParkinsonCEO, Hindsight Software Ltdalan.parkinson@hindsightsoftware.co.uk@alan_parkinson
LinksTest Data Builders: an alternate to the ObjectMother pattern - http://ow.ly/jEYkf
NatPryce.com
Creating data with the test data builder pattern
Creating data with the test data builder pattern
Upcoming SlideShare
Loading in …5
×

Creating data with the test data builder pattern

2,679 views
2,470 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,679
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • HowWhenWhy
  • To isolate data between tests, script cleans and populates the databaseRequires direct access to the database
  • SQL Scripts are brittle to changePortability issues between database vendorsHigh maintenance costDifficult to create dataHard write by handSmall sets of data created – often reused across many tests.Run Application, add data and create Script from Database DumpLots of small variationsFor large sets of tests data schema changes are expensiveCan’t be used with Concurrent / Parallel Test ExecutionIgnores business rules on data – Script my load data that does not follow the correct business rules, cause test to fail. Hard to debugLimits reuse of Test artifactsCan’t access databases on production systems - NO smoke testing deployments –
  • Our Applications expose API’s all the timeREST, SOAP and RMI to name a fewUse them to create our test dataOn Demand – Given StepDevelopers maintain the public API – receives free maintenanceCode reuse – Code can be reused for Testing the REST services.Tests can be reused for Smoke testing deploymentsAs it doesn't clean the database. Requires generated data to be uniqueIgnores system state - the same tests can be repeatedly executed with the same result
  • Public API code - Large messy code for creating test data on demandNice abstraction is requiredReadable test setup codeCode reuseEasy and low maintenanceNat PryceCreate a builder for each class or resourceHas an instance variable for each constructor parameterInitialises its instance variables to commonly used or safe valuesHas a `build` method that creates a new object using the values in its instance variablesHas "chainable" public methods for overriding the values in its instance variables.
  • Simplest example of a builder used in Unit testsAll builders feature a build method - No parametersReturns value objectInstead we would make REST/API calls to our
  • Sensible defaults Click - Can be overriddenWritten a fluent styleEasy to read
  • Returns object describing the remotely created datae.g. unique IDIssueBuilder would return the Key of the created Issue.Even if the Any other useful information that is required by the test
  • The imperative style uses highly reusable granular steps which outlines much of the user interface. This binds the scenario to that UI and requires more design decisions made up front.Makes the Scenario brittle to minor changes in UI when no Behaviour or functionality has changed.
  • Each step states an idea.Sometimes it’s not really clear precisely what is being doneThe username and password detail has been pushed inside the test implementationWe don’t care about these details in this example – It doesn’t add anythingUse sensible defaults for these values – Data Builder also uses sensible defaults.
  • RelationshipsRefactor build method to lazily initialize
  • Sensible defaults Can be overriddenWritten a fluent styleEasy to readEmbedding builders
  • As we are creating remote objects, defaults should lazily initialized to avoid performance penalty
  • ID’s are best generated - previously run the same test suite and have not cleared the database, manually created unique ID’s could already be in use.Randomness - Repeating the test should not generate the same IDWe have found Hashes work quite well for Alphanumeric generationIssue – generates unique ID in the dataProject – requires us to generate a unique IDProject ID is up to 10 characters long and Alpha onlyGenerated IDs avoid clashes with stale dataHashes – MD5Seeding data generation ImportantTest method name useful componentRandom numberBusiness rules – Data length and typeAlpha only string generator
  • Different product versions/configurationsDifferent data formatsDifferent devicesCan be supported by the Abstract Factory patternCreate families of builders to support them
  • Avoid SQLUse exposed API’sGenerate Unique dataData Builder PatternFactories for your Data Builders
  • Test Data Builders: an alternate to the Object Mother patternCreate objects with complex constructors in Unit TestsHas an instance variable for each constructor parameterInitialises its instance variables to commonly used or safe valuesHas a `build` method that creates a new object using the values in its instance variablesHas "chainable" public methods for overriding the values in its instance variables.
  • Creating data with the test data builder pattern

    1. 1. Creating Data with the Test DataBuilder PatternCukeUp! 2013Alan Parkinson
    2. 2. Create test data with the mostappropriate tools andusing a sensible DSL
    3. 3. Scenario AUTDatabase
    4. 4. Build methodSafe DefaultsChainable
    5. 5. public class UserBuilder {String name = “admin”;String password = “admin”;…public User build() {return new User(admin, password);}…}
    6. 6. User user = new UserBuilder() .build();User user = new UserBuilder().withName(“Alan”).withPassword(“secret”).build();
    7. 7. Build methodSafe DefaultsChainable
    8. 8. Imperative ExampleGiven a User "dave" exists with password "secret"And I am not logged inWhen I navigate to the home pageThen I am redirected to the login form....
    9. 9. Refactored to be DeclarativeGiven I am an unauthenticated UserWhen I attempt to view some restricted contentThen I am shown a login formWhen I authenticate with valid credentials….
    10. 10. private UserDescription user;@Given("^I am an … $")public void unauthenticated_user() {user = new UserBuilder().build();…}Declarative Example
    11. 11. private UserDescription user;@Given("^ a User … $")public void a_user(String name, password) {user = new UserBuilder().withName(name).withPassword(password).build();}
    12. 12. private UserDescription user;private UserBuilder userBuilder = new UserBuilder();@Given("^I am an … $")public void unauthenticated_user() {user = userBuilder.build();}@Given("^an email address $")public void user_email(String emailAddress) {userBuilder.withEmail(emailAddress);user = userBuilder.build();}
    13. 13. public class IssueBuilder {String summary = “Default Summary”;Project project = new ProjectBuilder().build();String reporter = new UserBuilder().build();…public IssueBuilder withProject(Project project) {this.project = project;return this;}public IssueDescription build() {…}}
    14. 14. Issue issue = new IssueBuilder().withSummary(“Icon hover bug”).build();.withReporter(new UserBuilder().withName(“Alan”).build()).build();
    15. 15. public class IssueBuilder {…Project project = null;…public IssueDescription build() {if (project == null) {project = new ProjectBuilder().build();}…}}
    16. 16. Unique
    17. 17. Factories
    18. 18. Create test data with the mostappropriate tools andusing a sensible DSL
    19. 19. QuestionsAlan ParkinsonCEO, Hindsight Software Ltdalan.parkinson@hindsightsoftware.co.uk@alan_parkinson
    20. 20. LinksTest Data Builders: an alternate to the ObjectMother pattern - http://ow.ly/jEYkf
    21. 21. NatPryce.com

    ×