Automated Testing with Ruby

17,357 views
17,003 views

Published on

Slides for talk presented at OSDC 2008 in Sydney.

Published in: Technology
2 Comments
16 Likes
Statistics
Notes
No Downloads
Views
Total views
17,357
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
358
Comments
2
Likes
16
Embeds 0
No embeds

No notes for slide

Automated Testing with Ruby

  1. 1. Automated Testing with Ruby Keith Pitty Open Source Developers’ Conference, Sydney 2008 4th December
  2. 2. Once upon a time...
  3. 3. way back in 1983...
  4. 4. a young programmer made his way from the world of Unix at university...
  5. 5. to the world of IBM mainframe programming.
  6. 6. He learnt to use such weird and wonderful technologies as...
  7. 7. PL/I, IMS, CICS, TSO and ISPF/PDF.
  8. 8. Fortunately he had a good mentor who taught him about modular programming...
  9. 9. and how to write unit tests with...
  10. 10. Job Control Language
  11. 11. “JCL is the stuff of nightmares for many programmers and operators.” From editorial review for “MVS JCL in Plain English”
  12. 12. fast forward to 2001
  13. 13. Our programmer was not so young any more...
  14. 14. but he had moved on from mainframe progamming...
  15. 15. to the exciting new world of Java...
  16. 16. and...
  17. 17. as a byproduct of eXtreme Programming...
  18. 18. he had fallen in love with...
  19. 19. JUnit
  20. 20. He loved using JUnit to do test-driven development and refactoring...
  21. 21. and encouraged others to use it whenever he had the opportunity.
  22. 22. fast forward to 2005
  23. 23. By now our hero had begun to explore...
  24. 24. and...
  25. 25. He liked the way tests were “baked in” and how you could run them with rake.
  26. 26. Then, one day in 2007, a fellow Rails programmer enquired...
  27. 27. “Are you using autotest?”
  28. 28. Sheepishly he admitted he hadn’t even heard of it...
  29. 29. We’ll leave our story there for now.
  30. 30. Autotest
  31. 31. “a continuous testing facility meant to be used during development.”
  32. 32. sudo gem install ZenTest cd path/to/railsapp autotest
  33. 33. “As soon as you save a file, autotest will run the corresponding dependent tests.”
  34. 34. Test::Unit
  35. 35. an implementation of xUnit
  36. 36. the default Ruby testing tool
  37. 37. distributed with Ruby since 2001
  38. 38. also the default testing tool for Rails
  39. 39. assert_kind_of BowlingAnalysis, @bowling_analysis assert_equal quot;Brett Leequot;, @bowling_analysis.player.full_name assert_equal quot;9.3quot;, @bowling_analysis.overs.to_s assert_equal 1, @bowling_analysis.maidens assert_equal 2, @bowling_analysis.wickets assert_equal 50, @bowling_analysis.runs
  40. 40. Rails by default provides unit, functional and integration tests
  41. 41. RSpec
  42. 42. RSpec allows you to specify behaviour
  43. 43. Specifying a model
  44. 44. describe Player do before(:each) do @valid_attributes = { :first_name => quot;value for first_namequot;, :last_name => quot;value for last_namequot;, :active => true } end it quot;should create a new instance given valid attributesquot; do Player.create!(@valid_attributes) end end
  45. 45. Specifying a controller
  46. 46. describe PlayersController do # missing code here will be revealed soon it quot;should respond successfully to get 'index' with list of playersquot; do Player.should_receive(:find).and_return(@players) get 'index' response.should be_success assigns[:players].should == @players end end
  47. 47. What makes a good test?
  48. 48. 1. Isolated 2. Automated Kent Beck suggests: 3. Quick to write 4. Quick to run 5. Unique
  49. 49. describe PlayersController do before(:each) do @player_1 = mock(Player, {:first_name => quot;Gregquot;, :last_name => quot;Normanquot;, :active => true}) @player_2 = mock(Player, {:first_name => quot;Adamquot;, :last_name => quot;Scottquot;, :active => true}) @players = [@player_1, @player_2] end it quot;should respond successfully to get 'index' with list of playersquot; do Player.should_receive(:find).and_return(@players) get 'index' response.should be_success assigns[:players].should == @players end end
  50. 50. Mocks
  51. 51. Mocks mimic real objects
  52. 52. Mocks allow tests to be isolated
  53. 53. For more see “Mock Dialogue” by Jim Weirich and Joe O’Brien
  54. 54. Other Mock Frameworks
  55. 55. mocha flexmock rr
  56. 56. Autospec
  57. 57. Autospec rather than autotest since RSpec 1.1.5
  58. 58. More on RSpec
  59. 59. Can also specify views or integrate views with controller specs
  60. 60. Integration Testing
  61. 61. Can use Test::Unit but I prefer...
  62. 62. Cucumber
  63. 63. A replacement for RSpec Story Runner
  64. 64. based on definition of scenarios within features
  65. 65. Feature: Name of feature In order to derive some business value As a user I want to take certain actions Scenario: Name of scenario Given a prerequisite When I take some specific action Then I should notice the expected outcome
  66. 66. cucumber or AUTOFEATURE=true autospec
  67. 67. can be used in conjunction with tools like Webrat and Selenium
  68. 68. Webrat
  69. 69. simulates in-browser testing by leveraging the DOM without performance hit
  70. 70. Feature: Player belongs to group In order for a player to be included As a recorder I want to record when a player joins or leaves Scenario: Record when a new player joins Given a player is not in the system When I request a list of active players And I follow quot;Add Playerquot; And I fill in quot;player_first_namequot; with quot;Gregquot; And I fill in quot;player_last_namequot; with quot;Normanquot; And I press quot;Save Playerquot; Then I should see quot;Active Playersquot; And I should see quot;Greg Normanquot;
  71. 71. makes use of Cucumber step definitions for Webrat, for example...
  72. 72. When /^I follow quot;(.*)quot;$/ do |link| clicks_link(link) end When /^I fill in quot;(.*)quot; with quot;(.*)quot;$/ do |field, value| fills_in(field, :with => value) end When /^I press quot;(.*)quot;$/ do |button| clicks_button(button) end Then /^I should see quot;(.*)quot;$/ do |text| response.body.should =~ /#{text}/m end
  73. 73. Selenium
  74. 74. • runs tests via a browser • handles JavaScript
  75. 75. a little more effort than just installing the Selenium gem
  76. 76. Feature: Check OSDC Site In order to keep track of conference details A participant Should be able to browse the OSDC site Scenario: Check the home page Given I am on the OSDC home page Then I should see the text quot;Welcome to the Open Source Developers' Conferencequot;
  77. 77. require 'spec' require 'selenium' Before do @browser = Selenium::SeleniumDriver.new(quot;localhostquot;, 4444, quot;*chromequot;, quot;http://localhostquot;, 15000) @browser.start end After do @browser.stop end Given /I am on the OSDC home page/ do @browser.open 'http://www.osdc.com.au/' end Then /I should see the text quot;(.*)quot;/ do |text| @browser.is_text_present(text).should == true end
  78. 78. Fixtures
  79. 79. allow data for automated tests to be defined using yaml
  80. 80. can be a pain to maintain
  81. 81. Machinist
  82. 82. Blueprints to generate ActiveRecord objects
  83. 83. Hole.blueprint do number 1 end (1..18).each {|n| Hole.make(:number => n) }
  84. 84. Machinist with Sham
  85. 85. Sham.name { Faker::Name.name } Sham.date do Date.civil((2005..2009).to_a.rand, (1..12).to_a.rand, (1..28).to_a.rand) end Player.blueprint do first_name { Sham.name } last_name { Sham.name } active true end Round.blueprint do date_played { Sham.date } end
  86. 86. use blueprints in cucumber steps
  87. 87. now available as a gem on github
  88. 88. Other Tools
  89. 89. JavaScript Unit Testing
  90. 90. Rails plugins: javascript_test javascript_test_autotest
  91. 91. js_autotest
  92. 92. see Dr Nic’s blog post
  93. 93. Shoulda
  94. 94. Extends Test::Unit with the idea of contexts
  95. 95. Testing Philosophy
  96. 96. How much effort is warranted?
  97. 97. Is it taking too much effort to learn this new testing tool?
  98. 98. My Opinion
  99. 99. Automated testing can be viewed as a trade-off.
  100. 100. E <= ΔQ Effort invested in automated tests should result in at least an equivalent improvement in software quality.
  101. 101. I think it is worth striving to continually improve my command of automated testing tools...
  102. 102. always remembering the business context.
  103. 103. Quotes
  104. 104. “Producing successful, reliable software involves mixing and matching an all-too-variable number of error removal approaches, typically the more of them the better.” Robert L. Glass Facts and Fallacies of Software Engineering
  105. 105. “Whether you are a hard-core ‘test first’ person is not the point. The point is that everyone can benefit from tests that are automated, easy to write, and easy to run.” Hal Fulton The Ruby Way
  106. 106. References
  107. 107. • Hal Fulton. The Ruby Way. Addison-Wesley, 2007 • Obie Fernandez. The Rails Way. Addison-Wesley, 2008 • David Chelimsky et al. The RSpec Book: Behaviour Driven Development with Ruby. The Pragmatic Programmers, 2009 • Robert L. Glass. Facts and Fallacies of Software Engineering. Addison-Wesley, 2003
  108. 108. • http://zentest.rubyforge.org/ZenTest/ • http://rspec.info • http://rubyhoedown2008.confreaks.com/02-joe- obrien-and-jim-weirich-mock-dialogue.html • http://www.infoq.com/news/2008/10/ qualities_good_test • http://github.com/aslakhellesoy/cucumber
  109. 109. • http://github.com/brynary/webrat • http://github.com/aslakhellesoy/cucumber/wikis/ setting-up-selenium • http://github.com/notahat/machinist • http://toolmantim.com/article/2008/10/27/ fixtureless_datas_with_machinist_and_sham
  110. 110. • http://drnicwilliams.com/2008/01/04/autotesting- javascript-in-rails/ • http://www.thoughtbot.com/projects/shoulda • http://pragdave.blogs.pragprog.com/pragdave/ 2008/04/shoulda-used-th.html
  111. 111. Thanks for listening! http://keithpitty.com

×