2

いくつかの単体テストを に入れましたmysite/vncbrowser/tests.py。これらを次のように実行できます。

cd mysite
python manage.py test vncbrowser

ではtests.py、モデル クラスを次のようにインポートします。

from vncbrowser.models import Project, Stack, Integer3D, Double3D

...そして、Integer3D次のようなテストでカスタム フィールド タイプへの の挿入をテストします。

class InsertionTest(TestCase):

    def test_stack_insertion(self):
        s = Stack()
        s.title = "Example Stack"
        s.image_base = "http://foo/bar/"
        s.dimension = Integer3D(x=2048, y=1536, z=460)
        s.resolution = Double3D(x=5.0001, y = 5.0002, z=9.0003)
        s.save()
        self.assertEqual(s.id, 1)

しかし、 でテストを実行すると、ソース内ののチェックが失敗python manage.py test vncbrowserすることがわかりました。ファイルでは、 (そのファイルで以前に定義された)への裸の参照には完全な名前があり、テストから渡されたオブジェクトには完全な名前があるようです。isinstance(value, Integer3D)models.pymodels.pyInteger3Dvncbrowser.models.Integer3Dmysite.vncbrowser.models.Integer3D

models.pyいくつかのデバッグ ステートメントからの関連コードは次のとおりです。

class Integer3D(object):
    [... elided ...]

class Integer3DField(models.Field):
    def to_python(self, value):
        a = Integer3D()
        print >> sys.stderr, "value is %s, of type %s" % (value, type(value))
        print >> sys.stderr, "but a new Integer3D instance is", type(a)
        if isinstance(value, Integer3D):
            print >> sys.stderr, "isinstance check worked"
            return value
        print >> sys.stderr, "isinstance check failed"

...この出力を生成します(明確にするためにいくつかの改行とスペースが追加されています):

value is <vncbrowser.models.Integer3D object at 0x22bbf90>, of type
      <class 'vncbrowser.models.Integer3D'>

but a new Integer3D instance is
      <class 'mysite.vncbrowser.models.Integer3D'>

isinstance check failed

インポートを次のように変更することで、このテストを機能させることができますtests.py

 from mysite.vncbrowser.models import Project, Stack, Integer3D, Double3D

mysite...しかし、ファイルに資格が必要な理由がわかりませんtests.py。私のdjangoソースの他の場所では必要ないようです。明らかな何かが欠けていると確信していますが、おそらく誰かが説明できますか?

(実際、そのステートメントの直前からfrom mysite....印刷すると、パスが含まれますが、含まれないため、インポートが機能する理由もわかりません。)sys.path/home/mark/foo/mysite//home/mark/foo/

現在の作業ディレクトリは/home/mark/foo/mysite/、実行したときですpython manage.py test vncbrowser


要求に応じて、私のプロジェクトのレイアウトは次のとおりです。

 ── mysite
    ├── custom_postgresql_psycopg2
    │   ├── base.py
    │   └── __init__.py
    ├── __init__.py
    ├── manage.py
    ├── settings.py
    ├── urls.py
    └── vncbrowser
        ├── __init__.py
        ├── models.py
        ├── tables.sql
        ├── tests.py
        └── views.py

__init__.py上記のファイルはすべて空です。Python 2.6.5 と Django 1.3 を使用しています。私は virtualenv で Python を使用しています。tests.py"\n".join(sys.path)の開始時に出力すると、次のようになります。

/home/mark/foo/mysite
/home/mark/foo/env/lib/python2.6/site-packages/distribute-0.6.10-py2.6.egg
/home/mark/foo/env/lib/python2.6
/home/mark/foo/env/lib/python2.6/plat-linux2
/home/mark/foo/env/lib/python2.6/lib-tk
/home/mark/foo/env/lib/python2.6/lib-old
/home/mark/foo/env/lib/python2.6/lib-dynload
/usr/lib/python2.6
/usr/lib64/python2.6
/usr/lib/python2.6/plat-linux2
/usr/lib/python2.6/lib-tk
/usr/lib64/python2.6/lib-tk
/home/mark/foo/env/lib/python2.6/site-packages

更新: lbp's answerで提案されているように、tests.py の上部に以下を追加してみました:

import vncbrowser as vnc_one
import mysite.vncbrowser as vnc_two

print "vnc_one:", vnc_one.__file__
print "vnc_two:", vnc_two.__file__

...出力を生成しました:

vnc_one: /home/mark/foo/mysite/vncbrowser/__init__.pyc
vnc_two: /home/mark/foo/mysite/../mysite/vncbrowser/__init__.pyc
4

2 に答える 2

2

実際に知りたいことを 1つ 知るために、PYTHONPATH のすべてを知る必要はありませんvncbrowser。Python パスを出力する代わりに、次の操作を実行できます。

import vncbrowser as vnc_one
import mysite.vncbrowser as vnc_two

print vnc_one.__file__
print vnc_two.__file__

ファイル システムに 2 つの異なるパスが表示されます。次に、その理由を理解し始めることができます。

これは単なる推測ですが、vnc_one は Python パスのどこかにインストールされ、vnc_two はソース コードに存在すると思います。(編集:間違った推測)

さらに、ランダムな発言:

また、を使用して、tests.py の import ステートメントをより簡単にすることができます。

from models import ...

それ以外の

from XXX.models import ...
于 2011-09-20T12:34:35.890 に答える
0

lbpの回答とコメントは、問題を理解して解決するのに役立ちました。それが私が受け入れている回答ですが、混乱の原因が他の人に役立つ可能性があるため、別の回答で説明する価値があると思いました。

を実行すると、テストを実行する前にサイトディレクトリ(私の例では)がmanage.py追加されます。したがって、Djangoドキュメント(私の場合)で提案されているインポート行を使用してモデルをインポートし、続いてのインスタンスを作成すると、パッケージ階層のルートは次のように想定されるため、タイプはになります。の各エントリから開始します。/home/mark/foo/mysitesys.pathtests.pyfrom vncbrowser.models import Integer3DInteger3Dvncbrowser.models.Integer3Dsys.path

ただし、パッケージのこの名前は実際には正しくありません。これは、アプリケーションディレクトリがサイトディレクトリにネストされており(django-admin.pyDjangoチュートリアルで提案されているように)、どちらもPythonパッケージであるためです。つまり、クラスの実際の名前、およびで有効な名前models.pyは、完全修飾されmysite.vncbrowser.models.Integer3Dたです。

通常、これは問題を引き起こしません。なぜなら、Pythonを上手に書いている場合、の使用はisinstance まれであり、ダックタイピングは特定のオブジェクトのクラスのフルネームの違いが無関係であることを意味するからです。to_pythonただし、カスタムフィールドタイプを作成するときは、メソッドが文字列で呼び出されたのかオブジェクトで呼び出されたのかを区別する必要があり、ドキュメントではその使用が提案isinstanceされています。

将来この混乱を避けるために、lbpがコメントで示唆しているように、アプリケーションをサイトの名前に誤って依存させるリスクを回避するために、アプリケーションを別の(パッケージではない)ディレクトリに配置しています。サイトパッケージにアプリケーションパッケージをネストする奇妙なデフォルトの推奨階層で簡単に発生します。

于 2011-09-25T15:15:59.673 に答える