Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
more than a
side salad:
behaviour driven testing and
test driven design in Django
with Lettuce
Danielle Madeley
 blogs.gn...
Just what is test
driven
development?
Tests first;
code second
http://www.nilkanth.com/2007/06/08/three­monkeys­of­test­driven­development/
But how do we
write tests when
we don't know
what the code
looks like?
Don't test code;
test behaviours
As a visitor to the site
I want to create an account using my Google
login
So that I can log in without needing another
pa...
GivenI have a valid Google account
WhenI visit the siteAnd I click create account
ThenI am redirected to Google
http://www...
Lettuce
http://lettuce.it
http://www.flickr.com/photos/65567316@N00/2742564457
Feature: Authenticate to API
As a searcher/API user
I want to authenticate to the API
So that I can make queries
Scenario:...
Steps
http://www.flickr.com/photos/60364452@N00/504844510
from lettuce import step, world
@step(r'I get the resource "([^"]*)"')
def get_resource(step, url):
"""
Make a GET request...
Steps are
stateful
http://www.flickr.com/photos/chrisconnell/3201514924/
from django.test.client import Client
from lettuce import before, step, world
from nose.tools import assert_equals
@before...
./manage.py
harvest
# settings.py
INSTALLED_APPS = (
...
'lettuce.django',
'myapp',
)
LETTUCE_APPS = (
'myapp',
)
LETTUCE_USE_TEST_DATABASE = ...
Selenium
http://www.flickr.com/photos/21663307@N02/3599012763
from lettuce import before, world
# import external lettuce steps
import lettuce_webdriver.webdriver
@before.all
def set_b...
def site_url(url):
base_url = 'http://%s' % socket.gethostname()
if server.port is not 80:
base_url += ':%d' % server.port...
Scenario: Add consumer with blank Contact name
When I log in to admin with username "admin" and
And I click "Consumers"
An...
Fixtures
Feature: Create new API key
As an administrator
I want to create a new API key
So that I can enable others to query API
Ba...
Built in steps using
Django's model
introspection
Given I have users in the database:
...
Then there should be 1 consumer ...
Which are extendable
@creates_models(User)
def create_user(step):
data = hashes_data(step)
for hash_ in data:
is_superuser...
Best practice
Given I have items in my cart
When I go to checkout
And I pay for the items
Then everything worked
write reusable
steps
write reusable scenarios
Scenario Outline: I edit a user to add a team
Given users have permissions:
| user | organisation...
tie each feature file
to a single story
include scenarios
and anti-scenarios
Other uses
http://www.flickr.com/photos/omcoc/3050378171/
fin ;-P
questions?
colophon This presentation was done in reveal.js using Junction, Cantarell
and Source Code Pro with pho...
More than a side salad: behaviour driven testing and test driven design in Django with Lettuce
More than a side salad: behaviour driven testing and test driven design in Django with Lettuce
More than a side salad: behaviour driven testing and test driven design in Django with Lettuce
More than a side salad: behaviour driven testing and test driven design in Django with Lettuce
Upcoming SlideShare
Loading in …5
×

More than a side salad: behaviour driven testing and test driven design in Django with Lettuce

4,806 views

Published on

Published in: Technology, Business
  • Be the first to comment

More than a side salad: behaviour driven testing and test driven design in Django with Lettuce

  1. 1. more than a side salad: behaviour driven testing and test driven design in Django with Lettuce Danielle Madeley  blogs.gnome.org/danni  dannipenguin
  2. 2. Just what is test driven development?
  3. 3. Tests first; code second
  4. 4. http://www.nilkanth.com/2007/06/08/three­monkeys­of­test­driven­development/
  5. 5. But how do we write tests when we don't know what the code looks like?
  6. 6. Don't test code; test behaviours
  7. 7. As a visitor to the site I want to create an account using my Google login So that I can log in without needing another password
  8. 8. GivenI have a valid Google account WhenI visit the siteAnd I click create account ThenI am redirected to Google http://www.flickr.com/photos/27369469@N08/2660160225
  9. 9. Lettuce http://lettuce.it http://www.flickr.com/photos/65567316@N00/2742564457
  10. 10. Feature: Authenticate to API As a searcher/API user I want to authenticate to the API So that I can make queries Scenario: I am not authenticated to the API When I get the resource "/api/v3/hello/" Then I get the response code 401
  11. 11. Steps http://www.flickr.com/photos/60364452@N00/504844510
  12. 12. from lettuce import step, world @step(r'I get the resource "([^"]*)"') def get_resource(step, url): """ Make a GET request to the given URL """ world.response = world.client.get(url)
  13. 13. Steps are stateful http://www.flickr.com/photos/chrisconnell/3201514924/
  14. 14. from django.test.client import Client from lettuce import before, step, world from nose.tools import assert_equals @before.each_scenario def set_default_client(scenario): world.client = Client() @step(r'I get the resource "([^"]*)"') def get_resource(step, url): world.response = world.client.get(url) @step(r'I get the response code (d+)') def check_response_code(step, code): code = int(code) assert_equals(world.response.status_code, code)
  15. 15. ./manage.py harvest
  16. 16. # settings.py INSTALLED_APPS = ( ... 'lettuce.django', 'myapp', ) LETTUCE_APPS = ( 'myapp', ) LETTUCE_USE_TEST_DATABASE = True
  17. 17. Selenium http://www.flickr.com/photos/21663307@N02/3599012763
  18. 18. from lettuce import before, world # import external lettuce steps import lettuce_webdriver.webdriver @before.all def set_browser(): """ Create a browser instance for use in tests. """ world.browser = webdriver.PhantomJS(...) world.browser.set_window_size(1200, 800)
  19. 19. def site_url(url): base_url = 'http://%s' % socket.gethostname() if server.port is not 80: base_url += ':%d' % server.port return urlparse.urljoin(base_url, url) @step("I visit the site") def open_site(step): step.given('I visit "%s"' % site_url('/'))
  20. 20. Scenario: Add consumer with blank Contact name When I log in to admin with username "admin" and And I click "Consumers" And I click "Add consumer" And I fill in "Organisation" with "OOOO" And I fill in "Contact name" with "" And I fill in "Contact number" with "0399999999" And I fill in "Website" with "www.test.com" And I press "Save" Then I should see "This field is required" And there should be 0 consumers in the database
  21. 21. Fixtures
  22. 22. Feature: Create new API key As an administrator I want to create a new API key So that I can enable others to query API Background: Given I have users in the database: | username | password | is_superuser | | admin | secret | true |
  23. 23. Built in steps using Django's model introspection Given I have users in the database: ... Then there should be 1 consumer in the database And consumer should be present in the database: ...
  24. 24. Which are extendable @creates_models(User) def create_user(step): data = hashes_data(step) for hash_ in data: is_superuser = hash_.pop('is_superuser', Fals if is_superuser: user = User.objects.create_superuser(**ha else: user = User.objects.create_user(**hash_) user.save() reset_sequence(User)
  25. 25. Best practice
  26. 26. Given I have items in my cart When I go to checkout And I pay for the items Then everything worked
  27. 27. write reusable steps
  28. 28. write reusable scenarios Scenario Outline: I edit a user to add a team Given users have permissions: | user | organisation | permission | | peon@org.org | OrgCorp | organisation_user | And I log in with email "<email>" through the profile serve When I visit site page "organisation/1/admin/user/4/edit" And I select option "Team 1" from selector "Team" And I press "Save" Then there should be 1 organisation member metadata in the Then organisation member metadata should be present in the | organisation__name | user__email | team | | OrgCorp | peon@org.org | Team 1 | Examples: | email | | god@god.org | | superuser@org.org | | poweruser@org.org |
  29. 29. tie each feature file to a single story
  30. 30. include scenarios and anti-scenarios
  31. 31. Other uses http://www.flickr.com/photos/omcoc/3050378171/
  32. 32. fin ;-P questions? colophon This presentation was done in reveal.js using Junction, Cantarell and Source Code Pro with photography from the Creative Commons. Infoxchange is hiring. Come and chat to me!  blogs.gnome.org/danni  dannipenguin http://www.flickr.com/photos/mau3ry/3763640652/

×