Запустите ruby ​​отладчик, если тест rspec не пройден

Часто, когда тест не проходит, я провожу довольно много времени, пытаясь выяснить причину его провала. Было бы полезно, если бы RSpec мог запустить отладчик Ruby при неудачном завершении теста, чтобы я мог сразу же проверить локальные переменные, чтобы выяснить причину.

Обходной путь, который я сейчас использую, выглядит примерно так:

# withing some test
debugger unless some_variable.nil?
expect(some_variable).to be_nil

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

Изменить: я пробовал Плимут. Это не сработало достаточно надежно для меня. Также история развития, кажется, указывает на то, что это не очень хорошо поддерживаемый гем, поэтому я бы предпочел не полагаться на него.

Обновление: я попробовал pry-rescue и найти его аккуратным. Тем не менее, я часто использую Zeus, и мне было интересно, есть ли способ заставить его работать с pry-rescue,

7 ответов

Решение

Используйте спасение, это духовный преемник Плимута:

Из файла Readme:

Если вы используете RSpec или respec, вы можете открыть сеанс pry при каждом сбое теста, используя rescue rspec или rescue respec:

$ rescue rspec
From: /home/conrad/0/ruby/pry-rescue/examples/example_spec.rb @ line 9 :

     6:
     7: describe "Float" do
     8:   it "should be able to add" do
 =>  9:     (0.1 + 0.2).should == 0.3
    10:   end
    11: end

RSpec::Expectations::ExpectationNotMetError: expected: 0.3
     got: 0.30000000000000004 (using ==)
[1] pry(main)>

Мне нравится решение @jon-rowe (дополнительные гемы не нужны) с небольшим редактированием: я действительно не забочусь о других ошибках так, как RSpec::Expectations::ExpectationNotMetError,

  config.around(:each) do |example|
    example.run.tap do |result|
      debugger if result.is_a?(RSpec::Expectations::ExpectationNotMetError)
    end
  end

Вы не получите доступ к локальным переменным (легко) без debugger находясь в области блока, однако RSpec предоставляет вам вокруг хуков, которые позволят вам сделать это:

config.around(:each) do |example|
  result = example.run
  debugger if result.is_a?(Exception)
  puts "Debugging enabled"
end

Затем у вас есть доступ к @ivars а также subject / let(:var) содержание на данный момент.

Из документации Rspec:

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

Что я делаю, так это вызываю любопытство в этом сообщении. См. Пример:

      describe "failing" do
  context "test" do
    it "should start pry" do
      a = 3
      b = 1
      expect(a).to be == b, "#{require 'pry';binding.pry}"
    end
  end
end

Удачной отладки!

Вам нужно перехватить исключение ExpectationNotMatched во время его создания. Включите в свои помощники следующий код, и RSpec остановится при создании исключения. Это будет несколько уровней глубоко внутри совпадений, поэтому в отладчике скажите "где", затем "до 5" или "до 6", и вы будете внутри instance_exec вашего блока. Отладчик некорректно отображает код в используемой версии, но вы можете еще раз "подняться" и перейти к коду, работающему в том же контексте, где оценивается ваш тест, так что вы можете проверить переменные экземпляра (но не локальные переменные, кажется).

require 'debugger'
require 'rspec'

Debugger.start
class RSpec::Expectations::ExpectationNotMetError
  alias_method :firstaid_initialize, :initialize

  def initialize *args, &b
    send(:firstaid_initialize, *args, &b)
    puts "Stopped due to #{self.class}: #{message} at "+caller*"\n\t"
    debugger
    true # Exception thrown
  end
end

describe "RSpec" do
  it "should load use exceptions on should failure" do
    @foo = :bar    # An instance variable I can examine
    1.should == 2
  end
end

Для этого вы можете использовать камень Плимута https://github.com/banister/plymouth. Это использует pry, хотя (лучшая) альтернатива irb.

НТН

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

Другие вопросы по тегам