Testing SMS Interactions in Ruby on Rails
By Chris Rittersdorf on 03 Apr 2012
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.
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.