RSpec - Szybki przewodnik
RSpec to platforma testów jednostkowych dla języka programowania Ruby. RSpec różni się od tradycyjnych frameworków xUnit, takich jak JUnit, ponieważ RSpec jest narzędziem programistycznym opartym na zachowaniu. Oznacza to, że testy napisane w RSpec koncentrują się na „zachowaniu” testowanej aplikacji. RSpec nie kładzie nacisku na to, jak aplikacja działa, ale na to, jak się zachowuje, innymi słowy, co aplikacja faktycznie robi.
Środowisko RSpec
Przede wszystkim musisz zainstalować Rubiego na swoim komputerze. Jeśli jednak nie zrobiłeś tego wcześniej, możesz pobrać i zainstalować Rubiego z głównej witryny Rubiego - Ruby .
Jeśli instalujesz Ruby w systemie Windows, powinieneś mieć tutaj instalator Ruby dla Windows - http://www.rubyinstaller.org
W tym samouczku będziesz potrzebować tylko edytora tekstu, takiego jak Notatnik i konsola wiersza poleceń. W poniższych przykładach będzie używany program cmd.exe w systemie Windows.
Aby uruchomić cmd.exe, po prostu kliknij menu Start i wpisz „cmd.exe”, a następnie naciśnij klawisz Return.
W wierszu poleceń w oknie cmd.exe wpisz następujące polecenie, aby zobaczyć, jakiej wersji Ruby używasz -
ruby -v
Powinieneś zobaczyć poniższe wyjście, które wygląda podobnie do tego -
ruby 2.2.3p173 (2015-08-18 revision 51636) [x64-mingw32]
W przykładach w tym samouczku będzie używany Ruby 2.2.3, ale wystarczy dowolna wersja Rubiego wyższa niż 2.0.0. Następnie musimy zainstalować klejnot RSpec dla twojej instalacji Ruby. Klejnot to biblioteka Ruby, której możesz użyć we własnym kodzie. Aby zainstalować klejnot, musisz użyć rozszerzeniagem Komenda.
Zainstalujmy teraz klejnot Rspec. Wróć do okna cmd.exe i wpisz:
gem install rspec
Powinieneś mieć listę zależnych klejnotów, które zostały zainstalowane, są to klejnoty, które klejnot rspec musi działać poprawnie. Na końcu wyjścia powinieneś zobaczyć coś, co wygląda tak -
Done installing documentation for diff-lcs, rspec-support, rspec-mocks,
rspec-expectations, rspec-core, rspec after 22 seconds
6 gems installed
Nie martw się, jeśli wynik nie wygląda dokładnie tak samo. Ponadto, jeśli używasz komputera Mac lub Linux, może być konieczne uruchomieniegem install rspec polecenie za pomocą sudo lub użyj narzędzia takiego jak HomeBrew lub RVM, aby zainstalować gem rspec.
Hello World
Aby rozpocząć, stwórzmy katalog (folder) do przechowywania naszych plików RSpec. W oknie cmd.exe wpisz:
cd \
Następnie wpisz -
mkdir rspec_tutorial
I na koniec wpisz -
cd rspec_tutorial
Stąd utworzymy kolejny katalog o nazwie spec, zrób to, wpisując -
mkdir spec
W tym folderze będziemy przechowywać nasze pliki RSpec. Pliki RSpec są nazywane „specyfikacjami”. Jeśli wydaje ci się to mylące, możesz myśleć o pliku specyfikacji jako pliku testowym. RSpec używa terminu „specyfikacja”, który jest skrótem od „specyfikacji”.
Ponieważ RSpec jest narzędziem testowym BDD, celem jest skupienie się na tym, co robi aplikacja i czy jest zgodna ze specyfikacją. W rozwoju opartym na zachowaniu specyfikacja jest często opisywana jako „historia użytkownika”. RSpec ma na celu wyjaśnienie, czy kod docelowy zachowuje się poprawnie, innymi słowy zgodnie ze specyfikacją.
Wróćmy do naszego kodu Hello World. Otwórz edytor tekstu i dodaj następujący kod -
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
Następnie zapisz to w pliku o nazwie hello_world_spec.rb w folderze specyfikacji, który utworzyłeś powyżej. Teraz z powrotem w oknie cmd.exe uruchom to polecenie -
rspec spec spec\hello_world_spec.rb
Po zakończeniu polecenia powinieneś zobaczyć wynik, który wygląda następująco -
Finished in 0.002 seconds (files took 0.11101 seconds to load)
1 example, 0 failures
Gratulacje, właśnie utworzyłeś i uruchomiłeś swój pierwszy test jednostkowy RSpec!
W następnej sekcji będziemy nadal omawiać składnię plików RSpec.
Przyjrzyjmy się bliżej kodowi naszego HelloWorldprzykład. Przede wszystkim, jeśli nie jest to jasne, testujemy funkcjonalnośćHelloWorldklasa. Jest to oczywiście bardzo prosta klasa, która zawiera tylko jedną metodęsay_hello().
Oto ponownie kod 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
Opis Keyword
Słowo describejest słowem kluczowym RSpec. Służy do definiowania „Przykładowej grupy”. Możesz myśleć o „grupie przykładowej” jako o zbiorze testów. Plikdescribesłowo kluczowe może przyjmować nazwę klasy i / lub argument w postaci łańcucha. Musisz także przekazać argument blokowy dodescribe, będzie to zawierało poszczególne testy lub, jak są one znane w RSpec, „Przykłady”. Blok jest po prostu blokiem Ruby wyznaczonym przez Rubydo/end słowa kluczowe.
Słowo kluczowe kontekstu
Plik context słowo kluczowe jest podobne do describe. Może również akceptować nazwę klasy i / lub argument w postaci łańcucha. Powinieneś użyć bloku zcontexttakże. Idea kontekstu polega na tym, że obejmuje on testy określonego typu.
Na przykład możesz określić grupy przykładów z różnymi kontekstami, takimi jak ten -
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”
Plik context słowo kluczowe nie jest obowiązkowe, ale pomaga dodać więcej szczegółów na temat przykładów, które zawiera.
Słowo kluczowe it
Słowo itto kolejne słowo kluczowe RSpec, które jest używane do definiowania „Przykładu”. Przykładem jest w zasadzie test lub przypadek testowy. Znowu, jakdescribe i context, it akceptuje zarówno nazwę klasy, jak i argumenty łańcuchowe i powinno być używane z argumentem blokowym, oznaczonym za pomocą do/end. W przypadkuit, zwyczajowo przekazuje się tylko łańcuch i argument blokowy. Argument łańcuchowy często używa słowa „powinien” i ma na celu opisanie, jakie konkretne zachowanie powinno się zdarzyć wewnątrzit block. Innymi słowy, opisuje, że oczekiwany wynik dotyczy przykładu.
Zanotuj it block z naszego przykładu HelloWorld -
it "The say_hello method should return 'Hello World'" do
Ciąg znaków jasno określa, co powinno się stać, gdy wywołujemy polecenie przywitania się na wystąpieniu klasy HelloWorld. Ta część filozofii RSpec, przykład to nie tylko test, to także specyfikacja (specyfikacja). Innymi słowy, przykład zarówno dokumentuje, jak i testuje oczekiwane zachowanie twojego kodu Ruby.
Oczekiwane słowo kluczowe
Plik expectsłowo kluczowe jest używane do zdefiniowania „Oczekiwania” w RSpec. Jest to etap weryfikacji, podczas którego sprawdzamy, czy został spełniony określony oczekiwany warunek.
Z naszego przykładu HelloWorld mamy -
expect(message).to eql "Hello World!"
Pomysł z expectstwierdzenia są takie, że czytają jak normalny angielski. Możesz powiedzieć to głośno jako „Spodziewaj się, że zmienna wiadomość będzie równa łańcuchowi„ Hello World ””. Chodzi o to, że jest opisowy, a także łatwy do odczytania, nawet dla nietechnicznych interesariuszy, takich jak kierownicy projektów.
The to keyword
Plik to słowo kluczowe jest używane jako część expectsprawozdania. Pamiętaj, że możesz również użyć rozszerzenianot_tosłowo kluczowe, aby wyrazić coś przeciwnego, gdy chcesz, aby oczekiwanie było fałszywe. Możesz zobaczyć, że to jest używane z kropką,expect(message).to,ponieważ w rzeczywistości jest to zwykła metoda Rubiego. W rzeczywistości wszystkie słowa kluczowe RSpec są tak naprawdę tylko metodami Rubiego.
The eql keyword
Plik eqlsłowo kluczowe jest specjalnym słowem kluczowym RSpec zwanym Matcher. Używasz dopasowań, aby określić, jaki typ warunku testujesz jako prawdziwy (lub fałszywy).
W naszym HelloWorld expect oświadczenie, jasne jest, że eqloznacza równość ciągów. Zauważ, że istnieją różne typy operatorów równości w Rubim, a co za tym idzie różne odpowiadające im dopasowania w RSpec. W dalszej części omówimy wiele różnych typów dopasowań.
W tym rozdziale utworzymy nową klasę Ruby, zapiszemy ją we własnym pliku i utworzymy oddzielny plik specyfikacji do testowania tej klasy.
Po pierwsze, w naszej nowej klasie nazywa się StringAnalyzer. To prosta klasa, która, jak się domyślacie, analizuje ciągi. Nasza klasa ma tylko jedną metodęhas_vowels?który, jak sugeruje jego nazwa, zwraca prawdę, jeśli łańcuch zawiera samogłoski, a fałsz, jeśli nie. Oto implementacja dlaStringAnalyzer -
class StringAnalyzer
def has_vowels?(str)
!!(str =~ /[aeio]+/i)
end
end
Jeśli korzystałeś z sekcji HelloWorld, utworzyłeś folder o nazwie C: \ rspec_tutorial \ spec.
Usuń plik hello_world.rb, jeśli go masz, i zapisz powyższy kod StringAnalyzer w pliku o nazwie string_analyzer.rb w folderze C: \ rspec_tutorial \ spec.
Oto źródło naszego pliku specyfikacji do testowania 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
Zapisz to w tym samym katalogu specyfikacji, nadając mu nazwę string_analyzer_test.rb.
W oknie cmd.exe przejdź do folderu C: \ rspec_tutorial i uruchom to polecenie: dir spec
Powinieneś zobaczyć następujące -
Katalog 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
Teraz mamy zamiar przeprowadzić nasze testy, uruchom polecenie: rspec spec
Gdy przekazujesz nazwę folderu do rspec, uruchamia wszystkie pliki specyfikacji w folderze. Powinieneś zobaczyć ten wynik -
No examples found.
Finished in 0 seconds (files took 0.068 seconds to load)
0 examples, 0 failures
Powodem tego jest to, że domyślnie rspecuruchamia tylko pliki, których nazwy kończą się na „_spec.rb”. Zmień nazwę string_analyzer_test.rb na string_analyzer_spec.rb. Możesz to łatwo zrobić, uruchamiając to polecenie -
ren spec\string_analyzer_test.rb string_analyzer_spec.rb
A teraz biegnij rspec spec, powinieneś zobaczyć wyjście, które wygląda następująco -
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)
Teraz zapisz zmiany, które właśnie wprowadziłeś w string_analyizer.rb i ponownie uruchom komendę rspec spec, powinieneś zobaczyć wynik, który wygląda następująco -
..
Finished in 0.002 seconds (files took 0.11401 seconds to load)
2 examples, 0 failures
Gratulacje, przykłady (testy) w Twoim pliku specyfikacji są teraz zaliczane. Naprawiliśmy błąd w wyrażeniu regularnym używającym metody samogłosek, ale nasze testy są dalekie od zakończenia.
Warto byłoby dodać więcej przykładów testujących różne typy ciągów wejściowych metodą ma samogłoski.
Poniższa tabela przedstawia niektóre permutacje, które można dodać w nowych Przykładach (blokuje)
Ciąg wejściowy | Opis | Oczekiwany wynik z has_vowels? |
---|---|---|
„aaa”, „eee”, „iii”, „o” | Tylko jedna samogłoska i żadne inne litery. | prawdziwe |
„abcefg” | `` Co najmniej jedna samogłoska i kilka spółgłosek '' | prawdziwe |
„mnklp” | Tylko spółgłoski. | fałszywy |
'' | Pusty ciąg (bez liter) | fałszywy |
„abcde55345 & ??” | Samogłoski, spółgłoski, cyfry i znaki interpunkcyjne. | prawdziwe |
„423432 %%% ^ &” | Tylko cyfry i znaki interpunkcyjne. | fałszywy |
„AEIOU” | Tylko samogłoski wielkimi literami. | prawdziwe |
„AeiOuuuA” | Tylko wielkie i małe samogłoski. | prawdziwe |
„AbCdEfghI” | Samogłoski i spółgłoski wielkimi i małymi literami. | prawdziwe |
„BCDFG” | Tylko spółgłoski z wielkich liter. | fałszywy |
'' | Tylko białe znaki. | fałszywy |
Do Ciebie należy decyzja, które przykłady dodać do pliku specyfikacji. Jest wiele warunków do przetestowania, musisz określić, który podzbiór warunków jest najważniejszy i najlepiej przetestować kod.
Plik rspec polecenie oferuje wiele różnych opcji, aby zobaczyć je wszystkie, wpisz rspec-Wsparcie. Poniższa tabela zawiera listę najpopularniejszych opcji i opisuje ich działanie.
Sr.No. | Opcja / flaga i opis |
---|---|
1 | -I PATH Dodaje PATH do ścieżki ładowania (wymagania), która rspec używane podczas wyszukiwania plików źródłowych Rubiego. |
2 | -r, --require PATH Dodaje określony plik źródłowy, który ma być wymagany w specyfikacji. akta). |
3 | --fail-fast Dzięki tej opcji rspec przestanie działać specyfikacje po niepowodzeniu pierwszego przykładu. Domyślnie rspec uruchamia wszystkie określone pliki specyfikacji, niezależnie od liczby błędów. |
4 | -f, --format FORMATTER Ta opcja umożliwia określenie różnych formatów wyjściowych. Więcej informacji na temat formatów wyjściowych można znaleźć w sekcji dotyczącej elementów formatujących. |
5 | -o, --out FILE Ta opcja powoduje, że rspec zapisuje wyniki testu do pliku wyjściowego FILE zamiast do standardowego wyjścia. |
6 | -c, --color Włącza kolor na wyjściu rspec. Pomyślne wyniki przykładu zostaną wyświetlone zielonym tekstem, awarie zostaną wydrukowane czerwonym tekstem. |
7 | -b, --backtrace Wyświetla pełne ślady błędów w danych wyjściowych rspec. |
8 | -w, --warnings Wyświetla ostrzeżenia Rubiego w danych wyjściowych rspec. |
9 | -P, --pattern PATTERN Załaduj i uruchom pliki specyfikacji, które pasują do wzorca WZÓR. Na przykład, jeśli podasz -p „* .rb”, rspec uruchomi wszystkie pliki Ruby, a nie tylko te, które kończą się na „_spec.rb”. |
10 | -e, --example STRING Ta opcja kieruje rspec do uruchamiania wszystkich przykładów, które zawierają tekst STRING w swoich opisach. |
11 | -t, --tag TAG Z tą opcją rspec będzie uruchamiał tylko przykłady zawierające znacznik TAG. Zauważ, że TAG jest określony jako symbol Ruby. Więcej informacji można znaleźć w sekcji dotyczącej tagów RSpec. |
Jeśli pamiętasz nasz oryginalny przykład Hello World, zawierał on wiersz, który wyglądał następująco:
expect(message).to eq "Hello World!"
Słowo kluczowe eql to RSpec„Dopasowujący”. Tutaj przedstawimy inne typy dopasowań w RSpec.
Równość / Dopasowanie tożsamości
Dopasowania do testowania pod kątem równości obiektów lub wartości.
Matcher | Opis | Przykład |
---|---|---|
eq | Przechodzi, gdy faktyczne == oczekiwano | oczekiwać (rzeczywiste). do oczekiwanego równ |
eql | Przechodzi, gdy current.eql? (Oczekiwane) | oczekiwać (rzeczywiste) .do eql oczekiwano |
być | Przechodzi, gdy faktyczne. Równe? (Oczekiwane) | spodziewać się (rzeczywiste) |
równy | Przechodzi również, gdy current.equal? (Oczekiwane) | oczekiwać (rzeczywiste). równe oczekiwane |
Przykład
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
Gdy powyższy kod zostanie wykonany, wygeneruje następujący wynik. Liczba sekund może się nieznacznie różnić na Twoim komputerze -
.
Finished in 0.036 seconds (files took 0.11901 seconds to load)
1 example, 0 failures
Porównanie dopasowań
Dopasowania do porównywania z wartościami.
Matcher | Opis | Przykład |
---|---|---|
> | Przechodzi, gdy rzeczywisty> oczekiwany | oczekiwać (rzeczywiste). być> oczekiwane |
> = | Przechodzi, gdy rzeczywista> = oczekiwana | oczekiwać (rzeczywiste). być> = oczekiwane |
< | Przechodzi, gdy faktycznie <oczekiwano | oczekiwać (rzeczywiste). być <oczekiwane |
<= | Przechodzi, gdy faktyczne <= oczekiwane | oczekiwać (rzeczywiste). być <= oczekiwane |
be_between włącznie | Przechodzi, gdy wartość rzeczywista wynosi <= min i> = maks | oczekiwać (rzeczywiste). to be_between (min, max) .inclusive |
be_between na wyłączność | Przechodzi, gdy wartość rzeczywista wynosi <min i> maks | oczekiwać (rzeczywiste). to be_between (min, max). wyłączne |
mecz | Przechodzi, gdy rzeczywisty pasuje do wyrażenia regularnego | oczekiwać (rzeczywiste). do dopasowania (/ regex /) |
Przykład
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
Gdy powyższy kod zostanie wykonany, wygeneruje następujący wynik. Liczba sekund może się nieznacznie różnić na Twoim komputerze -
.
Finished in 0.013 seconds (files took 0.11801 seconds to load)
1 example, 0 failures
Dopasowywanie klas / typów
Dopasowania do testowania typu lub klasy obiektów.
Matcher | Opis | Przykład |
---|---|---|
be_instance_of | Przechodzi, gdy rzeczywista jest instancją oczekiwanej klasy. | oczekiwać (rzeczywiste) .to be_instance_of (oczekiwane) |
be_kind_of | Przechodzi, gdy rzeczywiste jest instancją oczekiwanej klasy lub którejkolwiek z jej klas nadrzędnych. | oczekiwać (rzeczywiste). to be_kind_of (oczekiwane) |
odpowiedzi na | Przechodzi, gdy rzeczywisty odpowiada na określoną metodę. | oczekiwać (rzeczywiste). to respond_to (oczekiwane) |
Przykład
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
Gdy powyższy kod zostanie wykonany, wygeneruje następujący wynik. Liczba sekund może się nieznacznie różnić na Twoim komputerze -
.
Finished in 0.002 seconds (files took 0.12201 seconds to load)
1 example, 0 failures
Dopasowania prawda / fałsz / brak
Dopasowania do testowania, czy wartość jest prawdziwa, fałszywa lub zerowa.
Matcher | Opis | Przykład |
---|---|---|
Mów prawdę | Przechodzi, gdy current == true | oczekiwać (rzeczywiste). być prawdziwe |
być fałszywe | Przechodzi, gdy current == false | oczekiwać (rzeczywiste). być fałszywe |
be_truthy | Przechodzi, gdy wartość rzeczywista nie jest fałszywa ani zerowa | oczekiwać (rzeczywistego). to be_truthy |
be_falsey | Przechodzi, gdy wartość rzeczywista jest fałszywa lub zerowa | oczekiwać (faktyczny). to be_falsey |
be_nil | Przechodzi, gdy wartość rzeczywista wynosi zero | oczekiwać (rzeczywiste). to be_nil |
Przykład
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
Gdy powyższy kod zostanie wykonany, wygeneruje następujący wynik. Liczba sekund może się nieznacznie różnić na Twoim komputerze -
.
Finished in 0.003 seconds (files took 0.12301 seconds to load)
1 example, 0 failures
Dopasowywanie błędów
Dopasowania do testowania, gdy blok kodu wywołuje błąd.
Matcher | Opis | Przykład |
---|---|---|
podnieść_error (ErrorClass) | Przechodzi, gdy blok wywołuje błąd typu ErrorClass. | spodziewać się {blok} .to podnieść_error (ErrorClass) |
podnieść_error ("komunikat o błędzie") | Pomija, gdy blok wywołuje błąd z komunikatem „komunikat o błędzie”. | oczekuj {blok} .to podnieść_error („komunikat o błędzie”) |
podnieść_error (ErrorClass, „komunikat o błędzie”) | Przechodzi, gdy blok wywołuje błąd typu ErrorClass z komunikatem „komunikat o błędzie” | spodziewać się {blok} .to podnieść_error (ErrorClass, „komunikat o błędzie”) |
Przykład
Zapisz poniższy kod w pliku o nazwie error_matcher_spec.rb i uruchom go za pomocą tego polecenia - 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
Gdy powyższy kod zostanie wykonany, wygeneruje następujący wynik. Liczba sekund może się nieznacznie różnić na Twoim komputerze -
.
Finished in 0.002 seconds (files took 0.12101 seconds to load)
1 example, 0 failures
W tym rozdziale omówimy dublowanie RSpec, znane również jako makiety RSpec. Double to przedmiot, który może „zastępować” inny przedmiot. Prawdopodobnie zastanawiasz się, co to dokładnie oznacza i dlaczego go potrzebujesz.
Załóżmy, że tworzysz aplikację dla szkoły i masz klasę reprezentującą klasę uczniów i inną klasę dla uczniów, czyli klasę Classroom i klasę Student. Najpierw musisz napisać kod jednej z zajęć, więc powiedzmy, że zacznij od klasy Classroom -
class ClassRoom
def initialize(students)
@students = students
end
def list_student_names
@students.map(&:name).join(',')
end
end
To jest prosta klasa, ma jedną metodę list_student_names, która zwraca rozdzielany przecinkami ciąg nazw uczniów. Teraz chcemy stworzyć testy dla tej klasy, ale jak to zrobić, jeśli jeszcze nie utworzyliśmy klasy Student? Potrzebujemy testu Double.
Ponadto, jeśli mamy „fikcyjną” klasę, która zachowuje się jak obiekt Student, wówczas nasze testy ClassRoom nie będą zależeć od klasy Student. Nazywamy ten test izolacją.
Jeśli nasze testy ClassRoom nie opierają się na innych klasach, to gdy test się nie powiedzie, możemy od razu wiedzieć, że w naszej klasie ClassRoom jest błąd, a nie w jakiejś innej klasie. Pamiętaj, że w prawdziwym świecie możesz budować klasę, która wymaga interakcji z inną klasą napisaną przez kogoś innego.
W tym miejscu przydatne stają się RSpec Doubles (mocks). Nasza metoda list_student_names wywołuje metodę name dla każdego obiektu Studenta w jego zmiennej składowej @students. Dlatego potrzebujemy Double, który implementuje metodę name.
Oto kod dla ClassRoom wraz z przykładem RSpec (test), ale zauważ, że nie ma zdefiniowanej klasy studenta -
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
Gdy powyższy kod zostanie wykonany, wygeneruje następujący wynik. Upływający czas może się nieznacznie różnić na Twoim komputerze -
.
Finished in 0.01 seconds (files took 0.11201 seconds to load)
1 example, 0 failures
Jak widać, używając pliku test doubleumożliwia przetestowanie kodu nawet wtedy, gdy opiera się on na klasie, która jest niezdefiniowana lub niedostępna. Oznacza to również, że gdy zdarzy się niepowodzenie testu, możesz od razu stwierdzić, że jest to spowodowane problemem w Twojej klasie, a nie zajęciami napisanymi przez kogoś innego.
Jeśli przeczytałeś już sekcję o RSpec Doubles (aka Mocks), to już widziałeś RSpec Stubs. W RSpec kod pośredniczący jest często nazywany kodem metody, jest to specjalny rodzaj metody, która „zastępuje” istniejącą metodę lub metodę, która jeszcze nie istnieje.
Oto kod z sekcji dotyczącej 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
W naszym przykładzie metoda allow () udostępnia kody pośredniczące metod, których potrzebujemy do przetestowania klasy ClassRoom. W tym przypadku potrzebujemy obiektu, który będzie działał jak instancja klasy Student, ale ta klasa w rzeczywistości (jeszcze) nie istnieje. Wiemy, że klasa Student musi udostępniać metodę name () i używamy metody allow (), aby utworzyć skrót metody dla name ().
Należy zauważyć, że składnia RSpec zmieniła się nieco na przestrzeni lat. W starszych wersjach RSpec powyższe kody pośredniczące metody byłyby zdefiniowane w ten sposób -
student1.stub(:name).and_return('John Smith')
student2.stub(:name).and_return('Jill Smith')
Weźmy powyższy kod i zamieńmy dwa allow() wiersze ze starą składnią 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
Zobaczysz to wyjście po wykonaniu powyższego kodu -
.
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
Zaleca się użycie nowej składni allow (), gdy chcesz utworzyć kody pośredniczące metod w przykładach RSpec, ale udostępniliśmy tutaj starszy styl, abyś mógł go rozpoznać, jeśli go zobaczysz.
Podczas pisania testów jednostkowych często wygodnie jest uruchomić konfigurację i kod dezaktywacji przed i po testach. Kod instalacji to kod, który konfiguruje lub „ustawia” warunki testu. Kod dezaktywacji wykonuje porządki, upewnia się, że środowisko jest spójne dla kolejnych testów.
Ogólnie rzecz biorąc, testy powinny być od siebie niezależne. Kiedy uruchamiasz cały zestaw testów i jeden z nich kończy się niepowodzeniem, chcesz mieć pewność, że się nie powiódł, ponieważ testowany kod zawiera błąd, a nie dlatego, że poprzedni test pozostawił środowisko w niespójnym stanie.
Najpopularniejsze haki używane w RSpec to haki przed i po hakach. Umożliwiają zdefiniowanie i uruchomienie kodu konfiguracji i dezaktywacji, które omówiliśmy powyżej. Rozważmy ten przykładowy kod -
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
Po uruchomieniu tego kodu otrzymasz następujące dane wyjściowe -
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
Przyjrzyjmy się bliżej temu, co się dzieje. Metoda before (: each) służy do definiowania kodu konfiguracji. Kiedy przekazujesz: each argument, instruujesz metodę before, aby była uruchamiana przed każdym przykładem w Twojej grupie przykładów, tj. Dwa, które blokuje wewnątrz bloku opisującego w powyższym kodzie.
W wierszu: @simple_class = SimpleClass.new tworzymy nową instancję klasy SimpleClass i przypisujemy ją do zmiennej instancji obiektu. Jaki obiekt możesz się zastanawiać? RSpec tworzy specjalną klasę za kulisami w zakresie bloku opisu. Umożliwia to przypisywanie wartości zmiennym instancji tej klasy, do których można uzyskać dostęp w ramach bloków it w przykładach. Ułatwia to również pisanie czystszego kodu w naszych testach. Jeśli każdy test (przykład) potrzebuje instancji SimpleClass, możemy umieścić ten kod w podpięciu przed i nie musimy go dodawać do każdego przykładu.
Zwróć uwagę, że wiersz „Tworzenie nowej instancji klasy SimpleClass” jest zapisywany w konsoli dwukrotnie, co pokazuje, że przed wywołaniem przechwytywania w każdym z it blocks.
Jak już wspomnieliśmy, RSpec ma również podpięcie after, a zarówno podpięcia przed, jak i po mogą przyjąć: all jako argument. Hak after będzie działać za określonym celem. Cel: all oznacza, że hak będzie działał przed / po wszystkich przykładach. Oto prosty przykład ilustrujący, kiedy wywoływany jest każdy punkt zaczepienia.
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
Po uruchomieniu powyższego kodu zobaczysz to wyjście -
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
Tagi RSpec zapewniają łatwy sposób uruchamiania określonych testów w plikach specyfikacji. Domyślnie RSpec uruchomi wszystkie testy w uruchamianych plikach specyfikacji, ale może być konieczne wykonanie tylko ich części. Powiedzmy, że masz kilka testów, które działają bardzo szybko i że właśnie dokonałeś zmiany w kodzie aplikacji i chcesz po prostu przeprowadzić szybkie testy. Ten kod pokaże, jak to zrobić za pomocą tagów 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
Teraz zapisz powyższy kod w nowym pliku o nazwie tag_spec.rb. Z wiersza poleceń uruchom następujące polecenie: rspec --tag slow tag_spec.rb
Zobaczysz to wyjście -
Opcje uruchamiania: include {: slow => true}
This test is slow!
.
Finished in 10 seconds (files took 0.11601 seconds to load)
1 example, 0 failures
Następnie uruchom to polecenie: rspec --tag fast tag_spec.rb
Zobaczysz to wyjście -
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
Jak widać, znaczniki RSpec bardzo ułatwiają wykonanie podzbioru testów!
Jedną z mocnych stron RSpec jest to, że zapewnia wiele sposobów pisania testów, czystych testów. Gdy testy są krótkie i czytelne, łatwiej jest skupić się na oczekiwanym zachowaniu, a nie na szczegółach pisania testów. Przedmioty RSpec to kolejny skrót umożliwiający pisanie prostych, nieskomplikowanych testów.
Rozważ ten kod -
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
W rzeczywistości jest to całkiem jasne, ale moglibyśmy użyć funkcji tematu RSpec, aby zmniejszyć ilość kodu w przykładzie. Robimy to, przenosząc instancję obiektu osoby do wiersza opisu.
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
Po uruchomieniu tego kodu zobaczysz to wyjście -
..
Finished in 0.003 seconds (files took 0.11201 seconds to load)
2 examples, 0 failures
Zwróć uwagę, o ile prostsza jest druga próbka kodu. Wzięliśmy ten jedenit block w pierwszym przykładzie i zastąpiłem go dwoma it blocks które wymagają mniej kodu i są równie przejrzyste.
Czasami przykłady RSpec wymagają łatwego sposobu udostępniania kodu wielokrotnego użytku. Najlepszym sposobem na osiągnięcie tego jest pomocników. Helpery to w zasadzie zwykłe metody Rubiego, które udostępniasz w przykładach. Aby zilustrować korzyści płynące z używania pomocników, rozważmy ten kod -
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
Ten kod jest przejrzysty, ale zawsze dobrze jest ograniczyć liczbę powtórzeń kodu, gdy tylko jest to możliwe. Możemy wziąć powyższy kod i zmniejszyć część tego powtórzenia za pomocą metody pomocniczej o nazwie 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
Po uruchomieniu powyższego kodu zobaczysz to wyjście -
..
Finished in 0.002 seconds (files took 0.11401 seconds to load)
2 examples, 0 failures
Jak widać, byliśmy w stanie wprowadzić logikę tworzenia i wyprowadzania obiektu psa do Pomocnika, co pozwala na to, aby nasze przykłady były krótsze i czystsze.
RSpec to elastyczne i potężne narzędzie. Funkcjonalność metadanych w RSpec nie jest wyjątkiem. Metadane ogólnie odnoszą się do „danych o danych”. W RSpec oznacza to dane o Twoimdescribe, context i it blocks.
Spójrzmy na przykład -
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
Po uruchomieniu powyższego kodu zobaczysz to wyjście -
..
Finished in 0.002 seconds (files took 0.11301 seconds to load)
2 examples, 0 failures
Metadane zapewniają sposób przypisywania zmiennych w różnych zakresach w plikach RSpec. Zmienna example.metadata to skrót Ruby, który zawiera inne informacje o grupach Przykłady i Przykłady.
Na przykład przepiszmy powyższy kod, aby wyglądał następująco -
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
Kiedy uruchamiamy ten kod, widzimy wszystkie wartości w przykładzie. Hash 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
Najprawdopodobniej nie będziesz musiał używać wszystkich tych metadanych, ale spójrz na pełną wartość opisu -
Przykładowa grupa ze zmienną metadanych i kontekstem z inną zmienną może uzyskać dostęp do zmiennej metadanych w bloku kontekstu.
To jest zdanie utworzone z opisu bloku opisu + zawartego w nim opisu bloku kontekstowego + opisu bloku it block.
Warto tutaj zauważyć, że te trzy ciągi czytają się razem jak normalne angielskie zdanie. . . co jest jednym z pomysłów stojących za RSpec, mając testy, które brzmią jak angielskie opisy zachowań.
Możesz przeczytać sekcję o metadanych RSpec przed przeczytaniem tej sekcji, ponieważ, jak się okazuje, filtrowanie RSpec jest oparte na metadanych RSpec.
Wyobraź sobie, że masz plik specyfikacji, który zawiera dwa rodzaje testów (Przykłady): pozytywne testy funkcjonalne i negatywne (błędy) testy. Zdefiniujmy je w ten sposób -
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
Teraz zapisz powyższy tekst jako plik o nazwie „filter_spec.rb”, a następnie uruchom go za pomocą tego polecenia -
rspec filter_spec.rb
Zobaczysz dane wyjściowe, które wyglądają mniej więcej tak -
..
Finished in 0.003 seconds (files took 0.11201 seconds to load)
2 examples, 0 failures
A co by było, gdybyśmy chcieli ponownie uruchomić tylko pozytywne testy w tym pliku? A może tylko negatywne testy? Możemy to łatwo zrobić za pomocą filtrów RSpec. Zmień powyższy kod na ten -
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
Zapisz zmiany w filter_spec.rb i uruchom to nieco inne polecenie -
rspec --tag positive filter_spec.rb
Teraz zobaczysz wyjście, które wygląda następująco -
Run options: include {:positive=>true}
.
Finished in 0.001 seconds (files took 0.11401 seconds to load)
1 example, 0 failures
Określając --tag positive, mówimy RSpec, aby uruchamiał Przykłady tylko ze zdefiniowaną zmienną metadanych: positive. Moglibyśmy zrobić to samo z negatywnymi testami, uruchamiając polecenie w ten sposób -
rspec --tag negative filter_spec.rb
Pamiętaj, że to tylko przykłady, możesz określić filtr o dowolnej nazwie.
RSpec Formatters
Elementy formatujące umożliwiają RSpec wyświetlanie wyników testów na różne sposoby. Utwórzmy nowy plik RSpec zawierający ten kod -
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
Teraz zapisz to w pliku o nazwie formatter_spec.rb i uruchom to polecenie RSpec -
rspec formatter_spec.rb
Powinieneś zobaczyć wyjście, które wygląda następująco -
.
Finished in 0.002 seconds (files took 0.11401 seconds to load)
1 example, 0 failures
Teraz uruchom to samo polecenie, ale tym razem określ formater, na przykład:
rspec --format progress formatter_spec.rb
Tym razem powinieneś zobaczyć to samo wyjście -
.
Finished in 0.002 seconds (files took 0.11401 seconds to load)
1 example, 0 failures
Powodem jest to, że program formatujący „postęp” jest domyślnym programem formatującym. Spróbujmy teraz innego programu formatującego, spróbuj uruchomić to polecenie -
rspec --format doc formatter_spec.rb
Teraz powinieneś zobaczyć to wyjście -
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
Jak widać, wyjście wygląda zupełnie inaczej w przypadku programu formatującego „doc”. Ten formater prezentuje wynik w stylu podobnym do dokumentacji. Możesz się zastanawiać, jak wyglądają te opcje w przypadku niepowodzenia testu (przykład). Zmieńmy kod wformatter_spec.rb wyglądać tak -
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
Oczekiwania expect(1 + 1).to eq(1)powinien zawieść. Zapisz zmiany i ponownie uruchom powyższe polecenia -
rspec --format progress formatter_spec.rb i pamiętaj, ponieważ program formatujący „postęp” jest domyślny, możesz po prostu uruchomić: rspec formatter_spec.rb. Powinieneś zobaczyć to wyjście -
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
Teraz wypróbujmy program formatujący dokumenty, uruchom to polecenie -
rspec --format doc formatter_spec.rb
Teraz, po nieudanym teście, powinieneś zobaczyć ten wynik -
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
Nieudane przykłady
rspec ./formatter_spec.rb:3 # Plik specyfikacji, aby zademonstrować, jak działają elementy formatujące RSpec podczas uruchamiania niektórych testów. Test zwykle wywołuje metodę Expect () przynajmniej raz.
Formattery RSpec oferują możliwość zmiany sposobu wyświetlania wyników testów, możliwe jest nawet utworzenie własnego niestandardowego programu formatującego, ale jest to bardziej zaawansowany temat.
Kiedy uczysz się RSpec, możesz dużo czytać o oczekiwaniach i na początku może to być trochę zagmatwane. Są dwa główne szczegóły, o których należy pamiętać, kiedy zobaczysz termin Oczekiwanie -
Oczekiwanie to po prostu stwierdzenie w pliku it block który używa expect()metoda. Otóż to. To nie jest bardziej skomplikowane. Gdy masz taki kod:expect(1 + 1).to eq(2), masz w swoim przykładzie Oczekiwanie. Spodziewasz się, że wyrażenie1 + 1 ocenia do 2. Sformułowanie jest ważne, ponieważ RSpec jest platformą testową BDD. Nazywając tę instrukcję oczekiwaniem, staje się jasne, że kod RSpec opisuje „zachowanie” testowanego kodu. Chodzi o to, że wyrażasz, jak powinien zachowywać się kod, w sposób przypominający dokumentację.
Składnia oczekiwań jest stosunkowo nowa. Zanimexpect() Metoda została wprowadzona (w 2012 r.), RSpec używał innej składni, która była oparta na should()metoda. Powyższe oczekiwanie jest zapisane w starej składni w następujący sposób:(1 + 1).should eq(2).
Możesz napotkać starą składnię RSpec dla oczekiwań podczas pracy ze starszym kodem lub starszą wersją RSpec. Jeśli używasz starej składni z nową wersją RSpec, zobaczysz ostrzeżenie.
Na przykład z tym kodem -
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
Po uruchomieniu otrzymasz wynik, który wygląda następująco -
. 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
O ile nie musisz używać starej składni, zdecydowanie zaleca się użycie Expect () zamiast should ().