mirror of
https://github.com/apache/superset.git
synced 2026-04-07 10:31:50 +00:00
228 lines
6.6 KiB
Markdown
228 lines
6.6 KiB
Markdown
---
|
|
title: End-to-End Testing
|
|
sidebar_position: 4
|
|
---
|
|
|
|
<!--
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
-->
|
|
|
|
# End-to-End Testing
|
|
|
|
Apache Superset uses Playwright for end-to-end testing, migrating from the legacy Cypress tests.
|
|
|
|
## Running Tests
|
|
|
|
### Playwright (Recommended)
|
|
|
|
```bash
|
|
cd superset-frontend
|
|
|
|
# Run all tests
|
|
npm run playwright:test
|
|
# or: npx playwright test
|
|
|
|
# Run specific test file
|
|
npx playwright test tests/auth/login.spec.ts
|
|
|
|
# Run with UI mode for debugging
|
|
npm run playwright:ui
|
|
# or: npx playwright test --ui
|
|
|
|
# Run in headed mode (see browser)
|
|
npm run playwright:headed
|
|
# or: npx playwright test --headed
|
|
|
|
# Debug specific test file
|
|
npm run playwright:debug tests/auth/login.spec.ts
|
|
# or: npx playwright test --debug tests/auth/login.spec.ts
|
|
```
|
|
|
|
### Cypress (Deprecated)
|
|
|
|
Cypress tests are being migrated to Playwright. For legacy tests:
|
|
|
|
```bash
|
|
cd superset-frontend/cypress-base
|
|
npm run cypress-run-chrome # Headless
|
|
npm run cypress-debug # Interactive UI
|
|
```
|
|
|
|
## Project Architecture
|
|
|
|
```
|
|
superset-frontend/playwright/
|
|
├── components/core/ # Reusable UI components
|
|
├── pages/ # Page Object Models
|
|
├── tests/ # Test files organized by feature
|
|
├── utils/ # Shared constants and utilities
|
|
└── playwright.config.ts
|
|
```
|
|
|
|
## Design Principles
|
|
|
|
We follow **YAGNI** (You Aren't Gonna Need It), **DRY** (Don't Repeat Yourself), and **KISS** (Keep It Simple, Stupid) principles:
|
|
|
|
- Build only what's needed now
|
|
- Reuse existing patterns and components
|
|
- Keep solutions simple and maintainable
|
|
|
|
## Page Object Pattern
|
|
|
|
Each page object encapsulates:
|
|
|
|
- **Actions**: What you can do on the page
|
|
- **Queries**: Information you can get from the page
|
|
- **Selectors**: Centralized in private static SELECTORS constant
|
|
- **NO Assertions**: Keep assertions in test files
|
|
|
|
**Example Page Object:**
|
|
|
|
```typescript
|
|
export class AuthPage {
|
|
// Selectors centralized in the page object
|
|
private static readonly SELECTORS = {
|
|
LOGIN_FORM: '[data-test="login-form"]',
|
|
USERNAME_INPUT: '[data-test="username-input"]',
|
|
} as const;
|
|
|
|
// Actions - what you can do
|
|
async loginWithCredentials(username: string, password: string) {}
|
|
|
|
// Queries - information you can get
|
|
async getCurrentUrl(): Promise<string> {}
|
|
|
|
// NO assertions - those belong in tests
|
|
}
|
|
```
|
|
|
|
**Example Test:**
|
|
|
|
```typescript
|
|
import { test, expect } from '@playwright/test';
|
|
import { AuthPage } from '../../pages/AuthPage';
|
|
import { LOGIN } from '../../utils/urls';
|
|
|
|
test('should login with correct credentials', async ({ page }) => {
|
|
const authPage = new AuthPage(page);
|
|
await authPage.goto();
|
|
await authPage.loginWithCredentials('admin', 'general');
|
|
|
|
// Assertions belong in tests, not page objects
|
|
expect(await authPage.getCurrentUrl()).not.toContain(LOGIN);
|
|
});
|
|
```
|
|
|
|
## Core Components
|
|
|
|
Reusable UI interaction classes for common elements (`components/core/`):
|
|
|
|
- **Form**: Container with properly scoped child element access
|
|
- **Input**: Supports `fill()`, `type()`, and `pressSequentially()` methods
|
|
- **Button**: Standard click, hover, focus interactions
|
|
|
|
**Usage Example:**
|
|
|
|
```typescript
|
|
import { Form } from '../components/core';
|
|
|
|
const loginForm = new Form(page, '[data-test="login-form"]');
|
|
const usernameInput = loginForm.getInput('[data-test="username-input"]');
|
|
await usernameInput.fill('admin');
|
|
```
|
|
|
|
## Test Reports
|
|
|
|
Playwright generates multiple reports for better visibility:
|
|
|
|
```bash
|
|
# View interactive HTML report (opens automatically on failure)
|
|
npm run playwright:report
|
|
# or: npx playwright show-report
|
|
|
|
# View test trace for debugging failures
|
|
npx playwright show-trace test-results/[test-name]/trace.zip
|
|
```
|
|
|
|
### Report Types
|
|
|
|
- **List Reporter**: Shows progress and summary table in terminal
|
|
- **HTML Report**: Interactive web interface with screenshots, videos, and traces
|
|
- **JSON Report**: Machine-readable format in `test-results/results.json`
|
|
- **GitHub Actions**: Annotations in CI for failed tests
|
|
|
|
### Debugging Failed Tests
|
|
|
|
When tests fail, Playwright automatically captures:
|
|
|
|
- **Screenshots** at the point of failure
|
|
- **Videos** of the entire test run
|
|
- **Traces** with timeline and network activity
|
|
- **Error context** with detailed debugging information
|
|
|
|
All debugging artifacts are available in the HTML report for easy analysis.
|
|
|
|
## Configuration
|
|
|
|
- **Config**: `playwright.config.ts` - matches Cypress settings
|
|
- **Base URL**: `http://localhost:8088` (assumes Superset running)
|
|
- **Browsers**: Chrome only for Phase 1 (YAGNI)
|
|
- **Retries**: 2 in CI, 0 locally (matches Cypress)
|
|
|
|
## Contributing Guidelines
|
|
|
|
### Adding New Tests
|
|
|
|
1. **Check existing components** before creating new ones
|
|
2. **Use page objects** for page interactions
|
|
3. **Keep assertions in tests**, not page objects
|
|
4. **Follow naming conventions**: `feature.spec.ts`
|
|
|
|
### Adding New Components
|
|
|
|
1. **Follow YAGNI**: Only build what's immediately needed
|
|
2. **Use Locator-based scoping** for proper element isolation
|
|
3. **Support both string selectors and Locator objects** via constructor overloads
|
|
4. **Add to `components/core/index.ts`** for easy importing
|
|
|
|
### Adding New Page Objects
|
|
|
|
1. **Centralize selectors** in private static SELECTORS constant
|
|
2. **Import shared constants** from `utils/urls.ts`
|
|
3. **Actions and queries only** - no assertions
|
|
4. **Use existing components** for DOM interactions
|
|
|
|
## Migration from Cypress
|
|
|
|
When porting Cypress tests:
|
|
|
|
1. **Port the logic**, not the implementation
|
|
2. **Use page objects** instead of inline selectors
|
|
3. **Replace `cy.intercept/cy.wait`** with `page.waitForRequest()`
|
|
4. **Use shared constants** from `utils/urls.ts`
|
|
5. **Follow the established patterns** shown in `tests/auth/login.spec.ts`
|
|
|
|
## Best Practices
|
|
|
|
- **Centralize selectors** in page objects
|
|
- **Centralize URLs** in `utils/urls.ts`
|
|
- **Use meaningful test descriptions**
|
|
- **Keep page objects action-focused**
|
|
- **Put assertions in tests, not page objects**
|
|
- **Follow the existing patterns** for consistency
|