Моя веб-игра в Интернете в Интернете, блог о разработке (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”