RSpec vs Test :: Jednostka w szynach


15

Nigdy nie byłem tak naprawdę przekonany o korzyściach, które uzyskasz, przechodząc na RSpec z Test :: Unit w Ruby on Rails (pomimo od czasu do czasu czytania o RSpec).

Co takiego jest w RSpec, że wydaje się, że używa go większość projektów Rails?

(niektóre przykłady kodu wyraźnie wskazujące na przewagę jednego nad drugim byłyby bardzo mile widziane)


4
Zaledwie rok później patrzę z niesmakiem na Test :: Unit ... RSpec FTW!
Paweł Gościcki,

Prawie duplikaty na StackOverflow: RSpec vs Test :: Unit i RSpec vs. Shoulda
sondra.kinsey

Odpowiedzi:


13

Jest to w dużej mierze kwestia gustu, a większość narzędzi testujących wartych ich soli obsługuje oba. Osobiście wolę RSpec od Test :: Unit, ponieważ a) wyniki i układ testów koncentrują się na tym, co powinien zrobić testowany obiekt (w przeciwieństwie do kodu) oraz b) mówiąc „X powinien Y” ma dla mnie więcej sensu niż „twierdzenie, że X predykat Y”.

Aby dać ci kontekst dla powyższych punktów, oto (całkiem dobrze wymyślone) porównanie kodu wyjściowego / źródłowego dwóch funkcjonalnie równoważnych testów jednostkowych, jednego napisanego przy użyciu RSpec i drugiego przy użyciu Test :: Unit.

Testowany kod

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

Test :: Jednostka

 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 :: Wyjście jednostkowe (tak pełne, jak to tylko możliwe)

Ξ 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.

Wyjście RSpec (formatator dokumentacji)

Ξ 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 Myślę, że Berin (poprzedni respondent) łączy role Ogórka (który wyrósł z projektu RSpec, ale jest niezależny) i RSpec. Ogórek to narzędzie do automatycznego testowania akceptacji w stylu BDD, podczas gdy RSpec to biblioteka kodów do testowania, która może być używana na poziomie jednostki, integracji i funkcjonalności. Dlatego użycie RSpec nie wyklucza testów jednostkowych - po prostu nazywamy je „specyfikacjami” testów jednostkowych.


Nie spodziewałem się smutku, kiedy tu przyjechałem
Rzym

3

Ostatnio wydaje się, że Cucumber otrzymuje więcej wsparcia w społeczności Railsów. Oto najważniejszy argument, który usłyszałem podczas wywiadu z leadem RSpec (ze starego podcastu Ruby on Rails).

W zwinnej społeczności (w tym czasie) duży nacisk kładziono na Test Driven Development z naciskiem na testowanie w pierwszej kolejności w celu udowodnienia, że ​​trzeba coś zmienić. Było w tym coś złego z filozoficznego punktu widzenia. Zasadniczo testowanie jest sposobem na sprawdzenie, czy implementacja jest poprawna, więc co myślisz inaczej o projekcie jazdy? Przypuszczenie RSpec przypuszczało, że najpierw określasz , i czy nie byłoby wspaniale, gdyby specyfikacja sprawdzała również wyniki Twojej implementacji?

Prosta zmiana nazwy assertcelu shouldpomaga skupić umysł w prawidłowy sposób do specyfikacji pisać i myśleć o projektowaniu. To jednak tylko część równania.

Co ważniejsze, ponieważ wielu wierzących TDD twierdziło, że testy udokumentowały projekt, większość dokumentacji była co najwyżej słaba. Testy są dość nieprzejrzyste dla osób, które nie są programistami nieznającymi języka. Nawet wtedy projekt nie jest od razu widoczny z czytania większości testów.

Jako drugi cel RSpec opracował sposób generowania pisemnej dokumentacji na podstawie specyfikacji. Jest to pisemna specyfikacja, która daje RSpec przewagę nad prostym Test :: Unit do sterowania projektem aplikacji. Po co pisać coś więcej niż raz, kiedy można jednocześnie dokumentować i weryfikować spójność projektu?

Rozumiem, że Cucumber, który miał okazję przyjść później i wyciągnąć wnioski z RSpec, lepiej radzi sobie z tym drugorzędnym celem bez utraty głównego celu (możliwość przetestowania implementacji ze specyfikacji). Cucumber robi to z dość podobnym do angielskiego interfejsem API, który nieprogramiści mogą w rozsądny sposób wywołać grok. Mogą potrzebować pomocy ze strony programistów w celu uzupełnienia niektórych definicji nowych metod weryfikacji, ale została zaprojektowana z myślą o rozszerzalności.

Najważniejsze jest to, że RSpec / Cucumber nie powinien całkowicie zastępować testów jednostkowych. Mogą one lepiej nadawać się do dokumentowania i weryfikowania projektu - ale należy jeszcze wykonać kilka testów wdrożeniowych, szczególnie w przypadku subtelnych błędów wynikających z wdrożenia, a nie z projektu aplikacji. Zmniejsza to jednak liczbę testów, które musisz napisać.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.