Measuring Test Coverage with Simplecov

I’m using the awesome Simplecov gem to see where I stand with test coverage within my apps.

It’s very simple to use:

(1) install the gem:

gem 'simplecov', require: false, group: :test

(2) include the gem in your test suite (for me that meant at the very top of test/test_helper.rb):

require 'simplecov'
SimpleCov.start

(3) run your tests

# for example
bin/rails test

(4) and then, just open the .index html file in /coverage

Rails Assertions List

I’ve partial lists of test assertions and examples, but I want to document one foe myself.

# check that a user is redirected to a certain place
assert_redirected_to account_path(@account)

# check that one value is contained in another
assert_includes @account.account_users.pluck(:user_id), user.id

# check that there’s an h1 tag with text equal to @account.name
assert_select “h1”, @account.name

# check that the this text isn’t present (within a h4 tag)
assert_select “h4”, {count: 0, text: “Different Account”}

# check that a count is decreased by 1 after the delete action
assert_difference “@account.account_users.count”, -1 do        
delete account_account_user_path(@account, user.id)      
end

# check if something is true
assert account_user.reload.admin?

Useful Rails Testing Gems

Here’s a list of Rails gems that have been helpful in testing for me:

RSpec Rails – for using the RSpec framework for testing

Capybara – for testing the app like a visitor would interact with the web app

Factory Girl Rails – makes it easy to create instances of models and associations

Shoulda Matchers – makes it easier to test and verify things with methods that use easy to understand language

Database Cleaner – to help keep your test environment from having a bunch of extra and redundant data

Warden – since I use Devise, this makes it easy to sign in in my Capybara tests without having to go to the login screen each time (and then to the pages I really want to test)

Guard – allows me to automatically test the code and specs that I change so I don’t need to remember to manually kick off a test each time a change is made

Launchy – useful with Capybara tests when I can’t figure out why a test is failing.  Launchy launches a browser so you can see the contents of the page.’save_and_open_page’ line to your spec when you want to do this.

 

Testing Braintree on Ruby on Rails

I’m using Braintree with a Ruby on Rails app via the braintree_ruby gem.

I needed to test responses in some of my tests.  Here’s how I was able to simulate some transactions.

I created a transaction, such as this:

result = Braintree::Transaction.sale( :amount => “100.00”, :payment_method_nonce => nonce_from_the_client )

To simulate different types of transactions, I changed nonce_from_the_client to the different options here putting the string in quotation marks.

To test a declined transaction, I used a nonce for a declined transaction and adjusted the amount to one that would fail, such as this:

result = Braintree::Transaction.sale( :amount => “2000.00”, :payment_method_nonce => “fake-processor-declined-visa-nonce” )

 

Testing Webhooks Locally

I wanted to be able to test webhooks locally so I didn’t have to keep deploying to code to test them.  The problem with testing webhooks is that the service (Stripe, Braintree, etc.) needs a URL to callback.  Ngrok is awesome, free software that allows you to test webhook callbacks locally by creating a tunnel that maps to your localhost address.

  1. Download ngrok
  2. Unzip the file
  3. Run the executable
  4. In the command prompt that comes up, type ‘ngrok http 3000’ (assuming that your local Rails app is running on port 3000 – i.e. localhost:3000), then enter
  5. ngrok should return some URLs that map to localhost:3000
  6. specify one of these URLs as the callback URL in your service’s settings

 

Rails 4 Testing Email

My new favorite way to test email is to use the Mailcatcher gem.  It’s easy to install the Mailcatcher gem (per the instructions, do not include it in your gemfile due to the high likelihood that it will mess something up).

It’s as easy as the instructions say:

  1. gem install mailcatcher (in cmd window)
  2. mailcatcher (in cmd window)
  3. Go to http://localhost:1080/
  4. Send mail through smtp://localhost:1025
  5. Add these to you development.rb file:
    config.action_mailer.delivery_method = :smtp
    config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }

After you do that, you can go into your rails console and send emails.  Once you send emails, when you visit http://127.0.0.1:1080/

You’ll see the emails that were sent.  The screen will look somewhat similar to an email client, and you see tabs to see the html, as well as text, versions of the email.

I’m using Sendgrid and Heroku, if you have the same set-up, you may have to comment out the config settings in your environment.rb file.

Testing that a Method Returns a Value with Rspec

I’m not sure if it’s because I haven’t had coffee yet today or what, but it took me awhile to think about how to test that a method returned a value.

For example, I had a method that returns either true or false.

def self.is_this_the_right_user?(user_id)

  if user_id == current_user.id

    return true

  else

    return false

  end

end

Initially in my RSpec, I had:

expect { User.is_this_the_right_user?(user_id) }.to eq true

Of course, that wasn’t correct.  Instead:

r = User.is_this_the_right_user?(user_id)

r.should eq true

How to Validate End Date After Start Date

I had an Event model where I had to write a simple validation that made sure that the end date was after the start date.  Here’s how I did it:

# event.rb
validate :end_after_start
validates :start_date, :end_date, :presence => true

private
def end_after_start
  return if end_date.blank? || start_date.blank?
 
  if end_date < start_date
    errors.add(:end_date, "must be after the start date") 
  end 
 end



private

Testing Email with RSpec

I ran into two types of errors when testing if emails triggered in the code with RSpec.

The first issue was that RSpec was not correctly determining if an email was triggered.  I knew the email was getting triggered correctly, but my test was failing.  The reason was that I was putting the should matcher too late.

Mailer.should_receive(:email_name)

I was putting this after calling the method I was testing (i.e. post :create) like I do with all of my other matchers.  However, with Mailer.should_receive, it should go before the call.

The second issue I had was that I was getting the error message:

Undefined method ‘deliver’ for nil:NilClass

For this, I had to stub out the response, like so:

Mailer.should_receive(:email_name).and_return(double(“Mailer”, :deliver => true))