mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Plugin testing docs now recommend datasette.client, closes #1102
This commit is contained in:
parent
a8e66f9065
commit
12877d7a48
1 changed files with 27 additions and 30 deletions
|
|
@ -11,24 +11,24 @@ If you use the template described in :ref:`writing_plugins_cookiecutter` your pl
|
|||
|
||||
from datasette.app import Datasette
|
||||
import pytest
|
||||
import httpx
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_plugin_is_installed():
|
||||
app = Datasette([], memory=True).app()
|
||||
async with httpx.AsyncClient(app=app) as client:
|
||||
response = await client.get("http://localhost/-/plugins.json")
|
||||
assert 200 == response.status_code
|
||||
installed_plugins = {p["name"] for p in response.json()}
|
||||
assert "datasette-plugin-template-demo" in installed_plugins
|
||||
datasette = Datasette([], memory=True)
|
||||
response = await datasette.client.get("/-/plugins.json")
|
||||
assert response.status_code == 200
|
||||
installed_plugins = {p["name"] for p in response.json()}
|
||||
assert "datasette-plugin-template-demo" in installed_plugins
|
||||
|
||||
This test uses the `HTTPX <https://www.python-httpx.org/>`__ Python library to run mock HTTP requests through a fresh instance of Datasette. This is the recommended way to write tests against a Datasette instance.
|
||||
|
||||
It also uses the `pytest-asyncio <https://pypi.org/project/pytest-asyncio/>`__ package to add support for ``async def`` test functions running under pytest.
|
||||
This test uses the :ref:`internals_datasette_client` object to exercise a test instance of Datasette. ``datasette.client`` is a wrapper around the `HTTPX <https://www.python-httpx.org/>`__ Python library which can imitate HTTP requests using ASGI. This is the recommended way to write tests against a Datasette instance.
|
||||
|
||||
This test also uses the `pytest-asyncio <https://pypi.org/project/pytest-asyncio/>`__ package to add support for ``async def`` test functions running under pytest.
|
||||
|
||||
You can install these packages like so::
|
||||
|
||||
pip install pytest pytest-asyncio httpx
|
||||
pip install pytest pytest-asyncio
|
||||
|
||||
If you are building an installable package you can add them as test dependencies to your ``setup.py`` module like this:
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ If you are building an installable package you can add them as test dependencies
|
|||
name="datasette-my-plugin",
|
||||
# ...
|
||||
extras_require={
|
||||
"test": ["pytest", "pytest-asyncio", "httpx"]
|
||||
"test": ["pytest", "pytest-asyncio"]
|
||||
},
|
||||
tests_require=["datasette-my-plugin[test]"],
|
||||
)
|
||||
|
|
@ -65,12 +65,11 @@ Here's an example that uses the `sqlite-utils library <https://sqlite-utils.read
|
|||
.. code-block:: python
|
||||
|
||||
from datasette.app import Datasette
|
||||
import httpx
|
||||
import pytest
|
||||
import sqlite_utils
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def ds(tmp_path_factory):
|
||||
def datasette(tmp_path_factory):
|
||||
db_directory = tmp_path_factory.mktemp("dbs")
|
||||
db_path = db_directory / "test.db"
|
||||
db = sqlite_utils.Database(db_path)
|
||||
|
|
@ -78,7 +77,7 @@ Here's an example that uses the `sqlite-utils library <https://sqlite-utils.read
|
|||
{"id": 1, "name": "Cleo", "age": 5},
|
||||
{"id": 2, "name": "Pancakes", "age": 4}
|
||||
], pk="id")
|
||||
ds = Datasette(
|
||||
datasette = Datasette(
|
||||
[db_path],
|
||||
metadata={
|
||||
"databases": {
|
||||
|
|
@ -92,25 +91,23 @@ Here's an example that uses the `sqlite-utils library <https://sqlite-utils.read
|
|||
}
|
||||
}
|
||||
)
|
||||
return ds
|
||||
return datasette
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_example_table_json(ds):
|
||||
async with httpx.AsyncClient(app=ds.app()) as client:
|
||||
response = await client.get("http://localhost/test/dogs.json?_shape=array")
|
||||
assert 200 == response.status_code
|
||||
assert [
|
||||
{"id": 1, "name": "Cleo", "age": 5},
|
||||
{"id": 2, "name": "Pancakes", "age": 4},
|
||||
] == response.json()
|
||||
async def test_example_table_json(datasette):
|
||||
response = await datasette.client.get("/test/dogs.json?_shape=array")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == [
|
||||
{"id": 1, "name": "Cleo", "age": 5},
|
||||
{"id": 2, "name": "Pancakes", "age": 4},
|
||||
]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_example_table_html(ds):
|
||||
async with httpx.AsyncClient(app=ds.app()) as client:
|
||||
response = await client.get("http://localhost/test/dogs")
|
||||
assert ">Some dogs</h1>" in response.text
|
||||
async def test_example_table_html(datasette):
|
||||
response = await datasette.client.get("/test/dogs")
|
||||
assert ">Some dogs</h1>" in response.text
|
||||
|
||||
Here the ``ds()`` function defines the fixture, which is than automatically passed to the two test functions based on pytest automatically matching their ``ds`` function parameters.
|
||||
Here the ``datasette()`` function defines the fixture, which is than automatically passed to the two test functions based on pytest automatically matching their ``datasette`` function parameters.
|
||||
|
||||
The ``@pytest.fixture(scope="session")`` line here ensures the fixture is reused for the full ``pytest`` execution session. This means that the temporary database file will be created once and reused for each test.
|
||||
|
||||
|
|
@ -119,5 +116,5 @@ If you want to create that test database repeatedly for every individual test fu
|
|||
.. code-block:: python
|
||||
|
||||
@pytest.fixture
|
||||
def ds(tmp_path_factory):
|
||||
# ...
|
||||
def datasette(tmp_path_factory):
|
||||
# This fixture will be executed repeatedly for every test
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue