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

Acceptance Testing: The DIrty Details

Acceptance Testing: The DIrty Details

Presented at CodeMash 2.0.1.4

Web based acceptance tests are quite valuable, and you should absolutely be writing them. However, there are many different ways that acceptance tests can be written, and choosing the right ones can mean the difference between success and failure for your project. This talk will get into the dirty details of dealing with AJAX, managing test data, keeping tests isolated, and working with your customer or Business Analyst. The result will be cleaner tests that run faster and are easier to write.

Kevin Berridge

January 10, 2014
Tweet

More Decks by Kevin Berridge

Other Decks in Programming

Transcript

  1. The Dirty Details ✤ What and Why! ✤ Process! ✤

    Tool Choice! ✤ Choosing Tests! ✤ Test Data! ✤ Ajax! ✤ Test Tips and Tricks
  2. Why write Acceptance Tests? ✤ Most “real” kind of test

    you can write! ✤ Test the entire stack JS, HTML, Domain, and Database! ✤ Catch bugs unit tests don’t! ✤ Help focus and drive your dev process! ✤ New level of confidence! ✤ Lessen the load on QA testers! ✤ Feedback earlier
  3. Why NOT write Acceptance Tests? ✤ Time consuming to write!

    ✤ Slow to run! ✤ Brittle! ✤ False Negatives
  4. Who should write the tests? ✤ Your actual customer! ✤

    A business analyst! ✤ A developer! ✤ A tester
  5. When should a test be written? ✤ First! ✤ Before

    “done”! ✤ After “done”! ✤ After released
  6. What language should tests be written in? ✤ Ruby! ✤

    Whatever language you are using! ✤ IF it has a good browser automation library
  7. What tests should be written? How many features should you

    test? How much of the feature should you test?
  8. What tests should be written? How many features should you

    test? How much of the feature should you test? All the “important” ones As little as possible “Prove the existence of the feature, not the correctness.” - Gary Bernhardt
  9. How do we reset the database? ✤ Build the db

    from scratch between each test run! ✤ Wipe the db between each test run! ✤ Run each test in a transactional fixture
  10. How do we wipe the db? ✤ Database Cleaner Ruby

    Gem! ✤ Manually:! ✤ Drop all FKs! ✤ Black list “system data” tables! ✤ Truncate all other tables! ✤ Re-enable all FKs
  11. How do we do transactional fixtures? Tests Browser Web Server

    Database Transaction Managed Controlled Start transactional fixture End transactional fixture
  12. How do we clear session? ✤ After each test, call

    your framework’s
 reset sessions method! ✤ Every test has to login
  13. How do we setup test data? Automate the application +

    Robust against change in code and database - Slow + Very real - Verbose - Some data can’t be configured through the app - Brittle against change in the UI
  14. How do we setup test data? Seed the database +

    Any data can be setup + Fast - Brittle against change in the DB + Tooling: FactoryGirl, any db framework - Brittle against change in domain rules - Not real
  15. How do we setup test data? Incident Report Case Party

    1. Incident Report creates a Case 2. Incident Report creates a Case with a Party - Brittle against change in domain rules 3. Incident Report creates a Case with 2 Parties (1 optional) 4. Incident Report creates a Case with 3 Parties (1 optional)
  16. How do we setup test data? Use the domain +

    Any data can be setup + Fast - Brittle against change in the domain + Robust against change in DB and UI - Requires access to domain objects - Not terribly real
  17. How do we setup test data? Use the Builder pattern

    new TaskBuilder().Build(); new TaskBuilder().WithName(“write talk”).Build();
  18. How do we setup test data? Use the Builder pattern

    + More robust against change in the domain + Just like using the domain - Brittle against some changes in the domain - Requires access to the builder objects
  19. How do we deal with Ajax? What’s the problem? visit

    tasklistpage! click “my first task”! fillin “name”, “take out the trash”! click “Save”! shouldsee “take out the trash” opens a dialog closes dialog, updates list is the dialog ready? has the list been updated?
  20. How do we deal with Ajax? Explicit Waits visit tasklistpage!

    click “my first task”! waitfor “new task dialog”, visible! fillin “name”, “take out the trash”! click “Save”! waitfor “new task dialog”, notvisible! shouldsee “take out the trash”
  21. How do we deal with Ajax? Implicit Waits visit tasklistpage!

    click “my first task”! fillin “name”, “take out the trash”! click “Save”! shouldsee “take out the trash” waits automatically waits automatically
  22. Robust Locators ✤ Locate by label:
 browser.FillIn(“username”).With(“kberridge”);
 browser.FillIn(“password”).With(“not my password”);!

    ✤ Decouple from HTML structure:
 browser.FindCss("div.my-section table tbody tr td input.special-field”);
 browser.FindCss(“.my-section .special-field”);! ✤ Write your HTML to be easy to test
  23. Refactor Away Duplication ✤ Control Extensions
 browser.FillInDropdown(“Type”, “Home”);! ✤ Page

    Objects
 var tweetsPage = loginPage.Login(“kberridge”, “not my password”);
 tweetsPage.SendTweet(“This talk is so great! #codemash”);
 Assert.IsTrue(tweetsPage.HasTweet(“This talk is so great! #codemash”));
  24. Use Your Framework ✤ Trust the implicit waits
 browser.ClickLink("Open Dialog");


    browser.FindCss("#my-dialog").Exists().ShouldBeTrue();
 browser.FindField("#my-dialog .somefield").FillInWith("something");! ✤ Use scopes
 browser.ClickLink(“Open Dialog”);
 var dialog = browser.FindCss(“#my-dialog”);
 dialog.FillIn(“some field”).With(“something”);
  25. Review ✤ Make AT part of YOUR process! ✤ Write

    the right tests! ✤ Test Isolation And Test Data! ✤ Ajax! ✤ Test code “best practices”