From fc7cfd8fb3fc8de240131ac1e66f44497c95d965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Leblanc?= Date: Wed, 17 Mar 2021 15:14:22 -0400 Subject: [PATCH 1/4] update README with test fixture documentation --- README.rst | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/README.rst b/README.rst index 9dfb6c5..6f92a70 100644 --- a/README.rst +++ b/README.rst @@ -95,7 +95,61 @@ Sometimes it is useful to be able to access the database outside the context of return users +Using a test database fixture with pytest +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A suggested way of to override the database URL and yield a session fixture in your tests is to use environment variables. + +.. code-block:: python + + # Contents of app/configs.py + import json + import os + + DEV, PROD, TEST = ("development", "production", "test") + CURRENT_ENV = os.environ.get("PYTHON_ENV", DEV) + config = {DEV: "sqlite://dev.db", PROD: "postgresql://user:password@sql.mydomain.com/mydb", TEST: "sqlite://"} + DATABASE_URL = config[CURRENT_ENV] + + + # Contents of test_app.py + import pytest + from fastapi.testclient import TestClient + + from app.configs import DATABASE_URL + from app.db import Base # from sqlalchemy.ext.declarative import declarative_base + from app.models import User + from main import app, db + + + @pytest.fixture(scope="function", name="session") + def session_fixture(): + engine = get_engine(DATABASE_URL) + Base.metadata.drop_all(engine) + Base.metadata.create_all(engine) + with db(): + yield db.session + + + @pytest.fixture(scope="function", name="client") + def client_fixture(): + return TestClient(app) + + + def test_users_route(session, client): + # Save a fake user + NAME = 'Gontrand' + user = User(name=NAME) + session.add(user) + session.commit() + + response = client.get('users') + response_user = response.json()[0] + assert response_user['name'] == NAME + +Run your tests with ``PYTHON_ENV=test pytest`` or use dotenv_ to manage these programmatically with an ``.env`` file. .. _FastAPI: https://github.com/tiangolo/fastapi .. _SQLAlchemy: https://github.com/pallets/flask-sqlalchemy .. _pip: https://pip.pypa.io/en/stable/quickstart/ +.. _dotenv: https://github.com/theskumar/python-dotenv From 73ede833954819e7810d8aa9391cf8895f686287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Leblanc?= Date: Wed, 17 Mar 2021 15:19:06 -0400 Subject: [PATCH 2/4] Update README.rst --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 6f92a70..5a5bd70 100644 --- a/README.rst +++ b/README.rst @@ -114,6 +114,7 @@ A suggested way of to override the database URL and yield a session fixture in y # Contents of test_app.py import pytest + from sqlalchemy import create_engine from fastapi.testclient import TestClient from app.configs import DATABASE_URL From c79eb618b24ecf972b187b0d6e1ed4ce31ad065c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Leblanc?= Date: Wed, 17 Mar 2021 15:19:10 -0400 Subject: [PATCH 3/4] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 5a5bd70..5e7a86b 100644 --- a/README.rst +++ b/README.rst @@ -125,7 +125,7 @@ A suggested way of to override the database URL and yield a session fixture in y @pytest.fixture(scope="function", name="session") def session_fixture(): - engine = get_engine(DATABASE_URL) + engine = create_engine(DATABASE_URL) Base.metadata.drop_all(engine) Base.metadata.create_all(engine) with db(): From 566ffe6bf245d88c06ac03dc5dca3c8df2517fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Leblanc?= Date: Mon, 29 Mar 2021 14:50:54 -0400 Subject: [PATCH 4/4] Don't forget to dispose the engine object after every test --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 5e7a86b..844e9c1 100644 --- a/README.rst +++ b/README.rst @@ -130,6 +130,7 @@ A suggested way of to override the database URL and yield a session fixture in y Base.metadata.create_all(engine) with db(): yield db.session + engine.dispose() @pytest.fixture(scope="function", name="client")