おさらい
最終目標 : trello
前回 : seed データを投入して、ルートページと index ページで seed データの一覧表示できるところまで
その2 の目標
1.前回の分のテストを書く
1. なぜテストを書くのか
なぜなんだ
→ 安全だからです。
あー、とっても答えになってないですね
そう言う時は先生に聞きます
Rails Tutorial が僕の基本的な先生です。(10章までやった)
先生は テスト駆動開発(TDD) を推奨していました
テスト駆動開発とはなんぞや
- テストを先に書く
- もちろん失敗する
- 失敗しないように実装していく
だいたいこんな感じ。
なんでそんなことすんの?
あれ?なんでそんなことするの?
なぜなんだ(本日2回目)
ということで一旦ググる
良さげな記事を発見
【初心者向け】テスト駆動開発とRspecについて調べてみた
ありがとうございます。勉強になります。
2. インストールする
だいたいわかったので
とりあえず RSpec をインストールする。。。
# ~~省略~~
group :development, :test do
gem 'rspec-rails'
end
参考:RSpec 公式
Gemfile を更新したらば、web コンテナで gem をインストールしていく
# bundle install
# rspec -v
RSpec 3.8
- rspec-core 3.8.0
- rspec-expectations 3.8.2
- rspec-mocks 3.8.0
- rspec-rails 3.8.2
- rspec-support 3.8.0
# rails g rspec:install
Running via Spring preloader in process 495
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
入ってますね。
3. どんなテストを書くか
/
(ルートページ) と /index
にアクセスした際に
seed に入れたデータが全て取得できることを確認する。
必要なテストは2つ
-
/
ルートページにアクセスした際に、 期待するデータの全てが取得できること -
/index
にアクセスした際に、期待しt(ry
こんなもんかな
まだしなきゃいけないことあるなら思いついた時にやります。
とりあえず今回はこの二つ
4. 作業開始(準備)
まずはテストファイルを作成します。
$ touch spec/controllers/index_page_spec.rb
今後 Contoroller のテストを行うものは全て spec/controllers/
に入れようと思います。
memo
hogehoge_spec.rb
の _spec
これ
書かなくてもテストは実行できるんです。
じゃあなんで書くのかと言うと
bundle exec rspec
でテストを実行した時に _spec
がついてるファイルを
わざわざ指定しなくても、まとめて実行できるんです。
つまり
$ bundle exec rspec spec/hoge/hoge.rb
$ bundle exec rspec spec/fuga/fuga.rb
$ bundle exec rspec spec/piyo.rb
$ bundle exec rspec poyo.rb
と、しないといけないところを
お尻に _spec
とつけるだけで
$ bundle exec rspec
上記のをまとめて実行できるようになるんですね、すごい!
めっちゃ便利なので積極的にお尻にスペックをつけましょう。
(この認識に誤りがあったら教えてください。mm)
それでは作業に戻ります。
RSpec.describe 'TasksController' do
context 'show index page' do
it 'show task list on root page' do
end
it 'show task list on index page' do
end
end
end
# bundle exec rspec
..
Finished in 0.00874 seconds (files took 0.13328 seconds to load)
2 examples, 0 failures
何も書いてないので、当然グリーンになります。
公式 に書いてあった書き方を真似てみました。
一行目で、君は RSpec の仲間だよ〜って教えてあげてるんだと思います。
んー、ちょっと微妙な理解っぽいので、もう少し調べてみます
公式を読み進めてみると。。
Controller のテストの書き方かな? リンクがありましたね
こちら
いいぞ、すごいそれっぽいぞ
Controller specs are marked by :type => :controller or if you have set
config.infer_spec_type_from_file_location! by placing them in spec/controllers.
コントローラーのテストだよーって教えてあげるためには、どこかに :type => :controller
を書くか spec/controllers/
に配置する必要があるみたいです。
コントローラーのテストだよって教えてあげないといけないんですね
render_views
というものがあるみたい
僕のは こちら に該当したので、書き方を変えます。
require 'rails_helper'
RSpec.describe TasksController do
render_views
context 'show index' do
it 'show task list on root page' do
end
it 'show task list on index page' do
end
end
end
type ~~
を書くように書いてありましたが、さっき spec/controllers/
配下なら書かなくていいよとも書いてあったので書きません。
あと、ここではコントローラーを' '
で囲わなくても大丈夫だったので、こうします
require 'rails-helper'
????
...誰ですか???!!!
〜回想〜
$ bundle install
$ rails g rspec:install
Running via Spring preloader in process 495
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
いた...。
いた!!
いました。
どうやら このヘルパーを require しないと render_views が使えないみたいです。
オマケがありました
おそらく Rails のヘルパーを使う事を明記したので、Rails で作成したコントローラーが文字列でなくても認識してくれたのかなって思います。
書かなくていいことは書きたくないので ' '
消しました
# bundle exec rspec
..
Finished in 0.04538 seconds (files took 7.39 seconds to load)
2 examples, 0 failures
は??なんか7秒もかかりました。
ふざけんな、なんでじゃ、なんもテストしとらんのに!
ちょっとテストの時間がかかるのはストレスですが、一旦後回しにします。
テストの時間がかかる事を対策することに時間がかかりそうなので
5. 作業開始(本当に)
ちょっと予想外に調べるものが多かったので、章分けしました。
それでは気を取り直してやっていきますか
(もう結構しんどい、こんなややこしいの...?)
とりあえず、index を開いてほしい。
公式をみるとそれっぽいことが書いてあった。
~~
it 'show task list on index page' do
get :index
end
~~
# bundle exec rspec
..
Finished in 0.48295 seconds (files took 5.18 seconds to load)
2 examples, 0 failures
いい感じ、なぜか時間も短くなってるし、なげえけどな
~~
it 'show task list on index page' do
get :index
expect(response).to render_template('index')
expect(response.body).to eq 'task 001 : hogehoge'
end
~~
# bundle exec rspec
.F
Failures:
1) TasksController show index show task list on index page
Failure/Error: expect(response).to render_template('index')
NoMethodError:
assert_template has been extracted to a gem. To continue using it,
add `gem 'rails-controller-testing'` to your Gemfile.
# ./spec/controllers/index_page_spec.rb:12:in `block (3 levels) in <top (required)>'
Finished in 0.48037 seconds (files took 5.57 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/controllers/index_page_spec.rb:10 # TasksController show index show task list on index page
なんか Gem がないよって怒ってますね
どうやら assert_template
を使うには rails-controller-testing
という Gem が必要みたい
は?なにこいつめっちゃ親切にエラーを出すじゃないか、やさしい
5.1 Gem install
インストールは公式を見た方が最新の情報が書いてあったりするので、安全だと思っています。
ので
公式 を見ます。
Gemfile のどこに書いてもいいみたい、けどまあ RSpec を使う環境でしか使わないし、一緒の所に書いておきましょうか。
group :development, :test do
gem 'rspec-rails'
gem 'rails-controller-testing'
end
# bundle
あっ、へ〜、公式の install 方法に書いてあったので真似たのですが bundle install
は bundle
と省略できるんですね、便利。
よく使うからきっと用意されたのでしょう、楽チンなので覚えました
1) TasksController show index show task list on index page
Failure/Error: expect(response.body).to eq 'task 001 : hogehoge'
expected: "task 001 : hogehoge"
got: "<!DOCTYPE html>\n<html>\n <head>\n <title>Myapp</title>\n \n \n\n <link rel=\"styleshee...\"></script>\n </head>\n\n <body>\n <h1>Your Tasks</h1>\n\n<ul>\n</ul>\n\n </body>\n</html>\n"
(compared using ==)
Diff:
@@ -1,2 +1,20 @@
-task 001 : hogehoge
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Myapp</title>
+
+
+
+ <link rel="stylesheet" media="all" href="/assets/application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css" data-turbolinks-track="reload" />
+ <script src="/assets/application-3c2e77f06bf9a01c87fc8ca44294f3d3879d89483d83b66a13a89fc07412dd59.js" data-turbolinks-track="reload"></script>
+ </head>
+
+ <body>
+ <h1>Your Tasks</h1>
+
+<ul>
+</ul>
+
+ </body>
+</html>
# ./spec/controllers/index_page_spec.rb:13:in `block (3 levels) in <top (required)>'
なんで..
天才なので閃きました
rails db:seed
をしたのは開発環境、 RSpec はテスト環境に対してテストを実行している、つまり、テスト環境には seed データが投入されていない!!!!!!!!
Q.E.D.
俺でなきゃ見逃しちゃうね
..え、そうなの??
まあ、よくわかんねーけど、テスト環境でも rails db:seed
してもらえばいいんじゃね?(鼻ほじ)
5.2 VS テスト環境
before do
`rails db:seed`
end
ダメでした
まあ流石にダメな予感はしてました。
With RSpec, how to seed the database on load?
めっちゃそれっぽい!!!!!!
before do
`rails db:reset RAILS_ENV=test`
end
さっきのはニアピンだったんですね。
rails
コマンドは ENV=development
に向けてやってる見たい
ここでしっかりと「お前はテスト向きにコマンドやりやがれ」と命令してあげる事で、はいわかりましたテスト向きですね。と聞き分けよくやってくれるみたい
それと、毎回 rails db:seed
をやると無限にデータが増えるので、 rails db:reset
にしました
1) TasksController show index show task list on index page
Failure/Error: expect(response.body).to eq 'task 001 : hogehoge'
expected: "task 001 : hogehoge"
got: "<!DOCTYPE html>\n<html>\n <head>\n <title>Myapp</title>\n \n \n\n <link rel=\"styleshee.../li>\n <li>task 002 : fugafuga</li>\n <li>task 003 : piyopiyo</li>\n</ul>\n\n </body>\n</html>\n"
(compared using ==)
Diff:
@@ -1,2 +1,23 @@
-task 001 : hogehoge
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Myapp</title>
+
+
+
+ <link rel="stylesheet" media="all" href="/assets/application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css" data-turbolinks-track="reload" />
+ <script src="/assets/application-3c2e77f06bf9a01c87fc8ca44294f3d3879d89483d83b66a13a89fc07412dd59.js" data-turbolinks-track="reload"></script>
+ </head>
+
+ <body>
+ <h1>Your Tasks</h1>
+
+<ul>
+ <li>task 001 : hogehoge</li>
+ <li>task 002 : fugafuga</li>
+ <li>task 003 : piyopiyo</li>
+</ul>
+
+ </body>
+</html>
# ./spec/controllers/index_page_spec.rb:17:in `block (3 levels) in <top (required)>'
おおおおおおお!!!入ってるっぽいじゃん!!!
まあただ、全然違う箇所見てるよ、と怒られてしまったので、
expect(response.body).to eq 'task 001 : hogehoge'
この辺をいじる
5.3 データの取得方法
it 'show task list on index page' do
get :index
expect(response).to render_template('index')
expect(response.body.ui.li).to include 'task 001 : hogehoge'
end
すげー適当
1) TasksController show index show task list on index page
Failure/Error: expect(response.body.ui.li).to include 'task 001 : hogehoge'
NoMethodError:
undefined method `ui' for #<String:0x0000561683469d40>
# ./spec/controllers/index_page_spec.rb:17:in `block (3 levels) in <top (required)>'
だよね。
ということは、これまでの経験的に、画面に表示されている要素を取得するため Gem が用意されているのではないだろうか?という仮説が立つ
capybaraのhave_contentなどで、含まれていてほしい単語の数を指定したい。
ほら
で、次は capybara
を調べる
capybara
ほらぁ!!!!
成長を感じている...
そしてググり力も上がってきている...
にっこり。
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
gem 'chromedriver-helper'
end
あれれ??すでにいるんですけど...ドユコト
If the application that you are testing is a Rails app, add this line to your test helper file:
翻訳:
テストしているアプリケーションがRailsアプリケーションの場合は、この行をテストヘルパーファイルに追加します。
へ〜、入ってるだけじゃ使えないのね
require 'rails_helper'
require 'capybara/rails'
~~
it 'show task list on index page' do
get :index
expect(response).to render_template('index')
expect(page).to have_content('task 001 : hogehoge')
end
よし、これで使えるわけだ
1) TasksController show index show task list on index page
Failure/Error: expect(page).to have_content('task 001 : hogehoge')
NameError:
undefined local variable or method `page' for #<RSpec::ExampleGroups::TasksController::ShowIndex:0x0000558ab86d98e8>
# ./spec/controllers/index_page_spec.rb:19:in `block (3 levels) in <top (required)>'
ダメみたい
そもそもpage
って何よって感じに思ってたらそこで怒られた、capybara
を理解する必要がありそう
5.4 VS capybara
いや、長い。まじで
5.4.1 エラー発見しやすくしてみた
it 'show task list on index page' do
visit '/index'
get :index
expect(response).to render_template('index')
expect(page).to have_content('task 001 : hogehoge')
end
capybara が使えてんのかダメなのか、確認するために
capybara の method かな? visit
を最初に書いておく
ここで落ちれば capybara がちゃんと入ってないことが証明されるだろう
1) TasksController show index show task list on index page
Failure/Error: visit '/index'
NoMethodError:
undefined method `visit' for #<RSpec::ExampleGroups::TasksController::ShowIndex:0x00005564b14ad970>
ちなみにダメでした。
5.4.2 requore の記載場所を変えてみた
capybara の公式に
Load RSpec 3.5+ support by adding the following line (typically to your spec_helper.rb file):
spec_helper.rb
にかけってって書いてありました
せっかくなのでrails_helper
も一緒に引っ越ししましょう。
require 'rails_helper'
require 'capybara/rails'
require 'capybara/rspec'
同じエラー
ちょっとまじできつい、わからない
やろうとしてることが難しいのかなとも思ったけど、
画面に表示されているもの取得するだけなんだから難しくないでしょうに
助けてください。
- したいこと。
- index ページできちんとモデルが表示されているかのテスト
- seed データを入れて、ローカルホストに接続したら seed データが表示された
- テストでも同じことをしたい
- わからないこと
- そもそも開発環境で使っている seeds をテストでも使うのが普通なのか
- capybara を使う必要があるのか
- 使うとしたら何が間違っていたのか
- 使わないならどうしたらいいのか
すごくざっくりした質問になってしまって申し訳ございません。
また、質問をするなら Qiita じゃなくて、ここの方がいいよ、とかあったら教えてください。
5.4.3 敗退
やめました。
capybara 使うのやめました。
it 'show task list on index page' do
get :index
expect(response).to render_template('index')
expect(response.body).to include 'task 001 : hogehoge'
end
これで通りました。
この方向でもっとちゃんと探したい。