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.
Automated Testing
    with Ruby
                  Keith Pitty

Open Source Developers’ Conference, Sydney 2008
           ...
Once upon a time...
way back in 1983...
a young programmer made his way
          from the world
      of Unix at university...
to the world of
IBM mainframe programming.
He learnt to use such
weird and wonderful
 technologies as...
PL/I, IMS, CICS, TSO and ISPF/PDF.
Fortunately he had a good mentor
      who taught him about
     modular programming...
and how to write unit tests with...
Job Control Language
“JCL is the stuff of nightmares for
many programmers and operators.”


            From editorial review for “MVS JCL in Pl...
fast forward to 2001
Our programmer was
not so young any more...
but he had moved on
from mainframe progamming...
to the exciting new world of Java...
and...
as a byproduct of
eXtreme Programming...
he had fallen in love with...
JUnit
He loved using JUnit to do
 test-driven development
     and refactoring...
and encouraged others to use it
whenever he had the opportunity.
fast forward to 2005
By now our hero had
 begun to explore...
and...
He liked the way
tests were “baked in”
 and how you could
 run them with rake.
Then, one day in 2007,
a fellow Rails programmer
         enquired...
“Are you using autotest?”
Sheepishly he admitted
he hadn’t even heard of it...
We’ll leave our story there for now.
Autotest
“a continuous testing facility
meant to be used during development.”
sudo gem install ZenTest

cd path/to/railsapp

autotest
“As soon as you save a file,
      autotest will run the
corresponding dependent tests.”
Test::Unit
an implementation of xUnit
the default Ruby testing tool
distributed with Ruby since 2001
also the default testing tool for Rails
assert_kind_of BowlingAnalysis, @bowling_analysis
assert_equal quot;Brett Leequot;, @bowling_analysis.player.full_name
ass...
Rails by default provides
unit, functional and integration tests
RSpec
RSpec allows you to specify behaviour
Specifying a model
describe Player do
  before(:each) do
    @valid_attributes = {
      :first_name => quot;value for first_namequot;,
     ...
Specifying a controller
describe PlayersController do

  # missing code here will be revealed soon

  it quot;should respond successfully to get '...
What makes a
 good test?
1. Isolated

                      2. Automated

Kent Beck suggests:   3. Quick to write

                      4. Quick t...
describe PlayersController do

  before(:each) do
    @player_1 = mock(Player, {:first_name => quot;Gregquot;,
           ...
Mocks
Mocks mimic real objects
Mocks allow tests to be isolated
For more see “Mock Dialogue”
by Jim Weirich and Joe O’Brien
Other Mock
Frameworks
mocha

flexmock

  rr
Autospec
Autospec rather than autotest
     since RSpec 1.1.5
More on RSpec
Can also specify views
                  or
integrate views with controller specs
Integration
  Testing
Can use Test::Unit
  but I prefer...
Cucumber
A replacement for RSpec Story Runner
based on definition of
scenarios within features
Feature: Name of feature
  In order to derive some business value
  As a user
  I want to take certain actions

  Scenario...
cucumber
           or

AUTOFEATURE=true autospec
can be used in conjunction with tools like
          Webrat and Selenium
Webrat
simulates in-browser testing
   by leveraging the DOM
  without performance hit
Feature: Player belongs to group
  In order for a player to be included
  As a recorder
  I want to record when a player j...
makes use of
Cucumber step definitions
for Webrat, for example...
When /^I follow quot;(.*)quot;$/ do |link|
  clicks_link(link)
end

When /^I fill in quot;(.*)quot; with quot;(.*)quot;$/ ...
Selenium
• runs tests via a browser
• handles JavaScript
a little more effort than
just installing the Selenium gem
Feature: Check OSDC Site
  In order to keep track of conference details
  A participant
  Should be able to browse the OSD...
require 'spec'
require 'selenium'

Before do
  @browser = Selenium::SeleniumDriver.new(quot;localhostquot;,
4444, quot;*ch...
Fixtures
allow data for automated tests
    to be defined using yaml
can be a pain to maintain
Machinist
Blueprints to generate
ActiveRecord objects
Hole.blueprint do
  number 1
end

(1..18).each {|n| Hole.make(:number => n) }
Machinist with Sham
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)
en...
use blueprints in cucumber steps
now available as a gem on github
Other Tools
JavaScript
Unit Testing
Rails plugins:

     javascript_test
javascript_test_autotest
js_autotest
see Dr Nic’s blog post
Shoulda
Extends Test::Unit
with the idea of contexts
Testing
Philosophy
How much effort
 is warranted?
Is it taking
too much effort
  to learn this
new testing tool?
My Opinion
Automated testing
can be viewed as a trade-off.
E <= ΔQ

Effort invested in automated tests
      should result in at least
    an equivalent improvement
         in soft...
I think it is worth striving
to continually improve my command
    of automated testing tools...
always remembering
the business context.
Quotes
“Producing successful, reliable software
    involves mixing and matching
      an all-too-variable number
     of error r...
“Whether you are a hard-core
‘test first’ person is not the point.
   The point is that everyone
 can benefit from tests tha...
References
• Hal Fulton. The Ruby Way. Addison-Wesley, 2007
• Obie Fernandez. The Rails Way. Addison-Wesley,
  2008

• David Chelimsk...
• http://zentest.rubyforge.org/ZenTest/
• http://rspec.info
• http://rubyhoedown2008.confreaks.com/02-joe-
  obrien-and-ji...
• http://github.com/brynary/webrat
• http://github.com/aslakhellesoy/cucumber/wikis/
  setting-up-selenium

• http://githu...
• http://drnicwilliams.com/2008/01/04/autotesting-
  javascript-in-rails/

• http://www.thoughtbot.com/projects/shoulda
• ...
Thanks for listening!

    http://keithpitty.com
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Automated Testing with Ruby
Upcoming SlideShare
Loading in …5
×

Automated Testing with Ruby

23,122 views

Published on

Slides for talk presented at OSDC 2008 in Sydney.

Published in: Technology

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

×