Minitestを使用して間違ったクラスへのメソッドディスパッチに関して非常に奇妙な問題が発生しています。Rubyメソッド呼び出しが間違った(トップレベルモジュール)クラスになる
私はdnsrubyライブラリ(https://github.com/alexdalitz/dnsruby)のメンテナンスを手伝っており、断続的に失敗する特定のテストがあります(https://github.com/alexdalitz/dnsruby/blob/master/test/tc_resolv.rb#L56)。
てこにブレークポイントを設定することで、私はそれが失敗したとき、それは内部ルビー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
には、Resolv
クラスを指定しないでください。
これをどのように修正できますか?
誰かがresolvを必要としていることが分かったら、そこで起こっていることを見つけやすくなります。 resolv.rbでエラーを発生させようとしましたが、どこに必要なのか分かりましたか? – phoet
興味深いアイデア。私はそれを行い、それを必要としていたテストファイルを見つけました。しかし、そのファイルと問題のテストファイルだけをテストしたとき、エラーは発生しませんでした。 :: ResolvとDnsruby :: Resolvの両方が利用可能でしたが、正しい(つまり異なる)クラスを指していて、テストは合格しました。したがって、問題は 'resolv'が必要であるということではなく、何とかDnsruby :: Resolvが_some_の場合にはResolvを指すように上書きされているということです。 –
'TracePoint'または' set_trace_func'を使って、あるクラスによってオーバーライドされるかどうかを調べることができます。 – phoet