writing clean and dry infrastructure test code
TRANSCRIPT
Writing clean and DRY
infrastructure test code
Vagif Abilov, Miles AS
About myself
Mail: [email protected]
Twitter: @ooobject
GitHub: object
BitBucket: object
Blog:
http://bloggingabout.net/blogs/vagif/default.aspx
Articles: http://www.codeproject.com
Agenda
How good is test code? Or how bad?
Testers as first class citizens
10 steps that lead to cleaner test code
Case studies and examples
How good is test code? Or how bad?
What quality do you expect from test code?
Test code tends to have inferior quality comparing to
production code
Test code tends to have superior quality comparing to
production code
Test and production code tend to have same quality
How long is a test’s lifetime?
Test code lasts as long as production code
Test code can be discarded while production code is still
in use
Test code can outlive production code
Testers as first class citizens
Anything that is deployed to production or shipped to customers is subject to more rigid requirements than internal matters
Product internals are external matters, test internals are internal matters
Software testers’ choices of tools and languages usually meet more liberal reception by management and principal architects
There is no excuse for a tester of not turning liberal management attitude to his/her own advantage –software testers have better chances to adopt most recent methods and technology
10 steps that lead to cleaner test code
1. Bridge communication gap
2. Use executable specifications
3. Let actors act in scenario definitions
4. «Push HOW down the stack»
5. Reduce translation layers
6. Practice explorative scripting
7. Expose test automation frameworks
8. DRY – explore community
9. Embrace dynamic languages
10. Care only about persistent state that matters
1. Bridge communication gap
“BDD is a 2nd generation, outside-in, pull-based, multiple-stakeholder, multiple-scale, high-automation, Agile methodology. It describes a cycle of interactions with well-defined outputs, resulting in the delivery of working, tested software that matters.” – Dan North
“BDD is not primarily a testing thing. You happen to get tests out of it afterwards, but there's usually still more testing that needs to be done. It's much more about developing an understanding of what you're about to produce.” – Liz Keogh
“Conversations are much more important than the BDD tools.” – Liz Keogh
2. Use executable specifications
Scenario: The answer with the highest vote gets to the
top
Given there is a question «What is your favourite
color» with the answers
| Answer | Vote |
| Red | 1 |
| Green | 1 |
When I upvote the answer «Green»
Then the answer «Green» should be on the top
Advantages of executable specifications
Written in a natural language (and local language)
Written in a formalised way
Integrated into daily builds
Living documentation
Set development milestones
Functional coverage
Functional coverage
Examples of executable specifications
Relish
Publishing executable specifications on the web
Examples: GDS/whitehall
brighterplanet/flight
3. Let actors act in scenario definitionsFeature: Pay bill
Background: Prices
Given the following operations are available:
| operation | price |
| routine check up | 10 |
| shots | 5 |
Scenario: Dave pays for Fluffy
Given Dave owns a pet Fluffy
And Dave brings Fluffy into the clinic for the following operations:
| routine check up |
| shots |
When the veterinarian charges Dave for the visit
And Dave pays cash
Then Dave is given a receipt which looks like this:
Operations:
$10 (routine check up)
$5 (shots)
Total to pay: $15 from Mann Wynne’s blog
Real world example
Adding an actor to a scenario
Distributing election reports
Scenario: Received report is saved and notification message is enqueued
Given table RP07 doesn’t contain reports for 46010000
And notification queue is empty
When receival service receives report RP07 with data
| Element | Value |
| dateCreated | 2013-05-01T10:01:02 |
| identifier | 46010000 |
| mandates | Ap=6;H=5;V=4 |
Then receival service should return OK
And table RP07 should contain report for 46010000
And notification queue should contain message
| Code | Identifier | Mandates |
| RP07 | 46010000 | Ap=6;H=5;V=4 |(Code example 1)
Revised scenario
Scenario: Parliament overview is updated shortly upon the report receival
Given I see following Parliament party mandates overview| Party | Mandates || Ap | 3 || H | 2 || V | 1 |
When receival service receives report RP07 with data| Party | Mandates || Ap | 6 || H | 5 || V | 4 |
And I wait 10 seconds
Then I should see following Parliament party mandates overview| Party | Mandates || Ap | 6 || H | 5 || V | 4 |
4. «Push HOW down the stack»
As said by Seb Rose and Matt Wynne
Gojko Adzic defines three levels of UI test automation- business/rule- user interface/workflow- technical
Specifications reflect a problem domain
From Matt Wynne’s blog
5. Reduce translation layers
BDD fixtures translate between system concepts
and user concepts. The more work the fixtures do,
the more wrong your system is
@richardadalton
Finding most efficient feature
implementation language
Scenario: Refunded items should be returned to stock
Given a customer buys a black jumper
And I have 3 black jumpers left in stock
When he returns the jumper for a refund
Then I should have 4 black jumpers in stock
Step definition examples
1. C#/SpecFlow
2. Ruby
3. F#/TickSpec
(Code examples 2-4)
6. Practice explorative scripting
Don’t rush building test automation framework before
you explore the system
Try finding REPL tool for the language of your tests
Explore the system from script sessions
Use exploration results to build automated tests
Beware that manual test scripts and automated tests
carry different contexts and usually can’t be easily
substituted
DEMO
Web UI scripting using
scriptcs and FluentAutomation
7. Expose test automation frameworks
If you have WebDriver APIs in your test methods,
you're doing it wrong (Simon Stewart)
UI
Tests Tests
UI
Automatio
n
API
«Page» in PageObject can be misleading
Despite the term "page" object, these objects
shouldn't usually be built for each page, but rather
for the significant elements on a page (Martin
Fowler)
Fowler also gives an alternative name: Panel
In general PageObject classes in UI automation
library should not bear names of HTML pages
Rather than exposing logical page control API you
can model a test automation framework after user’s
behavior
Example: Google search automation
Feature: Search for professional events
In order to keep updated about professional events
As a service subscriber
I want to be able to search for conferences
Scenario: Search for professional conference Web sites
Given I am a service subscriber
When I search for "Agile Testing Days"
Then I should receive results starting with "www.agiletestingdays.com"
Page pattern vs. behavioral pattern
Page pattern fits well regression tests and
automation of external Web sites
Behavioral pattern focuses on high level user
activities and can be easier to apply when Web site
structure is subject to major changes
(Code examples 5-8)
8. DRY – explore community
In fact it’s not just about DRY – it’s DRO (Don’t
Repeat Others)
There’s plenty of libraries (mostly open-source) that
have already solved your plumbing needs
Generating of pseudo-random test data
Converting Gherkin tables to DTOs
Comparing Gherkin tables with contents of data sources
Replacing DTOs with dynamic objects
Example: user data validation
Scenario: Validate users
Given the following users exists in the database:
| Name | Birth date | Length in meters|
| John | 1940-10-09 | 1.80 |
| Paul | 1942-06-18 | 1.80|
| George | 1943-02-25 | 1.77 |
| Ringo | 1940-07-07 | 1.68 |
Then the following users must exist in the database:
| John | 1940-10-09 | 1.80 |
| Paul | 1942-06-18 | 1.80|
| George | 1943-02-25 | 1.77 |
| Ringo | 1940-07-07 | 1.68 |
(Code examples 9-12)
9. Embrace dynamic languages
Less ceremony – more action
Access databases without creating proxy classes
and DTOs
Access Web services without importing WSDL files
Eliminate data transfer objects
Code examples 13-15)
10. Care only about persistent state that matters
Don’t set expectations about persistent state for the
test
Don’t restore persistent state after the test
Don’t take an effort of complex data deletion routines
Just push aside data that stand on the way of your
test
Code examples (16-17)
Once again...
1. Bridge communication gap
2. Use executable specifications
3. Let actors act in scenario definitions
4. Push HOW down
5. Reduce translation layers
6. Practice explorative scripting
7. Expose test automation frameworks
8. DRY – explore community
9. Embrace dynamic languages
10. Care only about persistent state that matters
Karaoke time!
«Beautiful Code»
Christina Agile-Era
Writing clean and DRY infrastructure test code
Thank you!
Vagif Abilov
@ooobject
GitHub: object
BitBucket: object