Testing SMS Interactions in Ruby on Rails

By Chris Rittersdorf on 02 04 2012

In my last blog post, I discussed how to incorporate Twilio into
your Ruby on Rails application. However, I didn't discuss how to
automate testing these interactions. This time I'll show you how to do
just that by using the new Ruby Gem sms-spec, so that you can be
confident that you're building quality, tested code for your SMS enabled
Ruby on Rails application.

Test Infected Texting

Since I'm a Ruby on Rails developer, I love to use RSpec and
Cucumber to test my applications. I'd have to be hard pressed to
step outside of my comfort zone and write a line of production code
without having an associated test.

But recently I encountered a problem while working on a project. It
sends and receives messages via Twilio. I wanted to test these SMS
interactions with my application, but I couldn't find any out-of-the-box
solutions that would help me test this kind of behavior. So I got to
work and build a gem called sms-spec.

sms-spec

sms-spec helps you to test SMS interactions using RSpec and
Cucumber. It does this by changing the behavior of classes that handle
SMS communication in your application. Instead of actually sending and
receiving SMS messages to its respective service, sms-spec aggregates
these messages. You can then inspect them and make assertions about
them.

The rest of this article shows you how to get started using
sms-spec.

RSpec

Before we can start writing specs for our SMS interactions. We have to
configure the gem in our application. Insert the following line into the
‘test' section of your Gemfile:

If you haven't already install rspec:

We also have to set up the sms-spec driver we want to use. Add the
following to the bottom of your spec_helper.rb file:

This line tells sms-spec what classes to override. The driver will vary
depending on what RubyGem you're using to handle your SMS
communications. Unfortunately twilio-ruby is currently the only
available driver. But I'd like to make sms-spec support as many SMS
libraries as possible. If you would like to see a specific SMS Ruby Gem
supported, visit the sms-spec issues page and request an enhancement
to the project.

Now that sms-spec is configured, we can use it in an RSpec example.
Let's take a look at an example of a controller that sends out SMS
notifications:

This controller handles user registrations. The user simply submits
their mobile phone number with a form. The application then saves the
registration to the database, and if the registration is successful, a
text message is sent back to the user asking them to reply with "YES" to
confirm their registration. We can test this behavior with the following
spec:

By adding sms-spec, to this project and including SmsSpec::Helpers in
the example, we can use the following helper methods:

  • open_last_text_message_for(phone_number)
  • current_text_message

The first method, open_last_text_message_for grabs an instance of
the last text message sent to the given phone number. That sets us up to
be able to use the current_text_message method.

By getting an instance of the current text message, we can make
assertions about it. We care about what's in the body of the message for
the most part and. sms-spec gives us the ability to check this with the
have_body matcher. In this example, we use the have_body matcher
to assert that the content of the current_text_message is what we
expect it to be.

In the previous example, we looked at how a user can register for our
web application by submitting their phone number. If they mistyped their
phone number, there's a chance that the confirmation text message could
have been sent to the incorrect phone. Because of this the user should
reply to the text message to ensure that they have registered with the
correct phone number. When the user replies to the text message, the SMS
service (in this case Twilio) posts a callback to our application. This
behavior i demonstrated with the following controller action:

The behavior for this controller action is much more complicated than the create action. It would be helpful to test its behavior. The twilio-ruby driver provides the twiml_message helper method to simulate messages posted from Twilio to our application. In the following spec, we leverage this helper:

The twiml_message helper takes an originating phone number and a message body as parameters, and builds up a TwiML post from this information.

Cucumber

In addition to RSpec integration sms-spec includes steps to help you test SMS interactions with your application using cucumber. Assuming we've already configured our application to use cucumber, it's easy to get started using sms-spec with Cucumber to test our SMS interactions full-stack.

In order to give our cucumber tests access to the helper files, we need to change our env.rb file:

To start, we will generate the steps file for our cucumber test. sms-spec gives us a generator to do this:

By running this we generate the following:

Then we can create a cucumber feature that tests how the use registers for our application, and then gets sent a confirmation SMS message:

Summary

It's always a good idea to test your code. And when you don't have the appropriate tools to do so, it's helpful to yourself and others to create those tools. Sms-spec is proving to be a great tool for my own purposes, and one that I'd love to share with others. So if you want to be able to test SMS interactions in your Ruby on Rails application, give sms-spec a try. I think you'll like it.