2014-01-07 36 views
30

我有一個項目的目錄結構如下(我認爲這是非常標準):我的測試框架確保py.test包括sys.path中的應用程序目錄

my_project 
    setup.py 
    mypkg 
     __init__.py 
     foo.py 
    tests 
     functional 
      test_f1.py 
     unit 
      test_u1.py 

我使用py.test ,並且我希望能夠在my_project目錄中運行py.test tests以運行我的測試。這確實起作用,直到我嘗試在測試中使用(例如)import mypkg導入我的應用程序代碼。此時,我收到錯誤「No module named mypkg」。在做一點調查之後,看起來py.test運行的測試文件的目錄是sys.path,但是而不是運行的目錄是py.test

爲了解決這個問題,我添加了一個conftest.py文件到我的tests目錄,包含下面的代碼:

import sys, os 

# Make sure that the application source directory (this directory's parent) is 
# on sys.path. 

here = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 
sys.path.insert(0, here) 

這似乎是工作,但它確保了一個好辦法測試看到應用程序代碼?有沒有更好的方法來實現這一點,或者我在如何讓自己的項目結構化方面做錯了事情?

我已經看過一些其他使用py.test(例如,pip)的項目,但我看不到執行此類操作的代碼,但運行py.test tests似乎在此工作。我不知道爲什麼,但我擔心他們可能以更簡單的方式取得同樣的結果。

我查看了py.test文檔,但是我看不到這個問題的解釋或推薦的方法來處理它。

回答

26

正如你所說你自己py.test基本上假設你正確地設置了PYTHONPATH。有實現這一目標的幾種方法:

  • 給項目一個setup.py併爲此項目的virtualenv使用pip install -e .。這可能是標準方法。

  • 作爲一個變種,如果你有一個virtualenv但沒有setup.py使用你的venv的工具來添加項目目錄在sys.path,例如,如果使用pew,則使用pew add .;如果使用virtualenv和virtualenvwrapper的擴展,則使用add2virtualenv .

  • 如果你總是喜歡sys.path上的當前工作目錄,那麼你總是可以在shell中總是導出PYTHONPATH=''。這是確保sys.path上的空字符串,python將解釋爲當前正在工作的目錄。儘管這可能是安全隱患。

  • 我自己最喜歡的黑客濫用py.test如何加載conftest文件:在項目的頂級目錄中放置一個空的conftest.py

py.test以這種方式運行的原因是爲了使在測試/安裝包的結算的目錄中運行測試變得容易。如果它無條件地將項目目錄添加到PYTHONPATH中,那麼這將不再可能。

+1

只需加入第一點:如果你沒有virtualenv,你可以使用「python setup.py develop」來達到同樣的效果。 –

+0

謝謝,我知道PYTHONPATH黑客的各種選項。但是,一般來說,我不傾向於使用它們,我只是從項目根目錄運行Python並且它可以工作。 IIRC,unittest也可以在沒有任何PYTHONPATH黑客入侵的情況下工作(至少,我從來沒有做過足夠複雜的任何事情來打破它:-))我想用py.test我只需要咬緊牙關,習慣於正確設置我的PYTHONPATH 。 –

+5

conftest.py hack是個好主意!!!太糟糕了,這是一種濫用,它可能會消失:( – lab419

8

答案實際上要容易得多,如here所示。

所有你需要做的就是將__init__.py添加到你的測試目錄和它的每個子目錄,就像這樣;

tests/__init__.py 
tests/functional/__init__.py 
tests/unit/__init__.py 
+1

這實際上是爲包添加了測試。可能並不總是需要的 –

+1

-1因爲在pytest文檔的[「良好實踐」部分]中明確拒絕**(http://doc.pytest.org/en/latest/goodpractices.html )。 – wim