RSpec - это инструмент тестирования предметно-ориентированного языка (DSL), созданный для тестирования кода Ruby. Идея состоит в том, чтобы сначала написать тесты, а затем написать достаточно кода для прохождения тестов, а затем провести рефакторинг. Поскольку RSpec - это инструмент тестирования разработки, управляемого поведением (BDD), он фокусируется на описании того, что делает приложение и соответствует ли оно спецификации. RSpec действительно легко читается. Принятие подхода, основанного на тестировании, сделает вас лучшим разработчиком, поскольку заставит критически относиться к программе и ее функциям. Сегодня я покажу вам, как легко начать писать тесты с использованием RSpec.

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

gem install rspec

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

mkdir rspec_example
cd rspec_example/
rspec --init

Эта команда создаст два файла, первый находится в папке с именем spec с именем spec_helper.rb, а другой - .rspec. Внутри этой папки спецификации мы будем писать наши тесты. Мы можем начать с простого примера. Давайте попробуем создать программу-приветствие, которая запишет имя и поприветствует вас. Сначала давайте создадим рубиновый файл в главном каталоге и файл спецификации приветствия внутри папки spec.

touch greeting.rb
touch spec/greeting_spec.rb

В файле welcome.rb мы собираемся создать класс приветствия, который будет инициализирован именем.

class Greeting
  def initialize(name)
    @name = name
  end
end

Теперь, следуя тестовой разработке, давайте напишем тест для реализации приветствия. Мы хотим, чтобы у класса Greeting был метод, который будет приветствовать при вызове. Приступим к созданию тестового скелета для нашего welcome_spec.rb.

require './greeting'
RSpec.describe Greeting do

end

Сначала нам потребуется "./greeting". В тестовом файле мы описываем поведение класса. Чтобы RSpec знал, с каким классом мы имеем дело, мы должны заключить определение теста в блок RSpec.describe. Важно знать, что имя класса не является обязательным и при желании может быть заменено строкой. Слово описать является ключевым словом RSpec и используется для описания «группы примеров», которую можно рассматривать как набор тестов. Для нашей программы нам нужен метод, который будет выдавать приветствие с включенным именем. Итак, теперь мы можем приступить к описанию метода.

require './greeting'
RSpec.describe Greeting do
  describe '#greet_me' do
    it 'prints a greeting with the name' do
    end
  end
end

Ключевое слово «it» используется для определения «Example», который является нашим тестом. Как и description, он принимает имя класса или строковый аргумент и должен использоваться с аргументом блока. Внутри этого блока мы будем тестировать поведение нашей программы. Мы хотим создать новый экземпляр класса Greeting и вызвать для него метод greet_me. Затем мы должны ожидать, что он выведет приветствие. Теперь наш тест будет выглядеть так.

require './greeting'
RSpec.describe Greeting do
  describe '#greet_me' do
    it 'prints a greeting with the name' do
      greeting = Greeting.new('Ray')
      expect(greeting.greet_me).to eq('Hello Ray')
    end
  end
end

Ключевое слово expect в RSpec используется для определения «ожидания». Это шаг, на котором мы проверяем, оправдались ли определенные ожидания. Метод .eq называется сопоставителем. Когда вызывается метод greet_me и на выходе получается «Hello Ray», тест проходит. Синтаксис очень легко читается и читается почти как обычный английский. Запустите команду rspec на терминале, и вы увидите что-то вроде этого.

rspec
Failures:
1) Greeting#greet_me prints a greeting with the name
     Failure/Error: expect(greeting.greet_me).to eq('Hello Ray')
     
     NoMethodError:
       undefined method `greet_me' for #<Greeting:0x00005639ee5775c8 @name="Ray">
     # ./spec/greeting_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.00139 seconds (files took 0.06321 seconds to load)
1 example, 1 failure

Тест не прошел, потому что у нас не определен метод greet_me. Итак, давайте шаг за шагом создадим метод с именем greet_me в файле welcome.rb.

class Greeting
  def initialize(name)
    @name = name
  end
  def greet_me

  end
end

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

Failures:
1) Greeting#greet_me prints a greeting with the name
     Failure/Error: expect(greeting.greet_me).to eq('Hello Ray')
     
       expected: "Hello Ray"
            got: nil
     
       (compared using ==)
     # ./spec/greeting_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.01522 seconds (files took 0.06191 seconds to load)
1 example, 1 failure

Ошибка сообщает вам, что ожидает увидеть «Hello Ray», но вместо этого получила ноль. Возможно, вы увидите, как этот цикл обратной связи может быть полезен при создании вашего кода. Теперь, когда мы знаем, что делать дальше, давайте пройдем тест. Давайте добавим это в наш код.

class Greeting
  def initialize(name)
    @name = name
  end
  def greet_me
    "Hello #{@name}"
  end
end

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

Finished in 0.00151 seconds (files took 0.06547 seconds to load)
1 example, 0 failures

Тесты также являются важной частью документации. Вы можете запустить команду, которая покажет вам, за что отвечает метод. Таким образом, если кто-то новичок в проекте и хочет узнать больше о классе Greeting, он сможет увидеть, как он себя ведет.

rspec --format documentation

Greeting
  #greet_me
    prints a greeting with the name
Finished in 0.00095 seconds (files took 0.06487 seconds to load)
1 example, 0 failures

Тестирование поможет вам убедиться, что ваш код ведет себя именно так, как вы хотите. Этот процесс также сделает вас лучшим разработчиком. Опыт работы с RSpec упоминается в большинстве предложений о работе, поэтому это ценные знания, которые могут быть полезны для вас, если вы планируете работать в качестве разработчика Ruby. Удачи в написании тестов и удачного кодирования! 😎