Запустите отладчик ruby, если тест rspec не прошел - программирование
Подтвердить что ты не робот

Запустите отладчик 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.

4b9b3361

Ответ 1

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

Из Readme:

Если вы используете RSpec или respec, вы можете открыть сеанс pry при каждом провале теста, используя аварийный 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)>

Ответ 2

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

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

После этого у вас есть доступ к содержимому @ivars и subject/let(:var).

Ответ 3

Мне нравится решение @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

Ответ 4

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

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

Ответ 5

Вы можете использовать plymouth gem https://github.com/banister/plymouth. Он использует pry, хотя (лучше) альтернативу irb.

НТН

Ответ 6

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