Как я регистрирую каждый метод, которым это называют в программе Ruby?

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

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

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

С этим я мог начать пытаться осуществить рефакторинг его. Без него он будет очень трудной задачей разгладить его, из-за размера кодовой базы (20k + случаи модульного теста).

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

Существует ли способ зарегистрировать этот уровень детализации, не внося оптовые изменения в кодовую базу? Я взглянул на профилировщика Ruby, чтобы видеть, могло ли это помочь, и это, вероятно, могло; мне любопытно, если существует лучший путь (особенно регистрирующий имя файла, содержащее вызываемый метод).

Заранее спасибо

33
задан John Feminella 8 February 2010 в 04:49
поделиться

1 ответ

Это определенно возможно - на самом деле, есть даже способ для этого! Просто добавьте это где-нибудь в коде перед точкой, в которой вы хотите начать регистрацию:

set_trace_func proc { |event, file, line, id, binding, classname|
  printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}

Секретный соус, который вам нужен, исходит из Kernel # set_trace_func , как указано выше:

  • set_trace_func (proc) = > proc
  • set_trace_func (nil) => nil

Устанавливает proc в качестве обработчика для трассировки или отключает трассировку, если параметр равен nil . proc принимает до шести параметров: имя события, имя файла, номер строки, идентификатор объекта, привязку и имя класса. proc вызывается всякий раз, когда происходит событие. Событиями являются: c-call (вызов подпрограммы языка C), c-return (возврат из подпрограммы языка C), вызов (вызов Ruby), class (начало определения класса или модуля), end (завершение определения класса или модуля), строка (выполнение кода с новой строки ), raise (вызов исключения) и return (возврат из метода Ruby). Трассировка отключена в контексте proc.

Вот удобный пример:

class Test
  def test
    a = 1
    b = 2
  end
end

set_trace_func proc { |event, file, line, id, binding, classname|
  printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}

t = Test.new
t.test

(Примечание: не пытайтесь использовать это в irb , если вам не нужен огромный экран с прокруткой текста.) В результате вы получите:

    line test.rb:11               false
  c-call test.rb:11        new    Class
  c-call test.rb:11 initialize   Object
c-return test.rb:11 initialize   Object
c-return test.rb:11        new    Class
    line test.rb:12               false
    call test.rb:2        test     Test
    line test.rb:3        test     Test
    line test.rb:4        test     Test
  return test.rb:4        test     Test

Вы можете поиграть со строкой форматирования выше, чтобы получить только те результаты, которые вы хотите зарегистрировать (например, похоже, что вас интересуют только события call ). Надеюсь, что это поможет, и удачи в разборе всех этих модульных тестов!

60
ответ дан 27 November 2019 в 17:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: