2011-09-20 8 views
2

나는 mysite/vncbrowser/tests.py 일부 단위 테스트를 넣었습니다, 나는 이러한를 실행할 수 있습니다Django에서 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) 

, 나는로 테스트를 실행할 때, models.py 소스의 isinstance(value, Integer3D) 확인에 실패했습니다. models.py 파일에서 해당 파일의 앞에 정의 된 Integer3D에 대한 노출 된 참조는 전체 이름이 vncbrowser.models.Integer3D 인 반면 테스트에서 전달 된 개체는 전체 이름이 mysite.vncbrowser.models.Integer3D입니다.

디버깅 문과 models.py에서 해당 코드 :

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 

걸 수

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" 

는 ... 즉 (명확성을 위해 추가 된 일부 바꿈과 공백)이 출력을 생성 tests.py에서 가져 오기를 변경하여이 테스트 작업을 수행하십시오.

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

... tests.py 파일에 mysite 자격이 필요한 이유는 알 수 없습니다. 내 장고 소스의 다른 곳에서는 필요하지 않은 것 같습니다. 나는 명백한 것을 놓치고 있다고 확신하지만 아마도 누군가가 설명 할 수 있을까요?

(필자는 from mysite.... 수입 작품은, 사실, 난 그냥 그 문 앞에서 sys.path를 인쇄하는 경우 때문에, 경로 /home/mark/foo/mysite/을 포함하지만, 왜 모르겠어요하지 /home/mark/foo/.)

내 현재 작업 디렉토리 내가 python manage.py test vncbrowser을 실행할 때 /home/mark/foo/mysite/입니다. 요청으로 다음과 같이


, 내 프로젝트의 레이아웃은 다음과 같습니다

── 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 파이썬을 사용하고, 나는 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__ 

...그 다른vncbrowser에서오고있다 : 당신은 당신이 실제로 알고 싶은 한 가지를 알기 위해 당신의 PYTHONPATH의 전부를 알 필요가 없습니다

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

가져 오기가 제대로 작동하지 않는 경우 물리적 파일 레이아웃을 설명해야합니다. 'manage.py'를 사용할 때 어떤 디렉토리에 있습니까? 현재 작업 디렉토리는 무엇입니까? 패키지 디렉토리에'__init __. py' 파일이 있습니까? –

+0

@ S.Lott : 죄송합니다. 지금 레이아웃을 추가했습니다.나는'manage.py'를 실행할 때'mysite' 디렉토리에 있습니다. 처음에'cd mysite'에 의해 표시되기를 바랍니다. –

+0

"에 의해"... 명시 적으로 암시 적으로보다 낫다. "Indicated by"는 놓치기 쉽습니다. 도움이 필요하면 조건을 놓치지 않게해야합니다. –

답변

2

: 이는 출력을 생산했다. 파이썬 경로를 인쇄하는 대신 다음을 수행 할 수 있습니다.

import vncbrowser as vnc_one 
import mysite.vncbrowser as vnc_two 

print vnc_one.__file__ 
print vnc_two.__file__ 

그리고 파일 시스템에 두 가지 경로가 표시됩니다. 그런 다음 이유를 파악할 수 있습니다.

이것은 야생의 추측이지만 vnc_one은 파이썬 경로의 어딘가에 설치되어 있고 vnc_two는 소스 코드에 상주한다고 생각합니다. (편집 : 잘못된 추측)

또한, 임의의 발언 : 또한

, 당신은

from models import ... 

대신

from XXX.models import ... 
사용하여, tests.py 간단한에서 import 문을 만들 수 있습니다
+0

답변 해 주셔서 감사합니다. - 귀하가 제안한 것을 시도한 결과를 제 질문에 추가했습니다. –

+0

'/ home/xxx/foo'가 파이썬 경로의'/ home/xxx/foo/mysite' 앞에 있어야한다는 것을 의미하지 않습니까? 더 나은 해결책은 Django 프로젝트에서 Django 프로젝트를 분리하는 것입니다. – pvoosten

+0

미안하지만, 왜'/ home/mark/foo/mysite /../'를보고 있는지 이해할 수 없다. 그건'sys.path'가 아니다. –

0

lbp's answer 및 의견을 통해 문제를 이해하고 해결하는 데 도움이되었으므로이를 받아 들일 수있는 대답이되었지만 다른 대답으로 설명 할 가치가 있다고 생각했습니다. 다른 사람들을 도울 수 있기 때문에 내 혼란의 원천이 생겼다.

당신이 manage.py을 실행

, 그것은 테스트를 실행하기 전에 sys.path에 (내 예 /home/mark/foo/mysite) 사이트 디렉토리를 추가합니다. 따라서 수입 라인 suggested in the Django documentation (내 경우에는 from vncbrowser.models import Integer3D)을 사용하여 tests.py에서 모델을 가져온 다음 Integer3D의 인스턴스를 생성하면 패키지 계층의 루트가 다음과 같이 가정되므로 vncbrowser.models.Integer3D이됩니다. sys.path의 각 항목에서 시작하십시오.

그러나이 응용 프로그램 디렉토리는 (django-admin.py과 장고 자습서에서 제안한 것처럼) 사이트 디렉토리에 중첩되어 있으며 실제로 둘 다 파이썬 패키지이므로이 패키지 이름은 실제로 올바르지 않습니다. 즉, 클래스의 실제 이름과 models.py에 유효한 이름은 정규화 된 mysite.vncbrowser.models.Integer3D입니다. 당신이 잘 파이썬을 작성하는 경우, isinstanceshould be rare의 사용 및 오리 입력이 특정 객체의 클래스의 전체 이름에 차이는 무관해야한다는 것을 의미하기 때문에

일반적으로,이, 문제를 만들지 않습니다. 그러나 사용자 정의 필드 유형을 작성할 때 to_python 메소드가 문자열 또는 객체로 호출되었는지 여부를 구별해야하고 the documentationisinstance을 사용하도록 제안합니다.

나중에이 혼란을 피하기 위해, 설명에서 lbp으로 제안 했으므로 이제 응용 프로그램을 실수로 응용 프로그램의 이름에 종속시키는 위험을 피하기 위해 응용 프로그램을 별도의 패키지가 아닌 디렉토리에 넣을 것입니다. 사이트 - 사이트 패키지에 응용 프로그램 패키지를 중첩하는 이상한 기본 제안 계층 구조로 인해 쉽게 발생할 수 있습니다.

관련 문제