RSpec vs Test :: Unità in Rails

13

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

Di cosa si tratta RSpec sembra che la maggior parte del progetto Rails lo stia usando?

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

    
posta Paweł Gościcki 17.12.2010 - 11:38
fonte

2 risposte

11

È in gran parte una questione di gusti, e la maggior parte degli strumenti di test che meritano il loro sale supportano entrambi. La mia preferenza personale è per RSpec su Test :: Unit perché a) l'output e il layout dei test si focalizzano su cosa l'oggetto sotto test dovrebbe fare (a differenza di ciò che è il codice) eb) dicendo "X dovrebbe Y" ha più senso per me che 'asserire che X predicato Y'.

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

Codice sotto test

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à (il più completo possibile)

Ξ 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 (formattatore di 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

P.S. Penso che Berin (precedente rispondente) stia combinando i ruoli di Cucumber (che è cresciuto fuori 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 il test che può essere, ed è, utilizzata a livello di unità, integrazione e funzionalità. Quindi l'uso di RSpec non preclude il test delle unità: è solo che chiami le specifiche dei tuoi test unitari.

    
risposta data 17.12.2010 - 15:50
fonte
2

Ultimamente sembra che Cucumber abbia avuto più supporto nella comunità di Rails. Ecco l'argomento in pillole che ho ascoltato da un'intervista con il lead di RSpec (da un vecchio Ruby on Rails Podcast).

Nella comunità agile (al momento) c'è stata una grande spinta per lo sviluppo guidato dai test, con l'enfasi sul test prima di dimostrare che dovevi cambiare qualcosa. C'era qualcosa di sbagliato in questo senso. In sostanza, il test è un modo per verificare che la tua implementazione sia corretta, quindi come pensi in modo diverso rispetto al design di guida? Il capo di RSpec ha supposto che specifichi prima, e non sarebbe bello se la specifica verificasse anche i risultati della tua implementazione?

Il semplice rinominare assert in should aiuta a focalizzare la mente nel modo corretto di scrivere le specifiche e a pensare al design. Tuttavia, questa è solo una parte dell'equazione.

Ancora più importante, dal momento che molti bertisti di TDD affermavano che i test documentavano la progettazione, la maggior parte della documentazione era al massimo povera. I test sono abbastanza opachi per i non sviluppatori che non conoscono 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 alla semplice Test :: Unit per guidare la progettazione di un'applicazione. Perché scrivere qualcosa più di una volta quando puoi documentare e verificare la coerenza del design allo stesso tempo?

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

La linea di fondo è che RSpec / Cucumber non dovrebbe sostituire del tutto il test delle unità. Possono essere più adatti per documentare e verificare la progettazione, ma ci sono diversi test di implementazione che devono essere ancora fatti, in particolare con i bug sottili che derivano dall'implementazione e non dal design dell'applicazione. Tuttavia, riduce il numero di test che devi scrivere.

    
risposta data 17.12.2010 - 14:17
fonte

Leggi altre domande sui tag