Skip to main content

nvda-addon-testkit

Project board — live roadmap and status for this repo's issues.

End-to-end testing for NVDA add-ons, against a real NVDA, in CI.

Your add-on's logic can be unit-tested with stubs. What cannot be stubbed is whether it installs, registers, and behaves inside NVDA itself. This kit provisions a disposable portable NVDA, installs your add-on into it, and lets pytest drive it.

def test_my_addon_announces_itself(nvda, addon_under_test):
    before = nvda.speech.index()
    nvda.keys.press("NVDA+shift+m")
    assert "my add-on is ready" in nvda.speech.wait_for("ready", timeout=10, since=before).text
    nvda.log.assert_no_errors()

The same test reads as plain steps with the (experimental) DSL:

def test_my_addon_announces_itself(nvda, addon_under_test):
    nvda.press("NVDA+shift+m")
    nvda.should_hear("my add-on is ready")
    nvda.should_have_no_errors()

Install

pip install nvda-addon-testkit

Configure

[tool.nvda-testkit]
addon-bundle = "dist/my-addon-*.nvda-addon"
nvda-channel = "stable"

Run in GitHub Actions

jobs:
  e2e:
    runs-on: windows-2025
    steps:
      - uses: actions/checkout@v5
      - uses: zirekhq/nvda-addon-testkit@v1
        with:
          nvda-channel: stable
      - run: pytest tests_e2e/ -v

The action is OS-agnostic — pick whichever Windows runner matches what your users run. This repository's e2e test suite runs on both windows-2025 and windows-2022 (the latter for Windows 10 22H2, including builds still on Extended Security Updates).

What you get

Fixture What it gives you
nvda a connected client, reset between tests
addon_bundle the path to your built .nvda-addon
addon_under_test that bundle, installed and enabled, NVDA restarted
Namespace Use it for
nvda.speech what NVDA asked to say, and waiting for it
nvda.braille the raw text sent to the braille display
nvda.keys sending gestures through NVDA's own input pipeline
nvda.config reading and writing NVDA's configuration
nvda.log structured log records, and assert_no_errors()
nvda.addons two-phase install, remove, and state

nvda.eval() runs a single expression inside NVDA; nvda.exec() runs a full multi-statement scenario and returns whatever it binds to __result__. Both need --nvda-allow-eval. A bad scenario raises ScenarioSyntaxError, so catching bare except Exception: pass around either call still swallows it — catch the types you expect instead.

nvda.restart_harness() kills and relaunches the NVDA process — use it to finish a two-phase add-on install or reset to a clean process. It does not exercise NVDA's own restart logic. For that, use nvda.restart_nvda(), which triggers NVDA's real core.restart() and waits for the replacement process — needs --nvda-allow-eval, since it is built on nvda.eval().

A real wx.Dialog.ShowModal() never returns control to any of the above — NVDA's main-thread queue doesn't drain while one is up. Open it with nvda.exec_nowait() instead of exec() (queues the scenario without waiting for it to finish), then close it with nvda.simulate_modal(gesture, timeout=10.0), which sends real injected keyboard input once our process takes the foreground.

Requirements

Windows to run the tests. NVDA is downloaded automatically — you do not need one installed, and nothing touches an NVDA you already have.

Tests run serially: only one NVDA can own a desktop session, so pytest-xdist with more than one worker is refused rather than silently producing nonsense.

Developing the kit itself

The host side is fully testable on Linux against a scriptable double:

pip install -e ".[dev]"
python tools/build_spy.py
pytest                       # host and spy unit tests, any platform
pytest tests_e2e/ -v         # real NVDA, Windows only
nvda-testkit doctor          # check this machine

Licence

GPL-2.0-or-later.


💝 Support This Project

If this repository saves you time and effort, please consider supporting it!

Metadata

Release files for nvda-addon-testkit 1.1.0

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

Source distribution (sdist)

Source distribution for nvda-addon-testkit 1.1.0
File Size Uploaded
nvda_addon_testkit-1.1.0.tar.gz 202.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nvda-addon-testkit 1.1.0
File Interpreter ABI Platform
nvda_addon_testkit-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 264.5 kB

Release files / nvda_addon_testkit-1.1.0.tar.gz

Download URL nvda_addon_testkit-1.1.0.tar.gz
Size 202.0 kB
Tags Source
SHA-256 checksum
How to use checksums
52a7ac0e07f768cb69235bbbfe4cefdb6315dea92a81ec7ee829fd2f3dbf453a
BLAKE2b-256 checksum
How to use checksums
65d1b73bcad565fe64d86459c02bf5395fa111421cbb952d5aa9dda3b6a06064
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nvda_addon_testkit-1.1.0-py3-none-any.whl

Download URL nvda_addon_testkit-1.1.0-py3-none-any.whl
Size 62.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e19d9a0b45bbed26803785460797a95156db8de3f8ab140be971cda8c3ebc2ec
BLAKE2b-256 checksum
How to use checksums
acf5331bfecc07a73a42f25eddbe033bf7d7801114facccb50e7e0cbc5c04027
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.0

2 release files

0.1.3

2 release files

0.1.1

2 release files

0.1.0

2 release files

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