RSpec - Guida rapida

RSpec è un framework di unit test per il linguaggio di programmazione Ruby. RSpec è diverso dai tradizionali framework xUnit come JUnit perché RSpec è uno strumento di sviluppo guidato dal comportamento. Ciò significa che i test scritti in RSpec si concentrano sul "comportamento" di un'applicazione testata. RSpec non pone l'accento su come funziona l'applicazione ma piuttosto su come si comporta, in altre parole, su cosa fa effettivamente l'applicazione.

Ambiente RSpec

Prima di tutto, dovrai installare Ruby sul tuo computer. Tuttavia, se non l'hai già fatto prima, puoi scaricare e installare Ruby dal sito Web principale di Ruby - Ruby .

Se stai installando Ruby su Windows, dovresti avere il programma di installazione di Ruby per Windows qui su - http://www.rubyinstaller.org

Per questo tutorial, avrai solo bisogno di un editor di testo, come Blocco note e una console a riga di comando. Gli esempi qui useranno cmd.exe su Windows.

Per eseguire cmd.exe, è sufficiente fare clic sul menu Start e digitare "cmd.exe", quindi premere il tasto Invio.

Al prompt dei comandi nella finestra cmd.exe, digita il seguente comando per vedere quale versione di Ruby stai utilizzando:

ruby -v

Dovresti vedere l'output di seguito simile a questo:

ruby 2.2.3p173 (2015-08-18 revision 51636) [x64-mingw32]

Gli esempi in questo tutorial useranno Ruby 2.2.3 ma qualsiasi versione di Ruby superiore alla 2.0.0 sarà sufficiente. Successivamente, dobbiamo installare la gem RSpec per la tua installazione di Ruby. Una gemma è una libreria Ruby che puoi usare nel tuo codice. Per installare una gemma, è necessario utilizzare ilgem comando.

Installiamo ora la gemma Rspec. Torna alla finestra cmd.exe e digita quanto segue:

gem install rspec

Dovresti avere un elenco di gemme dipendenti che sono state installate, queste sono gemme di cui la gem rspec ha bisogno per funzionare correttamente. Alla fine dell'output, dovresti vedere qualcosa che assomiglia a questo -

Done installing documentation for diff-lcs, rspec-support, rspec-mocks,
   rspec-expectations, rspec-core, rspec after 22 seconds 
6 gems installed

Non preoccuparti, se il tuo output non è esattamente lo stesso. Inoltre, se utilizzi un computer Mac o Linux, potrebbe essere necessario eseguire entrambigem install rspec comando utilizzando sudo oppure usa uno strumento come HomeBrew o RVM per installare rspec gem.

Hello World

Per iniziare, creiamo una directory (cartella) per memorizzare i nostri file RSpec. Nella finestra cmd.exe, digita quanto segue:

cd \

Quindi digitare -

mkdir rspec_tutorial

E infine, digita -

cd rspec_tutorial

Da qui, creeremo un'altra directory denominata spec, fallo digitando -

mkdir spec

Memorizzeremo i nostri file RSpec in questa cartella. I file RSpec sono noti come "specifiche". Se questo ti sembra confuso, puoi pensare a un file spec come a un file di prova. RSpec utilizza il termine "specifica" che è una forma abbreviata per "specifica".

Poiché RSpec è uno strumento di test BDD, l'obiettivo è concentrarsi su ciò che fa l'applicazione e se segue o meno una specifica. Nello sviluppo guidato dal comportamento, la specifica è spesso descritta in termini di "User Story". RSpec è progettato per chiarire se il codice di destinazione si sta comportando correttamente, in altre parole seguendo la specifica.

Torniamo al nostro codice Hello World. Apri un editor di testo e aggiungi il seguente codice:

class HelloWorld

   def say_hello 
      "Hello World!"
   end
   
end

describe HelloWorld do 
   context “When testing the HelloWorld class” do 
      
      it "should say 'Hello World' when we call the say_hello method" do 
         hw = HelloWorld.new 
         message = hw.say_hello 
         expect(message).to eq "Hello World!"
      end
      
   end
end

Quindi, salvalo in un file denominato hello_world_spec.rb nella cartella delle specifiche che hai creato sopra. Ora torna nella finestra cmd.exe, esegui questo comando -

rspec spec spec\hello_world_spec.rb

Al termine del comando, dovresti vedere un output simile a questo:

Finished in 0.002 seconds (files took 0.11101 seconds to load) 
1 example, 0 failures

Congratulazioni, hai appena creato ed eseguito il tuo primo unit test RSpec!

Nella sezione successiva, continueremo a discutere la sintassi dei file RSpec.

Diamo uno sguardo più da vicino al codice del nostro HelloWorldesempio. Prima di tutto, nel caso non fosse chiaro, stiamo testando la funzionalità diHelloWorldclasse. Questa ovviamente è una classe molto semplice che contiene un solo metodosay_hello().

Ecco di nuovo il codice RSpec -

describe HelloWorld do 
   context “When testing the HelloWorld class” do 
      
      it "The say_hello method should return 'Hello World'" do 
         hw = HelloWorld.new 
         message = hw.say_hello 
         expect(message).to eq "Hello World!" 
      end
      
   end 
end

La parola chiave di descrizione

La parola describeè una parola chiave RSpec. Viene utilizzato per definire un "gruppo di esempio". Puoi pensare a un "gruppo di esempio" come a una raccolta di test. Ildescribela parola chiave può accettare un nome di classe e / o un argomento stringa. È inoltre necessario passare un argomento di blocco adescribe, questo conterrà i singoli test, o come sono conosciuti in RSpec, gli "Esempi". Il blocco è solo un blocco Ruby designato dal Rubydo/end parole chiave.

La parola chiave di contesto

Il context la parola chiave è simile a describe. Anch'esso può accettare un nome di classe e / o un argomento stringa. Dovresti usare un blocco concontextanche. L'idea di contesto è che racchiude test di un certo tipo.

Ad esempio, puoi specificare gruppi di esempi con contesti diversi come questo:

context “When passing bad parameters to the foobar() method” 
context “When passing valid parameters to the foobar() method” 
context “When testing corner cases with the foobar() method”

Il context la parola chiave non è obbligatoria, ma aiuta ad aggiungere ulteriori dettagli sugli esempi che contiene.

La parola chiave it

La parola itè un'altra parola chiave RSpec utilizzata per definire un "Esempio". Un esempio è fondamentalmente un test o un test case. Di nuovo, mi piacedescribe e context, it accetta sia il nome della classe che gli argomenti stringa e deve essere utilizzato con un argomento blocco, designato con do/end. In caso diit, è consuetudine passare solo una stringa e un argomento di blocco. L'argomento stringa utilizza spesso la parola "dovrebbe" e ha lo scopo di descrivere quale comportamento specifico dovrebbe verificarsi all'interno delit block. In altre parole, descrive che il risultato atteso è per l'esempio.

Notare la it block dal nostro esempio HelloWorld -

it "The say_hello method should return 'Hello World'" do

La stringa rende chiaro cosa dovrebbe accadere quando chiamiamo say hello su un'istanza della classe HelloWorld. Questa parte della filosofia RSpec, un esempio, non è solo un test, è anche una specifica (una specifica). In altre parole, un esempio documenta e verifica il comportamento previsto del codice Ruby.

La parola chiave attesa

Il expectla parola chiave viene utilizzata per definire una "aspettativa" in RSpec. Questo è un passaggio di verifica in cui controlliamo che una specifica condizione prevista sia stata soddisfatta.

Dal nostro esempio HelloWorld, abbiamo:

expect(message).to eql "Hello World!"

L'idea con expectaffermazioni è che si leggono come l'inglese normale. Puoi dirlo ad alta voce come "Aspettati che il messaggio variabile sia uguale alla stringa" Hello World "". L'idea è che sia descrittiva e anche di facile lettura, anche per gli stakeholder non tecnici come i project manager.

The to keyword

Il to la parola chiave è utilizzata come parte di expectdichiarazioni. Nota che puoi anche usare ilnot_toparola chiave per esprimere il contrario, quando si desidera che l'aspettativa sia falsa. Puoi vedere che a è usato con un punto,expect(message).to,perché in realtà è solo un normale metodo Ruby. In effetti, tutte le parole chiave RSpec sono in realtà solo metodi Ruby.

The eql keyword

Il eqlparola chiave è una parola chiave RSpec speciale chiamata Matcher. Utilizzi Matcher per specificare il tipo di condizione che stai testando per essere vera (o falsa).

Nel nostro HelloWorld expect dichiarazione, è chiaro che eqlsignifica uguaglianza delle stringhe. Nota che ci sono diversi tipi di operatori di uguaglianza in Ruby e di conseguenza diversi Matcher corrispondenti in RSpec. Esploreremo i molti diversi tipi di Matcher in una sezione successiva.

In questo capitolo, creeremo una nuova classe Ruby, la salveremo nel suo file e creeremo un file spec separato per testare questa classe.

Innanzitutto, nella nostra nuova classe, si chiama StringAnalyzer. È una classe semplice che, hai indovinato, analizza le stringhe. La nostra classe ha un solo metodohas_vowels?che, come suggerisce il nome, restituisce true se una stringa contiene vocali e false se non lo fa. Ecco l'implementazione perStringAnalyzer -

class StringAnalyzer 
   def has_vowels?(str) 
      !!(str =~ /[aeio]+/i) 
   end 
end

Se hai seguito la sezione HelloWorld, hai creato una cartella chiamata C: \ rspec_tutorial \ spec.

Elimina il file hello_world.rb se ce l'hai e salva il codice StringAnalyzer sopra in un file chiamato string_analyzer.rb nella cartella C: \ rspec_tutorial \ spec.

Ecco la fonte del nostro file delle specifiche per testare StringAnalyzer -

require 'string_analyzer' 

describe StringAnalyzer do 
   context "With valid input" do 
      
      it "should detect when a string contains vowels" do 
         sa = StringAnalyzer.new 
         test_string = 'uuu' 
         expect(sa.has_vowels? test_string).to be true 
      end 
		
      it "should detect when a string doesn't contain vowels" do 
         sa = StringAnalyzer.new 
         test_string = 'bcdfg' 
         expect(sa.has_vowels? test_string).to be false
      end 
      
   end 
end

Salvalo nella stessa directory delle specifiche, assegnandogli il nome string_analyzer_test.rb.

Nella finestra cmd.exe, accedi alla cartella C: \ rspec_tutorial ed esegui questo comando: dir spec

Dovresti vedere quanto segue:

Directory di C: \ rspec_tutorial \ spec

09/13/2015 08:22 AM  <DIR>    .
09/13/2015 08:22 AM  <DIR>    ..
09/12/2015 11:44 PM                 81 string_analyzer.rb
09/12/2015 11:46 PM              451 string_analyzer_test.rb

Ora eseguiremo i nostri test, eseguire questo comando: rspec spec

Quando passi il nome di una cartella a rspec, esegue tutti i file delle specifiche all'interno della cartella. Dovresti vedere questo risultato -

No examples found.

Finished in 0 seconds (files took 0.068 seconds to load)
0 examples, 0 failures

Il motivo per cui ciò è accaduto è che, per impostazione predefinita, rspecesegue solo file i cui nomi terminano con "_spec.rb". Rinomina string_analyzer_test.rb in string_analyzer_spec.rb. Puoi farlo facilmente eseguendo questo comando:

ren spec\string_analyzer_test.rb string_analyzer_spec.rb

Adesso corri rspec di nuovo spec, dovresti vedere un output simile a questo -

F.
Failures:

   1) StringAnalyzer With valid input should detect when a string contains vowels
      Failure/Error: expect(sa.has_vowels? test_string).to be true 
         expected true
            got false
      # ./spec/string_analyzer_spec.rb:9:in `block (3 levels) in <top (required)>'

Finished in 0.015 seconds (files took 0.12201 seconds to load)
2 examples, 1 failure

Failed examples:
rspec ./spec/string_analyzer_spec.rb:6 # StringAnalyzer With valid 
   input should detect when a string contains vowels
Do you see what just happened? Our spec failed because we have a bug in 
   StringAnalyzer. The bug is simple to fix, open up string_analyzer.rb
   in a text editor and change this line:
!!(str =~ /[aeio]+/i)
to this:
!!(str =~ /[aeiou]+/i)

Ora, salva le modifiche appena apportate in string_analyizer.rb ed esegui di nuovo il comando rspec spec, ora dovresti vedere l'output che assomiglia a -

..
Finished in 0.002 seconds (files took 0.11401 seconds to load)
2 examples, 0 failures

Congratulazioni, ora gli esempi (test) nel file delle specifiche vengono superati. Abbiamo corretto un bug nell'espressione regolare che ha il metodo delle vocali ma i nostri test sono lungi dall'essere completi.

Avrebbe senso aggiungere altri esempi che testino vari tipi di stringhe di input con il metodo has vowels.

La tabella seguente mostra alcune delle permutazioni che potrebbero essere aggiunte in nuovi esempi (blocca)

Stringa di input Descrizione Risultato previsto con has_vowels?
"aaa", "eee", "iii", "o" Solo una vocale e nessun'altra lettera. vero
"abcefg" 'Almeno una vocale e alcune consonanti' vero
"mnklp" Solo consonanti. falso
'' Stringa vuota (senza lettere) falso
"abcde55345 & ??" Vocali, consonanti, numeri e caratteri di punteggiatura. vero
"423432 %%% ^ &" Solo numeri e caratteri di punteggiatura. falso
"AEIOU" Solo vocali maiuscole. vero
"AeiOuuuA" Solo vocali maiuscole e minuscole. vero
"AbCdEfghI" Vocali e consonanti maiuscole e minuscole. vero
"BCDFG" Solo consonanti maiuscole. falso
'' Solo caratteri di spazio vuoto. falso

Sta a te decidere quali esempi aggiungere al file delle specifiche. Esistono molte condizioni da verificare, è necessario determinare quale sottoinsieme di condizioni è più importante e testare al meglio il codice.

Il rspec Il comando offre molte opzioni diverse, per vederle tutte, digita rspec-Aiuto. La tabella seguente elenca le opzioni più popolari e descrive cosa fanno.

Sr.No. Opzione / bandiera e descrizione
1

-I PATH

Aggiunge PATH al percorso di caricamento (richiesto) that rspec utilizza quando si cercano i file sorgenti di Ruby.

2

-r, --require PATH

Aggiunge un file di origine specifico da richiedere nelle specifiche. File).

3

--fail-fast

Con questa opzione, rspec interromperà l'esecuzione delle specifiche dopo che il primo esempio fallisce. Per impostazione predefinita, rspec esegue tutti i file spec specificati, indipendentemente dal numero di errori presenti.

4

-f, --format FORMATTER

Questa opzione consente di specificare diversi formati di output. Vedere la sezione sui formattatori per maggiori dettagli sui formati di output.

5

-o, --out FILE

Questa opzione indica a rspec di scrivere i risultati del test nel file di output FILE invece che nell'output standard.

6

-c, --color

Abilita il colore nell'output di rspec. I risultati di esempio riusciti verranno visualizzati in testo verde, gli errori verranno stampati in testo rosso.

7

-b, --backtrace

Visualizza tutti i backtrace degli errori nell'output di rspec.

8

-w, --warnings

Visualizza gli avvisi di Ruby nell'output di rspec.

9

-P, --pattern PATTERN

Carica ed esegui i file delle specifiche che corrispondono al pattern PATTERN. Ad esempio, se passi -p "* .rb", rspec eseguirà tutti i file Ruby, non solo quelli che terminano con "_spec.rb".

10

-e, --example STRING

Questa opzione indica a rspec di eseguire tutti gli esempi che contengono il testo STRING nelle loro descrizioni.

11

-t, --tag TAG

Con questa opzione, rspec eseguirà solo esempi che contengono il tag TAG. Nota che TAG è specificato come un simbolo Ruby. Vedere la sezione sui tag RSpec per maggiori dettagli.

Se ricordi il nostro esempio originale Hello World, conteneva una riga simile a questa:

expect(message).to eq "Hello World!"

La parola chiave eql è un file RSpec"Matcher". Qui introdurremo gli altri tipi di matcher in RSpec.

Corrispondenze di uguaglianza / identità

Matcher per testare l'uguaglianza di oggetti o valori.

Matcher Descrizione Esempio
eq Passa quando effettivo == previsto aspettarsi (effettivo) .to eq atteso
eql Passa quando actual.eql? (Previsto) aspettarsi (effettivo) .to eql previsto
essere Passa quando effettivo.uguale? (Previsto) aspettarsi (effettivo)
pari Passa anche quando effettivo.uguale? (Previsto) aspettarsi (effettivo) .per eguagliare il previsto

Esempio

describe "An example of the equality Matchers" do 

   it "should show how the equality Matchers work" do 
      a = "test string" 
      b = a 
      
      # The following Expectations will all pass 
      expect(a).to eq "test string" 
      expect(a).to eql "test string" 
      expect(a).to be b 
      expect(a).to equal b 
   end
   
end

Quando il codice precedente viene eseguito, produrrà il seguente output. Il numero di secondi potrebbe essere leggermente diverso sul tuo computer -

.
Finished in 0.036 seconds (files took 0.11901 seconds to load)
1 example, 0 failures

Matcher di confronto

Matcher per il confronto con i valori.

Matcher Descrizione Esempio
> Passa quando effettivo> previsto aspettarsi (effettivo) .per essere> previsto
> = Passa quando effettivo> = previsto aspettarsi che (effettivo) sia> = previsto
< Passa quando effettivo <previsto aspettarsi che (effettivo) sia <previsto
<= Passa quando effettivo <= previsto aspettarsi che (effettivo) sia <= previsto
essere_tra compreso Passa quando effettivo è <= min e> = max aspettarsi che (effettivo) sia_between (min, max) .inclusive
be_between esclusivo Passa quando il valore effettivo è <min e> max aspettarsi che (effettivo) sia_between (min, max) .exclusive
incontro Passa quando actual corrisponde a un'espressione regolare aspettati che (effettivo) corrisponda (/ regex /)

Esempio

describe "An example of the comparison Matchers" do

   it "should show how the comparison Matchers work" do
      a = 1
      b = 2
      c = 3		
      d = 'test string'
      
      # The following Expectations will all pass
      expect(b).to be > a
      expect(a).to be >= a 
      expect(a).to be < b 
      expect(b).to be <= b 
      expect(c).to be_between(1,3).inclusive 
      expect(b).to be_between(1,3).exclusive 
      expect(d).to match /TEST/i 
   end
   
end

Quando il codice precedente viene eseguito, produrrà il seguente output. Il numero di secondi potrebbe essere leggermente diverso sul tuo computer -

. 
Finished in 0.013 seconds (files took 0.11801 seconds to load) 
1 example, 0 failures

Corrisponditori di classe / tipo

Matcher per testare il tipo o la classe degli oggetti.

Matcher Descrizione Esempio
be_instance_of Passa quando actual è un'istanza della classe prevista. aspettarsi (effettivo) .essere_istanza_di (atteso)
be_kind_of Passa quando actual è un'istanza della classe prevista o di una delle sue classi padre. aspettarsi (effettivo) .essere_kind_of (previsto)
rispondere a Passa quando effettivo risponde al metodo specificato. aspettarsi (effettivo) .per rispondere_to (atteso)

Esempio

describe "An example of the type/class Matchers" do
 
   it "should show how the type/class Matchers work" do
      x = 1 
      y = 3.14 
      z = 'test string' 
      
      # The following Expectations will all pass
      expect(x).to be_instance_of Fixnum 
      expect(y).to be_kind_of Numeric 
      expect(z).to respond_to(:length) 
   end
   
end

Quando il codice precedente viene eseguito, produrrà il seguente output. Il numero di secondi potrebbe essere leggermente diverso sul tuo computer -

. 
Finished in 0.002 seconds (files took 0.12201 seconds to load) 
1 example, 0 failures

Corrispondenze vero / falso / zero

Matcher per verificare se un valore è vero, falso o nullo.

Matcher Descrizione Esempio
essere vero Passa quando effettivo == vero aspettarsi che (effettivo) sia vero
essere falso Passa quando effettivo == falso aspettarsi che (effettivo). sia falso
be_truthy Passa quando il valore effettivo non è falso o nullo aspettarsi (effettivo) .essere_truthy
be_falsey Passa quando il valore effettivo è falso o nullo aspettarsi (effettivo) .to be_falsey
be_nil Passa quando l'attuale è nullo aspettarsi (effettivo) .to be_nil

Esempio

describe "An example of the true/false/nil Matchers" do
   it "should show how the true/false/nil Matchers work" do
      x = true 
      y = false 
      z = nil 
      a = "test string" 
      
      # The following Expectations will all pass
      expect(x).to be true 
      expect(y).to be false 
      expect(a).to be_truthy 
      expect(z).to be_falsey 
      expect(z).to be_nil 
   end 
end

Quando il codice precedente viene eseguito, produrrà il seguente output. Il numero di secondi potrebbe essere leggermente diverso sul tuo computer -

. 
Finished in 0.003 seconds (files took 0.12301 seconds to load) 
1 example, 0 failures

Corrispondenze di errore

Matcher per il test, quando un blocco di codice genera un errore.

Matcher Descrizione Esempio
raise_error (ErrorClass) Passa quando il blocco genera un errore di tipo ErrorClass. aspettati {block} .to raise_error (ErrorClass)
raise_error ("messaggio di errore") Passa quando il blocco genera un errore con il messaggio "messaggio di errore". aspettati {block} .to raise_error ("messaggio di errore")
raise_error (ErrorClass, "messaggio di errore") Passa quando il blocco genera un errore di tipo ErrorClass con il messaggio "messaggio di errore" aspettati {block} .to raise_error (ErrorClass, "messaggio di errore")

Esempio

Salva il codice seguente in un file con il nome error_matcher_spec.rb ed eseguilo con questo comando - rspec error_matcher_spec.rb.

describe "An example of the error Matchers" do 
   it "should show how the error Matchers work" do 
      
      # The following Expectations will all pass 
      expect { 1/0 }.to raise_error(ZeroDivisionError)
      expect { 1/0 }.to raise_error("divided by 0") 
      expect { 1/0 }.to raise_error("divided by 0", ZeroDivisionError) 
   end 
end

Quando il codice precedente viene eseguito, produrrà il seguente output. Il numero di secondi potrebbe essere leggermente diverso sul tuo computer -

. 
Finished in 0.002 seconds (files took 0.12101 seconds to load) 
1 example, 0 failures

In questo capitolo, discuteremo RSpec Double, noto anche come RSpec Mocks. Un Double è un oggetto che può "sostituire" un altro oggetto. Probabilmente ti starai chiedendo cosa significhi esattamente e perché ne avresti bisogno.

Supponiamo che tu stia creando un'applicazione per una scuola e che tu abbia una classe che rappresenta un'aula di studenti e un'altra classe per gli studenti, ovvero una classe in Aula e una classe Studente. Devi prima scrivere il codice per una delle classi, quindi diciamo che, inizia con la classe Classroom -

class ClassRoom 
   def initialize(students) 
      @students = students 
   end 
   
   def list_student_names 
      @students.map(&:name).join(',') 
   end 
end

Questa è una classe semplice, ha un metodo list_student_names, che restituisce una stringa delimitata da virgole di nomi di studenti. Ora, vogliamo creare test per questa classe, ma come possiamo farlo se non abbiamo ancora creato la classe Studente? Abbiamo bisogno di un doppio di prova.

Inoltre, se abbiamo una classe "fittizia" che si comporta come un oggetto Student, i nostri test ClassRoom non dipenderanno dalla classe Student. Chiamiamo questo isolamento di prova.

Se i nostri test ClassRoom non si basano su altre classi, allora quando un test fallisce, possiamo sapere immediatamente che c'è un bug nella nostra classe ClassRoom e non in qualche altra classe. Tieni presente che, nel mondo reale, potresti creare un corso che deve interagire con un altro corso scritto da qualcun altro.

È qui che RSpec Double (mock) diventa utile. Il nostro metodo list_student_names chiama il metodo name su ogni oggetto Student nella sua variabile membro @students. Pertanto, abbiamo bisogno di un Double che implementa un metodo di nome.

Ecco il codice per ClassRoom insieme a un esempio RSpec (test), ma si noti che non è stata definita alcuna classe 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

Quando il codice precedente viene eseguito, produrrà il seguente output. Il tempo trascorso potrebbe essere leggermente diverso sul tuo computer -

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

Come puoi vedere, utilizzando un file test doubleti permette di testare il tuo codice anche quando si basa su una classe che non è definita o non disponibile. Inoltre, questo significa che quando si verifica un fallimento del test, puoi subito dire che è a causa di un problema nella tua classe e non di una classe scritta da qualcun altro.

Se hai già letto la sezione su RSpec Double (aka Mocks), allora hai già visto RSpec Stubs. In RSpec, uno stub è spesso chiamato Method Stub, è un tipo speciale di metodo che "sostituisce" un metodo esistente o un metodo che non esiste ancora.

Ecco il codice dalla sezione su RSpec Doubles -

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

Nel nostro esempio, il metodo allow () fornisce gli stub del metodo di cui abbiamo bisogno per testare la classe ClassRoom. In questo caso, abbiamo bisogno di un oggetto che agisca proprio come un'istanza della classe Student, ma quella classe non esiste (ancora). Sappiamo che la classe Student deve fornire un metodo name () e usiamo allow () per creare uno stub del metodo per name ().

Una cosa da notare è che la sintassi di RSpec è cambiata leggermente nel corso degli anni. Nelle versioni precedenti di RSpec, gli stub del metodo sopra sarebbero stati definiti in questo modo:

student1.stub(:name).and_return('John Smith') 
student2.stub(:name).and_return('Jill Smith')

Prendiamo il codice sopra e sostituiamo i due allow() righe con la vecchia sintassi RSpec -

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')
      
      student1.stub(:name).and_return('John Smith')
      student2.stub(:name).and_return('Jill Smith') 
      
      cr = ClassRoom.new [student1,student2] 
      expect(cr.list_student_names).to eq('John Smith,Jill Smith') 
   end 
end

Vedrai questo output quando esegui il codice sopra -

.
Deprecation Warnings:

Using `stub` from rspec-mocks' old `:should` syntax without explicitly 
   enabling the syntax is deprec 

ated. Use the new `:expect` syntax or explicitly enable `:should` instead. 
   Called from C:/rspec_tuto 

rial/spec/double_spec.rb:15:in `block (2 levels) in <top (required)>'.
If you need more of the backtrace for any of these deprecations 
   to identify where to make the necessary changes, you can configure 

`config.raise_errors_for_deprecations!`, and it will turn the 
   deprecation warnings into errors, giving you the full backtrace.

1 deprecation warning total

Finished in 0.002 seconds (files took 0.11401 seconds to load)
1 example, 0 failures

Si consiglia di utilizzare la nuova sintassi allow () quando è necessario creare stub di metodo negli esempi di RSpec, ma qui abbiamo fornito lo stile precedente in modo che lo riconoscerai se lo vedi.

Quando si scrivono unit test, è spesso conveniente eseguire il codice di installazione e smontaggio prima e dopo i test. Il codice di installazione è il codice che configura o "imposta" le condizioni per un test. Il codice di smontaggio esegue la pulizia, si assicura che l'ambiente sia in uno stato coerente per i test successivi.

In generale, i tuoi test dovrebbero essere indipendenti l'uno dall'altro. Quando esegui un'intera suite di test e uno di essi fallisce, vuoi avere la certezza che non sia riuscito perché il codice che sta testando ha un bug, non perché il test precedente ha lasciato l'ambiente in uno stato incoerente.

Gli hook più comuni utilizzati in RSpec sono prima e dopo gli hook. Forniscono un modo per definire ed eseguire il codice di installazione e smontaggio di cui abbiamo discusso in precedenza. Consideriamo questo codice di esempio:

class SimpleClass 
   attr_accessor :message 
   
   def initialize() 
      puts "\nCreating a new instance of the SimpleClass class" 
      @message = 'howdy' 
   end 
   
   def update_message(new_message) 
      @message = new_message 
   end 
end 

describe SimpleClass do 
   before(:each) do 
      @simple_class = SimpleClass.new 
   end 
   
   it 'should have an initial message' do 
      expect(@simple_class).to_not be_nil
      @simple_class.message = 'Something else. . .' 
   end 
   
   it 'should be able to change its message' do
      @simple_class.update_message('a new message')
      expect(@simple_class.message).to_not be 'howdy' 
   end
end

Quando esegui questo codice, otterrai il seguente output:

Creating a new instance of the SimpleClass class 
. 
Creating a new instance of the SimpleClass class 
. 
Finished in 0.003 seconds (files took 0.11401 seconds to load) 
2 examples, 0 failures

Diamo uno sguardo più da vicino a cosa sta succedendo. Il metodo before (: each) è dove definiamo il codice di configurazione. Quando passi l'argomento: each, stai istruendo il metodo before da eseguire prima di ogni esempio nel tuo gruppo di esempi, cioè i due blocchi all'interno del blocco di descrizione nel codice sopra.

Nella riga: @simple_class = SimpleClass.new, stiamo creando una nuova istanza della classe SimpleClass e assegnandola a una variabile di istanza di un oggetto. Quale oggetto ti starai chiedendo? RSpec crea una classe speciale dietro le quinte nell'ambito del blocco di descrizione. Ciò consente di assegnare valori alle variabili di istanza di questa classe, a cui è possibile accedere all'interno dei blocchi it negli Esempi. Questo semplifica anche la scrittura di codice più pulito nei nostri test. Se ogni test (Esempio) necessita di un'istanza di SimpleClass, possiamo mettere quel codice nell'hook precedente e non doverlo aggiungere a ogni esempio.

Si noti che, la riga "Creazione di una nuova istanza della classe SimpleClass" viene scritta due volte sulla console, questo mostra che, prima che hook fosse chiamato in ciascuna delle it blocks.

Come abbiamo accennato, RSpec ha anche un hook after e entrambi gli hook prima e dopo possono prendere: all come argomento. L'hook after verrà eseguito dopo il target specificato. Il target: all significa che l'hook verrà eseguito prima / dopo tutti gli esempi. Ecco un semplice esempio che illustra quando viene chiamato ogni hook.

describe "Before and after hooks" do 
   before(:each) do 
      puts "Runs before each Example" 
   end 
   
   after(:each) do 
      puts "Runs after each Example" 
   end 
   
   before(:all) do 
      puts "Runs before all Examples" 
   end 
   
   after(:all) do 
      puts "Runs after all Examples"
   end 
   
   it 'is the first Example in this spec file' do 
      puts 'Running the first Example' 
   end 
   
   it 'is the second Example in this spec file' do 
      puts 'Running the second Example' 
   end 
end

Quando esegui il codice sopra, vedrai questo output:

Runs before all Examples 
Runs before each Example 
Running the first Example 
Runs after each Example 
.Runs before each Example 
Running the second Example 
Runs after each Example 
.Runs after all Examples

I tag RSpec forniscono un modo semplice per eseguire test specifici nei file delle specifiche. Per impostazione predefinita, RSpec eseguirà tutti i test nei file spec che esegue, ma potrebbe essere necessario eseguire solo un sottoinsieme di essi. Supponiamo che tu abbia alcuni test che vengono eseguiti molto rapidamente e che hai appena apportato una modifica al codice dell'applicazione e desideri eseguire solo i test rapidi, questo codice mostrerà come farlo con i tag RSpec.

describe "How to run specific Examples with Tags" do 
   it 'is a slow test', :slow = > true do 
      sleep 10 
      puts 'This test is slow!' 
   end 
   
   it 'is a fast test', :fast = > true do 
      puts 'This test is fast!' 
   end 
end

Ora salva il codice sopra in un nuovo file chiamato tag_spec.rb. Dalla riga di comando, esegui questo comando: rspec --tag slow tag_spec.rb

Vedrai questo output -

Opzioni di esecuzione: include {: slow => true}

This test is slow! 
. 
Finished in 10 seconds (files took 0.11601 seconds to load) 
1 example, 0 failures

Quindi, esegui questo comando: rspec --tag fast tag_spec.rb

Vedrai questo output -

Run options: include {:fast = >true} 
This test is fast! 
. 
Finished in 0.001 seconds (files took 0.11201 seconds to load) 
1 example, 0 failures

Come puoi vedere, RSpec Tags rende molto facile un sottoinsieme di test!

Uno dei punti di forza di RSpec è che fornisce molti modi per scrivere test, test puliti. Quando i tuoi test sono brevi e ordinati, diventa più facile concentrarsi sul comportamento previsto e non sui dettagli di come sono scritti i test. Gli argomenti RSpec sono un'altra scorciatoia che ti consente di scrivere test semplici e diretti.

Considera questo codice:

class Person 
   attr_reader :first_name, :last_name 
   
   def initialize(first_name, last_name) 
      @first_name = first_name 
      @last_name = last_name 
   end 
end 

describe Person do 
   it 'create a new person with a first and last name' do
      person = Person.new 'John', 'Smith'
      
      expect(person).to have_attributes(first_name: 'John') 
      expect(person).to have_attributes(last_name: 'Smith') 
   end 
end

In realtà è abbastanza chiaro così com'è, ma potremmo usare la funzionalità oggetto di RSpec per ridurre la quantità di codice nell'esempio. Lo facciamo spostando l'istanza dell'oggetto persona nella riga di descrizione.

class Person 
   attr_reader :first_name, :last_name 
   
   def initialize(first_name, last_name) 
      @first_name = first_name 
      @last_name = last_name 
   end 
	
end 

describe Person.new 'John', 'Smith' do 
   it { is_expected.to have_attributes(first_name: 'John') } 
   it { is_expected.to have_attributes(last_name: 'Smith') }
end

Quando esegui questo codice, vedrai questo output:

.. 
Finished in 0.003 seconds (files took 0.11201 seconds to load) 
2 examples, 0 failures

Nota quanto è più semplice il secondo esempio di codice. Abbiamo preso quelloit block nel primo esempio e lo ha sostituito con due it blocks che finiscono per richiedere meno codice e sono altrettanto chiari.

A volte i tuoi esempi RSpec necessitano di un modo semplice per condividere codice riutilizzabile. Il modo migliore per farlo è con gli helper. Gli helper sono fondamentalmente normali metodi Ruby che condividi attraverso esempi. Per illustrare il vantaggio dell'utilizzo di helper, consideriamo questo codice:

class Dog 
   attr_reader :good_dog, :has_been_walked 
   
   def initialize(good_or_not) 
      @good_dog = good_or_not 
      @has_been_walked = false 
   end 
   
   def walk_dog 
      @has_been_walked = true 
   end 
end 

describe Dog do 
   it 'should be able to create and walk a good dog' do 
      dog = Dog.new(true) 
      dog.walk_dog 
      
      expect(dog.good_dog).to be true
      expect(dog.has_been_walked).to be true 
   end 
   
   it 'should be able to create and walk a bad dog' do 
      dog = Dog.new(false) 
      dog.walk_dog 

      expect(dog.good_dog).to be false
      expect(dog.has_been_walked).to be true 
 
   end 
end

Questo codice è chiaro, ma è sempre una buona idea ridurre il codice ripetuto quando possibile. Possiamo prendere il codice sopra e ridurre alcune di queste ripetizioni con un metodo di supporto chiamato create_and_walk_dog ().

class Dog
   attr_reader :good_dog, :has_been_walked 
   
   def initialize(good_or_not)
      @good_dog = good_or_not 
      @has_been_walked = false 
   end 
   
   def walk_dog 
      @has_been_walked = true 
   end 
end 

describe Dog do 
   def create_and_walk_dog(good_or_bad)
      dog = Dog.new(good_or_bad)
      dog.walk_dog
      return dog 
   end 
   
   it 'should be able to create and walk a good dog' do
      dog = create_and_walk_dog(true)
      
      expect(dog.good_dog).to be true
      expect(dog.has_been_walked).to be true 
   end 
   
   it 'should be able to create and walk a bad dog' do 
      dog = create_and_walk_dog(false)
      
      expect(dog.good_dog).to be false
      expect(dog.has_been_walked).to be true 
   end 
end

Quando esegui il codice sopra, vedrai questo output:

.. 
Finished in 0.002 seconds (files took 0.11401 seconds to load) 
2 examples, 0 failures

Come puoi vedere, siamo stati in grado di inserire la logica per creare e portare a spasso un oggetto per cani in un aiutante che consente ai nostri esempi di essere più brevi e puliti.

RSpec è uno strumento flessibile e potente. La funzionalità dei metadati in RSpec non fa eccezione. I metadati si riferiscono generalmente a "dati sui dati". In RSpec, questo significa che i dati sul tuodescribe, context e it blocks.

Diamo un'occhiata a un esempio:

RSpec.describe "An Example Group with a metadata variable", :foo => 17 do 
   context 'and a context with another variable', :bar => 12 do 
      
      it 'can access the metadata variable of the outer Example Group' do |example| 
         expect(example.metadata[:foo]).to eq(17) 
      end
      
      it 'can access the metadata variable in the context block' do |example|  
         expect(example.metadata[:bar]).to eq(12) 
      end 
      
   end 
end

Quando esegui il codice sopra, vedrai questo output:

.. 
Finished in 0.002 seconds (files took 0.11301 seconds to load) 
2 examples, 0 failures

I metadati forniscono un modo per assegnare variabili in vari ambiti all'interno dei file RSpec. La variabile example.metadata è un hash Ruby che contiene altre informazioni sui tuoi gruppi di esempi e di esempi.

Ad esempio, riscriviamo il codice sopra in questo modo:

RSpec.describe "An Example Group with a metadata variable", :foo => 17 do
   context 'and a context with another variable', :bar => 12 do 
      
      it 'can access the metadata variable in the context block' do |example|
         expect(example.metadata[:foo]).to eq(17) 
         expect(example.metadata[:bar]).to eq(12) 
         example.metadata.each do |k,v|
         puts "#{k}: #{v}"
      end
		
   end 
end

Quando eseguiamo questo codice, vediamo tutti i valori nell'hash example.metadata -

.execution_result: #<RSpec::Core::Example::ExecutionResult:0x00000002befd50>
block: #<Proc:0x00000002bf81a8@C:/rspec_tutorial/spec/metadata_spec.rb:7>
description_args: ["can access the metadata variable in the context block"]
description: can access the metadata variable in the context block
full_description: An Example Group with a metadata variable and a context 
   with another variable can access the metadata variable in the context block
described_class:
file_path: ./metadata_spec.rb
line_number: 7
location: ./metadata_spec.rb:7
absolute_file_path: C:/rspec_tutorial/spec/metadata_spec.rb
rerun_file_path: ./metadata_spec.rb
scoped_id: 1:1:2
foo: 17
bar: 12
example_group:
{:execution_result=>#<RSpec::Core::Example::ExecutionResult:
   0x00000002bfa0e8>, :block=>#<
   Proc:0x00000002bfac00@C:/rspec_tutorial/spec/metadata_spec.rb:2>, 
   :description_args=>["and a context with another variable"], 
	
   :description=>"and a context with another variable", 
   :full_description=>"An Example Group with a metadata variable
   and a context with another variable", :described_class=>nil, 
      :file_path=>"./metadata_spec.rb", 
		
   :line_number=>2, :location=>"./metadata_spec.rb:2", 
      :absolute_file_path=>"C:/rspec_tutorial/spec/metadata_spec.rb",
      :rerun_file_path=>"./metadata_spec.rb", 
		
   :scoped_id=>"1:1", :foo=>17, :parent_example_group=>
      {:execution_result=>#<
      RSpec::Core::Example::ExecutionResult:0x00000002c1f690>, 
      :block=>#<Proc:0x00000002baff70@C:/rspec_tutorial/spec/metadata_spec.rb:1>
      , :description_args=>["An Example Group with a metadata variable"], 
		
   :description=>"An Example Group with a metadata variable", 
   :full_description=>"An Example Group with a metadata variable", 
	:described_class=>nil, :file_path=>"./metadata_spec.rb", 
   :line_number=>1, :location=>"./metadata_spec.rb:1",
   :absolute_file_path=>
	
   "C:/rspec_tutorial/spec/metadata_spec.rb", 
   :rerun_file_path=>"./metadata_spec.rb", 
   :scoped_id=>"1", :foo=>17}, 
   :bar=>12}shared_group_inclusion_backtrace: [] 
	
last_run_status: unknown .
.
Finished in 0.004 seconds (files took 0.11101 seconds to load) 
2 examples, 0 failures

Molto probabilmente, non sarà necessario utilizzare tutti questi metadati, ma guarda il valore della descrizione completa:

Un gruppo di esempio con una variabile di metadati e un contesto con un'altra variabile possono accedere alla variabile di metadati nel blocco di contesto.

Questa è una frase creata dalla descrizione del blocco di descrizione + la descrizione del blocco di contesto contenuto + la descrizione per il it block.

Ciò che è interessante notare qui è che queste tre stringhe insieme si leggono come una normale frase inglese. . . che è una delle idee alla base di RSpec, con test che suonano come descrizioni del comportamento in inglese.

Si consiglia di leggere la sezione sui metadati RSpec prima di leggere questa sezione perché, a quanto pare, il filtro RSpec si basa sui metadati RSpec.

Immagina di avere un file spec e che contenga due tipi di test (esempi): test funzionali positivi e test negativi (errore). Definiamoli in questo modo -

RSpec.describe "An Example Group with positive and negative Examples" do 
   context 'when testing Ruby\'s build-in math library' do
      
      it 'can do normal numeric operations' do 
         expect(1 + 1).to eq(2) 
      end 
      
      it 'generates an error when expected' do
         expect{1/0}.to raise_error(ZeroDivisionError) 
      end
      
   end 
end

Ora salva il testo sopra come file chiamato 'filter_spec.rb' e poi eseguilo con questo comando -

rspec filter_spec.rb

Vedrai un output simile a questo -

.. 
Finished in 0.003 seconds (files took 0.11201 seconds to load) 
2 examples, 0 failures

E se volessimo rieseguire solo i test positivi in ​​questo file? O solo i test negativi? Possiamo farlo facilmente con RSpec Filters. Cambia il codice sopra in questo -

RSpec.describe "An Example Group with positive and negative Examples" do 
   context 'when testing Ruby\'s build-in math library' do
      
      it 'can do normal numeric operations', positive: true do 
         expect(1 + 1).to eq(2) 
      end 
      
      it 'generates an error when expected', negative: true do 
         expect{1/0}.to raise_error(ZeroDivisionError) 
      end
      
   end 
end

Salva le modifiche in filter_spec.rb ed esegui questo comando leggermente diverso -

rspec --tag positive filter_spec.rb

Ora vedrai un output simile a questo:

Run options: include {:positive=>true} 
. 
Finished in 0.001 seconds (files took 0.11401 seconds to load) 
1 example, 0 failures

Specificando --tag positive, stiamo dicendo a RSpec di eseguire solo esempi con la variabile di metadati: positive definita. Potremmo fare la stessa cosa con i test negativi eseguendo il comando in questo modo:

rspec --tag negative filter_spec.rb

Tieni presente che questi sono solo esempi, puoi specificare un filtro con qualsiasi nome desideri.

Formattatori RSpec

I formattatori consentono a RSpec di visualizzare l'output dei test in modi diversi. Creiamo un nuovo file RSpec contenente questo codice -

RSpec.describe "A spec file to demonstrate how RSpec Formatters work" do 
   context 'when running some tests' do 
      
      it 'the test usually calls the expect() method at least once' do 
         expect(1 + 1).to eq(2) 
      end
      
   end 
end

Ora salvalo in un file chiamato formatter_spec.rb ed esegui questo comando RSpec -

rspec formatter_spec.rb

Dovresti vedere un output simile a questo -

. 
Finished in 0.002 seconds (files took 0.11401 seconds to load) 
1 example, 0 failures

Ora esegui lo stesso comando ma questa volta specifica un formattatore, come questo -

rspec --format progress formatter_spec.rb

Questa volta dovresti vedere lo stesso output -

. 
Finished in 0.002 seconds (files took 0.11401 seconds to load) 
1 example, 0 failures

Il motivo è che il formattatore "progress" è il formattatore predefinito. Proviamo un altro formattatore successivo, prova a eseguire questo comando -

rspec --format doc formatter_spec.rb

Ora dovresti vedere questo output -

A spec file to demonstrate how RSpec Formatters work 
   when running some tests 
      the test usually calls the expect() method at least once
Finished in 0.002 seconds (files took 0.11401 seconds to load) 
1 example, 0 failures

Come puoi vedere, l'output è abbastanza diverso con il formattatore "doc". Questo formattatore presenta l'output in uno stile simile alla documentazione. Forse ti starai chiedendo come appaiono queste opzioni quando si verifica un errore in un test (Esempio). Cambiamo il codice informatter_spec.rb per assomigliare a questo -

RSpec.describe "A spec file to demonstrate how RSpec Formatters work" do 
   context 'when running some tests' do 
      
      it 'the test usually calls the expect() method at least once' do 
         expect(1 + 1).to eq(1) 
      end
      
   end 
end

L'aspettativa expect(1 + 1).to eq(1)dovrebbe fallire. Salva le modifiche e riesegui i comandi precedenti -

rspec --format progress formatter_spec.rb e ricorda, poiché il formattatore "progress" è quello predefinito, potresti semplicemente eseguire: rspec formatter_spec.rb. Dovresti vedere questo output -

F 
Failures:
1) A spec file to demonstrate how RSpec Formatters work when running some tests 
the test usually calls the expect() method at least once
   Failure/Error: expect(1 + 1).to eq(1)
	
      expected: 1
         got: 2
			  
      (compared using ==)			  
   # ./formatter_spec.rb:4:in `block (3 levels) in <top (required)>'

Finished in 0.016 seconds (files took 0.11201 seconds to load)
1 example, 1 failure
Failed examples:

rspec ./formatter_spec.rb:3 # A spec file to demonstrate how RSpec 
   Formatters work when running some tests the test usually calls 
   the expect() method at least once

Ora, proviamo il formattatore di documenti, esegui questo comando -

rspec --format doc formatter_spec.rb

Ora, con il test fallito, dovresti vedere questo output:

A spec file to demonstrate how RSpec Formatters work
   when running some tests
      the test usually calls the expect() method at least once (FAILED - 1)
		
Failures:

1) A spec file to demonstrate how RSpec Formatters work when running some
   tests the test usually calls the expect() method at least once
   Failure/Error: expect(1 + 1).to eq(1)
	
   expected: 1
        got: 2
		  
   (compared using ==)
   # ./formatter_spec.rb:4:in `block (3 levels) in <top (required)>'
	
Finished in 0.015 seconds (files took 0.11401 seconds to load) 
1 example, 1 failure

Esempi falliti

rspec ./formatter_spec.rb:3 # Un file spec per dimostrare come funzionano RSpec Formatters durante l'esecuzione di alcuni test, il test di solito chiama il metodo wait () almeno una volta.

RSpec Formatters offre la possibilità di modificare il modo in cui vengono visualizzati i risultati dei test, è anche possibile creare il proprio formattatore personalizzato, ma questo è un argomento più avanzato.

Quando impari RSpec, potresti leggere molto sulle aspettative e all'inizio può creare un po 'di confusione. Ci sono due dettagli principali che dovresti tenere a mente quando vedi il termine Aspettativa:

  • Un'aspettativa è semplicemente una dichiarazione in un file it block che utilizza l'estensione expect()metodo. Questo è tutto. Non è più complicato di così. Quando hai un codice come questo:expect(1 + 1).to eq(2), hai un'aspettativa nel tuo esempio. Ti aspetti che l'espressione1 + 1 valuta a 2. La formulazione è tuttavia importante poiché RSpec è un framework di test BDD. Chiamando questa dichiarazione un'aspettativa, è chiaro che il codice RSpec descrive il "comportamento" del codice che sta testando. L'idea è che tu esprima come dovrebbe comportarsi il codice, in un modo che si legge come la documentazione.

  • La sintassi delle aspettative è relativamente nuova. Prima diexpect() è stato introdotto (nel 2012), RSpec ha utilizzato una sintassi diversa basata su should()metodo. L'aspettativa di cui sopra è scritta in questo modo nella vecchia sintassi:(1 + 1).should eq(2).

È possibile incontrare la vecchia sintassi RSpec per le aspettative quando si lavora con un codice precedente o una versione precedente di RSpec. Se utilizzi la vecchia sintassi con una nuova versione di RSpec, vedrai un avviso.

Ad esempio, con questo codice -

RSpec.describe "An RSpec file that uses the old syntax" do
   it 'you should see a warning when you run this Example' do 
      (1 + 1).should eq(2) 
   end 
end

Quando lo esegui, otterrai un output simile a questo -

. Deprecation Warnings:

Using `should` from rspec-expectations' old `:should` 
   syntax without explicitly enabling the syntax is deprecated. 
   Use the new `:expect` syntax or explicitly enable 
	
`:should` with `config.expect_with( :rspec) { |c| c.syntax = :should }`
   instead. Called from C:/rspec_tutorial/spec/old_expectation.rb:3 :in 
   `block (2 levels) in <top (required)>'.

If you need more of the backtrace for any of these deprecations to
   identify where to make the necessary changes, you can configure 
`config.raise_errors_for_deprecations!`, and it will turn the deprecation 
   warnings into errors, giving you the full backtrace.

1 deprecation warning total 
Finished in 0.001 seconds (files took 0.11201 seconds to load) 
1 example, 0 failures

A meno che non sia necessario utilizzare la vecchia sintassi, si consiglia vivamente di utilizzare wait () invece di should ().