その他
    ホーム 技術発信 DoRuby rspec で、referer や user_agent 関連の機能もテストしよう

    rspec で、referer や user_agent 関連の機能もテストしよう

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    お恥ずかしながら、TDDを行わずにRailsで開発を行い続けてきたred です。最近、自分でも spec を書く用になりました。かなり捗ります。まだの方、お早めに。

    自分にとって、spec を覚えるにあたっての最大の難関は、参考になる情報をなかなか見つけられなかった、ということでした。

    結局、自分は、プロジェクトメンバの書いたものをコピペ改変することにより覚えました。

    もし、独学の方、まわりにspec を書いている方のいない Rails/Ruby プログラマの方、まずはこのブログの記述もしくは下の私のコードを写経してみて、そこから、RSpec on Rails の使い方を調べるのが、導入によろしいかと思います。

    =====

    これ以下の内容は、下記環境にて動作確認をしています。

    • ruby 1.8.7
    • rails 2.1.0
    • rspec 1.3.0
    • rspec-rails 1.3.2

    =====

    直近のプロジェクトでは、ユーザエージェントやリファラを見て、それによって LPO を行うナビゲーションを実装していました。

    つまりは、下記のような機能を実装しました。勿論、本物はもっと高機能です。

    #{RAILS_ROOT}/app/controllers/test_controller.rb

    class TestController < ApplicationController
    
      # リファラより、どの検索エンジンから流入したかを特定
      def referer
        referer = request.env['HTTP_REFERER']
        if referer.blank?
          @engine = "no referer"
        elsif referer.split("?")[0].include? "google"
          @engine = "google"
        elsif referer.split("?")[0].include? "yahoo"
          @engine = "yahoo"
        else
          @engine = "not determined"
        end
        render :text => @engine
      end
     
    
      # ユーザエージェントより、どのブラウザよりアクセスしているかを特定
      def ua
        ua = request.env['HTTP_USER_AGENT']
        if ua.include? "MSIE"
          @browser = "ie"
        elsif ua.include? "Firefox"
          @browser = "firefox"
        elsif ua.include? "Chrome"
          @browser = "chrome"
        elsif ua.include? "Opera"
          @browser = "opera"
        elsif ua.include? "safari"
          @browser = "safari"
        else
          @browser = "others"
        end
        render :text => @browser
      end
    
    end
    

    上記のようなアプリがうまく動いているか確認する際、通常のブラウザで見ることが不可能な場合は、Live HTTP Headers や User Agent Switcher のようなツールを使い、ユーザエージェントやリファラを詐称してチェックするのがセオリーかと思います。

    spec で上記テストを自動化したい場合、下記のように記述すれば実行することができます。

    #{RAILS_ROOT}/spec/controllers/test_controller_spec.rb

    require 'spec_helper'
    
    describe TestController do
      
      describe "referer" do
        it "google 検索からの流入かどうか判別するテスト" do
          request.env["HTTP_REFERER"] = "http://www.google.co.jp/search?q=test"
          get "referer"
          response.should be_success
          assigns[:engine].should == "google"
        end
        
        it "yahoo 検索からの流入かどうか判別するテスト" do
          request.env["HTTP_REFERER"] = "http://search.yahoo.co.jp/search?p=test"
          get "referer"
          response.should be_success
          assigns[:engine].should == "yahoo"
        end
      end
      
      describe "ua" do
        it "firefox を使っているかどうか判別するテスト" do
          request.env["HTTP_USER_AGENT"] = "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17 GTB6 (.NET CLR 3.5.30729)"
          get "ua"
          response.should be_success
          assigns[:browser].should == "firefox"
        end
        
        it "IE を使っているかどうか判別するテスト" do
          request.env["HTTP_USER_AGENT"] = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
          get "ua"
          response.should be_success
          assigns[:browser].should == "ie"
        end
      end
    end
    

    上記のように、get で controller/method にアクセスする前に、request.env の各項目の値を上書きすれば、該当のテストを作成することができます。

    dev_machine:rails_root red$ spec spec/controllers/test_controller_spec.rb 
    ....
    
    Finished in 0.065284 seconds
    
    4 examples, 0 failures
    dev_machine:rails_root red$ 
    

    describe や it は配列の each の中での実行も出来るので、テストしたいユーザエージェントやリファラとその結果をDB化しておくことにより、いちいちツールを用いて切り替えることなく、一気にhttp_header 関連のテストが行えるようになりました。

    参考:http://stackoverflow.com/questions/542856/how-do-i-set-http-referer-when-testing-in-rails

    記事を共有