2016-10-24 2 views
0

Я стараюсь, чтобы мой код был разумно организован, помещая тесты в отдельный каталог из моего приложения. Тем не менее, импорт работает либо для приложения , либо для испытаний, но не для обоих. Вот надуманный пример, который иллюстрирует мою текущую задачу:Более элегантное решение для импорта python через приложение/тесты?

myapp/ 
    app/ 
    main.py 
    settings.py 
    moods.py 
    test/ 
    test_moods.py 

Содержание файлов следующим образом:

main.py

import settings 
from moods import Moods 

words = Moods(settings.EXAMPLE) 
print(words.excited()) 

settings.py

EXAMPLE = "Wow$ Python$" 
DELIM = "$" 

moods.py

import settings 

class Moods: 
    def __init__(self, text): 
     self.text = text 

    def excited(self): 
     return self.text.replace(settings.DELIM, "!!!") 

test_moods.py

import sys, os, unittest 
sys.path.insert(0, os.path.abspath('..')) 

from app.moods import Moods 

class TestMood(unittest.TestCase): 
    def setUp(self): 
     self.words = Moods("Broken imports$ So sad$") 

    def test_mood(self): 
     self.assertEqual(self.words.excited(), "Broken imports!!! So sad!!!") 
     with self.assertRaises(AttributeError): 
      self.words.angry() 

if __name__ == "__main__": 
    unittest.main() 

В текущем состоянии, из myapp/ я могу запустить успешно следующее:

>> python3 app/main.py 
Wow!!! Python!!! 

Но когда я пытаюсь запускать тесты, импорт невозможен в moods.py:

>> python3 -m unittest discover test/ 
ImportError: Failed to import test module: test_moods 
[ stack trace here pointing to first line of moods.py ] 
ImportError: No module named 'settings' 

Если я изменяю строку 1 moods.py для чтения from app import settings, тест пройдет, но нормальное выполнение приложения завершится неудачно, потому что не видит модуля app.

Единственное решение, я могу думать, являются

  1. Ввод тестов в том же каталоге, что и код (который я пытался избежать)
  2. Добавление sys.path.insert(0, os.path.abspath('..')) к каждому файлу в мое приложение, чтобы сделать импорт работает так же, как и тестовые (0)

Есть ли более элегантный способ решить эту проблему импорта?

ответ

2

Вы должны иметь как app, так и test каталог в PYTHONPATH.

Один из способов заключается в замене этого:

sys.path.insert(0, os.path.abspath('..')) 

from app.moods import Moods 

с этим:

sys.path.insert(0, os.path.abspath('../app')) 

from moods import Moods 

Или вы можете установить переменную environament PYTHONPATH перед запуском тестов.

Почему? Потому что, когда вы запускаете main.py, тогда app находится на пути, а не app/.., поэтому вы хотите иметь то же самое при запуске тестов.

+0

Хм ...до сих пор это решение представляется наиболее перспективным. Он чист и сохраняет модификацию пути к тестовым файлам. Однако это не работает. Внедрение изменения кода, как было предложено выше, дает: 'ImportError: нет модуля с именем« moods » – vastlysuperiorman

+0

Ок ... странно, настройка' os.path.abspath ('app') 'работала. Я полагаю, это связано с тем, что я запускаю тесты из родительского каталога, и он знает каталог приложений? – vastlysuperiorman

+0

@vastlysuperiorman Если вы работаете из родительского каталога, то 'app' - правильный путь, да. – zvone

Смежные вопросы