{"id": "testing_plugins:testing-plugins-register-in-test", "page": "testing_plugins", "ref": "testing-plugins-register-in-test", "title": "Registering a plugin for the duration of a test", "content": "When writing tests for plugins you may find it useful to register a test plugin just for the duration of a single test. You can do this using pm.register() and pm.unregister() like this: \n from datasette import hookimpl\nfrom datasette.app import Datasette\nfrom datasette.plugins import pm\nimport pytest\n\n\n@pytest.mark.asyncio\nasync def test_using_test_plugin():\n class TestPlugin:\n __name__ = \"TestPlugin\"\n\n # Use hookimpl and method names to register hooks\n @hookimpl\n def register_routes(self):\n return [\n (r\"^/error$\", lambda: 1 / 0),\n ]\n\n pm.register(TestPlugin(), name=\"undo\")\n try:\n # The test implementation goes here\n datasette = Datasette()\n response = await datasette.client.get(\"/error\")\n assert response.status_code == 500\n finally:\n pm.unregister(name=\"undo\") \n To reuse the same temporary plugin in multiple tests, you can register it inside a fixture in your conftest.py file like this: \n from datasette import hookimpl\nfrom datasette.app import Datasette\nfrom datasette.plugins import pm\nimport pytest\nimport pytest_asyncio\n\n\n@pytest_asyncio.fixture\nasync def datasette_with_plugin():\n class TestPlugin:\n __name__ = \"TestPlugin\"\n\n @hookimpl\n def register_routes(self):\n return [\n (r\"^/error$\", lambda: 1 / 0),\n ]\n\n pm.register(TestPlugin(), name=\"undo\")\n try:\n yield Datasette()\n finally:\n pm.unregister(name=\"undo\")\n \n Note the yield statement here - this ensures that the finally: block that unregisters the plugin is executed only after the test function itself has completed. \n Then in a test: \n @pytest.mark.asyncio\nasync def test_error(datasette_with_plugin):\n response = await datasette_with_plugin.client.get(\"/error\")\n assert response.status_code == 500", "breadcrumbs": "[\"Testing plugins\"]", "references": "[]"}