Ruby on RailsでTest :: UnitからRSpecに切り替えることで得られる利点を、RSpecについて時々読んでいるにもかかわらず、私は本当に確信していません。
ほとんどのRailsプロジェクトがRSpecを使用しているように見えるのは、RSpecについての何ですか?
(一方が他方より優れていることを明確に示すいくつかのコード例は大歓迎です)
Ruby on RailsでTest :: UnitからRSpecに切り替えることで得られる利点を、RSpecについて時々読んでいるにもかかわらず、私は本当に確信していません。
ほとんどのRailsプロジェクトがRSpecを使用しているように見えるのは、RSpecについての何ですか?
(一方が他方より優れていることを明確に示すいくつかのコード例は大歓迎です)
回答:
それは主に好みの問題であり、それらの塩の価値があるほとんどのテストツールは両方をサポートしています。私の個人的な好みは、Test :: UnitよりもRSpecです。a)テストの出力とレイアウトは、テスト中のオブジェクトが(コードとは対照的に)行うべきことに焦点を当てており、b) 'X should Y'と言う「X述語Yをアサートする」よりも意味があります。
上記のポイントのコンテキストを提供するために、2つの機能的に同等の単体テストの出力/ソースコードの比較(かなり不自然な)を示します。1つはRSpecを使用して記述され、もう1つはTest :: Unitを使用します。
テスト対象のコード
class DeadError < StandardError; end
class Dog
def bark
raise DeadError.new "Can't bark when dead" if @dead
"woof"
end
def die
@dead = true
end
end
テスト::ユニット
require 'test/unit'
require 'dog'
class DogTest < Test::Unit::TestCase
def setup
@dog = Dog.new
end
def test_barks
assert_equal "woof", @dog.bark
end
def test_doesnt_bark_when_dead
@dog.die
assert_raises DeadError do
@dog.bark
end
end
end
RSpec
require 'rspec'
require 'dog'
describe Dog do
before(:all) do
@dog = Dog.new
end
context "when alive" do
it "barks" do
@dog.bark.should == "woof"
end
end
context "when dead" do
before do
@dog.die
end
it "raises an error when asked to bark" do
lambda { @dog.bark }.should raise_error(DeadError)
end
end
end
Test :: Unit出力(できる限りいっぱい)
Ξ code/examples → ruby dog_test.rb --verbose
Loaded suite dog_test
Started
test_barks(DogTest): .
test_doesnt_bark_when_dead(DogTest): .
Finished in 0.004937 seconds.
RSpec出力(ドキュメントフォーマッタ)
Ξ code/examples → rspec -fd dog_spec.rb
Dog
when alive
barks
when dead
raises an error when asked to bark
Finished in 0.00224 seconds
2 examples, 0 failures
2 tests, 2 assertions, 0 failures, 0 errors
PS Berin(前のレスポンダー)は、Cucumber(RSpecプロジェクトから発展したが独立している)とRSpecの役割を混同していると思います。CucumberはBDDスタイルの自動受け入れテスト用のツールであり、RSpecは単体、統合、および機能レベルで使用できるテスト用のコードライブラリです。したがって、RSpecを使用してもユニットテストは除外されません。ユニットテストを「仕様」と呼ぶだけです。
最近、CucumberがRailsコミュニティーでより多くのサポートを得ているようです。これは、RSpecのリード(古いRuby on Railsポッドキャストからのインタビュー)から聞いた簡単な議論です。
アジャイルコミュニティ(当時)では、何かを変更する必要があることを証明するために、最初にテストに重点を置いたテスト駆動開発が大きく推進されました。それには哲学的に間違った何かがありました。本質的に、テストは実装が正しいことを検証する方法です。それでは、駆動設計についてどう考えますか?RSpecのリードは、最初に指定することを推測しましたが、仕様が実装の結果もチェックするのは素晴らしいことではないでしょうか?
単純な名前の変更は、仕様を記述し、設計について考える正しい方法で心を集中assert
するのにshould
役立ちます。ただし、それは方程式の一部にすぎません。
さらに重要なことは、多くのTDDの信者がテストが設計を文書化したと主張していたため、ほとんどの文書は良くても不十分でした。テストは、言語になじみのない開発者にはかなり不透明です。それでも、ほとんどのテストを読んでもデザインがすぐにはわかりません。
そのため、RSpecは2番目の目標として、仕様から文書化されたドキュメントを生成する方法を考案しました。RSpecに、アプリケーションの設計を推進するための単純なTest :: Unitよりも優れているのは、この仕様書です。設計の一貫性を同時に文書化および検証できるのに、なぜ複数のことを書くのですか?
私の理解では、Cucumberは後で来てRSpecからレッスンを学ぶという利点があり、主要な目標(仕様から実装をテストする能力)を失うことなく、この2番目の目標をよりよく処理します。Cucumberは、プログラマーではない人が合理的に理解できるAPIのようなかなり英語でこれを行います。新しい検証方法の定義を記入するには、プログラマーの助けが必要かもしれませんが、拡張可能なように設計されています。
結論として、RSpec / Cucumberは単体テストを完全に置き換えるべきではありません。これらは設計の文書化と検証に適している可能性がありますが、特に、アプリケーションの設計ではなく実装に由来する微妙なバグがあるため、いくつかの実装テストを行う必要があります。ただし、記述する必要があるテストの数は減ります。