Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

pytest-anki

pytest-anki is a pytest plugin that allows developers to write tests for their Anki add-ons.

At its core lies the anki_session fixture that provides add-on authors with the ability to create and control headless Anki sessions to test their add-ons in:

from pytest_anki import AnkiSession

def test_addon_registers_deck(anki_session: AnkiSession):
    my_addon = anki_session.load_addon("my_addon")
    with anki_session.load_profile()
        with anki_session.deck_installed(deck_path) as deck_id:
            assert deck_id in my_addon.deck_ids

anki_session comes with a comprehensive API that allows developers to programmatically manipulate Anki, set up and reproduce specific configurations, simulate user interactions, and much more.

The goal is to provide add-on authors with a one-stop-shop for their functional testing needs, while also enabling them to QA their add-ons against a battery of different Anki versions, catching incompatibilities as they arise.

PyPI Code style: black tests

Disclaimer

Project State

Important: The plugin is currently undergoing a major rewrite and expansion of its feature-set, so the documentation below is very sparse at the moment. I am working on bringing the docs up to speed, but until then, please feel free to check out the inline documentation and also take a look at the plug-in's tests for a number of hopefully helpful examples.

Platform Support

pytest-anki has only been confirmed to work on Linux so far.

Installation

Requirements

pytest-anki requires Python 3.8+.

Installing the latest packaged build

$ pip install pytest-anki

or

$ poetry add --dev pytest-anki

Usage

Basic Use

In your tests add:

from pytest_anki import AnkiSession  # for type checking and completions

@pytest.mark.forked
def test_my_addon(anki_session: AnkiSession):
    # add some tests in here

The anki_session fixture yields an AnkiSession object that gives you access to the following attributes, among others:

app {AnkiApp} -- Anki QApplication instance
mw {AnkiQt} -- Anki QMainWindow instance
user {str} -- User profile name (e.g. "User 1")
base {str} -- Path to Anki base directory

Additionally, the fixture provides a number of helpful methods and context managers, e.g. for initializing an Anki profile:

@pytest.mark.forked
def test_my_addon(anki_session: AnkiSession):
    with anki_session.profile_loaded():
        assert anki_session.collection

Configuring the Anki Session

You can customize the Anki session context by passing arguments to the anki_session fixture using pytest's indirect parametrization, e.g.

import pytest

@pytest.mark.forked
@pytest.mark.parametrize("anki_session", [dict(load_profile=True)], indirect=True)
def test_my_addon(anki_session: AnkiSession):
    # profile / collection already pre-loaded!
    assert anki_session.collection

Additional Notes

When to use pytest-anki

Running your test in an Anki environment is expensive and introduces an additional layer of confounding factors. If you can mock your Anki runtime dependencies away, then that should always be your first tool of choice.

Where anki_session comes in handy is further towards the upper levels of the test pyramid, i.e. functional tests, end-to-end tests, and UI tests. Additionally the plugin can provide you with a convenient way to automate testing for incompatibilities with Anki and other add-ons.

The importance of forking your tests

You might have noticed that most of the examples above use a @pytest.mark.forked decorator. This is because, while the plugin does attempt to tear down Anki sessions as cleanly as possible on exit, this process is never quite perfect, especially for add-ons that monkey-patch Anki.

With unforked test runs, factors like that can lead to unexpected behavior, or worse still, your tests crashing. Forking a new subprocess for each test bypasses these limitations, and therefore my advice would be to mark any anki_session tests as forked by default.

To do this in batch for an entire test module, you can use the following pytest hook:

def pytest_collection_modifyitems(items):
    for item in items:
        item.add_marker("forked")

Future versions of pytest-anki will possibly do this by default.

Automated Testing

pytest-anki is designed to work well with continuous integration systems such as GitHub actions. For an example see pytest-anki's own GitHub workflows.

Troubleshooting

pytest hanging when using xvfb

Especially if you run your tests headlessly with xvfb, you might run into cases where pytest will sometimes appear to hang. Oftentimes this is due to blocking non-dismissable prompts that your add-on code might invoke in some scenarios. If you suspect that might be the case, my advice would be to temporarily bypass xvfb locally via pytest --no-xvfb to show the UI and manually debug the issue.

Contributing

Contributions are welcome! To set up pytest-anki for development, please first make sure you have Python 3.8+ and poetry installed, then run the following steps:

$ git clone https://github.com/glutanimate/pytest-anki.git

$ cd pytest-anki

# Either set up a new Python virtual environment at this stage
# (e.g. using pyenv), or let poetry create the venv for you

$ make install

Before submitting any changes, please make sure that pytest-anki's checks and tests pass:

make check
make lint
make test

This project uses black, isort and autoflake to enforce a consistent code style. To auto-format your code you can use:

make format

License and Credits

pytest-anki is

Copyright © 2019-2021 Aristotelis P. (Glutanimate) and contributors

Copyright © 2017-2019 Michal Krassowski

Copyright © 2017-2021 Ankitects Pty Ltd and contributors

All credits for the original idea for creating a context manager to test Anki add-ons with go to Michal. pytest-anki would not exist without his anki_testing project.

I would also like to extend a heartfelt thanks to AMBOSS for their major part in supporting the development of this plugin! Most of the recent feature additions leading up to v1.0.0 of the plugin were implemented as part of my work on the AMBOSS add-on.

pytest-anki is free and open-source software. Its source-code is released under the GNU AGPLv3 license, extended by a number of additional terms. For more information please see the license file that accompanies this program.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. Please see the license file for more details.

Release files for pytest-anki 1.0.0b7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-anki 1.0.0b7
File Size Uploaded
pytest-anki-1.0.0b7.tar.gz 33.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-anki 1.0.0b7
File Interpreter ABI Platform
pytest_anki-1.0.0b7-py3-none-any.whl Python 3 none any Details

Total release size: 74.6 kB

Release files / pytest-anki-1.0.0b7.tar.gz

Download URL pytest-anki-1.0.0b7.tar.gz
Size 33.4 kB
Tags Source
SHA-256 checksum
How to use checksums
357d2df7eba1d969d3c70ef9e89b3bc1a427679468a30d100c8ba11cc13a0d37
BLAKE2b-256 checksum
How to use checksums
69597ccac54dcd086ee19421dacb1e0643889f0dc5ace05c2d21350d64ab9790
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.13 CPython/3.8.10 Linux/5.15.0-41-generic

Release files / pytest_anki-1.0.0b7-py3-none-any.whl

Download URL pytest_anki-1.0.0b7-py3-none-any.whl
Size 41.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e4000f7113cf9ab7e387f8f984f9feedc64ef4fa7323af32b62bc7a30312c10f
BLAKE2b-256 checksum
How to use checksums
b69ada146075566b4c518dd3d0379727e5f25db90af802c953b39bc0a18fdf22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.13 CPython/3.8.10 Linux/5.15.0-41-generic
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page