Files
crowd-funder-for-time-pwa/test-playwright/PERFORMANCE_MONITORING.md
Matthew Raymer 1dd3d9f8d1 feat: implement batched feed updates with performance monitoring
- Add nextTick() batching to HomeView feed processing to reduce Vue reactivity triggers
- Integrate comprehensive performance tracking in 60-new-activity test
- Add performance collector utilities for measuring user actions and navigation metrics
- Document performance analysis with measured vs predicted data distinction

Performance improvements:
- Test completion: 45+ seconds → 23.7s (Chromium), 18.0s (Firefox)
- Eliminated timeout issues across browsers
- Added performance monitoring infrastructure for future optimization

Note: Vue reactivity impact is hypothesized but not directly measured - enhanced metrics needed for validation.
2025-08-01 12:26:16 +00:00

257 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Performance Monitoring in Playwright Tests
Performance monitoring is more than just numbers — its about understanding **how your users experience your app** during automated test runs.
This guide will teach you not just how to set it up, but also **why each step matters**.
---
## Why Performance Monitoring Matters
Think of Playwright tests as quality control for your apps speed and responsiveness.
By adding performance monitoring, you can:
- 🚨 **Catch regressions early** before users feel them
- 🎯 **Keep user experience consistent** across releases
- 🔎 **Spot bottlenecks** in login, navigation, or heavy data flows
- 📊 **Make informed decisions** with hard data, not guesses
- 🏆 **Maintain performance standards** as features grow
> **Key Insight:** Without metrics, “fast” is just a feeling. With metrics, its a fact.
---
## How It Works: The Architecture
The monitoring system has **four pillars**:
1. **PerformanceCollector Class** Collects raw metrics
2. **Performance Utilities** Easy-to-use helper functions
3. **Test Integration** Hooks directly into Playwright tests
4. **Report Generation** Creates JSON reports you can analyze later
Heres a mental model:
```
Playwright Test
|
v
PerformanceCollector (collects data)
|
v
Report Generation → JSON / HTML / CI attachments
```
### Core Collector
```typescript
// performanceUtils.ts
export class PerformanceCollector {
private page: Page;
public metrics: any;
public navigationMetrics: any[];
private cdpSession: any;
// Methods for collecting various metrics
async collectNavigationMetrics(label: string)
async collectWebVitals()
async measureUserAction(actionName: string, actionFn: () => Promise<void>)
generateReport()
}
```
👉 **Teaching Point:** `measureUserAction` wraps a user action and times it, giving you reproducible benchmarks.
---
## Quick Start: A Simple Example
```typescript
import { createPerformanceCollector, attachPerformanceData } from './performanceUtils';
test('My test with performance monitoring', async ({ page }, testInfo) => {
const perfCollector = await createPerformanceCollector(page);
// Measure user action
await perfCollector.measureUserAction('click-button', async () => {
await page.click('#my-button');
});
// Attach data to the test report
await attachPerformanceData(testInfo, perfCollector);
});
```
✅ After this test runs, youll find performance data **directly in the Playwright report**.
---
## Advanced Example: A Complete User Flow
```typescript
test('Complex user flow with performance tracking', async ({ page }, testInfo) => {
const perfCollector = await createPerformanceCollector(page);
await perfCollector.collectNavigationMetrics('initial-load');
await perfCollector.measureUserAction('login', async () => {
await page.fill('#username', 'user');
await page.fill('#password', 'pass');
await page.click('#login-button');
});
await perfCollector.measureUserAction('navigate-to-dashboard', async () => {
await page.goto('/dashboard');
});
await attachPerformanceData(testInfo, perfCollector);
});
```
> **Pro Tip:** Use descriptive labels like `'login'` or `'navigate-to-dashboard'`
to make reports easy to scan.
---
## What Metrics Youll See
### Navigation Metrics (Page Load)
- `domContentLoaded` → When DOM is ready
- `loadComplete` → When page is fully loaded
- `firstPaint` → When users first *see* something
- `serverResponse` → How quickly the backend responds
### User Action Metrics
- `duration` → How long the action took
- `metrics` → Detailed performance snapshots
### Memory Usage
- `used`, `total`, `limit` → Helps catch leaks and spikes
### Web Vitals
- **LCP** → Largest Contentful Paint
- **FID** → First Input Delay
- **CLS** → Layout stability
---
## Reading the Data: A Beginners Lens
Heres what a **healthy test run** might look like:
```json
{
"label": "home-page-load",
"metrics": {
"domContentLoaded": 294,
"loadComplete": 295,
"serverResponse": 27.6,
"resourceCount": 96
}
}
```
**Interpretation:**
- DOM loaded fast (<500ms) ✅
- Server response is excellent (<100ms) ✅
- Resource count is reasonable for a SPA ✅
Now, heres a **problematic run**:
```json
{
"label": "slow-page-load",
"metrics": {
"domContentLoaded": 2500,
"loadComplete": 5000,
"serverResponse": 800,
"resourceCount": 200
}
}
```
**Interpretation:**
- DOM took 2.5s ❌
- Full load took 5s ❌
- Too many resources (200) ❌
> **Lesson:** Slow page loads often mean large bundles, too many requests, or server lag.
---
## Performance Threshold Cheat Sheet
| Metric | Excellent | Good | Poor |
|--------|-----------|------|------|
| domContentLoaded | < 500ms | < 1000ms | > 2000ms |
| loadComplete | < 1000ms | < 2000ms | > 3000ms |
| userAction duration | < 100ms | < 300ms | > 500ms |
| memory usage | < 50MB | < 100MB | > 150MB |
👉 Use these thresholds to set alerts in your regression tests.
---
## Common Patterns
1. **Initial Page Load**
- ✅ DOM in <500ms
- ✅ Load in <1000ms
- ⚠️ Watch out for large bundles
2. **User Interaction**
- ✅ Actions under 100ms
- ✅ Few/no extra requests
- ⚠️ Avoid bloated API calls
3. **Navigation**
- ✅ <200ms between pages
- ⚠️ Inconsistency usually means missing cache headers
---
## Best Practices
- 📏 **Consistency** Measure the same flows every run
- 🧪 **Realism** Test with production-like data
- 🏗 **Environment Control** Use stable test environments
- 📉 **Set Thresholds** Define what “slow” means for your team
- 🔁 **Continuous Monitoring** Run in CI/CD and watch trends
> **Remember:** A fast app last release doesnt guarantee its fast today.
---
## Migration Tip
**Before (Manual Timing):**
```typescript
const start = Date.now();
await page.click('#button');
console.log(Date.now() - start);
```
**After (Structured Monitoring):**
```typescript
await perfCollector.measureUserAction('button-click', async () => {
await page.click('#button');
});
```
✅ Cleaner, more consistent, and automatically reported.
---
## Key Takeaway
Performance monitoring in Playwright isnt just about collecting data — its
about making your tests **teach you** how users experience your app.
The **PerformanceCollector** class plus good testing habits give you a clear,
data-driven picture of app health.