Follow Along as I Stumble on the Path to Learning RoR

Testing

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.


Stubbing current_user in Testing

Stubbing current_user is easy for testing:

@user = FactoryGirl.create(:user)

controller.stub!(:current_user).and_return(@user)


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