Adding Tests
I need to implement a full test suite for powercrud. At least pytest covering every module (to say >= 80% on coverage) and even some sleected playwright front end tests.
Why this matters
- Refactors to the core mixins and template tags routinely ship without regression checks.
- Async behaviour is partly covered, but the CRUD, filtering, and HTMX layers remain untested.
- Dependency updates (manual or via bots) are risky without automated verification.
Testing has to evolve past “async smoke tests” and become a first-class guardrail before we iterate on inline editing, dashboards, or template packs.
Objectives
- Stand up a
pytestsuite that exercises the full stack (mixins, template tags, management commands, validators) against the sample project. - Capture critical async behaviours already prototyped in
tests/async_tests/and extend them to cover conflict locks, progress payloads, and cleanup. - Add a thin Playwright smoke suite for HTMX interactions (modal CRUD, bulk selection, inline feedback) to catch JS regressions.
- Integrate the suite with coverage reporting (target ≥80%) so we can gate releases and dependency bumps.
High-level approach
- Stabilise fixtures and helpers
- Create pytest fixtures for sample models, views, and a minimal HTMX client.
- Provide factories for async tasks, cache state, and template overrides.
- Work module-by-module
- Protect the “happy path” flows first (CoreMixin, FormMixin, FilteringMixin, template tags).
- Layer on edge cases (invalid config, template overrides, async failure paths).
- Automate feedback loops
- Run unit/integration suites in CI across supported Python/Django versions.
- Follow up with Playwright smoke tests on at least one environment.
- Prepare for dependency automation
- Once the suite is trustworthy, bring in Dependabot/Renovate to keep Python/JS deps fresh.
Test coverage plan
Phase 1 · CRUD foundations (highest priority)
| Area | Files | Coverage focus | Notes |
|---|---|---|---|
| Core CRUD mixins | mixins/core_mixin.py, mixins/table_mixin.py, mixins/paginate_mixin.py, mixins/url_mixin.py |
List/detail rendering, pagination boundaries, URL + namespace resolution | Use Django’s test client against the sample app; assert context + template fragments. |
| Form & filtering mixins | mixins/form_mixin.py, mixins/filtering_mixin.py |
Field inclusion/exclusion, widget overrides, M2M filter logic (AND/OR), dropdown sorting | Fixtures with simple models and a FilterSet stub; ensure errors bubble correctly. |
| Template tags | templatetags/powercrud.py |
Snapshot table/detail output, boolean/date formatting, property handling | Use django-test-plus or similar to render templates and capture HTML snippets. |
Phase 2 · HTMX + bulk operations
| Area | Files | Coverage focus | Notes |
|---|---|---|---|
| HTMX mixin | mixins/htmx_mixin.py |
Response selection, HX headers, redirects vs fragments | Simulate HTMX and non-HTMX requests; validate headers via test client. |
| Bulk mixin | mixins/bulk_mixin/, mixins/async_mixin.py |
Selection persistence, bulk form validation, async hand-off | Cover both synchronous and async branches; assert redis/cache usage via fakes. |
| Async surface | async_context.py, async_hooks.py, tasks.py |
Conflict checks, progress updates, cleanup hooks | Extend existing async tests to include failure + retry scenarios. |
Phase 3 · Commands, validators, and plumbing
| Area | Files | Coverage focus | Notes |
|---|---|---|---|
| Management commands | management/commands/* |
Tailwind safelist, template copy, async cleanup | Use call_command with temporary directories; assert generated files. |
| Configuration helpers | conf.py, validators.py, logging.py |
Default loading, error handling, logging dict structure | Pure unit tests; assert raised exceptions/messages. |
| Admin/URLs/sample app | admin.py, urls.py, sample/ |
Basic smoke tests to ensure sample project aligns with docs | Ensure docs snippets remain accurate. |
Phase 4 · Front-end smoke (Playwright)
- Load the sample CRUD page, run through create/edit/delete, confirm HTMX modals.
- Exercise bulk selection persistence and progress to catch JS regressions.
- Tag these tests so they can run separately (e.g., nightly or gated on release).
Tooling & infrastructure
- pytest with
pytest-django,pytest-asynciofor async paths, andpytest-covfor coverage reporting. - Factory Boy (or a light internal factory module) for sample data.
- Playwright configured via
pytest-playwrightto reuse fixtures and align with existing tooling. - CI matrix covering the supported Python/Django versions (e.g., Python 3.12 and 3.13 with Django 4.2 & 5.0).
- Coverage thresholds enforced via
--cov-fail-under=80; revisit once we know the true baseline.
Dependency automation roadmap SEPARATE PROJECT
Once Phase 1 and Phase 2 tests are green in CI:
- Enable Dependabot (or Renovate) for:
- Python dependencies (
pyproject.toml/requirementsif present). - GitHub Actions workflows (if applicable).
- JavaScript tooling (
package.json/pnpm-lock.yamlor Vite config dependencies). - Schedule updates weekly; adjust cadence after observing noise level.
- Add automation to rebuild the Docker container / Tailwind assets if versions change.
Initial tasks
- Build pytest configuration & fixtures (
tests.settingsfallback, sqlite defaults). - Cover CoreMixin + table/pagination/url mixins with integration tests.
- Add FormMixin & FilteringMixin tests (including m2m AND logic).
- Snapshot template tag output for list/detail rendering.
- Exercise HTMX mixin triggers/targets and bulk-selection helpers.
- Validate async mixin enablement/manager resolution (conflict checks included).
- Cover management commands (tailwind safelist, template bootstrap, async cleanup).
- Add configuration/logging guardrail tests.
- Draft Playwright smoke scenarios (modal CRUD + bulk operations).
- Wire coverage reporting into CI.
Progress snapshot
- Mixins, template tags, HTMX helpers, bulk-selection logic, management commands, config helpers, and Playwright flows now have coverage (
test_core_phase1.py,test_form_filter_template_mixins.py,test_htmx_bulk_mixins.py,test_management_commands.py,test_conf_logging_validators.py,tests/playwright/). - Test settings fallback to SQLite so the suite can run without external services.
- Full
pytestrun in the dockerised dev environment now passes (122 tests); the remaining open item is wiring coverage into CI (parked until we tackle a Dependabot/Renovate project, at which point we can consider a Django/Python matrix—possibly viauvinstead of tox—in either GitHub or GitLab pipelines).