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.
Integration Testing In Python And why I Love it so Much Mike Leone Panoptic Development February 29, 2012
What are web application integration tests?
High-level TESTS
High-level TESTS That simulate Web Browser Interaction
A.K.A. Acceptance Testing Browser Testing
Web apps? Unit testing? Integration testing?
EXAMPLE Test that a user can log in to  your web app
EXAMPLE
USE CASES?
Customer-tracked user stories
Customer-tracked user stories “ A user should be able to create a profile and update their address”
High-level tests that span multiple components
High-level tests that span multiple components Beyond the scope of unit tests
Large, inherited applications
Large, inherited applications A less overwhelming way to track big feature sets
Non-application updates
Non-application updates Testing client applications after a data migration or infrastructure upgrades
But integration tests can test low-level logic too!
But integration tests can test low-level logic too! So let's write integration tests only, and forgo unit tests!
 
Pick your Battles
Pick your Battles <ul><li>Integration tests are SLOW </li></ul>
Pick your Battles <ul><li>Integration tests are SLOW
There's more state to manage </li></ul>
Pick your Battles <ul><li>Integration tests are SLOW
There's more state to manage
They take longer to update </li></ul>
Pick your Battles <ul><li>Integration tests are SLOW
There's more state to manage
They take longer to update </li></ul>
Very simple app or CMS?
Very simple app or CMS? <ul>An integration-only test suite may make sense </ul>
Existing tools
Existing tools: Bare-metal selenium
import xmlrpclib # Make an object to represent the XML-RPC server. server_url = &quot;http://localhost:8080/selenium-drive...
import xmlrpclib # Make an object to represent the XML-RPC server. server_url = &quot;http://localhost:8080/selenium-drive...
import xmlrpclib # Make an object to represent the XML-RPC server. server_url = &quot;http://localhost:8080/selenium-drive...
Existing tools: Splinter
from splinter.browser import Browser browser = Browser() browser.visit('http://google.com') browser.fill('q', 'splinter - ...
from splinter.browser import Browser browser = Browser() browser.visit('http://google.com') browser.fill('q', 'splinter - ...
from splinter.browser import Browser browser = Browser() browser.visit('http://google.com') browser.fill('q', 'splinter - ...
Navigation still a bit clunky </li></ul>
The  Ruby  community  is obsessed With testing
The  Ruby  community  is obsessed With testing How do they do it?
# Example: Capybara test framework include Rack::Test::Methods def test_it_says_welcome get '/' click 'link text' assert r...
# Example: Capybara test framework include Rack::Test::Methods def test_it_says_welcome get '/' click 'link text' assert r...
# Example: Capybara test framework include Rack::Test::Methods def test_it_says_welcome get '/' click 'link text' assert r...
Enter  easy_integration!
Enter  easy_integration!   The lightweight testing lib I wrote.
easy_integration <ul><li>Runs on top of splinter </li></ul>
easy_integration <ul><li>Runs on top of splinter </li><ul><ul><li>Which runs on top of selenium </li></ul></ul></ul>
easy_integration <ul><li>Runs on top of splinter </li><ul><ul><li>Which runs on top of selenium </li></ul></ul><li>No brow...
easy_integration <ul><li>Runs on top of splinter </li><ul><ul><li>Which runs on top of selenium </li></ul></ul><li>No brow...
Smart defaults: </li><ul><ul><li>Chrome browser
Upcoming SlideShare
Loading in …5
×

Integration Testing in Python

37,540 views

Published on

This presentation addresses web app integration testing (a.k.a. browser testing) in Python. It focuses on currently-available tools, including one that I wrote, and looks at some specific integration testing concerns for the Django web framework.

Published in: Technology

Integration Testing in Python

  1. 1. Integration Testing In Python And why I Love it so Much Mike Leone Panoptic Development February 29, 2012
  2. 2. What are web application integration tests?
  3. 3. High-level TESTS
  4. 4. High-level TESTS That simulate Web Browser Interaction
  5. 5. A.K.A. Acceptance Testing Browser Testing
  6. 6. Web apps? Unit testing? Integration testing?
  7. 7. EXAMPLE Test that a user can log in to your web app
  8. 8. EXAMPLE
  9. 9. USE CASES?
  10. 10. Customer-tracked user stories
  11. 11. Customer-tracked user stories “ A user should be able to create a profile and update their address”
  12. 12. High-level tests that span multiple components
  13. 13. High-level tests that span multiple components Beyond the scope of unit tests
  14. 14. Large, inherited applications
  15. 15. Large, inherited applications A less overwhelming way to track big feature sets
  16. 16. Non-application updates
  17. 17. Non-application updates Testing client applications after a data migration or infrastructure upgrades
  18. 18. But integration tests can test low-level logic too!
  19. 19. But integration tests can test low-level logic too! So let's write integration tests only, and forgo unit tests!
  20. 21. Pick your Battles
  21. 22. Pick your Battles <ul><li>Integration tests are SLOW </li></ul>
  22. 23. Pick your Battles <ul><li>Integration tests are SLOW
  23. 24. There's more state to manage </li></ul>
  24. 25. Pick your Battles <ul><li>Integration tests are SLOW
  25. 26. There's more state to manage
  26. 27. They take longer to update </li></ul>
  27. 28. Pick your Battles <ul><li>Integration tests are SLOW
  28. 29. There's more state to manage
  29. 30. They take longer to update </li></ul>
  30. 31. Very simple app or CMS?
  31. 32. Very simple app or CMS? <ul>An integration-only test suite may make sense </ul>
  32. 33. Existing tools
  33. 34. Existing tools: Bare-metal selenium
  34. 35. import xmlrpclib # Make an object to represent the XML-RPC server. server_url = &quot;http://localhost:8080/selenium-driver/RPC2&quot; app = xmlrpclib.ServerProxy(server_url) # Bump timeout a little higher than the default 5 seconds app.setTimeout(15) import os #os.system('start run_firefox.bat') os.system('&quot;C:Program FilesMozilla Firefoxfirefox.exe&quot;' + 'http://localhost:8080/selenium-driver/SeleneseRunner.html') print app.open('http://localhost:8080/AUT/000000A/http/www.google.com/') print app.verifyTitle('Google') print app.type('q','Selenium ThoughtWorks') print app.verifyValue('q','Selenium ThoughtWorks') print app.clickAndWait('btnG') print app.verifyTextPresent('selenium.thoughtworks.com','') print app.verifyTitle('Google Search: Selenium ThoughtWorks') print app.testComplete()
  35. 36. import xmlrpclib # Make an object to represent the XML-RPC server. server_url = &quot;http://localhost:8080/selenium-driver/RPC2&quot; app = xmlrpclib.ServerProxy(server_url) # Bump timeout a little higher than the default 5 seconds app.setTimeout(15) import os #os.system('start run_firefox.bat') os.system('&quot;C:Program FilesMozilla Firefoxfirefox.exe&quot;' + 'http://localhost:8080/selenium-driver/SeleneseRunner.html') print app.open('http://localhost:8080/AUT/000000A/http/www.google.com/') print app.verifyTitle('Google') print app.type('q','Selenium ThoughtWorks') print app.verifyValue('q','Selenium ThoughtWorks') print app.clickAndWait('btnG') print app.verifyTextPresent('selenium.thoughtworks.com','') print app.verifyTitle('Google Search: Selenium ThoughtWorks') print app.testComplete() Too much boilerplate
  36. 37. import xmlrpclib # Make an object to represent the XML-RPC server. server_url = &quot;http://localhost:8080/selenium-driver/RPC2&quot; app = xmlrpclib.ServerProxy(server_url) # Bump timeout a little higher than the default 5 seconds app.setTimeout(15) import os #os.system('start run_firefox.bat') os.system('&quot;C:Program FilesMozilla Firefoxfirefox.exe&quot;' + 'http://localhost:8080/selenium-driver/SeleneseRunner.html') print app.open('http://localhost:8080/AUT/000000A/http/www.google.com/') print app.verifyTitle('Google') print app.type('q','Selenium ThoughtWorks') print app.verifyValue('q','Selenium ThoughtWorks') print app.clickAndWait('btnG') print app.verifyTextPresent('selenium.thoughtworks.com','') print app.verifyTitle('Google Search: Selenium ThoughtWorks') print app.testComplete() Too much boilerplate Too verbose, API too big
  37. 38. Existing tools: Splinter
  38. 39. from splinter.browser import Browser browser = Browser() browser.visit('http://google.com') browser.fill('q', 'splinter - python acceptance testing for web applications') browser.find_by_css('.lsb').first.click() if browser.is_text_present('splinter.cobrateam.info'): print &quot;Yes, the official website was found!&quot; else: print &quot;No, it wasn't found... We need to improve our SEO techniques&quot; browser.quit()
  39. 40. from splinter.browser import Browser browser = Browser() browser.visit('http://google.com') browser.fill('q', 'splinter - python acceptance testing for web applications') browser.find_by_css('.lsb').first.click() if browser.is_text_present('splinter.cobrateam.info'): print &quot;Yes, the official website was found!&quot; else: print &quot;No, it wasn't found... We need to improve our SEO techniques&quot; browser.quit() Much better!
  40. 41. from splinter.browser import Browser browser = Browser() browser.visit('http://google.com') browser.fill('q', 'splinter - python acceptance testing for web applications') browser.find_by_css('.lsb').first.click() if browser.is_text_present('splinter.cobrateam.info'): print &quot;Yes, the official website was found!&quot; else: print &quot;No, it wasn't found... We need to improve our SEO techniques&quot; browser.quit() Much better! But... <ul><li>Still have to manage browser object
  41. 42. Navigation still a bit clunky </li></ul>
  42. 43. The Ruby community is obsessed With testing
  43. 44. The Ruby community is obsessed With testing How do they do it?
  44. 45. # Example: Capybara test framework include Rack::Test::Methods def test_it_says_welcome get '/' click 'link text' assert response.body.include?(“Welcome!”) end
  45. 46. # Example: Capybara test framework include Rack::Test::Methods def test_it_says_welcome get '/' click 'link text' assert response.body.include?(“Welcome!”) end
  46. 47. # Example: Capybara test framework include Rack::Test::Methods def test_it_says_welcome get '/' click 'link text' assert response.body.include?(“Welcome!”) end That's what I want
  47. 48. Enter easy_integration!
  48. 49. Enter easy_integration! The lightweight testing lib I wrote.
  49. 50. easy_integration <ul><li>Runs on top of splinter </li></ul>
  50. 51. easy_integration <ul><li>Runs on top of splinter </li><ul><ul><li>Which runs on top of selenium </li></ul></ul></ul>
  51. 52. easy_integration <ul><li>Runs on top of splinter </li><ul><ul><li>Which runs on top of selenium </li></ul></ul><li>No browser object management </li></ul>
  52. 53. easy_integration <ul><li>Runs on top of splinter </li><ul><ul><li>Which runs on top of selenium </li></ul></ul><li>No browser object management
  53. 54. Smart defaults: </li><ul><ul><li>Chrome browser
  54. 55. Test server running, port 8001 </li></ul></ul></ul>
  55. 56. easy_integration Tiny, simple API: <ul><ul><ul><li>visit()
  56. 57. click()
  57. 58. fill_in()
  58. 59. select()
  59. 60. displays() </li></ul></ul></ul>
  60. 61. easy_integration Tiny, simple API: <ul><ul><ul><li>visit()
  61. 62. click()
  62. 63. fill_in()
  63. 64. select()
  64. 65. displays() </li></ul></ul></ul>That's it
  65. 66. DEMO TIME (Django example)
  66. 67. Other tools: <ul><ul><ul><li>Nose
  67. 68. Lettuce </li></ul></ul></ul>
  68. 69. Still challenging for complex django apps <ul><li>Manage test server
  69. 70. Manage time-consuming database transactions </li></ul>
  70. 71. Coming in Django 1.4 <ul><li>LiveServerTestCase </li></ul>
  71. 72. Questions? <ul><li>https://github.com/mleone
  72. 73. https://github.com/mleone/easy-integration
  73. 74. http://www.panopticdev.com/ </li></ul>

×