Test emails with automated testing tools

Ghost Inspector calls it UI tests, Selenium calls it web browser automated tests, Capybara calls it acceptance tests. Despite how they call it, if you use a testing tool, that browses web pages and you would like to test the emails being sent during the tests, but you don't know how, this post is for you.

Most people (so do I), don't test the emails being sent or rely on mocks:

expect(MyContactMailer).to receive(:send_contact).with('…')

click_on 'Send email'

Mocking can be fine, if you assume that the framework to send emails works, and also that the email configuration is correct.

Can you assume that with 100% of confidence? I can't!

How I test

I use Capybara for acceptance tests. These tests visit pages, trigger clicks and check the page content based on the performed actions.

visit '/products'

click_on '#add-product'

fill_in 'product-title', with: 'Conference table'

click_on '#save'

expect(page).to have_content 'Product saved.'
expect(page).to have_content 'Conference table'

But besides Capybara, I also use Ghost Inspector. The main differences on how I use them are:

^ Usually through a Slack webhook combined with the Ghost Inspector API:

ghost exec prod

How I test emails

Long story short, check the video below:

I'm using PutsBox to test emails for real. It's a mix of disposable email tools and HTTP request recorders tools such as PutsReq.

In the video above I'm testing the Reset Password feature from PutsBox itself. The test tries to reset password using a @putsbox.com email, opens the email for real, clicks on the reset link, resets the password and finishes the test. The highlighted part is how PutsBox can be used for email testing.

Try it now! Send an email to what-you-want@putsbox.com, wait for a few seconds to give time to the email arrival, then check http://putsbox.com/what-you-want/inspect. No sign up required, it's free and open source.

Getting back to the test recorded above… As the Ghost Inspector test used to record the video is a little verbose, let's check an equivalent Capybara version:

visit '/'

click_on 'a[href="/users/sign_in"]'
click_on 'a[href="/users/password/new"]'

fill_in '#user_email', with: 'test-reset-password@putsbox.com'

click_on 'input[name="commit"]'

# waits for the email
sleep 60

# opens the email
visit 'http://preview.putsbox.com/p/test-reset-password/last'

# clicks on the reset link
click_on 'body > p:nth-child(3) > a'

# resets the password
fill_in '#user_password', with: 'password'

fill_in '#user_password_confirmation', with: 'password'

click_on 'input[name="commit"]'

Awesome, right?!

Conclusion

You can test emails being sent during your tests for real or not, it depends on your needs.

But if you do so, I recommend you to use something like Ghost Inspector or similar. I personally don't like having the tests that I run locally making external HTTP requests.