It is very common for Ruby applications to send transactional e-mails to users. What's not immediately obvious is how, as developers, we can test this functionality using our tools of choice: Cucumber and Rspec.
Ideally, the method should be re-usable so that we can simply add a single step to our scenarios, e.g:
And it should send me an "account confirmation" e-mail
One way to do this in a re-usable way is to add a new tag,
features/support/env.rb file, add the following:
Around('@email') do |scenario, block| ActionMailer::Base.delivery_method = :test ActionMailer::Base.perform_deliveries = true ActionMailer::Base.deliveries.clear block.call end
This ensures ActionMailer is in test mode (all e-mails will be added to an array we can inspect, rather than sent out to the real world), and it clears any other e-mails in the deliveries array before each step is executed. Now we can simply add the
Then we create a new
features/step_definitions/email_steps.rb file and add the following step definition:
Then /^it should send me an? "([^\"]*)" e\-mail$/ do |arg1| @email = ActionMailer::Base.deliveries.last @email.to.should include @user.email @email.subject.should include(arg1) end
This will test the subject line against the argument "account confirmation" in your scenario, so we could use this step for other types of e-mail; e.g. "password reminder".We can also test that the application doesn't send an e-mail, for example:
Then /^it should not send an e\-mail$/ do ActionMailer::Base.deliveries.size.should eq 0 end
Here's an example of the e-mail testing functionality in action:
@email Scenario: Creating an account Given I am logged out Then I should be able to register a new user account When I enter my details Then it should create a new account for me And it should send me an "account confirmation" e-mail
I hope this helps someone!