Development Workflow
This guide covers the recommended workflow for developing Test Packages, including manual testing, debugging, and AI-assisted development.
Manual Testing Workflow
Starting an Environment
The most efficient way to develop Test Packages is to start an environment and test manually:
# Start environment with specific version
php qit-cli.php env:up --woo nightly
# Or with multiple options
php qit-cli.php env:up --php=8.2 --wordpress=6.4 --woo=8.5
Output:
Removing dangling test environments...
Downloading plugins and themes... (WooCommerce: nightly)
Starting Docker Environment...
Installing WordPress...
Activating plugins...
✅ Environment ready: qitenv35a3979857a7a672
URL: http://localhost:32820
Credentials: admin/password
Stack: WordPress stable, PHP 8.2
Plugins: WooCommerce nightly
To run manual tests:
1. Navigate to your test directory
2. Load environment variables in this terminal:
source "$(qit env:source qitenv35a3979857a7a672)"
3. Run your tests:
npx playwright test
Loading Environment Variables
After starting an environment, load its variables into your terminal:
source "$(qit env:source qitenv35a3979857a7a672)"
This provides:
✓ QIT environment variables loaded
Environment: qitenv35a3979857a7a672
Site URL: http://localhost:32820
DB Port: 0
Now your terminal has access to:
QIT_SITE_URL- The WordPress site URLQIT_WP_ADMIN- Admin panel URLQIT_DB_NAME- Database nameQIT_DB_USER- Database usernameQIT_DB_PASS- Database passwordQIT_DB_HOST- Database host
After sourcing, @woocommerce/qit-runtime works automatically. qit.env.siteUrl, qit.wp(), qit.actions(), and qit.package() are all available in your Playwright tests.
Running Tests Manually
Navigate to your test package and run tests:
cd packages/checkout-tests/
npx playwright test
# Or run specific test
npx playwright test checkout.spec.js
# Or with debugging
npx playwright test --debug
# Or with UI mode
npx playwright test --ui
Development Cycle
-
Start environment once
php qit-cli.php env:up --woo nightly
source "$(qit env:source qitenv...)" -
Develop tests iteratively
# Edit test file
vim tests/checkout.spec.js
# Run test
npx playwright test checkout.spec.js
# See it fail, fix, repeat -
Test with full orchestration
# When ready, test with full lifecycle
php qit-cli.php run:e2e woocommerce --config=test.json -
Clean up when done
php qit-cli.php env:down
Utility Packages with env:up
Using Utility Packages for Setup
Utility packages work perfectly with env:up --global-setup:
# Start environment with utility packages only
php qit-cli.php env:up woocommerce --global-setup --config=utilities.json
utilities.json:
{
"test_types": {
"e2e": {
"default": {
"test_packages": [
"./utilities/disable-onboarding",
"./utilities/create-test-data",
"./utilities/configure-stripe"
]
}
}
}
}
This will:
- Start the environment
- Run globalSetup from all utility packages
- Leave environment running for manual testing
- NO test execution (utility packages have no run phase)
Why This Works
env:up --global-setupdoesn't require test packages- Utility packages are perfect for environment preparation
- Database changes persist (no snapshots with env:up)
- Environment stays running for development
Example Utility Package for Development
utilities/dev-setup/qit-test.json:
{
"package": "dev-setup",
"namespace": "utilities",
"test_type": "e2e",
"description": "Development environment setup",
"test": {
"phases": {
"globalSetup": [
"wp plugin install woocommerce-gateway-stripe --activate",
"wp plugin install wordpress-importer --activate",
"wp import /app/sample-data.xml --authors=create",
"wp option set woocommerce_task_list_hidden yes",
"wp user create testcustomer test@test.com --role=customer --user_pass=test123",
"wp wc product create --name='Test Product' --regular_price=9.99 --user=1",
"echo 'Development environment ready!'"
]
}
}
}
Debugging Failed Tests
PHP step debugging with Xdebug
For PHP-level debugging (breakpoints, variable inspection, profiling), see the Xdebug guide. Start an environment with qit env:up --xdebug and your IDE will catch breakpoints on every request.
Getting Context from Failed Tests
When tests fail, get AI-friendly context:
php qit-cli.php ai:context failed-e2e
This generates a comprehensive report including:
- Error messages and stack traces
- Test output and logs
- Environment configuration
- Screenshots (if available)
- Relevant code snippets
Understanding Test Packages
Get complete context about Test Packages:
php qit-cli.php ai:context understanding-test-packages
This provides:
- Test Package architecture
- Lifecycle explanation
- Manifest schema
- Command execution context
- Database isolation details
Test Package Development Best Practices
1. Start Simple
Begin with a minimal test:
test('can access site', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveTitle(/WooCommerce/);
});
2. Use Manual Testing First
Before orchestration, test manually:
# Start environment
php qit-cli.php env:up --woo nightly
source "$(qit env:source ...)"
# Test your commands work
cd my-package/
npm install
npx playwright test
3. Add to Manifest Incrementally
Start with minimal manifest:
{
"package": "my-test",
"namespace": "dev",
"test_type": "e2e",
"test": {
"phases": {
"run": ["npx playwright test"]
},
"results": {
"ctrf-json": "./results/ctrf.json",
"blob-dir": "./results/artifacts"
}
}
}
Then add phases as needed:
- Add
setupwhen you need dependencies - Add
globalSetupfor shared configuration - Add
teardownfor cleanup - Add
requires.secretsfor API keys
4. Test Isolation
Verify your tests work in isolation:
# Run just your package
php qit-cli.php run:e2e woocommerce --config=single-package.json
5. Use Verbose Mode for Debugging
php qit-cli.php run:e2e woocommerce --config=test.json --verbose
Interactive Development
Using Playwright UI Mode
For interactive test development:
# After loading environment
npx playwright test --ui
This provides:
- Visual test execution
- Step-by-step debugging
- Time travel debugging
- Element picker
Using Playwright Inspector
# Run with inspector
PWDEBUG=1 npx playwright test
Recording New Tests
Use Playwright codegen with QIT environment:
# Load environment first
source "$(qit env:source ...)"
# Record new test
npx playwright codegen $QIT_SITE_URL
File System and Database Persistence
Understanding Persistence in Manual Testing
When using env:up for manual testing:
File System
- Changes to WordPress files persist
- Uploaded media persists
- Plugin/theme installations persist
- Test artifacts accumulate
Example test showing filesystem persistence:
test('create filesystem marker', async ({ page }) => {
const fs = require('fs');
const markerFile = '/tmp/test-marker.txt';
fs.writeFileSync(markerFile, 'Test was here');
console.log(`Created marker at ${markerFile}`);
// This file persists between test runs
expect(fs.existsSync(markerFile)).toBeTruthy();
});
Database
- All changes persist
- No automatic cleanup
- No snapshots/restore
- Perfect for iterative development
Example test showing database persistence:
test('create test post', async ({ page }) => {
await page.goto('/wp-admin');
await page.fill('#user_login', 'admin');
await page.fill('#user_pass', 'password');
await page.click('#wp-submit');
// Create post
await page.goto('/wp-admin/post-new.php');
await page.fill('[aria-label="Add title"]', 'Test Post');
await page.click('button:has-text("Publish")');
// This post persists between test runs
console.log('Created test post - will persist');
});
Understanding Isolation in Orchestrated Tests
When using run:e2e with orchestration:
Database Isolation
- Snapshot taken after globalSetup
- Each package starts from snapshot
- Changes don't persist between packages
Filesystem Sharing
- Filesystem is shared between packages
- Files created by one package visible to others
- Useful for passing data between packages
Example showing the difference:
// Package 1
test('package 1 modifications', async () => {
// Database change - won't be seen by Package 2
await createWordPressPost('Package 1 was here');
// Filesystem change - WILL be seen by Package 2
fs.writeFileSync('/tmp/shared-data.txt', 'Package 1 data');
});
// Package 2
test('package 2 checks', async () => {
// Won't see the post (database isolated)
const posts = await getWordPressPosts();
expect(posts).not.toContain('Package 1 was here');
// WILL see the file (filesystem shared)
const data = fs.readFileSync('/tmp/shared-data.txt', 'utf8');
expect(data).toBe('Package 1 data');
});
Performance Optimization
Faster Development Cycles
-
Keep environment running
# Start once at beginning of day
php qit-cli.php env:up --woo nightly
source "$(qit env:source ...)" -
Use watch mode
{
"scripts": {
"test:watch": "playwright test --watch"
}
} -
Run specific tests
npx playwright test checkout.spec.js:10 -
Skip unnecessary setup
# During development, skip npm install if already done
[ -d node_modules ] || npm ci
Parallel Development
Run multiple environments:
# Terminal 1: Stable testing
php qit-cli.php env:up --woo stable
source "$(qit env:source ...)"
# Terminal 2: Nightly testing
php qit-cli.php env:up --woo nightly
source "$(qit env:source ...)"
Common Development Patterns
Pattern 1: TDD Workflow
# 1. Start environment
php qit-cli.php env:up --woo nightly
source "$(qit env:source ...)"
# 2. Write failing test
cat > test.spec.js << 'EOF'
test('checkout with coupon', async ({ page }) => {
// Test that will fail initially
});
EOF
# 3. Run test, see it fail
npx playwright test test.spec.js
# 4. Implement feature/fix
# 5. Run test, see it pass
# 6. Refactor if needed
Pattern 2: Debugging Production Issues
# 1. Reproduce issue manually
php qit-cli.php env:up --woo=8.5.1 --php=7.4
# Navigate to site, reproduce issue
# 2. Write test that captures issue
npx playwright codegen $QIT_SITE_URL
# 3. Add to test suite
# 4. Fix issue
# 5. Verify test passes
Pattern 3: Cross-Version Testing
# Test against multiple versions
for version in "8.4" "8.5" "nightly"; do
echo "Testing WooCommerce $version"
php qit-cli.php env:up --woo=$version
source "$(qit env:source ...)"
npx playwright test
php qit-cli.php env:down
done
Troubleshooting Development Issues
Environment Variables Not Set
# Check if variables loaded
echo $QIT_SITE_URL
# If empty, reload
source "$(qit env:source qitenv...)"
Port Conflicts
# Check what's using the port
lsof -i :32820
# Or use a different environment
php qit-cli.php env:down
php qit-cli.php env:up --woo nightly
Stale Environment
# Clean up and start fresh
php qit-cli.php env:down
docker system prune -f
php qit-cli.php env:up --woo nightly