Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

今さらながらRSpecに入門してみた

Ruby on Rails + RSpecの入門チュートリアルスライドです。

  • Be the first to comment

今さらながらRSpecに入門してみた

  1. 1. この RSpec には 夢があるッ!! inspire the るびま&ジョジョ 今さらながら RSpecに入門してみた
  2. 2. さくらば@ZARU 株式会社ベーシック&株式会社フルセイル TwitterとQiita、やってます。 楽しいことは誰にも譲らないで、自分で楽しむタイプです。 ! カレーと寿司とラーメンが好き ! プログラミングが好き ! どんな言語も好きだけど、JavaScriptが大好き ! 娘、産まれて育ってます
  3. 3. 今日は Railsアプリで、RSpec使った テストに入門した話をします。
  4. 4. その前に…
  5. 5. 宣伝!
  6. 6. 今月もQiita投稿大会やってます! ルール ! 月内に獲得したストック数が一番多いものが優勝 ! 月内に投稿された記事で咲いたストック数は優秀賞 ! 9月は優勝/優秀賞には天ぷら ! さくらばが優勝したら、割り勘ね…
  7. 7. 宣伝ここまで
  8. 8. はじめます
  9. 9. ? そもそもテストって何?
  10. 10. …っていう話は今回はしません。
  11. 11. まず、テストコードを 書けるようになってから考えよう。 道具について語るには、まず道具を知ることから。
  12. 12. TDD is dead. Long live testing. Rails作者:David Heinemeier Hansson
  13. 13. 偏った原理主義に走るなよ、環境は変わってきているんだし テストのあり方も変えていこうぜ。っていう話…と思ってます。
  14. 14. 「磯野ー!テストしようぜ!」
  15. 15. テストの原則 ! テストは信頼できるものであること ! テストは簡単に書けること ! テストは簡単に理解できること RSpecによるRailsテスト入門より引用
  16. 16. 前置きは終了。
  17. 17. この本を ベースに 話します。 分かりやすく とてもいい本です。 RSpec3用にリニューアルも 予定しているっぽいです。 買いましょう。
  18. 18. RSpecに 入門してみる
  19. 19. 今日、話すこと ! Gemfile + RSpec設定 ! モデルスペック ! ファクトリ ! コントローラスペック
  20. 20. Gemfile
  21. 21. group :development, :test do gem "rspec-rails", "~> 2.14.0" gem "factory_girl_rails", "~> 4.2.1" end group :test do gem "faker", "~> 1.1.2" gem "capybara", "~> 2.1.0" gem "database_cleaner", "~> 1.0.1" gem "launchy", "~> 2.3.0" gem "selenium-webdriver", "~> 2.39.0" end RSpec3が2014年6月くらいにリリースされているけど、今回は2系を使用。 3については下記ページ参照。 http://qiita.com/yujinakayama/items/a1d31b2caa35642e8e69 http://nilp.hatenablog.com/entry/2014/05/28/003335
  22. 22. 紹介
  23. 23. rspec-rails RSpec本体 + RailsでRSpec使うためのもろもろ。 factory_girl_rails 標準フィクスチャをもっと便利なファクトリとして提供してくれる。 テストデータをさくっと作るのにイケてるガール。 faker 名前・メールアドレスなどダミーデータを作ってくれる。 日本名に対応したFaker::Japaneseというのもある。 capybara Webアプリテストをコードレベルで行うことができる。 色々連携する。
  24. 24. database_cleaner まっさらな環境で、テストが実行できるように テストデータを消してくれる。 launchy 好きなタイミングでブラウザを開くことができる。 selenium-webdriver Seleniumでブラウザ上テストを実行できる。 他にもGuard・RuboCopとかテスト周りで便利なGemある
  25. 25. RSpecの設定
  26. 26. $ bundle exec rails g rspec:install create .rspec create spec create spec/spec_helper.rb .rspec --color --format documentation RSpecの実行結果を、見やすく楽しくしてくれる設定
  27. 27. こんな感じ
  28. 28. /config/application.rb config.generators do |g| g.test_framework :rspec, fixtures: true, view_specs: false, helper_specs: false, routing_specs: false, controller_specs: true, request_specs: false g.fixture_replacement :factory_girl, dir: "spec/factories” end ジェネレータで作成されるスペックファイルの設定。 ビューはRSpecではテストしないので作らない。 フィクスチャの代わりにファクトリを使う。
  29. 29. モデル スペック
  30. 30. 名前とメールアドレスを持つContactという モデルがあったとして、Contactモデルの スペックを書いてみる。 Contact name email さくっと、scaffoldしておく。 $ bundle exec rails g scaffold contact name:string email:string:unique $ bundle exec rake db:migrate Rails4.1からdb:test:cloneなどは、自動で行われるので必要なくなった
  31. 31. テストって どう書くの?
  32. 32. モデルスペックを書いてみる
  33. 33. $vi /spec/models/contact_spec.rb require 'spec_helper' describe Contact do it "全てのデータが有効な状態であること" it "名前がなければ無効な状態であること" it "メールがなければ無効な状態であること" it "重複したメールアドレスなら無効な状態であること" end まず、期待する動作をアウトライン的に 書き出してみる。
  34. 34. おもむろにテストを実行してみる。 $ bundle exec rspec
  35. 35. scaffoldで勝手に作られた コントローラースペックが動いてます。 +今作ったContactモデルのも。 当然、テストの中身を書いてないので、 pendingという状態になってます。
  36. 36. テストコードを書いてみる
  37. 37. require 'spec_helper' describe Contact do it "全てのデータが有効な状態であること" do contact = Contact.new( name: 'zaru', email: 'zaru@example.com' ) expect(contact).to be_valid end end Contactモデルを作成する(DBには保存しない) expect(オブジェクト).to 期待するもの、でテストできる RSpec2.11から、オブジェクト.should が expect() に変更になりました
  38. 38. おもむろにテストを実行してみる。 $ bundle exec rspec
  39. 39. テスト通ってる!
  40. 40. でも、実はこれ…
  41. 41. 中身ないContactオブジェクト でもテスト通る!
  42. 42. require 'spec_helper' describe Contact do it "全てのデータが有効な状態であること" do contact = Contact.new() expect(contact).to be_valid end end 通る!
  43. 43. なので、バリデーション設定しましょう。
  44. 44. $vi /app/models/contact.rb class Contact < ActiveRecord::Base validates :name, presence: true validates :email, presence: true, uniqueness: true end nameもemailも必須で、emailはユニーク扱い。
  45. 45. 中身のないContactオブジェクトのまま… 再度、実行!
  46. 46. 失敗してる!
  47. 47. 1個ずつバリデーションのテストしましょう
  48. 48. require 'spec_helper' describe Contact do it "名前がなければ無効な状態であること" do contact = Contact.new( name: nil ) expect(contact).to have(1).errors_on(:name) end it "メールがなければ無効な状態であること" do contact = Contact.new( email: nil ) expect(contact).to have(1).errors_on(:email) end end nameのデータを空にして エラーがでるかテスト
  49. 49. 重複のテストもしましょう
  50. 50. require 'spec_helper' describe Contact do it "重複したメールアドレスなら無効な状態であること" do Contact.create( name: 'zaru', email: 'zaru@example.com' ) contact = Contact.new( name: 'tofu', email: 'zaru@example.com' ) expect(contact).to have(1).errors_on(:email) end end createは、テストデータを DBに登録をしてくれる。
  51. 51. CPC設定完了 ニューラルリンケージ イオン濃度正常 メタ運動野パラメータ更新 原子炉臨界 パワーフロー正常 全システムオールグリーン ストライクフリーダム、システム起動
  52. 52. テストコードの書き方ポイント
  53. 53. ! スペックはアウトラインと考える ! describeでまとめて、itで期待する結果を書く contextは、状態の変化で使い分ける ! itには1個につき、結果を1つだけ期待する ! itは、◯◯である/◯◯すること、などの動詞にする ! 起きてほしいことと、起きてほしくないことを書く ! 境界値テストをすること ◯文字以上~◯文字以内の場合、その前後の値で
  54. 54. ついでに、 インスタンスメソッドをテストしてみる
  55. 55. 名前付きメールアドレスを返すメソッド class Contact < ActiveRecord::Base def nameAddr "%s<%s>" % [name, email] end end
  56. 56. require 'spec_helper' describe Contact do it "名前付きメールアドレスを返すこと" do contact = Contact.new( name: 'zaru', email: 'zaru@example.com' ) expect(contact.nameAddr).to eq 'zaru<zaru@example.com>' end end nameAddrを実行して、かえってくる文字列を比較する
  57. 57. テストコードをDRYに
  58. 58. beforeフックで、まとめる require 'spec_helper' describe Contact do before :each do @contact = Contact.new( name: 'zaru', email: 'zaru@example.com' ) end end Contactオブジェクトをインスタンス変数に格納 beforeは、describe中の各テストの前に実行される
  59. 59. ファクトリ
  60. 60. Factory Girl ひな形から テストデータを 量産できる可愛い子
  61. 61. Contactファクトリ作る
  62. 62. $vi /spec/factories/contacts.rb FactoryGirl.define do factory :contact do name "zaru" sequence(:email) { |n| "zaru#{n}@example.com" } end end 内部でインクリメンタルして、 違うメールアドレスを作ってくれる
  63. 63. テストコードを書きなおしてみる
  64. 64. it "全てのデータが有効な状態であること" do contact = Contact.new( name: 'zaru', email: 'zaru@example.com' ) expect(contact).to be_valid end it "全てのデータが有効な状態であること" do expect(FactoryGirl.build(:contact)).to be_valid end こうなる FactoryGirl.buildで、Contact.newと同様のことができる。 FactoryGirl.createで、Contact.createと同じ。
  65. 65. FactoryGirlって 打つの面倒
  66. 66. 省略できます
  67. 67. $vi /spec/spec_helper.rb RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods end it "全てのデータが有効な状態であること" do expect(build(:contact)).to be_valid end FactoryGirl省略できる
  68. 68. はい…
  69. 69. 今日はここまで!
  70. 70. サンプルコードはGitHubにあります。 https://github.com/zaru/rials_rspec_sample
  71. 71. 次回
  72. 72. ! コントローラースペック ! Capybaraさん ! REST WebAPIテスト
  73. 73. 予定は 未定…
  74. 74. $ shutdown -h now

×