Skip to content

Testing Strategy

How and when to use each testing tool available in the project.

Important Before running any tests, review os_HANGING_PROCESSES.md for known gotchas. Kill zombie processes first: bash scripts/kill-zombies.sh

LayerToolSpeedWhat it testsWhen to use
LintingPHPCS (Drupal + DrupalPractice)⚡ InstantCode style, best practicesEvery commit
UnitPHPUnit Unit⚡ Fast (~ms)Pure PHP logic, no Drupal bootstrapService classes, utility functions
KernelPHPUnit Kernel🟡 Medium (~sec)Database + Drupal APIs, no HTTPEntity operations, hooks, config, queries
E2EPlaywright🔴 Slow (~min)Full user flows in browserCritical paths: create group, join, post, search
AccessibilityNightwatch + Axe🔴 Slow (~10s)WCAG compliance, ARIANew pages/templates added by groups feature
Terminal window
ddev exec vendor/bin/phpcs --standard=phpcs.xml.dist web/modules/custom/do_*
ddev exec vendor/bin/phpcbf --standard=phpcs.xml.dist web/modules/custom/do_*
Terminal window
# Run all custom module tests
ddev exec phpunit -c phpunit.xml
# Run tests for one module
ddev exec phpunit web/modules/custom/do_discovery/tests/
ddev exec phpunit web/modules/custom/do_notifications/tests/
# Run phase integration tests
ddev exec phpunit web/modules/custom/do_tests/tests/src/Kernel/Phase1Test.php

Module-specific tests live inside each custom module:

web/modules/custom/do_discovery/
├── src/
├── tests/
│ └── src/
│ └── Kernel/
│ └── DiscoveryTest.php
└── do_discovery.info.yml

Phase integration tests (cross-cutting config verification) live in do_tests:

web/modules/custom/do_tests/
└── tests/
└── src/
└── Kernel/
├── Phase1Test.php ← group types, fields, relationships
├── Phase2Test.php ← vocabularies, views, pending groups
├── Phase3Test.php ← cardinality, tags, stream views
├── Phase4Test.php ← flags, statistics, hot content view
├── Phase5Test.php ← follow flags, notification queue, frequency field
├── Phase6Test.php ← content translation, languages, block placements
└── Phase7Test.php ← demo data integrity
Terminal window
# Run all e2e tests
npx playwright test
# Run tests for one phase
npx playwright test tests/e2e/phase1.spec.ts

Tests live in tests/e2e/phase{N}.spec.ts. Each phase covers full user flows:

  • Group CRUD, permissions, content posting
  • Flag toggles, search, RSS/iCal feeds
  • Notification settings, profile stats, language switching

Caution Never use waitForLoadState('networkidle') — Drupal sites with background AJAX will hang indefinitely. Use waitForLoadState('load') instead. See os_HANGING_PROCESSES.md §1.

Terminal window
composer nightwatch

Existing tests/Nightwatch/Tests/a11yTest.js runs Axe checks. Add test cases for group pages:

  • /group/*, /groups, group creation form
ModuleTest FileKey Tests
do_group_extrasGroupExtrasTest.phpArchive access, guidelines form alter
do_multigroupMultigroupTest.phpGroup audience form alter, cross-post badge
do_discoveryDiscoveryTest.phpHot score calculation, iCal route/controller
do_notificationsNotificationsTest.phpEvent recording, suppression, auto-subscribe
do_profile_statsProfileStatsTest.phpContribution stats, profile completeness
do_group_pinGroupPinTest.phpPin flag, Views query alter, sort order
do_group_missionGroupMissionTest.phpMission block, description truncation
do_group_languageGroupLanguageTest.phpLanguage negotiation plugin, group language field
PhasePHPUnit (module)PHPUnit (integration)PlaywrightStep
1 — FoundationPhase1Testphase1.spec.ts180
2 — Group TypesGroupExtrasTestPhase2Testphase2.spec.ts280
3 — ContentMultigroupTestPhase3Testphase3.spec.ts350
4 — DiscoveryDiscoveryTestPhase4Testphase4.spec.ts490
5 — NotificationsNotificationsTestPhase5Testphase5.spec.ts560
6 — Profiles & Admin4 module testsPhase6Testphase6.spec.ts650
7 — Demo DataPhase7Testphase7.spec.ts780
  1. ddev exec vendor/bin/phpcs --standard=phpcs.xml.dist web/modules/custom/do_*
  2. ddev exec phpunit -c phpunit.xml --testsuite=kernel
  3. ddev drush cr — no PHP errors
  4. ddev drush config:status — config is clean