Metadata-Version: 2.1
Name: pytest-async-sqlalchemy
Version: 0.1.3
Summary: Database testing fixtures using the SQLAlchemy asyncio API
Home-page: https://github.com/igortg/pytest-async-sqlalchemy
Author: Igor T. Ghisi
Author-email: igor.ghisi@gmail.com
Maintainer: Igor T. Ghisi
Maintainer-email: igor.ghisi@gmail.com
License: MIT
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Testing
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Operating System :: OS Independent
Classifier: License :: OSI Approved :: MIT License
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pytest (>=6.0.0)
Requires-Dist: sqlalchemy (>=1.4.0)

# pytest-async-sqlalchemy

![PyPI version](https://img.shields.io/pypi/v/pytest-async-sqlalchemy.svg)
![Python versions](https://img.shields.io/pypi/pyversions/pytest-async-sqlalchemy.svg)

Database testing fixtures using the SQLAlchemy asyncio API

You can install "pytest-async-sqlalchemy" via [pip] from [PyPI]

    $ pip install pytest-async-sqlalchemy

## Setup

### Providing a Session Scoped Event Loop

The first thing to do is to declare an `even_loop` fixture  with the scope set as "session". 
You can copy & paste the code below to your `conftest.py`:

    @pytest.fixture(scope="session")
    def event_loop():
        """
        Creates an instance of the default event loop for the test session.
        """
        if sys.platform.startswith("win") and sys.version_info[:2] >= (3, 8):
            # Avoid "RuntimeError: Event loop is closed" on Windows when tearing down tests
            # https://github.com/encode/httpx/issues/914
            asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

        loop = asyncio.new_event_loop()
        yield loop
        loop.close()

This is required since **pytest-async-sqlalchemy** shares the database connection between tests
for performance reasons, but the default `even_loop` fixture defined by 
[pytest-asyncio](http://pypi.org/project/pytest-asyncio) is function scoped<sup>1</sup> (i.e., it 
kills the database connection after each test). 

### Providing Database URL and Initialization

**pytest-async-sqlalchemy** provides placeholders to configure and initialize
the testing database: `database_url` and `init_database`. These two **must** be
defined in your project `conftest.py` like below:

    @pytest.fixture(scope="session")
    def database_url():
        return "postgresql+asyncpg://postgres:masterkey@localhost/dbtest"
    
    
    @pytest.fixture(scope="session")
    def init_database():
        from myprorject.db import metadata
    
        return metadata.create_all

The `database_url` must be a session-scoped fixture that returns the database URI.
`init_database` must also be a session-scoped fixture that returns the callable used
to initialize the database (in most cases, this would return the 
`metadata.create_all` function).    

## Usage

This plugin provides the following fixtures:

- `dbsession`: An `AsyncSession` object bounded to the test database. Database changes
  are discarded after each test function, so the same database is used for the entire 
  test suite (avoiding the overhead of initializing a database on every test).
- `database`: `database` provides a new database within the scope of the test function. 
  The value of the fixture is a string URL pointing to the database.

## Contributing

Contributions are very welcome. Tests can be run with [tox], please ensure
the coverage at least stays the same before you submit a pull request.

## License

Distributed under the terms of the [MIT] license, "pytest-async-sqlalchemy" is free and open source software

[pip]: http://pypi.org/project/pip
[PyPI]: https://pypi.org/project
[MIT]: http://opensource.org/licenses/MIT
[tox]: https://tox.readthedocs.io/en/latest/

---

<small>1. **pytest-async-sqlalchemy** can't provide its own `even_loop` since pytest plugins are not 
able to override fixtures from one another. So the only solution we have now is to aks the user to
declare its own `event_loop` fixture. Suggestions on how to overcome that in a better way are 
welcome, hit us on the Issues section.</small>


