![](/img/trans.png)
[英]ruby - is there a way to add code to run after each method definition
[英]Is it possible to run code after each line in Ruby?
我知道可以在ruby中使用掛鈎之前和之后修飾方法,但是是否可以為給定方法的每一行執行此操作?
例如,我有一個自動化測試,我想驗證每個步驟后頁面上沒有顯示錯誤。 該錯誤顯示為紅色的div和不可見的紅寶石作為raise
之類的東西,所以我必須手動檢查它(還有其他一些使用情況以及)。
我知道使用set_trace_func
可能是可能的。 但我認為這可能會帶來更多問題而不是好處,因為它可以在整個調用樹上運行(並且需要我自己過濾它)。
更新(澄清) :
我有興趣攔截在給定方法中執行的所有操作(或調用)。 這意味着調用了未指定數量的類,因此我不能只截取任何給定的類/方法集。
它是,您可以在Ruby編程語言的第8.9節中獲得如何執行此操作的完整描述。 在每次調用方法時運行代碼涉及將方法發送到具有method_missing
實現的TracedObject
類。 每當它收到一條消息時,它就會調用method_missing
並執行你分配給它的任何代碼。 (當然,這是一般追蹤)。
這是對此過程的一般描述,您可以查閱本書了解詳細信息。
這聽起來像你想跟蹤的每個對象的每一個方法調用,但只在每次調用一個 特定方法的跨度。 在這種情況下,您可以重新定義方法以打開和關閉儀器。 首先,使用Pinochle答案中提出的通用儀器,然后重新定義所討論的方法如下:
# original definition, in /lib/foo.rb:
class Foo
def bar(baz)
do_stuff
end
end
# redefinition, in /test/add_instrumentation_to_foo.rb:
Foo.class_eval do
original_bar = instance_method(:bar)
def bar(baz)
TracedObject.install!
original_bar.bind(self).call(baz)
TracedObject.uninstall!
end
end
你需要編寫install!
和uninstall
方法,但它們應該是非常簡單的:只需設置或取消設置類變量並在檢測邏輯中檢查它。
怎么樣(只是嘗試)
class User
def initialize(name)
@name = name
end
def say_hello
puts "hello #{@name}"
end
def say_hi(friend)
puts "hi #{@name} from #{friend}"
end
def say_bye(a, b = 'Anna')
puts "bye #{a} and #{b}"
end
end
User.class_eval do
User.instance_methods(false).each do |method|
original = instance_method(method)
define_method method do |*options|
parameters = original.parameters
if parameters.empty?
original.bind(self).call
else
original.bind(self).call(*options)
end
puts __method__
end
end
end
user = User.new("John")
user.say_hello
user.say_hi("Bob")
user.say_bye("Bob")
user.say_bye("Bob", "Lisa")
輸出:
hello John
say_hello
hi John from Bob
say_hi
bye Bob and Anna
say_bye
bye Bob and Lisa
say_bye
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.