#python #pytest
#python #pytest
Вопрос:
Я пытаюсь автоматически запускать тесты, когда код отправляется в мое приложение Flask, но каким-то образом PyTest возвращает неправильные результаты. Я пытался отключить кэширование, удалить папки кэша, удалить файлы .pyc, но проблема остается. Вот игрушечное воспроизведение проблемы.
Структура каталогов:
app.py
right/
main.py
test_solution1.py
wrong/
main.py
test_solution2.py
app.py
import pytest
from flask import Flask
app = Flask(__name__)
@app.route("/")
def submit():
pytest.main(["right", "-p", "no:cacheprovider"])
pytest.main(["wrong", "-p", "no:cacheprovider"])
return "OK"
if __name__ == "__main__":
app.run("0.0.0.0")
right/main.py
def subtract(a, b):
return a - b
right/test_solution1.py
import main
def test_subtract():
assert main.subtract(5, 3) == 2
wrong/main.py
def subtract(a, b):
return b - a
wrong/test_solution2.py
import main
def test_subtract():
assert main.subtract(5, 3) == 2
Если я загружаю приложение и посещаю localhost:5000
его в своем браузере, оно запускает тесты в каждом каталоге, как и ожидалось, но оба результата одинаковы. В нем говорится, что все тесты пройдены, хотя тесты для wrong
должны завершиться неудачей.
Если я поменяю порядок запуска тестов в приложении Flask, то тесты завершатся неудачно для обоих проектов, хотя они должны пройти для второго.
изменен маршрут отправки () для app.py
(теперь сначала выполняется «неправильный» проект)
@app.route("/", methods=["GET","POST"])
def submit():
pytest.main(["wrong", "-p", "no:cacheprovider"])
pytest.main(["right", "-p", "no:cacheprovider"])
return "OK"
Теперь оба теста показывают сбои, хотя «правильный» проект не имеет проблем.
Как я могу гарантировать, что pytest выполняет именно тот код, который находится в каталоге? Я предполагаю, что он каким-то образом кэширует результаты, как будто main.py
имена не конфликтуют, это работает нормально.
Удаление __pycache__
и аналогичные каталоги и файлы между запуском тестов не помогает. Остановка и перезагрузка сервера Flask между запуском тестов устраняет проблему.
Комментарии:
1. возникли проблемы с загрузкой второго скриншота, на котором показаны два сбоя, так что вот оно i.ritzastatic.com/63d4fd298862405fa48b2eb93e4de165/errors2.png
Ответ №1:
Это потому, что в Python, если вы попытаетесь импортировать два раза один и тот же модуль, Python не будет выполнять поиск в файловой системе во второй раз. Он будет использовать модуль, импортированный в первый раз. Вы пытаетесь импортировать модуль два раза main
. Даже если вы думаете, что это два разных модуля, с точки зрения Python вы пытаетесь импортировать один и тот же модуль дважды (потому что они оба названы main
). Вы можете прочитать более подробную информацию о системе кэширования модулей в документации.
В зависимости от того, что вы хотите сделать, может быть много решений. Вот два:
Решение 1
Вы можете просто изменить имя вашего основного модуля на другие имена:
app.py
right/
main1.py
test_solution1.py
wrong/
main2.py
test_solution2.py
test_solution.py
import main1
def test_subtract():
assert main1.subtract(5, 3) == 2
test_solution2.py
import main2
def test_subtract():
assert main2.subtract(5, 3) == 2
Решение 2
Вы сохраняете те же имена файлов, но указываете, какой подмодуль вы хотите импортировать:
test_solution.py
from right import main
def test_subtract():
assert main.subtract(5, 3) == 2
test_solution2.py
from wrong import main
def test_subtract():
assert main.subtract(5, 3) == 2
Это работает, потому что Python просматривает локальный каталог при поиске module, и вы запускаете Python в том же месте, где app.py
находятся папки and right
и wrong
.