Overview
PyQt Testing Tools is a professional testing toolkit for PyQt desktop applications. Catch UI bugs, verify behavior, analyze test reliability — all integrated with Claude Code workflows.
Key Features
- Snapshot Testing - Capture and compare UI state over time
- Visual Regression - Detect unintended layout/styling changes
- Mutation Testing - Verify UI responds correctly to edge cases
- Flakiness Detection - Identify non-deterministic test failures
- Test Recording - Record user interactions, replay as tests
- Widget Inspection - Deep introspection of Qt widget properties
Installation
# Install via pip
pip install pyqt-testing-tools
# Or with pytest plugin
pip install pyqt-testing-tools[pytest]
Quick Start
# Test with pytest
import pytest
from pyqt_testing import QtTestCase
class TestLoginDialog(QtTestCase):
def test_login_success(self):
# Arrange
dialog = LoginDialog()
dialog.show()
# Act
self.qt_type(dialog.username_field, "user@example.com")
self.qt_type(dialog.password_field, "password123")
self.qt_click(dialog.login_button)
# Assert
self.qt_wait_for_dialog(SuccessDialog)
self.qt_assert_visible(dialog.success_message)
def test_login_snapshot(self):
# Visual regression test
dialog = LoginDialog()
dialog.show()
# Compare with baseline
self.qt_snapshot_compare(
widget=dialog,
baseline="login-dialog-baseline.png"
)
Use Cases
Automated UI Regression Testing
Catch visual and behavioral regressions automatically. Run tests on every commit to prevent UI bugs from shipping.
End-to-End User Workflows
Script complete user journeys: open app → navigate → interact → verify results. Ensure critical paths always work.
Cross-Platform Testing
Test on multiple OS/Qt versions. Detect platform-specific rendering issues before users report them.
Performance Profiling
Measure UI responsiveness: widget load times, event handling latency, paint performance.
Integration Options
Standalone Library
Use directly in Python scripts:
from pyqt_testing import QtTester
tester = QtTester(app)
tester.click("MainWindow/QPushButton[0]")
tester.snapshot("current-state")
pytest Plugin
Integrate with pytest for test discovery and reporting:
# conftest.py
pytest_plugins = ['pyqt_testing.pytest_plugin']
# test_ui.py
def test_button_click(qt_tester):
qt_tester.click("my_button")
assert qt_tester.is_enabled("submit_button")
Claude Code MCP Server
Use via gpyqt-instrument for AI-assisted testing:
"Claude, run the login tests and report any failures"
"Claude, take a snapshot of the settings dialog and compare with baseline"
Testing Patterns
Page Object Pattern
class LoginPage:
def __init__(self, tester):
self.tester = tester
self.username = "LoginDialog/username_field"
self.password = "LoginDialog/password_field"
self.submit = "LoginDialog/submit_button"
def login(self, username, password):
self.tester.type(self.username, username)
self.tester.type(self.password, password)
self.tester.click(self.submit)
Data-Driven Testing
@pytest.mark.parametrize("input,expected", [
("valid@email.com", True),
("invalid-email", False),
("", False),
])
def test_email_validation(qt_tester, input, expected):
qt_tester.type("email_field", input)
assert qt_tester.is_valid("email_field") == expected
Mutation Testing
def test_error_handling(qt_tester):
# Inject edge cases
mutations = ["", None, "x" * 10000, "<script>", "\n\n\n"]
for mutation in mutations:
qt_tester.type("input_field", mutation)
# App should not crash
assert qt_tester.is_running()
Perfect For
- PyQt6 application developers - Native testing for PyQt apps
- QA teams - Automated regression and exploratory testing
- Claude Code users - AI-assisted UI test generation
- CI/CD pipelines - Headless UI testing on build servers
Architecture
┌──────────────────┐
│ Your PyQt App │
│ │
│ ┌────────────┐ │
│ │ Qt Event │ │
│ │ System │ │
│ └──────┬─────┘ │
└─────────┼────────┘
│
┌─────▼─────┐
│ PyQt │
│ Testing │
│ Tools │
└─────┬─────┘
│
┌─────▼─────────┐
│ Test Runner │
│ (pytest/MCP) │
└───────────────┘
Tests interact with Qt’s event system to simulate user actions. Widget state is captured via Qt’s introspection APIs.
Best Practices
- Use page objects - Encapsulate UI structure, tests reference pages not widgets
- Test behavior, not implementation - Assert outcomes, not internal state
- Keep tests independent - Each test should run successfully in isolation
- Baseline carefully - Visual baselines should represent correct UI, not first snapshot
- Run in CI - Use Xvfb (Linux) or virtual displays for headless testing
CI/CD Example
# .github/workflows/test.yml
name: UI Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
sudo apt-get install -y xvfb
pip install pyqt-testing-tools[pytest]
- name: Run UI tests
run: xvfb-run pytest tests/ui/
Documentation
Support
- GitHub Issues (repo coming soon)
- Discussions
- Email: support@silverwizard.dev