【发布时间】:2017-07-24 15:51:24
【问题描述】:
关于使用 Minitest 将方法分派到错误的类,我遇到了一个非常奇怪的问题。
我正在帮助维护 dnsruby 库 (https://github.com/alexdalitz/dnsruby),我们有一个间歇性失败的特定测试 (https://github.com/alexdalitz/dnsruby/blob/master/test/tc_resolv.rb#L56)。
通过在 pry 中设置断点,我发现当它失败时,它使用的是内部 Ruby Resolv 类的 getname 方法,而不是代码中指定的 Dnsruby::Resolv 类。 ::Resolv 和 Dnsruby::Resolv 似乎都指向 Ruby 内部的 Resolv 类:
[1] pry(#<TestResolv>)> ::Resolv.object_id
=> 70320518250220
[2] pry(#<TestResolv>)> Dnsruby::Resolv.object_id
=> 70320518250220
单独运行测试时不会发生错误 (ruby test/tc_resolv.rb)。当与其他测试结合使用时(使用ruby test/ts_online.rb 并修改其正在运行的测试文件列表),它通常会失败但有时不会。我发现似乎与失败相关的唯一因素是运行的测试代码量;运行的测试越多,失败的可能性就越大。
当测试成功时,::Resolv 甚至没有被定义:
[1] pry(#<TestResolv>)> ::Resolv.object_id
NameError: uninitialized constant Resolv
我在我们的代码库中搜索了require 'resolv',但没有找到。也许我们正在使用的另一个库需要它。尽管如此,Dnsruby::Resolv 中的Dnsruby:: 不应该指定我们自定义的Resolv 类吗?
我们如何解决这个问题?
【问题讨论】:
-
我想一旦你发现谁需要解决,就更容易发现那里发生了什么。您是否尝试过在 resolv.rb 中提出错误以便查看需要的位置?
-
有趣的想法。我这样做并找到了一个需要它的测试文件。但是,当我只测试那个文件和有问题的测试文件时,并没有发生错误; ::Resolv 和 Dnsruby::Resolv 都可用,但指向正确的(即不同的)类,并且测试通过了。所以问题不在于需要'resolv',而是在某些情况下,Dnsruby::Resolv 被覆盖以指向 ::Resolv。
-
您可以使用
TracePoint或set_trace_func来检查它是否被某个类覆盖。 -
我只是简单地查看了 github 问题。会不会,问题实际上与赛璐珞有关?两个并发实例,或者没有正确关闭或类似的东西?测试套件中有两个
Celluloid.boot但没有Celluloid.shutdown调用。 -
@phoet 感谢您的建议。我在 github.com/alexdalitz/dnsruby/issues/122 上打开了一个关于您发现的赛璐珞问题的新 Github 问题。