RSpec vs Test :: Unit in Rails


15

Non sono mai stato veramente convinto dei vantaggi che si ottengono passando a RSpec da Test :: Unit in Ruby on Rails (nonostante la lettura periodica di RSpec).

Cos'è RSpec che la maggior parte del progetto Rails sembra utilizzarlo?

(alcuni esempi di codice che indicano chiaramente i vantaggi dell'uno rispetto all'altro sarebbero molto apprezzati)


4
Solo 1 anno dopo e guardo con disgusto Test :: Unità ... RSpec FTW!
Paweł Gościcki,

Quasi duplicati su StackOverflow: RSpec vs Test :: Unit e RSpec vs. Shoulda
sondra.kinsey

Risposte:


13

È in gran parte una questione di gusti e la maggior parte degli strumenti di test merita entrambi il loro supporto al sale. La mia preferenza personale è per RSpec rispetto a Test :: Unit perché a) l'output e il layout dei test si concentra su ciò che si suppone faccia l'oggetto in esame (al contrario di quello che è il codice) eb) dicendo "X dovrebbe Y" ha più senso per me di "affermare che X predicato Y".

Per darti un po 'di contesto per i punti sopra, ecco un confronto (abbastanza elaborato) del codice di output / sorgente di due unit test funzionalmente equivalenti, uno scritto usando RSpec e l'altro usando Test :: Unit.

Codice in prova

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 :: Unit

 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 :: Uscita unità (piena quanto potrei farcela)

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

Uscita RSpec (formatter della documentazione)

Ξ 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 Penso che Berin (precedente risponditore) stia fondendo i ruoli di Cucumber (che è nato dal progetto RSpec ma è indipendente) e RSpec. Cucumber è uno strumento per test di accettazione automatizzati in stile BDD, mentre RSpec è una libreria di codici per test che può essere ed è utilizzata a livello di unità, integrazione e funzionalità. Quindi l'uso di RSpec non preclude il test unitario, è solo che tu chiami "specifiche" dei tuoi test unitari.


Non mi aspettavo di sentirmi triste quando sono venuto qui
Roman,

3

Ultimamente sembra che Cucumber abbia ottenuto un maggiore supporto nella comunità di Rails. Ecco l'argomento in poche parole che ho sentito da un'intervista con il protagonista di RSpec (da un vecchio Ruby su Rails Podcast).

Nella comunità agile (al momento) c'è stata una grande spinta per Test Driven Development con l'enfasi sul test prima di dimostrare che dovevi cambiare qualcosa. C'era qualcosa di filosoficamente sbagliato in questo. In sostanza, i test sono un modo per verificare che la tua implementazione sia corretta, quindi come pensi in modo diverso sul design di guida? Il lead di RSpec supponeva che tu specificassi per primo, e non sarebbe fantastico se la specifica controllasse anche i risultati della tua implementazione?

La semplice ridenominazione asserta shouldaiuta a focalizzare la mente in modo corretto secondo le specifiche di scrittura, e pensare a design. Tuttavia, questa è solo una parte dell'equazione.

Ancora più importante, dal momento che molti beleiver TDD sostenevano che i test documentavano il progetto, la maggior parte della documentazione era nella migliore delle ipotesi scarsa. I test sono abbastanza opachi per i non sviluppatori che non hanno familiarità con la lingua. Anche allora, il design non è immediatamente evidente dalla lettura della maggior parte dei test.

Quindi, come obiettivo secondario, RSpec ha escogitato un modo per generare documentazione scritta dalle specifiche. È questa specifica scritta che offre a RSpec un vantaggio rispetto al semplice Test :: Unit per guidare la progettazione di un'applicazione. Perché scrivere qualcosa più di una volta quando è possibile documentare e verificare la coerenza del progetto allo stesso tempo?

La mia comprensione è che Cucumber, che ha avuto il vantaggio di venire più tardi e apprendere lezioni da RSpec, fa un lavoro migliore di questo obiettivo secondario senza perdere l'obiettivo primario (capacità di testare l'implementazione dalle specifiche). Cucumber lo fa con un'API abbastanza inglese come i non programmatori possono ragionevolmente grok. Potrebbero aver bisogno dell'aiuto dei programmatori per compilare alcune definizioni di nuovi metodi di verifica, ma è progettato per essere estensibile.

In conclusione, RSpec / Cucumber non dovrebbe sostituire del tutto il test unitario. Possono essere più adatti a documentare e verificare il tuo progetto, ma ci sono ancora diversi test di implementazione che devono ancora essere fatti, in particolare con bug sottili che derivano dall'implementazione e non dal design dell'applicazione. Tuttavia, riduce il numero di test che devi scrivere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.