Railsで懸念をテストする方法


104

私が持っていることを考えるとPersonable、私のRailsでの懸念がある4アプリケーションfull_nameの方法を、どのように私はこの使用してRSpecのテストに行きますか?

Concerns / personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

どのテストフレームワークを使用していますか?また、Personableは通常のRubyモジュールであることも覚えておいてください。他のミックスインをテストするのと同じようにテストします。
リー・ジャービス2013年

ActiveSupport::ConcernRailsから削除されていませんか?少し前だと思った。
ラッセル

@LeeJarvis私はFactoryGirlと一緒にRspecを使用しています
Kyle


4
@ラッセル同意する。とは言っても、Railsのやり方に同意しなかったという理由で彼らがRailsのやり方に従っていたからといって、私は誰かの質問を助けません。とにかく、これはこの質問の主題から逃れるためのものです:-)
リージャービス

回答:


176

あなたが見つけたメソッドは確かに機能の少しをテストするために機能しますが、かなり壊れやすいようです-あなたのダミークラス(実際にStructはあなたのソリューションでは単に)はincludeあなたの関心事である実際のクラスのように振る舞うかそうでないかもしれません。さらに、モデルの問題をテストする場合、それに応じてデータベースを設定しない限り、オブジェクトの有効性をテストしたり、ActiveRecordコールバックを呼び出したりすることはできません(ダミークラスにはデータベーステーブルのバッキングがないため)それ)。さらに、懸念事項をテストするだけでなく、モデル仕様内で懸念事項の動作もテストする必要があります。

では、1石で2羽の鳥を殺してみませんか?RSpecの者の使用することにより、共有の例のグループを、あなたはそれら(例えば、モデル)を使用し、実際の授業に対するあなたの懸念をテストすることができますし、あなたは彼らが使用しているどこでもそれらをテストできるようになります。また、テストを1回記述し、問題を使用するモデル仕様に含めるだけで済みます。あなたの場合、これは次のようになります:

# app/models/concerns/personable.rb
module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

# spec/concerns/personable_spec.rb
require 'spec_helper'

shared_examples_for "personable" do
  let(:model) { described_class } # the class that includes the concern

  it "has a full name" do
    person = FactoryBot.build(model.to_s.underscore.to_sym, first_name: "Stewart", last_name: "Home")
    expect(person.full_name).to eq("Stewart Home")
  end
end

# spec/models/master_spec.rb
require 'spec_helper'
require Rails.root.join "spec/concerns/personable_spec.rb"

describe Master do
  it_behaves_like "personable"
end

# spec/models/apprentice_spec.rb
require 'spec_helper'

describe Apprentice do
  it_behaves_like "personable"
end

このアプローチの利点は、ARコールバックの呼び出しなど、ARオブジェクト以外では何もできないことに関心を持つことを始めると、さらに明白になります。


2
これの1つの欠点は、速度が低下することparallel_testsです。私は代わりに使用しての個別のテストを持っている方が良いだろうと思うshared_examples_forit_behaves_like
Artem Kalinchuk 2014年

6
@ArtemKalinchuk github.com/grosser/parallel_tests/issues/168 parallel_testsはファイルごとに基づいているので、それが本当かどうかはわかりません。したがって、共有された例が遅くなることはありません。また、適切にグループ化された共有動作は、テスト速度よりも優先されると主張します。
アーロンK 14

8
github.com/rspec/rspec-core/issues/407#issuecomment-1409871concernsディレクトリを必ず含めてくださいspec_helper.rb
Ziggy

1
そのリンクに懸念ディレクトリを含めることについて何も見つかりませんでした。これがどのように行われるかを明確にしていただけませんか?私の懸念の1つで、RSpecテストでモジュールを認識できません。
ジェイクスミス

4
_specshared_examples_for(この場合はpersonable_spec.rb)を含むファイル名に追加しないでください。追加すると、誤解を招く警告メッセージが表示されます-github.com/rspec/rspec-core/issues/828
Lalu

62

私が受け取ったコメントへの応答として、私がやったことはここにあります(誰か改善点があれば気軽に投稿してください)

spec / concerns / personable_spec.rb

require 'spec_helper'

describe Personable do
  let(:test_class) { Struct.new(:first_name, :last_name) { include Personable } }
  let(:personable) { test_class.new("Stewart", "Home") }

  it "has a full_name" do
    expect(personable.full_name).to eq("#{personable.first_name} #{personable.last_name}")
  end
end

1
はい、実際にと呼ばれるクラスをテストすると、他のテストが中断されPersonます。編集して修正します。
ラッセル

これは機能しません。それは私にエラーを与えます:undefined method 'full_name' for #<struct first_name="Stewart", last_name="Home">
カイル・デコ

Personableを拡張するのではなく、含めるようにしてください。答えを更新します。
ラッセル

今はうまくいきます。私を正しい方向に向け、@ Russellのリファクタリングを手伝ってくれてありがとう
Kyle

見事に機能し、見栄えが良い
Edward

7

別の考えは、with_model gemを使用してこのようなことをテストすることです。私は懸念を自分でテストしようとしていて、pg_search gemがこれを行っているのを見ました。変更される可能性があるため、個々のモデルでテストするよりもはるかに優れているように思われます。仕様で必要となるものを定義するとよいでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.