Rspec-test-doubles

提供:Dev Guides
移動先:案内検索

RSpec-テストダブル

この章では、RSpec Mocksとも呼ばれるRSpec Doublesについて説明します。 Doubleは、別のオブジェクトを「スタンドイン」できるオブジェクトです。 あなたはおそらく、それが正確に何を意味するのか、なぜそれが必要なのか疑問に思っているでしょう。

たとえば、学校用のアプリケーションを作成していて、生徒の教室を表すクラスと生徒用の別のクラス、つまり教室クラスと生徒クラスがあるとします。 最初にいずれかのクラスのコードを記述する必要があるため、クラスルームクラスから始めましょう。

class ClassRoom
   def initialize(students)
      @students = students
   end

   def list_student_names
      @students.map(&:name).join(',')
   end
end

これは単純なクラスであり、list_student_namesというメソッドが1つあり、学生名のカンマ区切り文字列を返します。 さて、このクラスのテストを作成したいのですが、Studentクラスをまだ作成していない場合はどうすればよいでしょうか? テストDoubleが必要です。

また、Studentオブジェクトのように動作する「ダミー」クラスがある場合、ClassRoomテストはStudentクラスに依存しません。 これをテスト分離と呼びます。

ClassRoomテストが他のクラスに依存しない場合、テストが失敗すると、ClassRoomクラスにバグがあり、他のクラスにはないことがすぐにわかります。 現実の世界では、他の誰かが書いた別のクラスと対話する必要があるクラスを構築している可能性があることに留意してください。

これは、RSpec Doubles(モック)が役立つ場所です。 list_student_namesメソッドは、@ studentsメンバー変数の各Studentオブジェクトでnameメソッドを呼び出します。 したがって、nameメソッドを実装するDoubleが必要です。

RSpecの例(テスト)とともにClassRoomのコードを示しますが、Studentクラスが定義されていないことに注意してください-

class ClassRoom
   def initialize(students)
      @students = students
   end

   def list_student_names
      @students.map(&:name).join(',')
   end
end

describe ClassRoom do
   it 'the list_student_names method should work correctly' do
      student1 = double('student')
      student2 = double('student')

      allow(student1).to receive(:name) { 'John Smith'}
      allow(student2).to receive(:name) { 'Jill Smith'}

      cr = ClassRoom.new [student1,student2]
      expect(cr.list_student_names).to eq('John Smith,Jill Smith')
   end
end

上記のコードが実行されると、次の出力が生成されます。 経過時間は、コンピュータ上でわずかに異なる場合があります-

.
Finished in 0.01 seconds (files took 0.11201 seconds to load)
1 example, 0 failures

ご覧のとおり、 test double を使用すると、未定義または使用できないクラスに依存している場合でもコードをテストできます。 また、これは、テストに失敗した場合、クラスの問題であり、他の誰かが書いたクラスではないことがすぐにわかることを意味します。