メールを含むテストもEmail Spec で楽々
Webシステムではメールをユーザー送り、メール内のURLクリックで処理を行うようなケースも間々あります。そんなプログラムの受け入れテスト、End-to-Endテストを行うには Request Specs や Steak に Email Spec で簡単に書けます。
Email Spec は Rails の ActionMailer のメール送信部分をフックし送信されたメール内容をライブラリー内に保持し、RSpecでテストを書けるようにするライブラリーです。 RSpecベースなので Request Specs や Steakだけでなく Cucumber でも使えます。
インストール
- Gemfile に gem 'email_spec' を追加し bundle install を実行。
- spec_helper.rb に以下を追加
require 'action_mailer' require 'email_spec' RSpec.configure do |config| config.include(EmailSpec::Helpers) config.include(EmailSpec::Matchers) end
テスト対象のコード
Steakの記事 で書いたTodoのサンプルにTodoの更新したら、メールを送り、そのメール内のURLをクリックするとTodo一覧が表示されるという、いかにもサンプルらしいコードを作ります。
- app/controller/todos_controller.rb 更新部分
def update @todo = Todo.find(params[:id]) respond_to do |format| if @todo.update_attributes(params[:todo]) format.html { redirect_to(@todo, :notice => 'Todo was successfully updated.') } format.xml { head :ok } mail = TodoMail.hello(todos_url) mail.transport_encoding = "8bit" mail.deliver else format.html { render :action => "edit" } format.xml { render :xml => @todo.errors, :status => :unprocessable_entity } end end end
- app/mailers/todo_mail.rb
class TodoMail < ActionMailer::Base default :from => "persion@user.com" def hello(url) @url = url mail(:to => "yy@ey-office.com", :subject => "ハロー") end end
- app/views/todo_mail/hello.text.erb
こんにちは!
<%= @url %>
----------------
テストだよ
- config/initializers/mailer.rb テスト環境のSMTPにあわせて書いて下さい
ActionMailer::Base.smtp_settings = { :delivery_method => :smtp, :raise_delivery_errors=> false, :address => "localhost", :port => 25, :domain => "test.com" }
Spec
このサンプルをテストするSpecは以下のように書けます
require 'spec_helper' describe "Todoの編集" do fixtures :todos it "編集するとメールが送信される" do visit edit_page(todos(:todo01).id) within "form" do click_button "Update Todo" end unread_emails_for("yy@ey-office.com").size.should == 1 open_email("yy@ey-office.com").should have_body_text(/こんにちは!/) end it "メール内のリンクをクリックすると一覧が表示される" do mail = open_email("yy@ey-office.com") click_email_link_matching(/^http:/, mail) page.should have_css("h1", :text => "Listing todos") end end
- unread_emails_for は未読メール情報の取得
- open_emailはメールアドレスやサブジェクトを指定して、送信されたメールの内容をテストできます
- click_email_link_matching は メール内のURL部分を正規表現で指定し、そのURLをクリックした場合のリクエストをアプリに送りアプリのテストを継続します
Email Specのヘルパーメソッドの概要は Email Specページ に書かれていますが、詳細は ヘルパーのソース を見るのが良いと思います :-)