| name | lorairo-test-generator |
| version | 1.0.0 |
| description | Generate pytest unit, integration, and GUI tests for LoRAIro with fixtures, mocks, 75%+ coverage, and pytest-qt for PySide6. Use when creating test suites or ensuring code quality. |
| metadata | {"short-description":"LoRAIro向けpytest/pytest-qtテスト生成(fixtures、mocks、カバレッジ重視)。"} |
| allowed-tools | ["Grep","Grep","Grep","Grep","Read","Write","Bash"] |
| dependencies | ["lorairo-mem"] |
Test Generation for LoRAIro
pytest+pytest-qt test generation with fixtures, mocks, and 75%+ coverage for LoRAIro project.
When to Use
Use this skill when:
- Creating tests: After implementing new features
- Improving coverage: Increasing existing test coverage
- Regression testing: After refactoring code
- GUI testing: Implementing PySide6 widget tests
Test Categories
pytest Markers
Three test levels:
@pytest.mark.unit
def test_calculate_score():
assert calculate_score(10, 20) == 0.5
@pytest.mark.integration
def test_repository_service_integration():
service = ImageProcessingService(repository)
result = service.process_batch(images)
assert len(result) > 0
@pytest.mark.gui
def test_widget_interaction(qtbot):
widget = ThumbnailWidget()
qtbot.addWidget(widget)
assert widget.isVisible()
Running Tests
uv run pytest
uv run pytest -m unit
uv run pytest -m integration
uv run pytest -m gui
uv run pytest --cov=src --cov-report=html
Core Patterns
1. Unit Tests
Repository test example:
@pytest.fixture
def test_repository(test_db_engine):
session_factory = scoped_session(sessionmaker(bind=test_db_engine))
repo = ImageRepository(session_factory)
yield repo
session_factory.remove()
@pytest.mark.unit
def test_add_image(test_repository):
"""Test image addition."""
image = Image(path="/test/image.jpg", phash="abc123")
result = test_repository.add(image)
assert result.id is not None
assert result.path == "/test/image.jpg"
Service test with mocks:
@pytest.fixture
def mock_repository():
repo = Mock(spec=ImageRepository)
repo.get_all.return_value = [Image(id=1, path="/img1.jpg")]
return repo
@pytest.mark.unit
def test_process_batch(mock_repository):
service = ImageProcessingService(mock_repository)
result = service.process_batch(["/img1.jpg"])
assert len(result) == 1
2. Integration Tests
Full workflow test:
@pytest.mark.integration
def test_full_workflow(test_repository):
"""Test complete workflow."""
images = [Image(path=f"/img{i}.jpg") for i in range(5)]
added = test_repository.batch_add(images)
assert len(added) == 5
results = test_repository.search(SearchCriteria(min_score=0.5))
assert isinstance(results, list)
3. GUI Tests (pytest-qt)
Widget test:
@pytest.fixture
def thumbnail_widget(qtbot):
widget = ThumbnailWidget()
qtbot.addWidget(widget)
return widget
@pytest.mark.gui
def test_signal_emission(qtbot, thumbnail_widget):
"""Test signal emission."""
with qtbot.waitSignal(thumbnail_widget.image_selected, timeout=1000) as blocker:
thumbnail_widget.select_image(0)
assert blocker.args[0] == "/path/to/image.jpg"
@pytest.mark.gui
def test_button_click(qtbot, thumbnail_widget):
"""Test button interaction."""
qtbot.mouseClick(thumbnail_widget._ui.loadButton, Qt.LeftButton)
assert thumbnail_widget._images_loaded is True
4. Fixtures
Common fixtures:
@pytest.fixture(scope="session")
def test_data_dir():
return Path(__file__).parent / "resources"
@pytest.fixture
def sample_image(test_data_dir):
return test_data_dir / "sample.jpg"
@pytest.fixture(params=[1, 5, 10])
def batch_size(request):
"""Parameterized fixture."""
return request.param
Best Practices
DO:
- Use AAA pattern (Arrange, Act, Assert)
- Single assertion per test
- Use fixtures for setup/teardown
- Apply appropriate pytest markers
- Maintain 75%+ code coverage
DON'T:
- Create dependencies between tests
- Call external APIs (use mocks)
- Hardcode paths (use
tests/resources/)
- Use print statements (use logger or assert messages)
- Write slow unit tests (keep under 1 second)
Coverage Requirements
uv run pytest --cov=src --cov-report=html
Project Structure
tests/
├── conftest.py # Shared fixtures
├── resources/ # Test data
│ ├── sample.jpg
│ └── test_config.toml
├── database/ # Database tests
│ └── test_db_repository.py
├── services/ # Service tests
│ └── test_image_processing_service.py
└── gui/ # GUI tests
├── widgets/
│ └── test_thumbnail_widget.py
└── window/
└── test_main_window.py
Test Sync (diff-driven, 旧 /test sync)
コード変更後に、テストの追加・修正・削除を差分から判定して同期する。新規実装直後だけでなく、
リファクタやシグネチャ変更の後にも使う。
手順
- 変更検出: 変更されたソースを特定し、種別を分類する。
git diff --name-status HEAD~1..HEAD -- 'src/**/*.py'
A (Added) → 対応テストを追加
M (Modified) → シグネチャ/振る舞い変更ならテストを修正(内部実装のみなら実行で確認、変更不要のことが多い)
D (Deleted) → 対応テストを削除(削除前にユーザー確認)
- 影響範囲の特定:
investigation agent または Grep で変更シンボルの参照元を追い、波及するテストを洗う。
- テストファイル対応表:
src/lorairo/services/foo.py → tests/unit/services/test_foo.py
src/lorairo/gui/widgets/bar.py → tests/unit/gui/widgets/test_bar.py
- 同期アクション実行: 追加は本 skill の Core Patterns に従い生成。修正は変更 API に合わせ更新。削除は確認後に実施。
- 検証: 新規/修正テストと回帰テストを
uv run pytest で確認(CI-equivalent filter は .claude/rules/testing.md)。
クイック品質チェック(Ruff/mypy/pytest)は make format / make mypy / uv run pytest で直接実行する(専用コマンドは不要)。
エラー診断は superpowers systematic-debugging + build-error-resolver agent に委ねる。
Memory Integration
Before writing tests:
- 類似のテストパターン・既存 fixture を確認する(
tests/conftest.py、近接する test_*.py)。
- 長期記憶に該当知見があれば [[lorairo-mem]] の
ltm_search.py で参照する。
After writing tests:
- 再利用価値のあるテスト戦略・モック方針は [[lorairo-mem]] に
type: howto で保存する。
Examples
See examples.md for detailed test implementation scenarios.
Reference
See reference.md for complete pytest and pytest-qt API reference.