Учебники

RSpec — Краткое руководство

RSpec — Введение

RSpec — это модуль модульного тестирования для языка программирования Ruby. RSpec отличается от традиционных платформ xUnit, таких как JUnit, потому что RSpec — это инструмент разработки, управляемый поведением. Это означает, что тесты, написанные на RSpec, фокусируются на «поведении» тестируемого приложения. RSpec делает упор не на том, как работает приложение, а на том, как оно ведет себя, другими словами, на самом деле, что делает приложение.

RSpec Environment

Прежде всего, вам нужно будет установить Ruby на ваш компьютер. Однако, если вы еще этого не сделали ранее, вы можете скачать и установить Ruby с главного сайта RubyRuby .

Если вы устанавливаете Ruby в Windows, у вас должен быть установщик Ruby для Windows здесь — http://www.rubyinstaller.org

Для этого урока вам понадобится только текстовый редактор, например Блокнот и консоль командной строки. Примеры здесь будут использовать cmd.exe на Windows.

Чтобы запустить cmd.exe, просто нажмите в меню «Пуск» и введите «cmd.exe», а затем нажмите клавишу «Return».

В командной строке в окне cmd.exe введите следующую команду, чтобы увидеть, какую версию Ruby вы используете:

ruby -v

Вы должны увидеть следующий вывод, который выглядит примерно так:

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

Примеры в этом руководстве будут использовать Ruby 2.2.3, но подойдет любая версия Ruby выше 2.0.0. Далее нам нужно установить гем RSpec для вашей установки Ruby. Gem — это библиотека Ruby, которую вы можете использовать в своем собственном коде. Чтобы установить драгоценный камень, вам нужно использовать команду драгоценного камня .

Давайте сейчас установим гем Rspec. Вернитесь в окно cmd.exe и введите следующее —

gem install rspec

У вас должен быть список установленных драгоценных камней, это камни, которые нужны для правильной работы rspec. В конце вывода вы должны увидеть что-то похожее на это —

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

Не волнуйтесь, если ваш вывод не выглядит точно так же. Кроме того, если вы используете компьютер Mac или Linux, вам может потребоваться выполнить команду gem install rspec с помощью sudo или использовать такой инструмент, как HomeBrew или RVM, чтобы установить гем rspec.

Hello World

Для начала давайте создадим каталог (папку) для хранения наших файлов RSpec. В окне cmd.exe введите следующее —

cd \

Затем введите —

mkdir rspec_tutorial

И наконец, введите —

cd rspec_tutorial

Отсюда мы собираемся создать еще один каталог с именем spec, сделав это, набрав —

mkdir spec

Мы собираемся хранить наши файлы RSpec в этой папке. Файлы RSpec известны как «спецификации». Если вас это смущает, вы можете рассматривать файл спецификации как тестовый файл. RSpec использует термин «spec», который является краткой формой для «спецификации».

Поскольку RSpec — это инструмент тестирования BDD, цель состоит в том, чтобы сосредоточиться на том, что делает приложение, и соответствует ли оно спецификации. При разработке, основанной на поведении, спецификация часто описывается в терминах «пользовательской истории». RSpec разработан, чтобы прояснить, правильно ли работает целевой код, другими словами, следуя спецификации.

Вернемся к нашему коду Hello World. Откройте текстовый редактор и добавьте следующий код —

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

Затем сохраните его в файл с именем hello_world_spec.rb в папке spec, которую вы создали выше. Теперь вернитесь в окно cmd.exe и выполните эту команду:

rspec spec spec\hello_world_spec.rb

Когда команда завершится, вы должны увидеть вывод, который выглядит следующим образом:

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

Поздравляем, вы только что создали и запустили свой первый модульный тест RSpec!

В следующем разделе мы продолжим обсуждение синтаксиса файлов RSpec.

RSpec — основной синтаксис

Давайте внимательнее посмотрим на код нашего примера HelloWorld . Прежде всего, если неясно, мы тестируем функциональность класса HelloWorld . Это, конечно, очень простой класс, который содержит только один метод say_hello () .

Вот снова код 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

Описание Ключевое слово

Слово description является ключевым словом RSpec. Он используется для определения «группы примеров». Вы можете думать о «Группе примеров» как о наборе тестов. Ключевое слово description может принимать имя класса и / или строковый аргумент. Вам также нужно передать аргумент блока для описания , который будет содержать отдельные тесты или, как они известны в RSpec, «Примеры». Блок — это просто блок Ruby, обозначенный ключевыми словами Ruby do / end .

Ключевое слово контекста

Контекстное ключевое слово похоже на описание . Он также может принимать имя класса и / или строковый аргумент. Вы должны также использовать блок с контекстом . Идея контекста заключается в том, что он включает тесты определенного типа.

Например, вы можете указать группы примеров с различным контекстом, как это —

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”

Ключевое слово context не является обязательным, но оно помогает добавить больше деталей о примерах, которые оно содержит.

Ключевое слово

Слово это другое ключевое слово RSpec, которое используется для определения «примера». Примером является в основном тест или контрольный пример. Опять же, как description и context, он принимает как имя класса, так и строковые аргументы и должен использоваться с аргументом блока, обозначенным do / end . В этом случае принято передавать только строку и аргумент блока. Строковый аргумент часто использует слово «следует» и предназначен для описания того, какое конкретное поведение должно происходить внутри блока it . Другими словами, он описывает ожидаемый результат для примера.

Обратите внимание на блок it из нашего примера HelloWorld —

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

Строка проясняет, что должно произойти, когда мы вызываем команду hello в экземпляре класса HelloWorld. Эта часть философии RSpec, Пример — это не просто тест, это также спецификация (спецификация). Другими словами, Пример документирует и тестирует ожидаемое поведение вашего кода Ruby.

Ожидаемое ключевое слово

Ключевое слово wait используется для определения «Ожидания» в RSpec. Это этап проверки, на котором мы проверяем, что определенное ожидаемое условие выполнено.

Из нашего примера HelloWorld, мы имеем —

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

Идея с ожидаемыми утверждениями заключается в том, что они читаются как нормальный английский. Вы можете сказать это вслух как «Ожидайте, что переменное сообщение будет равно строке« Hello World »». Идея заключается в том, что он описательный, а также легко читаемый, даже для нетехнических заинтересованных сторон, таких как менеджеры проектов.

The to keyword

Ключевое слово to используется как часть ожиданий . Обратите внимание, что вы также можете использовать ключевое слово not_to, чтобы выразить обратное, когда вы хотите, чтобы Ожидание было ложным. Вы можете видеть, что to используется с точкой, ожидаем (message) .to, потому что это на самом деле обычный метод Ruby. На самом деле все ключевые слова RSpec на самом деле являются просто методами Ruby.

The eql keyword

Ключевое слово eql — это специальное ключевое слово RSpec, называемое Matcher. Вы используете Matchers, чтобы указать, какой тип условия вы проверяете, чтобы быть истинным (или ложным).

В нашем ожидании HelloWorld ясно, что eql означает равенство строк. Обратите внимание, что в Ruby существуют различные типы операторов равенства и, следовательно, разные соответствующие Matchers в RSpec. Мы рассмотрим множество различных типов Matchers в следующем разделе.

RSpec — Написание спецификаций

В этой главе мы создадим новый класс Ruby, сохраним его в своем собственном файле и создадим отдельный файл спецификации для тестирования этого класса.

Во-первых, в нашем новом классе он называется StringAnalyzer . Это простой класс, который, как вы уже догадались, анализирует строки. В нашем классе есть только один метод has_vowels? который, как следует из его имен, возвращает true, если строка содержит гласные, и false, если нет. Вот реализация для StringAnalyzer

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

Если вы следовали разделу HelloWorld, вы создали папку с именем C: \ rspec_tutorial \ spec.

Удалите файл hello_world.rb, если он у вас есть, и сохраните приведенный выше код StringAnalyzer в файл с именем string_analyzer.rb в папке C: \ rspec_tutorial \ spec.

Вот источник нашего спецификационного файла для тестирования 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

Сохраните это в той же директории спецификации, присвоив ей имя string_analyzer_test.rb.

В окне cmd.exe перейдите в папку C: \ rspec_tutorial и выполните следующую команду: dir spec

Вы должны увидеть следующее —

Каталог 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

Теперь мы собираемся запустить наши тесты, запустите эту команду: rspec spec

Когда вы передаете имя папки в rspec , она запускает все файлы спецификации внутри папки. Вы должны увидеть этот результат —

No examples found.

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

Причина этого заключается в том, что по умолчанию rspec запускает только файлы, имена которых заканчиваются на «_spec.rb». Переименуйте string_analyzer_test.rb в string_analyzer_spec.rb. Вы можете сделать это легко, запустив эту команду —

ren spec\string_analyzer_test.rb string_analyzer_spec.rb

Теперь, запустите rspec spec снова, вы должны увидеть вывод, который выглядит следующим образом:

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)

Теперь сохраните изменения, которые вы только что внесли в string_analyizer.rb, и снова запустите команду спецификации rspec, теперь вы должны увидеть вывод, который выглядит как —

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

Поздравляем, примеры (тесты) в вашем спецификационном файле теперь проходят. Мы исправили ошибку в регулярном выражении, которое имеет метод гласных, но наши тесты далеки от завершения.

Было бы целесообразно добавить больше примеров, которые проверяют различные типы входных строк с помощью метода has vowels.

В следующей таблице приведены некоторые перестановки, которые можно добавить в новые примеры (блокируются).

Строка ввода Описание Ожидаемый результат с has_vowels?
‘ааа’, ‘э-э-э’, ‘iii’, ‘о’ Только одна гласная и никаких других букв. правда
‘Abcefg’ «По крайней мере, один гласный и несколько согласных» правда
‘Mnklp’ Только согласные. ложный
«» Пустая строка (без букв) ложный
‘Abcde55345 & ??’ Гласные, согласные, цифры и знаки препинания. правда
‘423432 %%% ^ &’ Только цифры и знаки препинания. ложный
‘AEIOU’ Только верхний регистр гласных. правда
‘AeiOuuuA’ Только верхний регистр и нижние гласные. правда
‘ABCDEFGHI’ Верхний и нижний регистр гласных и согласных. правда
‘BCDFG’ Только в верхнем регистре. ложный
» Только пробельные символы. ложный

Вам решать, какие примеры добавить в ваш файл спецификаций. Есть много условий для тестирования, вам нужно определить, какое подмножество условий является наиболее важным и тестирует ваш код лучше всего.

Команда rspec предлагает много разных опций, чтобы увидеть их все, наберите rspec -help. В следующей таблице перечислены наиболее популярные варианты и описано, что они делают.

Sr.No. Опция / флаг и описание
1

-Я ПУТЬ

Добавляет PATH к пути загрузки (требуется), который rspec использует при поиске исходных файлов Ruby.

2

-r, -require PATH

Добавляет определенный исходный файл, который требуется в вашей спецификации. файл (ы).

3

—fail-быстро

С этой опцией rspec прекратит запуск спецификаций после сбоя первого примера. По умолчанию rspec запускает все указанные файлы спецификаций, независимо от количества сбоев.

4

-f, —формат FORMATTER

Эта опция позволяет вам указать разные выходные форматы. См. Раздел «Форматтеры» для более подробной информации о форматах вывода.

5

-о, -из ФАЙЛА

Эта опция указывает rspec записывать результаты теста в выходной файл FILE вместо стандартного вывода.

6

-c, —color

Включает цвет в выводе rspec. Успешные примеры будут отображаться зеленым цветом, ошибки — красным.

7

-b, —backtrace

Отображает полные ошибки в выводе rspec.

8

-w, — предупреждения

Отображает предупреждения Ruby в выводе rspec.

9

-P, —pattern PATTERN

Загрузите и запустите файлы спецификаций, которые соответствуют шаблону PATTERN. Например, если вы передадите -p «* .rb», rspec запустит все файлы Ruby, а не только те, которые заканчиваются на «_spec.rb».

10

-e, — пример STRING

Эта опция указывает rspec запускать все Примеры, которые содержат текст STRING в своих описаниях.

11

-t, —tag TAG

С этой опцией rspec будет запускать только примеры, содержащие тег TAG. Обратите внимание, что TAG указан как символ Ruby. См. Раздел «Теги RSpec» для более подробной информации.

-Я ПУТЬ

Добавляет PATH к пути загрузки (требуется), который rspec использует при поиске исходных файлов Ruby.

-r, -require PATH

Добавляет определенный исходный файл, который требуется в вашей спецификации. файл (ы).

—fail-быстро

С этой опцией rspec прекратит запуск спецификаций после сбоя первого примера. По умолчанию rspec запускает все указанные файлы спецификаций, независимо от количества сбоев.

-f, —формат FORMATTER

Эта опция позволяет вам указать разные выходные форматы. См. Раздел «Форматтеры» для более подробной информации о форматах вывода.

-о, -из ФАЙЛА

Эта опция указывает rspec записывать результаты теста в выходной файл FILE вместо стандартного вывода.

-c, —color

Включает цвет в выводе rspec. Успешные примеры будут отображаться зеленым цветом, ошибки — красным.

-b, —backtrace

Отображает полные ошибки в выводе rspec.

-w, — предупреждения

Отображает предупреждения Ruby в выводе rspec.

-P, —pattern PATTERN

Загрузите и запустите файлы спецификаций, которые соответствуют шаблону PATTERN. Например, если вы передадите -p «* .rb», rspec запустит все файлы Ruby, а не только те, которые заканчиваются на «_spec.rb».

-e, — пример STRING

Эта опция указывает rspec запускать все Примеры, которые содержат текст STRING в своих описаниях.

-t, —tag TAG

С этой опцией rspec будет запускать только примеры, содержащие тег TAG. Обратите внимание, что TAG указан как символ Ruby. См. Раздел «Теги RSpec» для более подробной информации.

RSpec — Matchers

Если вы помните наш оригинальный пример Hello World, он содержал строку, которая выглядела так:

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

Ключевое слово eql — это RSpec «matcher». Здесь мы представим другие типы сопоставителей в RSpec.

Равенство / Идентичность

Сопоставители для проверки на предмет или равенство значений.

Сличитель Описание пример
уравнение Проходит, когда актуально == ожидается ожидаемый (фактический). к ожидаемому
EQL Проходит, когда актуально. ожидаемый (фактический). до ожидаемого
быть Проходит, когда актуально. ожидать (факт). быть ожидаемым
равный Также проходит, когда фактический.?? (Ожидается) ожидаемый (фактический). равный ожидаемому

пример

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

Когда приведенный выше код будет выполнен, он выдаст следующий вывод. Количество секунд может немного отличаться на вашем компьютере —

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

Сравнители

Сопоставители для сравнения со значениями.

Сличитель Описание пример
> Проходит, когда факт> ожидается ожидать (фактическое). быть> ожидаемым
> = Проходит, когда актуально> = ожидается ожидать (фактическое). быть> = ожидается
< Проходит, когда фактический <ожидается ожидать (фактическое). быть <ожидается
<= Проходит, когда фактический <= ожидаемый ожидать (фактическое). быть <= ожидается
be_between включительно Проходит, когда фактическое значение <= min и> = max ожидаемый (фактический) .в be_between (min, max) .inclusive
be_between эксклюзив Проходит, когда фактический <min и> max ожидаемый (фактический) .в be_between (min, max) .exclusive
матч Проходит, когда фактическое соответствует регулярному выражению ожидать (фактическое). к совпадению (/ regex /)

пример

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

Когда приведенный выше код будет выполнен, он выдаст следующий вывод. Количество секунд может немного отличаться на вашем компьютере —

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

Сопоставители классов / типов

Сопоставители для проверки типа или класса объектов.

Сличитель Описание пример
be_instance_of Проходит, когда фактический является экземпляром ожидаемого класса. ожидаемый (фактический) .в be_instance_of (ожидаемый)
be_kind_of Проходит, когда фактический является экземпляром ожидаемого класса или любого из его родительских классов. ожидаемый (фактический) .to be_kind_of (ожидаемый)
respond_to Проходит, когда фактическое отвечает на указанный метод. ожидаемый (фактический) .to response_to (ожидаемый)

пример

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

Когда приведенный выше код будет выполнен, он выдаст следующий вывод. Количество секунд может немного отличаться на вашем компьютере —

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

True / False / Nil Matchers

Соответствует для проверки, является ли значение истинным, ложным или нулевым.

Сличитель Описание пример
быть правдой Проходит, когда актуально == правда ожидать (фактическое). быть правдой
быть ложным Проходит, когда актуально == ложно ожидать (фактическое). быть ложным
be_truthy Проходит, когда фактический не ложь или ноль ожидать (фактическое). to be_truthy
be_falsey Проходит, когда фактическое значение равно false или равно нулю ожидать (фактический) .в be_falsey
be_nil Проходит, когда фактический ноль ожидать (фактический) .в be_nil

пример

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

Когда приведенный выше код будет выполнен, он выдаст следующий вывод. Количество секунд может немного отличаться на вашем компьютере —

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

Сопоставление ошибок

Сопоставители для тестирования, когда блок кода вызывает ошибку.

Сличитель Описание пример
raise_error (ErrorClass) Проходит, когда блок вызывает ошибку типа ErrorClass. ожидать {блок} .в поднять_ошибку (ErrorClass)
повышение_ответа («сообщение об ошибке») Проходит, когда блок выдает ошибку с сообщением «error error». Ожидаем {block} .to повысить_error («сообщение об ошибке»)
повышение_еррор (ErrorClass, «сообщение об ошибке») Проходит, когда блок выдает ошибку типа ErrorClass с сообщением «error error» wait {block} .to повысить_error (ErrorClass, «сообщение об ошибке»)

пример

Сохраните следующий код в файл с именем error_matcher_spec.rb и запустите его с помощью этой команды — 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

Когда приведенный выше код будет выполнен, он выдаст следующий вывод. Количество секунд может немного отличаться на вашем компьютере —

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

RSpec — Test Doubles

В этой главе мы обсудим RSpec Doubles, также известный как RSpec Mocks. Двойник — это объект, который может «стоять» за другим объектом. Вам, наверное, интересно, что именно это означает и зачем вам это нужно.

Допустим, вы создаете приложение для школы, и у вас есть класс, представляющий класс учащихся, и другой класс для учащихся, то есть у вас есть класс и класс ученика. Сначала вам нужно написать код для одного из классов, так что давайте начнем с класса Classroom —

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

Это простой класс, у него есть один метод list_student_names, который возвращает разделенную запятыми строку имен учеников. Теперь мы хотим создать тесты для этого класса, но как нам это сделать, если мы еще не создали класс Student? Нам нужен тест Double.

Кроме того, если у нас есть «фиктивный» класс, который ведет себя как объект Student, то наши тесты ClassRoom не будут зависеть от класса Student. Мы называем это тестом изоляции.

Если наши тесты ClassRoom не полагаются на какие-либо другие классы, то, когда тест не пройден, мы сразу можем знать, что в нашем классе ClassRoom есть ошибка, а не какой-то другой класс. Имейте в виду, что в реальном мире вы можете создавать класс, который должен взаимодействовать с другим классом, написанным кем-то другим.

Именно здесь RSpec Doubles (mocks) становятся полезными. Наш метод list_student_names вызывает метод name для каждого объекта Student в его переменной-члене @students. Поэтому нам нужен Double, который реализует метод имени.

Вот код для ClassRoom вместе с примером RSpec (test), но обратите внимание, что класс 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

Когда приведенный выше код будет выполнен, он выдаст следующий вывод. Прошедшее время может немного отличаться на вашем компьютере —

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

Как вы можете видеть, использование двойного теста позволяет вам тестировать ваш код, даже если он использует класс, который не определен или недоступен. Кроме того, это означает, что при сбое теста вы можете сразу сказать, что это связано с проблемой в вашем классе, а не с классом, написанным кем-то другим.

RSpec — заглушки

Если вы уже читали раздел о RSpec Doubles (он же Mocks), значит, вы уже видели заглушки RSpec. В RSpec заглушку часто называют заглушкой метода, это особый тип метода, который «заменяет» существующий метод или метод, который еще даже не существует.

Вот код из раздела на 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

В нашем примере метод allow () предоставляет заглушки метода, которые нам нужны для проверки класса ClassRoom. В этом случае нам нужен объект, который будет действовать как экземпляр класса Student, но этот класс на самом деле не существует (пока). Мы знаем, что класс Student должен предоставить метод name (), и мы используем allow () для создания заглушки метода для name ().

Стоит отметить, что синтаксис RSpec с годами немного изменился. В более старых версиях RSpec вышеприведенные заглушки метода были бы определены так:

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

Давайте возьмем приведенный выше код и заменим две строки allow () старым синтаксисом 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

Вы увидите этот вывод, когда вы выполните приведенный выше код —

.
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

Рекомендуется использовать новый синтаксис allow (), когда вам нужно создать заглушки методов в ваших примерах RSpec, но мы предоставили здесь более старый стиль, чтобы вы могли его распознать, если увидите.

RSpec — крючки

Когда вы пишете модульные тесты, часто удобно запускать код установки и удаления до и после ваших тестов. Код настройки — это код, который настраивает или «устанавливает» условия для теста. Разрушающий код выполняет очистку, он гарантирует, что среда находится в согласованном состоянии для последующих тестов.

Вообще говоря, ваши тесты должны быть независимы друг от друга. Когда вы запускаете весь набор тестов, и один из них дает сбой, вы хотите быть уверены, что он потерпел неудачу, потому что в тестируемом коде есть ошибка, а не потому, что предыдущий тест оставил среду в несовместимом состоянии.

Наиболее распространенные хуки, используемые в RSpec — это хуки до и после. Они предоставляют способ определения и запуска кода установки и разрыва, который мы обсуждали выше. Давайте рассмотрим этот пример кода —

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

Когда вы запустите этот код, вы получите следующий вывод:

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

Давайте внимательнее посмотрим на то, что происходит. Метод before (: each) — это место, где мы определяем код установки. Когда вы передаете аргумент: each, вы инструктируете метод before запускаться перед каждым примером в вашей группе примеров, т.е. двумя блоками it внутри блока description в приведенном выше коде.

В строке: @simple_class = SimpleClass.new мы создаем новый экземпляр класса SimpleClass и присваиваем его переменной экземпляра объекта. Какой объект вам может быть интересно? RSpec создает специальный класс за кулисами в области блока описания. Это позволяет вам присваивать значения переменным экземпляра этого класса, к которым вы можете обращаться внутри блоков it в ваших примерах. Это также облегчает написание более чистого кода в наших тестах. Если для каждого теста (примера) требуется экземпляр SimpleClass, мы можем поместить этот код в ловушку before и не добавлять его в каждый пример.

Обратите внимание, что строка «Создание нового экземпляра класса SimpleClass» записывается в консоль дважды, это показывает, что до вызова ловушки в каждом из блоков it .

Как мы уже упоминали, RSpec также имеет хук после и оба хука до и после могут принимать: все в качестве аргумента. Хук после будет работать после указанной цели. Цель: all означает, что ловушка будет выполняться до / после всех примеров. Вот простой пример, который иллюстрирует, когда вызывается каждый хук.

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

Когда вы запустите приведенный выше код, вы увидите этот вывод —

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

RSpec — Теги

Теги RSpec предоставляют простой способ запуска определенных тестов в ваших спецификационных файлах. По умолчанию RSpec запускает все тесты в специфицированных файлах, которые он запускает, но вам может потребоваться запустить только их подмножество. Допустим, у вас есть несколько тестов, которые выполняются очень быстро, и вы только что внесли изменения в код своего приложения и хотите просто запустить быстрые тесты, этот код продемонстрирует, как это сделать с помощью тегов 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

Теперь сохраните приведенный выше код в новый файл с именем tag_spec.rb. Из командной строки выполните эту команду: rspec —tag slow tag_spec.rb

Вы увидите этот вывод —

Параметры запуска: include {: slow => true}

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

Затем выполните эту команду: rspec —tag fast tag_spec.rb

Вы увидите этот вывод —

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

Как видите, теги RSpec упрощают проведение подмножества тестов!

RSpec — Предметы

Одна из сильных сторон RSpec заключается в том, что она предоставляет множество способов написания тестов, очистки тестов. Когда ваши тесты короткие и беспорядочные, становится легче сосредоточиться на ожидаемом поведении, а не на деталях написания тестов. Предметы RSpec — это еще один ярлык, позволяющий писать простые простые тесты.

Рассмотрим этот код —

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

Это на самом деле довольно ясно, как есть, но мы могли бы использовать функцию субъекта RSpec, чтобы уменьшить количество кода в примере. Мы делаем это, перемещая экземпляр объекта person в строку описания.

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

Когда вы запустите этот код, вы увидите этот вывод —

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

Обратите внимание, насколько проще второй пример кода. Мы взяли один блок it в первом примере и заменили его двумя блоками it, которые в итоге требуют меньше кода и так же понятны.

RSpec — Помощники

Иногда вашим примерам RSpec нужен простой способ поделиться повторно используемым кодом. Лучший способ сделать это с помощью помощников. Помощники — это обычные методы Ruby, которыми вы делитесь в примерах. Чтобы проиллюстрировать преимущества использования помощников, давайте рассмотрим этот код —

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

Этот код понятен, но всегда полезно сокращать повторяющийся код, когда это возможно. Мы можем взять приведенный выше код и уменьшить часть этого повторения с помощью вспомогательного метода с именем 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

Когда вы запустите приведенный выше код, вы увидите этот вывод —

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

Как видите, мы смогли продвинуть логику создания и перемещения объекта собаки в помощника, что позволяет нашим примерам быть короче и чище.

RSpec — метаданные

RSpec — гибкий и мощный инструмент. Функциональность метаданных в RSpec не является исключением. Метаданные обычно относятся к «данным о данных». В RSpec это означает данные о вашем описании , контексте и блокировках .

Давайте посмотрим на пример —

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

Когда вы запустите приведенный выше код, вы увидите этот вывод —

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

Метаданные позволяют назначать переменные в различных областях в файлах RSpec. Переменная example.metadata — это хэш Ruby, который содержит другую информацию о ваших примерах и группах примеров.

Например, давайте перепишем приведенный выше код, чтобы он выглядел так:

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 

Когда мы запускаем этот код, мы видим все значения в хеше 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

Скорее всего, вам не нужно будет использовать все эти метаданные, но посмотрите полное значение описания —

Группа примеров с переменной метаданных и контекстом с другой переменной может обращаться к переменной метаданных в блоке контекста.

Это предложение, созданное на основе описания блока описания + содержащегося в нем описания блока контекста + описания блока it .

Интересно отметить, что эти три строки читаются как обычное английское предложение. , , которая является одной из идей RSpec, имея тесты, которые звучат как английские описания поведения.

RSpec — фильтрация

Возможно, вы захотите прочитать раздел о метаданных RSpec, прежде чем читать этот раздел, потому что, как оказалось, фильтрация RSpec основана на метаданных RSpec.

Представьте, что у вас есть файл спецификации, и он содержит два типа тестов (Примеры): положительные функциональные тесты и отрицательные (ошибки) тесты. Давайте определим их так:

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

Теперь сохраните приведенный выше текст в виде файла с именем filter_spec.rb и запустите его с помощью этой команды:

rspec filter_spec.rb

Вы увидите вывод, который выглядит примерно так:

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

А что если мы захотим повторно запустить только положительные тесты в этом файле? Или только отрицательные тесты? Мы можем легко сделать это с RSpec Filters. Измените приведенный выше код на это —

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

Сохраните ваши изменения в filter_spec.rb и выполните эту немного другую команду —

rspec --tag positive filter_spec.rb

Теперь вы увидите вывод, который выглядит следующим образом —

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

Указывая —tag positive, мы говорим RSpec запускать примеры только с определенной переменной метаданных: positive. Мы могли бы сделать то же самое с отрицательными тестами, запустив такую ​​команду:

rspec --tag negative filter_spec.rb

Имейте в виду, что это только примеры, вы можете указать фильтр с любым именем, которое вы хотите.

Форматеры RSpec

Форматеры позволяют RSpec отображать результаты тестов различными способами. Давайте создадим новый файл RSpec, содержащий этот код —

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

Теперь сохраните это в файл с именем formatter_spec.rb и выполните команду RSpec —

rspec formatter_spec.rb

Вы должны увидеть результат, который выглядит следующим образом —

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

Теперь запустите ту же команду, но на этот раз укажите форматер, например:

rspec --format progress formatter_spec.rb

Вы должны увидеть тот же результат на этот раз —

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

Причина в том, что форматер «progress» является форматером по умолчанию. Давайте попробуем другой форматтер дальше, попробуйте запустить эту команду —

rspec --format doc formatter_spec.rb

Теперь вы должны увидеть этот вывод —

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

Как вы можете видеть, выходные данные в формататоре «doc» сильно отличаются. Этот форматтер представляет вывод в стиле, похожем на документацию. Вам может быть интересно, как выглядят эти параметры, когда у вас есть сбой в тесте (Пример). Давайте изменим код в formatter_spec.rb, чтобы он выглядел так:

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

Ожидаемое ожидание (1 + 1). Уравнение (1) должно потерпеть неудачу. Сохраните свои изменения и повторно запустите вышеупомянутые команды —

rspec — отформатируйте прогресс formatter_spec.rb и запомните, поскольку форматер «progress» используется по умолчанию, вы можете просто запустить: rspec formatter_spec.rb . Вы должны увидеть этот вывод —

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

Теперь давайте попробуем doc formatter, запустим эту команду —

rspec --format doc formatter_spec.rb

Теперь, с неудачным тестом, вы должны увидеть этот вывод —

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

Неудачные примеры

rspec ./formatter_spec.rb:3 # Файл спецификаций, демонстрирующий работу RSpec Formatters при выполнении некоторых тестов, тест обычно вызывает метод hope () хотя бы один раз.

Форматеры RSpec предоставляют возможность изменить способ отображения результатов теста, даже возможно создать собственный форматтер, но это более сложная тема.

RSpec — ожидания

Когда вы изучаете RSpec, вы можете много читать об ожиданиях, и это может сначала немного запутать. Есть две основные детали, которые вы должны иметь в виду, когда видите термин «ожидание»:

  • Ожидание — это просто оператор в блоке it, который использует метод wait () . Вот и все. Это не сложнее, чем это. Когда у вас есть код, подобный этому: ожидайте (1 + 1). К уравнению (2) , у вас есть ожидание в вашем примере. Вы ожидаете, что выражение 1 + 1 оценивается как 2 . Хотя формулировка важна, поскольку RSpec является тестовой средой BDD. Называя это утверждение ожиданием, становится ясно, что ваш код RSpec описывает «поведение» кода, который он тестирует. Идея состоит в том, что вы выражаете, как должен вести себя код таким образом, который читается как документация.

  • Синтаксис ожидания является относительно новым. До того, как был введен метод wait () (еще в 2012 году), RSpec использовал другой синтаксис, основанный на методе must () . Вышеуказанное ожидание записывается так в старом синтаксисе: (1 + 1) .should eq (2) .

Ожидание — это просто оператор в блоке it, который использует метод wait () . Вот и все. Это не сложнее, чем это. Когда у вас есть код, подобный этому: ожидайте (1 + 1). К уравнению (2) , у вас есть ожидание в вашем примере. Вы ожидаете, что выражение 1 + 1 оценивается как 2 . Хотя формулировка важна, поскольку RSpec является тестовой средой BDD. Называя это утверждение ожиданием, становится ясно, что ваш код RSpec описывает «поведение» кода, который он тестирует. Идея состоит в том, что вы выражаете, как должен вести себя код таким образом, который читается как документация.

Синтаксис ожидания является относительно новым. До того, как был введен метод wait () (еще в 2012 году), RSpec использовал другой синтаксис, основанный на методе must () . Вышеуказанное ожидание записывается так в старом синтаксисе: (1 + 1) .should eq (2) .

Вы можете столкнуться со старым синтаксисом RSpec для Ожиданий при работе со старым кодом или более старой версией RSpec. Если вы используете старый синтаксис с новой версией RSpec, вы увидите предупреждение.

Например, с этим кодом —

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

Когда вы запустите его, вы получите вывод, который выглядит следующим образом —

. 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

Если от вас не требуется использовать старый синтаксис, настоятельно рекомендуется использовать функцию ожидаем () вместо необходимости ().