Watir中封装Begin/Rescue至函数后无法捕获异常的问题求助
一、最初封装函数失效的原因
你第一次封装的函数之所以没生效,核心问题出在参数求值时机上:
当你调用exception_check(browser.select_list(:id => "P5500_P_NATIONALITY").select("Americans"))时,Ruby会先执行括号里的browser.select_list(...).select代码,再把结果传给函数。也就是说,异常在进入函数的begin块之前就已经触发了,自然不会被函数内部的rescue捕获。
你后来改成用yield传递代码块的思路是完全正确的——这样代码会在函数内部的begin块里执行,异常才会进入捕获范围。
二、为什么用yield后仍然没捕获到异常?
从你贴出的错误日志来看,抛出的异常确实是你指定要捕获的Watir::Exception::UnknownObjectException和Watir::Wait::TimeoutError,但rescue块没有生效,大概率是因为rescue块内部的代码本身出错了:
你的exception_check函数是一个独立的作用域,无法直接访问外部的browser、test_id这些局部变量。当rescue块尝试调用screenCapture(browser,...)或者log_fileWriter(...,test_id)时,会因为找不到这些变量而抛出NameError,这个新的异常会覆盖原本的Watir异常,让你误以为捕获逻辑失效。
三、修复方案
1. 传递必要变量到函数作用域
把browser和test_id作为参数传给异常处理函数,确保rescue块能访问到它们:
def exception_check(browser, test_id) yield rescue Watir::Wait::TimeoutError, Watir::Exception::UnknownObjectException, Watir::Exception::NoValueFoundException puts "Error handling caught an exception: Relationships Page. See log." log_fileWriter("after_header","Relationship Page:",$exception_error_code,"2",test_id) screenCapture(browser,"Add Relationship",test_id) end # 调用时传入变量 exception_check(browser, test_id) { browser.select_list(:id => "P5500_P_NATIONALITY").select("Americans") }
2. 先验证基础捕获逻辑
如果还是不确定问题,可以先简化rescue块,排除其他代码的干扰,验证捕获功能是否正常:
def exception_check yield rescue => e puts "Caught exception: #{e.class} - #{e.message}" end # 测试错误场景 exception_check { browser.text_field(:name => "qq").set("watir") }
如果这段代码能正常打印出异常信息,说明之前的问题确实出在rescue块里的log_fileWriter或screenCapture调用上。
3. 可选:使用实例变量(如果适合你的代码结构)
如果不想每次都传参数,可以把browser、test_id改成实例变量(比如@browser、@test_id),这样函数内部就能直接访问到它们。
内容的提问来源于stack exchange,提问作者bobbie_j

