В настоящее время я работаю над проектом, где мне нужно запускать тесты внутри другой файловой структуры, например:
/my_project
├── __init__.py
├── ...my python code
/given_proj
├── __init__.py
├── /package
│ ├── __init__.py
│ └── main.py
└── /tests
└── test_main.py
Изнутри моего проекта я хочу выполнить тесты в рамках данного проекта.
Мой текущий подход использует unittest.TextTestRunner следующим образом:
unittest.TextTestRunner().run(unittest.defaultTestLoader.discover('../given_proj/tests'))
.
Конечно, тестовый файл хочет импортировать из main.py
вот так from package.main import my_function
. Однако когда я запускаю свой код, тесты не запускаются, поскольку не удается найти модуль «пакет»:
...\given_proj\tests\test_main.py", line 2, in <module>
from package.main import my_function
ModuleNotFoundError: No module named 'package'
Когда я запускаю тесты с помощью python -m unittest discover -s tests
из командной строки в каталоге given_proj
, они работают нормально.
Я попробовал изменить рабочий каталог на given_proj
с помощью os.chdir('../given_proj')
, но результат тот же.
Я попробовал импортировать модуль вручную с помощью importlib.import_module()
. Вот я не уверен, сделал ли я это неправильно или это тоже не работает.
Как мне сделать так, чтобы тесты запускались так, как если бы я запускал их из фактического каталога, в котором они должны запускаться? В идеале мне вообще не нужно было бы менять «given_project», потому что я хочу сделать это с несколькими проектами.
Я свел его к очень минимальному проекту, если кто-нибудь захочет попробовать его воспроизвести. Файловая структура указана вверху сообщения.
Все файлы __init__.py
пусты.
/my_project/main.py
:
import os
import unittest
import os
import unittest
if __name__ == "__main__":
dirname = "../given_proj/tests" #either "./" or "../" depending of where you run the python file from
unittest.TextTestRunner().run(unittest.defaultTestLoader.discover(dirname))
/given_proj/package/main.py
:
def my_function(num):
return num*2
/given_proj/tests/test_main.py
:
import unittest
from package.main import my_function
class TestMain(unittest.TestCase):
def test_my_function(self):
result = my_function(5)
self.assertEqual(result, 10)
result = my_function(10)
self.assertEqual(result, 20)
result = my_function(0)
self.assertEqual(result, 0)
if __name__ == '__main__':
unittest.main()
О да, оно уже там. я отредактирую файловую структуру
Не в папке package
, в папке given_proj
...: добавьте файл __init__.py
в папку give_proj
и попробуйте выполнить тесты
ах, я забыл об этом в проекте воспроизведения, но он настоящий, он уже есть. Это не имеет значения. (Я только что добавил и попробовал, но все равно не работает)
Возможное решение — добавить в файл следующие инструкции test_main.py
:
import unittest
import sys # <-- add this import
sys.path.insert(1, '..') # <-- add this instruction
print(sys.path) # <--- TO CHECK THE CONTENT OF sys.path
#from package.main import my_function # <--- comment your import
from given_proj.package.main import my_function # <--- add this import
class TestMain(unittest.TestCase):
def test_my_function(self):
result = my_function(5)
self.assertEqual(result, 10)
result = my_function(10)
self.assertEqual(result, 20)
result = my_function(0)
self.assertEqual(result, 0)
if __name__ == '__main__':
unittest.main()
Если я выполню тестовый метод test_my_function()
в своей системе, он пройдет.
В инструкции sys.path.insert(1, '..')
добавьте путь для поиска тестового кода package
.
Если я перейду в папку given_proj
и выполню следующую команду:
> cd /path/to/given_proj
/path/to/given_proj> python tests/test_main.py
Результат выполнения следующий:
['/path/to/given_proj/tests', '..', '/other/paths']
.
Ran 1 test in 0.000s
OK
В выводе вы можете увидеть распечатку содержимого sys.path
.
Хм, это не работает для меня. Это работает только в том случае, если я использую абсолютный путь, который не работает для моего варианта использования. Было бы идеально, если бы мне не нужно было менять тестовый файл
Я изменил импорт: из from package.main import my_function
---> from given_proj.package.main import my_function
. В моей системе это тоже работает. Попробуйте свою систему и дайте мне отзыв.
теперь они работают при выполнении из кода в my_project
, но не запускаются при выполнении из реального проекта.
В моей системе, если я перейду в папку given_proj
и выполню команду: python tests/test_main.py
сработает. Чтобы понять, что именно происходит print(sys.path)
ты прав! я перешел в ложный каталог! Тысм
Я рад, что помог вам. Возможно, есть другие решения вашей проблемы, но на данный момент я не нашел ничего лучшего.
Пробовали добавить
__init__.py
в папкуgive_proj
?