Test Coverage
Building better software
Rails Developers Test
Rails Developers Test

 Rails has testing support baked in
Rails Developers Test

 Rails has testing support baked in
   In fact, it supports many different kinds of testing
Rails Developers Test

 Rails has testing support baked in
   In fact, it supports many different kinds of testing
 The Ra...
Rails Developers Test

 Rails has testing support baked in
   In fact, it supports many different kinds of testing
 The Ra...
Rails Developers Test

 Rails has testing support baked in
   In fact, it supports many different kinds of testing
 The Ra...
Testing Advantages
Testing Advantages
Tests can serve as your memory
Testing Advantages
Tests can serve as your memory
  They will remember 30,000 lines of code
Testing Advantages
Tests can serve as your memory
  They will remember 30,000 lines of code
  They will remember for 6 mon...
Testing Advantages
Tests can serve as your memory
  They will remember 30,000 lines of code
  They will remember for 6 mon...
Testing Advantages
Tests can serve as your memory
  They will remember 30,000 lines of code
  They will remember for 6 mon...
Testing Advantages
Tests can serve as your memory
  They will remember 30,000 lines of code
  They will remember for 6 mon...
Testing Advantages
Tests can serve as your memory
  They will remember 30,000 lines of code
  They will remember for 6 mon...
Testing Doubts
Testing Doubts

Testing slows you down (writing more code)
Testing Doubts

Testing slows you down (writing more code)
  Myth: remember to add troubleshooting and
  debugging time wh...
Testing Doubts

Testing slows you down (writing more code)
  Myth: remember to add troubleshooting and
  debugging time wh...
Testing Doubts

Testing slows you down (writing more code)
  Myth: remember to add troubleshooting and
  debugging time wh...
Unit Tests
Tests for your models
The Goal
The Goal
Ideally you want 100% coverage
The Goal
Ideally you want 100% coverage
  That means changing a line of code should break at
  least one test
The Goal
Ideally you want 100% coverage
  That means changing a line of code should break at
  least one test
That’s rarel...
The Goal
Ideally you want 100% coverage
  That means changing a line of code should break at
  least one test
That’s rarel...
The Goal
Ideally you want 100% coverage
  That means changing a line of code should break at
  least one test
That’s rarel...
The Goal
Ideally you want 100% coverage
  That means changing a line of code should break at
  least one test
That’s rarel...
Avoid Fixtures
Avoid Fixtures

 Rails has a feature called “fixtures” for loading data into
 the database for testing
Avoid Fixtures

 Rails has a feature called “fixtures” for loading data into
 the database for testing
   Rails clears the ...
Avoid Fixtures

 Rails has a feature called “fixtures” for loading data into
 the database for testing
   Rails clears the ...
Avoid Fixtures

 Rails has a feature called “fixtures” for loading data into
 the database for testing
   Rails clears the ...
What not to Test
What not to Test

 You need to test your code, not Rails itself
What not to Test

 You need to test your code, not Rails itself
 In other words, don’t test:
What not to Test

 You need to test your code, not Rails itself
 In other words, don’t test:
   new(), create(), save(), …
What not to Test

 You need to test your code, not Rails itself
 In other words, don’t test:
   new(), create(), save(), …...
What not to Test

 You need to test your code, not Rails itself
 In other words, don’t test:
   new(), create(), save(), …...
A Simple Model
We are going to add tests for this model
$ ruby script/generate model user email:string first_name:string
                              last_name:string




A Simpl...
$ ruby script/generate model user email:string first_name:string
                              last_name:string




       ...
We Already Have Tests!
We Already Have Tests!
                           require 'test_helper'
Rails creates a test file   class UserTest < Active...
We Already Have Tests!
                           require 'test_helper'
Rails creates a test file   class UserTest < Active...
We Already Have Tests!
                           require 'test_helper'
Rails creates a test file   class UserTest < Active...
Test the Validation
We are not testing that Rails validations work, we
are testing that User requires an email address
require 'test_helper'

 class UserTest < ActiveSupport::TestCase
  test "email is required" do
    user = User.new # no em...
require 'test_helper'

 class UserTest < ActiveSupport::TestCase
  test "email is required" do
    user = User.new # no em...
require 'test_helper'

 class UserTest < ActiveSupport::TestCase
  test "email is required" do
    user = User.new # no em...
require 'test_helper'

 class UserTest < ActiveSupport::TestCase
  test "email is required" do
    user = User.new # no em...
require 'test_helper'

 class UserTest < ActiveSupport::TestCase
  test "email is required" do
    user = User.new # no em...
One Aspect of full_name()
It’s important to test just one thing at a time
require 'test_helper'

    class UserTest < ActiveSupport::TestCase
     # ...

     test "full name is nil if first and la...
require 'test_helper'

    class UserTest < ActiveSupport::TestCase
     # ...

     test "full name is nil if first and la...
full_name() Edge Cases
Always try to test every edge case
you can think up
require 'test_helper'

    class UserTest < ActiveSupport::TestCase
     # ...

     test "full name will use just the firs...
require 'test_helper'

    class UserTest < ActiveSupport::TestCase
     # ...

     test "full name will use just the firs...
full_name() Normal Usage
Also test the normal intended usage
require 'test_helper'

class UserTest < ActiveSupport::TestCase
 # ...

 test "full name will combine first and last name i...
Passing Tests
I ran these tests in my code editor
(⌘R in TextMate)
Passing Tests
I ran these tests in my code editor
(⌘R in TextMate)
Functional Tests
Tests for your controllers
What not to Test
What not to Test
 It’s OK to decide not to test some things (controversial)
What not to Test
 It’s OK to decide not to test some things (controversial)
 I don’t test views (controversial)
What not to Test
 It’s OK to decide not to test some things (controversial)
 I don’t test views (controversial)
   They ch...
What not to Test
 It’s OK to decide not to test some things (controversial)
 I don’t test views (controversial)
   They ch...
What not to Test
 It’s OK to decide not to test some things (controversial)
 I don’t test views (controversial)
   They ch...
What not to Test
 It’s OK to decide not to test some things (controversial)
 I don’t test views (controversial)
   They ch...
A Simple Controller
We will add tests for the create action of
this controller
class UsersController < ApplicationController
           def new
             @user = User.new
           end

           ...
Test Failure and Success
I have added a couple of tests that validate the
success and failure scenarios of create
require 'test_helper'

   class UsersControllerTest < ActionController::TestCase
    test "entering a bad user shows the f...
require 'test_helper'

   class UsersControllerTest < ActionController::TestCase
    test "entering a bad user shows the f...
require 'test_helper'

   class UsersControllerTest < ActionController::TestCase
    test "entering a bad user shows the f...
require 'test_helper'

   class UsersControllerTest < ActionController::TestCase
    test "entering a bad user shows the f...
require 'test_helper'

   class UsersControllerTest < ActionController::TestCase
    test "entering a bad user shows the f...
More Passing Tests
We have now started some coverage for our
controllers as well
More Passing Tests
We have now started some coverage for our
controllers as well
Even More Tests
Rails doesn’t stop there
Other Tests Supported
Other Tests Supported
Integration tests are used to write system wide tests
that cross controllers/actions (like a login s...
Other Tests Supported
Integration tests are used to write system wide tests
that cross controllers/actions (like a login s...
Other Tests Supported
Integration tests are used to write system wide tests
that cross controllers/actions (like a login s...
Other Tests Supported
Integration tests are used to write system wide tests
that cross controllers/actions (like a login s...
Other Tests Supported
Integration tests are used to write system wide tests
that cross controllers/actions (like a login s...
Test Driven Development
Development practices focused on testing
The System
The System
Add a test
The System
Add a test
Run all tests and see if there is a failure
The System
Add a test
Run all tests and see if there is a failure
Write code to make the failing test pass
The System
Add a test
Run all tests and see if there is a failure
Write code to make the failing test pass
Run all tests t...
The System
Add a test
Run all tests and see if there is a failure
Write code to make the failing test pass
Run all tests t...
The System
Add a test
Run all tests and see if there is a failure
Write code to make the failing test pass
Run all tests t...
Red / Green / Refactor
TDD Advantages
TDD Advantages
The process creates a very tight feedback loop
TDD Advantages
The process creates a very tight feedback loop
  This helps find problems much faster
TDD Advantages
The process creates a very tight feedback loop
  This helps find problems much faster
  Dramatically reduces...
TDD Advantages
The process creates a very tight feedback loop
  This helps find problems much faster
  Dramatically reduces...
TDD Advantages
The process creates a very tight feedback loop
  This helps find problems much faster
  Dramatically reduces...
TDD Advantages
The process creates a very tight feedback loop
  This helps find problems much faster
  Dramatically reduces...
Let’s Test Drive a Feature
Let’s Test Drive a Feature


 We currently check that an email is provided
Let’s Test Drive a Feature


 We currently check that an email is provided
 Let’s add a simple reality check to make sure ...
Let’s Test Drive a Feature


 We currently check that an email is provided
 Let’s add a simple reality check to make sure ...
1. Add a Test
I have added the test I expect to fail and my goal
will now be to get it to work
require 'test_helper'

class UserTest < ActiveSupport::TestCase
 # ...

 test "email should be well formed" do
  user = Us...
2. Run all Tests (“Red”)
This shows that our new feature isn’t working
yet, as we expected
2. Run all Tests (“Red”)
This shows that our new feature isn’t working
yet, as we expected
3. Write Code
I am now adding the code to
make the feature work
class User < ActiveRecord::Base
   validates_presence_of :email
   validates_format_of :email,
                 :with => /...
class User < ActiveRecord::Base
   validates_presence_of :email
   validates_format_of :email,
                 :with => /...
4. Run all Tests (“Green”)
This shows that I have succeeded,
since my test now passes
4. Run all Tests (“Green”)
This shows that I have succeeded,
since my test now passes
5. Refactor
5. Refactor

Not needed in this case
5. Refactor

Not needed in this case
This step allows you to clean up messes you create to
make a test pass
5. Refactor

Not needed in this case
This step allows you to clean up messes you create to
make a test pass
You can refact...
Questions?
Test Your Application Lab
Your book has instructions for how to start
increasing the test coverage for your application
Test Coverage in Rails
Upcoming SlideShare
Loading in...5
×

Test Coverage in Rails

3,125

Published on

This was the eleventh speech of a three day Rails training I gave in Tulsa, OK in the spring 2010.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,125
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
58
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide








































































































  • Test Coverage in Rails

    1. 1. Test Coverage Building better software
    2. 2. Rails Developers Test
    3. 3. Rails Developers Test Rails has testing support baked in
    4. 4. Rails Developers Test Rails has testing support baked in In fact, it supports many different kinds of testing
    5. 5. Rails Developers Test Rails has testing support baked in In fact, it supports many different kinds of testing The Rails culture and community are very pro-testing
    6. 6. Rails Developers Test Rails has testing support baked in In fact, it supports many different kinds of testing The Rails culture and community are very pro-testing Many practice Test Driven Development (TDD)
    7. 7. Rails Developers Test Rails has testing support baked in In fact, it supports many different kinds of testing The Rails culture and community are very pro-testing Many practice Test Driven Development (TDD) You should too!
    8. 8. Testing Advantages
    9. 9. Testing Advantages Tests can serve as your memory
    10. 10. Testing Advantages Tests can serve as your memory They will remember 30,000 lines of code
    11. 11. Testing Advantages Tests can serve as your memory They will remember 30,000 lines of code They will remember for 6 months
    12. 12. Testing Advantages Tests can serve as your memory They will remember 30,000 lines of code They will remember for 6 months They will remember for other developers
    13. 13. Testing Advantages Tests can serve as your memory They will remember 30,000 lines of code They will remember for 6 months They will remember for other developers Upgrades and changes are easier
    14. 14. Testing Advantages Tests can serve as your memory They will remember 30,000 lines of code They will remember for 6 months They will remember for other developers Upgrades and changes are easier It can help prevent regressions (especially for bugs)
    15. 15. Testing Advantages Tests can serve as your memory They will remember 30,000 lines of code They will remember for 6 months They will remember for other developers Upgrades and changes are easier It can help prevent regressions (especially for bugs) It increases confidence that your code works
    16. 16. Testing Doubts
    17. 17. Testing Doubts Testing slows you down (writing more code)
    18. 18. Testing Doubts Testing slows you down (writing more code) Myth: remember to add troubleshooting and debugging time when not testing
    19. 19. Testing Doubts Testing slows you down (writing more code) Myth: remember to add troubleshooting and debugging time when not testing Testing doesn’t produce perfect code
    20. 20. Testing Doubts Testing slows you down (writing more code) Myth: remember to add troubleshooting and debugging time when not testing Testing doesn’t produce perfect code Truth: but it is a tool for producing better code
    21. 21. Unit Tests Tests for your models
    22. 22. The Goal
    23. 23. The Goal Ideally you want 100% coverage
    24. 24. The Goal Ideally you want 100% coverage That means changing a line of code should break at least one test
    25. 25. The Goal Ideally you want 100% coverage That means changing a line of code should break at least one test That’s rarely achieved
    26. 26. The Goal Ideally you want 100% coverage That means changing a line of code should break at least one test That’s rarely achieved Be practical
    27. 27. The Goal Ideally you want 100% coverage That means changing a line of code should break at least one test That’s rarely achieved Be practical Tests are about managing risks
    28. 28. The Goal Ideally you want 100% coverage That means changing a line of code should break at least one test That’s rarely achieved Be practical Tests are about managing risks Is the risk worth it? (think screen scraping code)
    29. 29. Avoid Fixtures
    30. 30. Avoid Fixtures Rails has a feature called “fixtures” for loading data into the database for testing
    31. 31. Avoid Fixtures Rails has a feature called “fixtures” for loading data into the database for testing Rails clears the test database before each test
    32. 32. Avoid Fixtures Rails has a feature called “fixtures” for loading data into the database for testing Rails clears the test database before each test This features creates at least as many problems as it solves and is best avoided
    33. 33. Avoid Fixtures Rails has a feature called “fixtures” for loading data into the database for testing Rails clears the test database before each test This features creates at least as many problems as it solves and is best avoided I’ll show how to avoid them manually, but there’s a plugin, called Factory Girl, that is even better
    34. 34. What not to Test
    35. 35. What not to Test You need to test your code, not Rails itself
    36. 36. What not to Test You need to test your code, not Rails itself In other words, don’t test:
    37. 37. What not to Test You need to test your code, not Rails itself In other words, don’t test: new(), create(), save(), …
    38. 38. What not to Test You need to test your code, not Rails itself In other words, don’t test: new(), create(), save(), … find(), first(), all(), …
    39. 39. What not to Test You need to test your code, not Rails itself In other words, don’t test: new(), create(), save(), … find(), first(), all(), … …
    40. 40. A Simple Model We are going to add tests for this model
    41. 41. $ ruby script/generate model user email:string first_name:string last_name:string A Simple Model We are going to add tests for this model
    42. 42. $ ruby script/generate model user email:string first_name:string last_name:string class User < ActiveRecord::Base validates_presence_of :email def full_name return nil if first_name.nil? and last_name.nil? "#{first_name} #{last_name}".strip end end A Simple Model We are going to add tests for this model
    43. 43. We Already Have Tests!
    44. 44. We Already Have Tests! require 'test_helper' Rails creates a test file class UserTest < ActiveSupport::TestCase # Replace this with your real tests. for each model or test "the truth" do assert true controller it builds end end
    45. 45. We Already Have Tests! require 'test_helper' Rails creates a test file class UserTest < ActiveSupport::TestCase # Replace this with your real tests. for each model or test "the truth" do assert true controller it builds end end Run tests with: rake Loaded suite /Users/james/Desktop/ road_tested/test/unit/ user_test Started . Finished in 0.076431 seconds. 1 tests, 1 assertions, 0 failures, 0 errors
    46. 46. We Already Have Tests! require 'test_helper' Rails creates a test file class UserTest < ActiveSupport::TestCase # Replace this with your real tests. for each model or test "the truth" do assert true controller it builds end end Run tests with: rake Loaded suite /Users/james/Desktop/ These don’t really test road_tested/test/unit/ user_test anything, but at least Started . Finished in 0.076431 seconds. they are all wired up 1 tests, 1 assertions, 0 failures, 0 errors
    47. 47. Test the Validation We are not testing that Rails validations work, we are testing that User requires an email address
    48. 48. require 'test_helper' class UserTest < ActiveSupport::TestCase test "email is required" do user = User.new # no email assert(!user.valid?, "User was valid without an email") assert(user.errors.invalid?(:email), "Email was missing but valid") end end Test the Validation We are not testing that Rails validations work, we are testing that User requires an email address
    49. 49. require 'test_helper' class UserTest < ActiveSupport::TestCase test "email is required" do user = User.new # no email assert(!user.valid?, "User was valid without an email") assert(user.errors.invalid?(:email), "Email was missing but valid") end end Test the Validation We are not testing that Rails validations work, we are testing that User requires an email address
    50. 50. require 'test_helper' class UserTest < ActiveSupport::TestCase test "email is required" do user = User.new # no email assert(!user.valid?, "User was valid without an email") assert(user.errors.invalid?(:email), "Email was missing but valid") end end Test the Validation We are not testing that Rails validations work, we are testing that User requires an email address
    51. 51. require 'test_helper' class UserTest < ActiveSupport::TestCase test "email is required" do user = User.new # no email assert(!user.valid?, "User was valid without an email") assert(user.errors.invalid?(:email), "Email was missing but valid") end end Test the Validation We are not testing that Rails validations work, we are testing that User requires an email address
    52. 52. require 'test_helper' class UserTest < ActiveSupport::TestCase test "email is required" do user = User.new # no email assert(!user.valid?, "User was valid without an email") assert(user.errors.invalid?(:email), "Email was missing but valid") end end Test the Validation We are not testing that Rails validations work, we are testing that User requires an email address
    53. 53. One Aspect of full_name() It’s important to test just one thing at a time
    54. 54. require 'test_helper' class UserTest < ActiveSupport::TestCase # ... test "full name is nil if first and last name are nil" do user = User.new # no first_name or last_name assert_nil(user.full_name) end end One Aspect of full_name() It’s important to test just one thing at a time
    55. 55. require 'test_helper' class UserTest < ActiveSupport::TestCase # ... test "full name is nil if first and last name are nil" do user = User.new # no first_name or last_name assert_nil(user.full_name) end end One Aspect of full_name() It’s important to test just one thing at a time
    56. 56. full_name() Edge Cases Always try to test every edge case you can think up
    57. 57. require 'test_helper' class UserTest < ActiveSupport::TestCase # ... test "full name will use just the first name if needed" do user = User.new(:first_name => "James") # no last_name assert_equal(user.first_name, user.full_name) end test "full name will use just the last name if needed" do user = User.new(:last_name => "Gray") # no first_name assert_equal(user.last_name, user.full_name) end end full_name() Edge Cases Always try to test every edge case you can think up
    58. 58. require 'test_helper' class UserTest < ActiveSupport::TestCase # ... test "full name will use just the first name if needed" do user = User.new(:first_name => "James") # no last_name assert_equal(user.first_name, user.full_name) end test "full name will use just the last name if needed" do user = User.new(:last_name => "Gray") # no first_name assert_equal(user.last_name, user.full_name) end end full_name() Edge Cases Always try to test every edge case you can think up
    59. 59. full_name() Normal Usage Also test the normal intended usage
    60. 60. require 'test_helper' class UserTest < ActiveSupport::TestCase # ... test "full name will combine first and last name if possible" do user = User.new(:first_name => "James", :last_name => "Gray") assert_equal("#{user.first_name} #{user.last_name}", user.full_name) end end full_name() Normal Usage Also test the normal intended usage
    61. 61. Passing Tests I ran these tests in my code editor (⌘R in TextMate)
    62. 62. Passing Tests I ran these tests in my code editor (⌘R in TextMate)
    63. 63. Functional Tests Tests for your controllers
    64. 64. What not to Test
    65. 65. What not to Test It’s OK to decide not to test some things (controversial)
    66. 66. What not to Test It’s OK to decide not to test some things (controversial) I don’t test views (controversial)
    67. 67. What not to Test It’s OK to decide not to test some things (controversial) I don’t test views (controversial) They change too frequently
    68. 68. What not to Test It’s OK to decide not to test some things (controversial) I don’t test views (controversial) They change too frequently They may be changed by designers
    69. 69. What not to Test It’s OK to decide not to test some things (controversial) I don’t test views (controversial) They change too frequently They may be changed by designers They shouldn’t contain complex logic anyway
    70. 70. What not to Test It’s OK to decide not to test some things (controversial) I don’t test views (controversial) They change too frequently They may be changed by designers They shouldn’t contain complex logic anyway You should still verify that your controllers work
    71. 71. A Simple Controller We will add tests for the create action of this controller
    72. 72. class UsersController < ApplicationController def new @user = User.new end def create @user = User.new(params[:user]) if @user.save flash[:notice] = "User created." redirect_to user_path(@user) else flash[:error] = "User could not be created." render :action => :new end end def show @user = User.find(1) end end A Simple Controller We will add tests for the create action of this controller
    73. 73. Test Failure and Success I have added a couple of tests that validate the success and failure scenarios of create
    74. 74. require 'test_helper' class UsersControllerTest < ActionController::TestCase test "entering a bad user shows the form with errors" do post :create # missing email assert_template(:new) # showed the new form assert_not_nil(flash[:error]) # with errors end test "you are taken to the show page when a user is created" do post :create, :user => {:email => "james@graysoftinc.com"} user = User.find_by_email("james@graysoftinc.com") assert_not_nil(user) # a User was created assert_redirected_to(user_path(user)) # sent to show page end end Test Failure and Success I have added a couple of tests that validate the success and failure scenarios of create
    75. 75. require 'test_helper' class UsersControllerTest < ActionController::TestCase test "entering a bad user shows the form with errors" do post :create # missing email assert_template(:new) # showed the new form assert_not_nil(flash[:error]) # with errors end test "you are taken to the show page when a user is created" do post :create, :user => {:email => "james@graysoftinc.com"} user = User.find_by_email("james@graysoftinc.com") assert_not_nil(user) # a User was created assert_redirected_to(user_path(user)) # sent to show page end end Test Failure and Success I have added a couple of tests that validate the success and failure scenarios of create
    76. 76. require 'test_helper' class UsersControllerTest < ActionController::TestCase test "entering a bad user shows the form with errors" do post :create # missing email assert_template(:new) # showed the new form assert_not_nil(flash[:error]) # with errors end test "you are taken to the show page when a user is created" do post :create, :user => {:email => "james@graysoftinc.com"} user = User.find_by_email("james@graysoftinc.com") assert_not_nil(user) # a User was created assert_redirected_to(user_path(user)) # sent to show page end end Test Failure and Success I have added a couple of tests that validate the success and failure scenarios of create
    77. 77. require 'test_helper' class UsersControllerTest < ActionController::TestCase test "entering a bad user shows the form with errors" do post :create # missing email assert_template(:new) # showed the new form assert_not_nil(flash[:error]) # with errors end test "you are taken to the show page when a user is created" do post :create, :user => {:email => "james@graysoftinc.com"} user = User.find_by_email("james@graysoftinc.com") assert_not_nil(user) # a User was created assert_redirected_to(user_path(user)) # sent to show page end end Test Failure and Success I have added a couple of tests that validate the success and failure scenarios of create
    78. 78. require 'test_helper' class UsersControllerTest < ActionController::TestCase test "entering a bad user shows the form with errors" do post :create # missing email assert_template(:new) # showed the new form assert_not_nil(flash[:error]) # with errors end test "you are taken to the show page when a user is created" do post :create, :user => {:email => "james@graysoftinc.com"} user = User.find_by_email("james@graysoftinc.com") assert_not_nil(user) # a User was created assert_redirected_to(user_path(user)) # sent to show page end end Test Failure and Success I have added a couple of tests that validate the success and failure scenarios of create
    79. 79. More Passing Tests We have now started some coverage for our controllers as well
    80. 80. More Passing Tests We have now started some coverage for our controllers as well
    81. 81. Even More Tests Rails doesn’t stop there
    82. 82. Other Tests Supported
    83. 83. Other Tests Supported Integration tests are used to write system wide tests that cross controllers/actions (like a login system)
    84. 84. Other Tests Supported Integration tests are used to write system wide tests that cross controllers/actions (like a login system) You can also test helpers
    85. 85. Other Tests Supported Integration tests are used to write system wide tests that cross controllers/actions (like a login system) You can also test helpers I usually don’t bother with simple view logic, but complex systems should be tested
    86. 86. Other Tests Supported Integration tests are used to write system wide tests that cross controllers/actions (like a login system) You can also test helpers I usually don’t bother with simple view logic, but complex systems should be tested Rails supports basic performance profiling
    87. 87. Other Tests Supported Integration tests are used to write system wide tests that cross controllers/actions (like a login system) You can also test helpers I usually don’t bother with simple view logic, but complex systems should be tested Rails supports basic performance profiling This can be handy when you are tuning
    88. 88. Test Driven Development Development practices focused on testing
    89. 89. The System
    90. 90. The System Add a test
    91. 91. The System Add a test Run all tests and see if there is a failure
    92. 92. The System Add a test Run all tests and see if there is a failure Write code to make the failing test pass
    93. 93. The System Add a test Run all tests and see if there is a failure Write code to make the failing test pass Run all tests to see them succeed
    94. 94. The System Add a test Run all tests and see if there is a failure Write code to make the failing test pass Run all tests to see them succeed Refactor code as needed
    95. 95. The System Add a test Run all tests and see if there is a failure Write code to make the failing test pass Run all tests to see them succeed Refactor code as needed Repeat
    96. 96. Red / Green / Refactor
    97. 97. TDD Advantages
    98. 98. TDD Advantages The process creates a very tight feedback loop
    99. 99. TDD Advantages The process creates a very tight feedback loop This helps find problems much faster
    100. 100. TDD Advantages The process creates a very tight feedback loop This helps find problems much faster Dramatically reduces debugging time
    101. 101. TDD Advantages The process creates a very tight feedback loop This helps find problems much faster Dramatically reduces debugging time It makes you more aware of YAGNI
    102. 102. TDD Advantages The process creates a very tight feedback loop This helps find problems much faster Dramatically reduces debugging time It makes you more aware of YAGNI Drives the design of the code
    103. 103. TDD Advantages The process creates a very tight feedback loop This helps find problems much faster Dramatically reduces debugging time It makes you more aware of YAGNI Drives the design of the code Encourages smaller and more modular code
    104. 104. Let’s Test Drive a Feature
    105. 105. Let’s Test Drive a Feature We currently check that an email is provided
    106. 106. Let’s Test Drive a Feature We currently check that an email is provided Let’s add a simple reality check to make sure it looks like an email address
    107. 107. Let’s Test Drive a Feature We currently check that an email is provided Let’s add a simple reality check to make sure it looks like an email address This isn’t perfect, but it could catch some mistakes
    108. 108. 1. Add a Test I have added the test I expect to fail and my goal will now be to get it to work
    109. 109. require 'test_helper' class UserTest < ActiveSupport::TestCase # ... test "email should be well formed" do user = User.new(:email => "not well formed!") assert(!user.valid?, "User was valid with a bad email") assert(user.errors.invalid?(:email), "Email was invalid but allowed") end end 1. Add a Test I have added the test I expect to fail and my goal will now be to get it to work
    110. 110. 2. Run all Tests (“Red”) This shows that our new feature isn’t working yet, as we expected
    111. 111. 2. Run all Tests (“Red”) This shows that our new feature isn’t working yet, as we expected
    112. 112. 3. Write Code I am now adding the code to make the feature work
    113. 113. class User < ActiveRecord::Base validates_presence_of :email validates_format_of :email, :with => /A[^@s]+@[^@s]+.[^@s]+z/, :message => "was not well formed" def full_name return nil if first_name.nil? and last_name.nil? "#{first_name} #{last_name}".strip end end 3. Write Code I am now adding the code to make the feature work
    114. 114. class User < ActiveRecord::Base validates_presence_of :email validates_format_of :email, :with => /A[^@s]+@[^@s]+.[^@s]+z/, :message => "was not well formed" def full_name return nil if first_name.nil? and last_name.nil? "#{first_name} #{last_name}".strip end end 3. Write Code I am now adding the code to make the feature work
    115. 115. 4. Run all Tests (“Green”) This shows that I have succeeded, since my test now passes
    116. 116. 4. Run all Tests (“Green”) This shows that I have succeeded, since my test now passes
    117. 117. 5. Refactor
    118. 118. 5. Refactor Not needed in this case
    119. 119. 5. Refactor Not needed in this case This step allows you to clean up messes you create to make a test pass
    120. 120. 5. Refactor Not needed in this case This step allows you to clean up messes you create to make a test pass You can refactor and verify that the tests stay Green (you didn’t change things)
    121. 121. Questions?
    122. 122. Test Your Application Lab Your book has instructions for how to start increasing the test coverage for your application
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×