Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django and the testing pyramid - DjangoCon Europe 2017

Django and the testing pyramid - DjangoCon Europe 2017

Video: https://www.youtube.com/watch?v=Mb4P0vnmymM

Model mommy lettuce factory boy expects gherkin behave. Travis mock splinter nose phantom hypothesis!

Most developers recognise the importance of testing in building maintainable software, but the sheer volume of tools and approaches can be bewildering and sometimes make it sound like you’re talking a different language.

In this talk we’ll look at the testing pyramid. We’ll discuss how approaching our testing in layers can increase developer productivity by reducing the time taken to run our test suites. We’ll look at the importance of different testing types including integration and acceptance testing. Finally we’ll introduce some tools and packages you can use to make writing good tests easier.

By the end you'll be able to talk TDD and BDD like a native!

Aaron Bassett

April 04, 2017
Tweet

More Decks by Aaron Bassett

Other Decks in Programming

Transcript

  1. Feature: Number verification Users can add verified mobile numbers to

    their profile Scenario: Adding a valid phone number Given I'm an authenticated user And I have a valid phone number When I go to the phone number page And I press the verify button Then I should not see the error message
  2. Feature: Number verification Users can add verified mobile numbers to

    their profile Scenario: Adding a valid phone number Given I'm an authenticated user And I have a valid phone number When I go to the phone number page And I press the verify button Then I should not see the error message
  3. Feature: Number verification Users can add verified mobile numbers to

    their profile Scenario: User enters an invalid phone number Given I'm an authenticated user When I go to the phone number page And I enter ‘not a number’ And I press the verify button Then I should see the error message
  4. Feature: Number verification Users can add verified mobile numbers to

    their profile Scenario: User enters an invalid phone number Given I'm an authenticated user When I go to the phone number page And I enter <invalid_number> And I press the verify button Then I should see the error message Examples: | invalid_number | | [email protected] | | 0 | | +441411111111 | | +44712345678 |
  5. Feature: Number verification Users can add verified mobile numbers to

    their profile Scenario: User enters an invalid phone number Given I'm an authenticated user When I go to the phone number page And I enter <invalid_number> And I press the verify button Then I should see the error message Examples: | invalid_number | | [email protected] | | 0 | | +441411111111 | | +44712345678 |
  6. @given("I'm an authenticated user") def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user')

    browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  7. @given("I'm an authenticated user") def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user')

    browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  8. @given("I'm an authenticated user") def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user')

    browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  9. @given("I'm an authenticated user") def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user')

    browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  10. @when('I go to the phone number page') def go_to_number_submission_page(browser): browser.visit(urljoin(browser.url,

    '/number/') @when('I enter <invalid_number>') def enter_invalid_number(browser, invalid_number): browser.fill('number', invalid_number) @when('I press the verify button') def submit_number(browser): browser.find_by_css('button[name=verify]').first.click()
  11. @when('I go to the phone number page') def go_to_number_submission_page(browser): browser.visit(urljoin(browser.url,

    '/number/') @when('I enter <invalid_number>') def enter_invalid_number(browser, invalid_number): browser.fill('number', invalid_number) @when('I press the verify button') def submit_number(browser): browser.find_by_css('button[name=verify]').first.click()
  12. @when('I go to the phone number page') def go_to_number_submission_page(browser): browser.visit(urljoin(browser.url,

    '/number/') @when('I enter <invalid_number>') def enter_invalid_number(browser, invalid_number): browser.fill('number', invalid_number) @when('I press the verify button') def submit_number(browser): browser.find_by_css('button[name=verify]').first.click()
  13. @given("I'm an authenticated user") def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user')

    browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  14. @given('I\'m logged in') @given("I'm an authenticated user") @given('I log in')

    def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user') browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  15. @given('I\'m logged in') @given("I'm an authenticated user") @given('I log in')

    def authenticat_user(browser): browser.visit(urljoin(browser.url, '/login/') browser.fill('username', 'test_user') browser.fill('password', 'test_password') button = browser.find_by_css('button[name=submit]').first.click()
  16. def start_number_verification(request): if request.method == "POST": if request.user.is_authenticated: number =

    request.POST.get("number", None) if re.search("[^0-9+-\\s]+", number): raise Exception existing_validation_requests = ValidationRequest.objects.filter( number=number, active=True ) if existing_validation_requests.exists(): raise Exception # AND SO ON...
  17. def start_number_verification(request): if request.method == "POST": if request.user.is_authenticated: number =

    request.POST.get("number", None) if re.search("[^0-9+-\\s]+", number): raise Exception existing_validation_requests = ValidationRequest.objects.filter( number=number, active=True ) if existing_validation_requests.exists(): raise Exception # AND SO ON...
  18. def start_number_verification(request): if request.method == "POST": if request.user.is_authenticated: number =

    request.POST.get("number", None) if re.search("[^0-9+-\\s]+", number): raise Exception existing_validation_requests = ValidationRequest.objects.filter( number=number, active=True ) if existing_validation_requests.exists(): raise Exception # AND SO ON...
  19. class NumberVerificationView(View): def start_number_verification(request): if request.user.is_authenticated: number = request.POST.get("number", None)

    if re.search("[^0-9+-\\s]+", number): raise Exception existing_validation_requests = ValidationRequest.objects.filter( number=number, active=True ) if existing_validation_requests.exists(): raise Exception # AND SO ON...
  20. class NumberVerificationView(LoginRequiredMixin, View): login_url = '/login/' redirect_field_name = 'redirect_to' def

    start_number_verification(request): number = request.POST.get("number", None) if re.search("[^0-9+-\\s]+", number): raise Exception existing_validation_requests = ValidationRequest.objects.filter( number=number, active=True ) if existing_validation_requests.exists(): raise Exception # AND SO ON...
  21. class NumberVerificationView(LoginRequiredMixin, FormView): ... def form_valid(self, form): number = request.POST.get("number",

    None) if re.search("[^0-9+-\\s]+", number): raise Exception existing_validation_requests = ValidationRequest.objects.filter( number=number, active=True ) if existing_validation_requests.exists(): raise Exception # AND SO ON...