根本的な問題は、(独自のモジュールを介して)ipython
奇妙なトリックを実行するため、その時点で「疑わしいモジュール」がそこに存在しないことです。したがって、doctestはそれに再帰しません。__main__
FakeModule
doctest
__dict__
Foo
これが1つの解決策です:
class Foo():
"""
>>> 3+2
5
"""
if __name__ in ("__main__", "__console__"):
import doctest, inspect, sys
m = sys.modules['__main__']
m.__test__ = dict((n,v) for (n,v) in globals().items()
if inspect.isclass(v))
doctest.testmod(verbose=True)
これは、要求に応じて生成されます。
$ ipython dot.py
Trying:
3+2
Expecting:
5
ok
1 items had no tests:
__main__
1 items passed all tests:
1 tests in __main__.__test__.Foo
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)
[[ snip snip ]]
In [1]:
グローバルを設定するだけでは機能しません__test__
。これも、考えているもののグローバルとして設定しても、によって復元される実際のオブジェクトには実際__main__
には配置されないためです。後者は、式が内部で使用しているものとまったく同じです(実際にはを使用しますが、そこに存在することがわかっているので、ここでは特別な注意は必要ありません...それはあなたが期待するオブジェクトではありません!-)。__dict__
m = sys.modules['__main__']
doctest
sys.modules.get
__main__
sys.modules
また、m.__test__ = globals()
別の理由で、直接設定するだけでも機能しません。doctest
の値__test__
が文字列、関数、クラス、またはモジュールであることを確認します。いくつかの選択がないglobals()
と、その条件を満たすことを保証できません(実際には機能しません)。 。ここでは、クラスのみを選択しています。関数なども必要な場合は、呼び出し内のgenexpor
の句でinを使用できます。if
dict
スクリプトを実行できるDjangoシェルをどのように実行しているかは正確にはわかりません(python manage.py shell
引数を受け入れないと思うので、何か他のことをしている必要があり、正確に何を推測することはできません!-)。同様のアプローチが役立つはずです(Djangoシェルがipythonを使用している場合でも、使用可能な場合はデフォルトであるか、プレーンPythonを使用している場合でも):__test__
取得したオブジェクトを適切に設定しますsys.modules['__main__']
(または__console__
、それがdoctest.testmodに渡される場合はI推測)は、doctestがテスト文字列を見つけるために内部で実行することを模倣しているため、機能するはずです。
そして、結論として、デザイン、アーキテクチャ、シンプルさ、透明性、そして「黒魔術」についての哲学的考察...:
このすべての努力は、基本的に、ipython(およびおそらくその部分をipythonに委任しているだけかもしれませんがDjango)があなたの「便利さ」のためにあなたに代わって行っている「黒魔術」を打ち負かすために必要なものです...いつでも2つのフレームワーク(またはそれ以上;-)がそれぞれ独自の黒魔術を独立して実行しているため、相互運用性は突然かなりの労力を必要とし、便利なものになる可能性があります;-)。
黒魔術、内省、偽のモジュールなどがなければ、同じ便利さが(ipython、django、および/またはdoctestのいずれか1つ以上によって)提供された可能性があると言っているのではありません。これらの各フレームワークの設計者と保守担当者は優れたエンジニアであり、宿題を徹底的に行い、必要と判断したユーザーの利便性を実現するために不可欠な最小限の黒魔術のみを実行していると思います。それにもかかわらず、そのような状況でも、フレームワークの作成者が考えていたものから少しでも外れたことをしたいと思うとすぐに、「黒魔術」は便利さの夢からデバッグの悪夢に突然変わります。
OK、この場合は悪夢ではないかもしれませんが、この質問はしばらく開いていて、賞金の誘惑があってもまだ多くの答えが得られていないことに気づきました-あなたは今2つの答えを選ぶことができますがから、doctestの__test__
特別な機能を使用して、@codeapeはironpythonの固有の__IP.magic_run
機能を使用しています。内部または文書化されていないものに依存しないので、私は私の方が好き__test__
です-doctestの文書化された機能ですが、__IP
これら2つの迫り来る主要なアンダースコアで、私に「深い内部、触れないでください」と叫びます;-) ... if次のポイントリリースで壊れます。私はまったく驚かないでしょう。それでも、好みの問題-その答えは間違いなくより「便利」であると考えられるかもしれません。
しかし、これはまさに私のポイントです。単純さ、透明性、および/または内部/文書化されていない/不安定な機能の回避という点で、利便性は莫大な代償を伴う可能性があります。したがって、私たち全員への教訓として、私たちが逃げることができる最小の黒魔術&c(あちこちで便利なイプシロンをあきらめることを犠牲にしても)、私たち全員が長期的には幸せになるでしょう(そして将来的に現在の取り組みを活用する必要のある他の開発者をより幸せにするでしょう)。