PyTest возвращает неправильные результаты при динамическом запуске

#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 .