Рубрики
Без рубрики

Python Pytest тестирование с SQLalchemy для моей игры

В этом блоге о разработке для моего онлайн -сингла/Coop 4x Space Game Post Я напишу о своем Python Py … Tagged с базой данных, тестированием, Gamedev, Python.

Моя веб-игра в Интернете в Интернете, блог о разработке (3 серии части)

В этом блоге о разработке для моего онлайн -одного Postive Game Post Sop 4x я напишу о своем тестировании Python Pytest в среде базы данных.

Моя игра должна отслеживать прогресс. Будь то прогресс в исследовании, строительные очереди, количество ресурсов и т. Д. Я использую таблицу, которую я называю Прогресс Для этого, по крайней мере, с целью создания тестовой игры в процессе осознания того, как я буду делать что -то в реальной игре.

Эта таблица будет обновлена с помощью периодической задачи, работающей в сельдерее, и, когда я написал функцию задачи, я понял, что мне понадобятся некоторые автоматические тесты. Было бы больно кодировать такую задачу, запустить работника локально, отслеживать базу данных для изменений, исправить ошибку, делать все это снова и так далее. Не говоря уже о болях рефакторинга, которые, несомненно, произойдут, когда я понимаю, какими должны быть мои структуры данных.

Итак, у меня было несколько забавных раундов борьбы с Pytest и прибором сеанса базы данных, и я в конце концов придумал что -то вроде следующего (из моего текущего кода):

# NOTE: I am not very experienced with SQL/ORM/RDBS so I may be doing
# stupid things. Please comment below to let me know if I can do something
# better or if I made you pull your hair with disgust

# TODO: probably be function scope, then make create_ and drop_all in another fixture
@fixture(scope="session")
def db_session():
    Base.metadata.create_all(engine)
    session = Session()
    yield session
    Base.metadata.drop_all(engine)
    session.close()

И пример для теста, который использует это:

# NOTE: I am not very experienced with SQL/ORM/RDBS so I may be doing
# stupid things. Please comment below to let me know if I can do something
# better or if I made you pull your hair with disgust

# TODO: move somewhere more common
@fixture
def game(db_session):
    game = GameMeta(name="testgame", seed=0)
    db_session.add(game)
    db_session.commit()
    yield game
    db_session.delete(game)
    db_session.commit()


def test_advance_all_games_progress(db_session, game):
    progress1 = Progress(progress=0.0, game=game)
    progress2 = Progress(progress=0.0, game=game)
    db_session.add(progress1)
    db_session.add(progress2)
    db_session.commit()

    advance_all_games_progress()

    stmt = select(Progress)
    result = db_session.execute(stmt)
    for progress in result.scalars():
        assert progress.progress > 0.0

    db_session.delete(progress1)
    db_session.delete(progress2)
    db_session.commit()


def test_progress_increment(db_session, game):
    progress = Progress(
        progress=1.0, game=game, increment_min=10.0, increment_max=100.0
    )
    db_session.add(progress)
    db_session.commit()

    advance_all_games_progress()
    progress = db_session.get(Progress, progress.id)
    assert progress.progress >= 10.0

    db_session.delete(progress)
    db_session.commit()


def test_progress_cap(db_session, game):
    progress = Progress(
        progress=1.0, cap=2.0, game=game, increment_min=10.0, increment_max=100.0
    )
    db_session.add(progress)
    db_session.commit()

    advance_all_games_progress()
    progress = db_session.get(Progress, progress.id)
    assert progress.progress > 1.0
    assert progress.progress <= 2.0

    db_session.delete(progress)
    db_session.commit()

Похоже, что сессии SQLALCHEMY поддерживают какую-то сеанс-а-сессию или вложенные сеансы, которые я должен изучить. Функция advance_all_games_progress Открывает сеанс внутри себя, и он вызван изнутри db_session приспособление.

Первоначально я пытался выполнить каждую операцию (создание макетных строк и объектов, например, уничтожение их позже) с собственным db_session. Это была катастрофа. После того, как вы создаете объект на основе ORM в сеансе, он привязан к нему, и как только сеанс заканчивается, вы в конечном итоге не могут реализовать его ленивые отношения и подобные. Есть метод под названием Высыпать что вы можете сделать для такого рода объектов, чтобы «разоблачить» их с сеанса, но тогда я не был уверен, должен ли я переоценить их на новую сессию для последующего использования (представьте себе игру приспособление). Я сделал все виды Случайное программирование Угадания и некоторые снимки в темноте во время гуглирования, но с простым приспособлением db_session и большим количеством db_session.commit У меня есть вещи на работу И я думаю, что я даже не делаю ничего странного. Пожалуйста, исправьте меня, если я совершенно неправ, спасибо:)

Теперь есть проблема с тем, что на самом деле есть тестовая база данных для проверки вещей. Используя Docker, я запустил локальный сервер Postgres и создал тестовую базу данных для тестирования игры. Похоже, это (из моего ReadMe):

docker run -d --name postgres -e POSTGRES_PASSWORD=password -p5432:5432 postgres:alpine
docker run --rm -it --network host postgres:alpine psql postgres://postgres:password@localhost:5432/
# or if you have the postgres-client package installed:
#   psql postgres://postgres:password@localhost:5432
CREATE DATABASE gametest;

Я упомянул Readme. Даже быть закрытым исходным кодом (пока?) Я нахожу важным включить инструкции для моего будущего самостоятельно для того, чтобы делать что -то со своими проектами.

Мой .env.test Файл имеет эту запись:

DATABASE_URL=postgres://postgres:password@localhost:5432/gametest

И где-то в моем коде, который основан на FastAPI и, таким образом, использует Starlette:

# config.py

TESTING = environ.get("TESTING")

config = Config(".env" if not TESTING else ".env.test")

...

DATABASE_URL = config("DATABASE_URL", default=None)

Наконец, мой conftest.py (для pytest) гарантирует, что тестирование Env var присутствует:

from starlette.config import environ

environ["TESTING"] = "True"

Теперь, когда я думаю об этом, немного странно, что код, который не должен работать для веб -работника Heroku, использует конфигурации Starlette. То есть мои «работники», которые должны выполнять задачи для игры, включают ссылку на конфигурации на основе Starlette. Ну что ж. Вещи работают, и сейчас мое внимание действительно на самом деле Создание игры Поэтому я должен упускать из виду такие вещи, что может быть вообще не проблем.

Моя веб-игра в Интернете в Интернете, блог о разработке (3 серии части)

Оригинал: “https://dev.to/amireldor/python-pytest-testing-with-sqlalchemy-for-my-game-37jc”