この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
入社してから3週間目の新入社員、HelloWorld?です。
現在、先輩から渡された課題をある程度こなした頃です。
その課題に関しては色々とつまづいた所があって、その一つに対してこのappiritsでこういうサイトがあるよー、という事でアウトプットしてみようかなと(新卒一番乗りしたかったのもあるよ!)。
で、問題のつまづいた所に関して、の前にどういう課題を渡されたかに関して大まかに。
・Railsを使って簡単な擬似管理画面を作る
・Rspecでテストコードを入れる
この他にも様々な要件がありましたが、取り敢えず問題となったのは、この組み合わせで起きた事でした。
後、自分のスキルも提示しておきます。
・プログラム経験:大学で4年間、主にC,C++、それから多少のJava,Javascript
・Ruby,Railsに関してはこのAppiritsでインターンの時に2週間教わった+社員となってからの2週間程度
・フレームワーク使用経験は上記のみ
プログラム自体は書き慣れてはいるけど、フレームワークとかは使った事ないよー、という感じです。
そして、詰まった所に関して。
管理画面という事で、Basic認証を導入してみて。そして、Basic認証を通してテストコードも書こう、という事をやってみる事にしました。
実装した所で参考にしたサイト:
http://threetreeslight.com/post/59357292457/rspecにおけるbasic-auth対応
Basic認証設定部分。全てのページに対して掛けています。
app/controller/apprication_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :basic
private
def basic
authenticate_or_request_with_http_basic do |user, pass|
user == 'user' && pass == 'admin'
end
end
Controllerのテストをさせる部分&テストをさせる為にBasic認証を通す部分
(DRYの為にSupportに書いてmoduleを作ったり、spec_helperに書き込んだりするべきだけど、取り敢えずここのテストしか書いてないので)
(更に加えるとテストする時はBasic認証とか外してテストするべきだよね、とか書いてあったりしたけど、今回はこういう事をしました、という事で)
spec/controllers/users_controller_spec.rb
RSpec.describe UsersController, type: :controller do
before(:all) do
@request.env ||= {}
user = "user"
pass = "admin"
@request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pass)
end
describe "GET #index" do
...
結果
動くけど、Basic認証通ってない!
それから色々試した所、
・requestがそもそもnilだと言われていた。
・before(:all)に入れずにテスト単体それぞれでBasic認証を通すようにしたら通った。
┗before(:all)はその前のモデルのテストでちょっと使ったりもしたから、これは問題ないんじゃないか……と思って訳が分からなくなる。
そこまで分かった後、先輩がちゃっと解決してくれました。
その事が色々書いてあったりするサイト:
http://qiita.com/srockstyle/items/6397c458d8f12dfcd02c
http://nilp.hatenablog.com/entry/2014/05/28/003335
結論
参考にしたサイトは、実装をした際に単一のテストしか記述していなくて。複数のテストに対してBasic認証を通す為には一つ、:allというホックに対して問題がありました。
describe MyClass do
before(:each) { } # このグループのそれぞれのテストの前に実行される
before(:all) { } # このグループの最初のテストの前に1度だけ実行される
end
before:allで一回だけ認証通しても、それぞれで認証通さないと全部弾かれてしまうよね、という結果でした。
修正
spec/controllers/users_controller_spec.rbのbefore(:all)をbefore(:each)に変更。
それだけ。
反省
まだ合計で1ヶ月程もrubyに対してもrailsに対しても学んでいないから、仕方ない事だけれども、それぞれのメソッドとか、仕様とかに対して上部しか分かっていないなー、と。分かったつもりになっている、という事でここは間違いないだろう、と決めつけてそこをエラー箇所から外していたので、自分では見つけられなかった。
まだ、そんな前提から疑わなければいけない段階でもあるし、そんな前提からこれからも疑っていたら時間が掛かり過ぎるし、デバッグの時間を削る為に、幅広い事が出来るようになる為にも積極的に知識を身につけていかないとなー、と。