Files

369 lines
10 KiB
Markdown
Raw Permalink Normal View History

2026-08-23 22:44:18 +08:00
# QwenPaw E2E Test Framework
End-to-end test framework built on Playwright + pytest + the Page Object Pattern.
## Directory Layout
```
tests/
├── config/ # Configuration module
│ ├── __init__.py
│ └── settings.py # Unified config management
├── pages/ # Page Object layer
│ ├── __init__.py
│ ├── base_page.py # Base page class
│ └── chat_page.py # Chat page object
├── fixtures/ # Pytest fixtures
│ └── __init__.py # Browser, page, API fixtures
├── utils/ # Utility functions
│ ├── __init__.py
│ └── helpers.py # Helper functions
├── tests/ # Test cases
│ └── test_chat_p0.py # Chat P0 test cases
├── data/ # Test data
├── reports/ # Test reports (auto-generated)
│ ├── screenshots/ # Screenshots
│ ├── videos/ # Recorded videos
│ ├── logs/ # Logs
│ └── allure-results/ # Allure reports
├── conftest.py # Pytest configuration
├── pytest.ini # Pytest configuration file
└── requirements.txt # Dependency list
```
## Quick Start
> **WARNING — Test Isolation Required**
>
> E2E tests write seed data (inbox events, plan state, workspace
> files) into the backend's working directory. If that directory is
> your real `~/.qwenpaw` you will **corrupt your actual QwenPaw data**.
>
> The framework enforces this rule: if `QWENPAW_WORKING_DIR` is unset
> or points inside your home directory, pytest will **refuse to start**
> with a clear RuntimeError.
### 0. Start the isolated test server (REQUIRED)
```bash
# From the repo root:
source e2e/scripts/start_test_server.sh --bg
# This starts QwenPaw on port 7077 with:
# QWENPAW_WORKING_DIR=/tmp/qwenpaw-e2e-test-work-dir/working
# The env var is exported so pytest inherits it automatically.
```
If you prefer manual setup:
```bash
export QWENPAW_WORKING_DIR=/tmp/my-e2e-workdir
mkdir -p "$QWENPAW_WORKING_DIR"
QWENPAW_WORKING_DIR="$QWENPAW_WORKING_DIR" python -m qwenpaw app --port 7077 &
```
### 1. Install dependencies
```bash
cd /Users/ming/.qwenpaw/workspaces/Hv3HJ9
pip install -r tests/requirements.txt
playwright install chromium
```
### 2. Ensure the QwenPaw service is running
```bash
qwenpaw start
# or
cd /Users/ming/Desktop/qwenpaw && python -m qwenpaw
```
### 3. Run tests
```bash
# Run all P0 tests
pytest tests/tests/test_chat_p0.py -v
# Run a specific test class
pytest tests/tests/test_chat_p0.py::TestNewChatAndBasicQA -v
# Run a specific test case
pytest tests/tests/test_chat_p0.py::TestNewChatAndBasicQA::test_new_chat_basic_qa_copy -v
# Run by marker
pytest tests/tests/test_chat_p0.py -m "chat_core" -v
pytest tests/tests/test_chat_p0.py -m "chat_file" -v
```
### 4. Headed mode (visual debugging)
```bash
QWENPAW_HEADLESS=false pytest tests/tests/test_chat_p0.py -v
```
### 5. Slow-motion mode (for debugging)
```bash
PLAYWRIGHT_SLOW_MO=1000 pytest tests/tests/test_chat_p0.py -v
```
## Test Case List
### P0 tests (core functionality)
| Test Class | Test Case | Feature Coverage | Priority |
|------------|-----------|------------------|----------|
| **TestNewChatAndBasicQA** | test_new_chat_basic_qa_copy | New chat, basic Q&A, message copy | P0 |
| **TestMultiTurnConversation** | test_multi_turn_context_awareness | Multi-turn dialogue, context understanding | P0 |
| **TestFileUploadAndQA** | test_upload_file_and_ask_questions | File upload, Q&A based on file | P0 |
| **TestSessionManagement** | test_session_rename_pin_delete_switch | End-to-end session management | P0 |
| **TestAdvancedFeatures** | test_model_switch_and_skill_invocation | Model switching, skill invocation | P0 |
| **TestInputValidationAndEdgeCases** | test_input_validation_and_special_chars | Special characters, code-block input | P0 |
## Configuration Options
### Environment variables
| Name | Default | Description |
|------|---------|-------------|
| `QWENPAW_WORKING_DIR` | **(required)** | Backend working directory for seed data. Must be outside `$HOME`. |
| `QWENPAW_BASE_URL` | `http://localhost:7077` | QwenPaw service URL |
| `QWENPAW_HEADLESS` | `true` | Headless mode (`true`/`false`) |
| `QWENPAW_TIMEOUT` | `30000` | Timeout (milliseconds) |
| `QWENPAW_USER_ID` | `default` | User ID |
| `QWENPAW_CHANNEL` | `console` | Channel name |
| `PLAYWRIGHT_SLOW_MO` | `0` | Slow-motion delay (milliseconds) |
### Examples
```bash
# Override the service URL
QWENPAW_BASE_URL=http://127.0.0.1:9000 pytest tests/tests/test_chat_p0.py -v
# Headed mode + slow motion
QWENPAW_HEADLESS=false PLAYWRIGHT_SLOW_MO=500 pytest tests/tests/test_chat_p0.py -v
# Increase timeout
QWENPAW_TIMEOUT=60000 pytest tests/tests/test_chat_p0.py -v
```
## Test Reports
### HTML report
```bash
pytest tests/tests/test_chat_p0.py --html=reports/test_report.html --self-contained-html
```
### Allure report
```bash
# Generate report
pytest tests/tests/test_chat_p0.py --alluredir=reports/allure-results
# View report
allure serve reports/allure-results
```
### Log files
Test logs are saved under `reports/logs/`.
## Framework Architecture
### Page Object Pattern
```
┌─────────────────────────────────────┐
│ Test Cases │
│ (tests/test_chat_p0.py) │
├─────────────────────────────────────┤
│ Page Objects │
│ (pages/chat_page.py) │
│ - Business-level methods │
│ - Encapsulated page operations │
├─────────────────────────────────────┤
│ Base Page │
│ (pages/base_page.py) │
│ - Generic page operations │
│ - Element find/wait/assert │
├─────────────────────────────────────┤
│ Playwright API │
└─────────────────────────────────────┘
```
### Main ChatPage methods
```python
# Navigation
chat_page.open() # Open the Chat page
chat_page.create_new_chat() # Start a new chat
# Message operations
chat_page.send_message("hello") # Send a message
chat_page.send_message_and_wait("hello") # Send and wait for reply
chat_page.wait_for_ai_response() # Wait for the AI reply
chat_page.copy_last_message() # Copy the message
# File upload
chat_page.upload_file("/path/to/file") # Upload a file
chat_page.verify_file_uploaded() # Verify upload succeeded
# Session management
chat_page.open_session_list() # Open the session list
chat_page.rename_session(0, "new name") # Rename a session
chat_page.pin_session(1) # Pin a session
chat_page.delete_session(0) # Delete a session
chat_page.switch_to_session(0) # Switch session
# Models and skills
chat_page.select_model("gpt-4") # Select model
chat_page.invoke_skill("skills") # Invoke skill
chat_page.expand_tool_details() # Expand tool details
# Assertions
chat_page.verify_welcome_screen() # Verify the welcome screen
chat_page.get_session_count() # Get the session count
chat_page.has_error() # Check for errors
```
## Writing New Tests
### Basic template
```python
import pytest
from pages.chat_page import ChatPage
@pytest.mark.p0
@pytest.mark.chat_core
class TestNewFeature:
"""New feature tests"""
@pytest.mark.test_id("P0-XXX")
def test_feature_name(self, chat_page: ChatPage, request: pytest.FixtureRequest):
"""Test description"""
test_name = request.node.name
# Step 1: Visit the page
chat_page.open()
# Step 2: Perform actions
chat_page.send_message("test message")
# Step 3: Verify the result
ai_message = chat_page.wait_for_ai_response()
assert ai_message is not None
# Step 4: Log the result
logger.info(f"Test {test_name} passed")
```
### Parametrized tests
```python
@pytest.mark.parametrize("message,expected_keyword", [
("hello", "hello"),
("who are you?", "introduce"),
("help", "help"),
])
def test_various_messages(self, chat_page, message, expected_keyword):
chat_page.open()
chat_page.send_message_and_wait(message)
ai_msg = chat_page.get_last_ai_message()
assert chat_page.verify_message_contains(ai_msg, expected_keyword)
```
## FAQ
### 1. Test failure: cannot connect to the QwenPaw service
```bash
# Check service status
qwenpaw status
# Start manually
cd /Users/ming/Desktop/qwenpaw && python -m qwenpaw
```
### 2. Test failure: element not found
```bash
# Debug in headed mode
QWENPAW_HEADLESS=false pytest tests/tests/test_chat_p0.py::TestNewChatAndBasicQA -v
# Increase timeout
QWENPAW_TIMEOUT=60000 pytest tests/tests/test_chat_p0.py -v
# Use slow motion to inspect page loading
PLAYWRIGHT_SLOW_MO=1000 QWENPAW_HEADLESS=false pytest tests/tests/test_chat_p0.py -v
```
### 3. Browser fails to launch
```bash
# Reinstall the browser
playwright install chromium
# Check dependencies
playwright install-deps chromium
```
### 4. Test report is not generated
```bash
# Make sure the directory exists
mkdir -p tests/reports
# Check permissions
chmod 755 tests/reports
```
## Advanced Usage
### Parallel execution
```bash
# Run with 4 workers in parallel
pytest tests/tests/test_chat_p0.py -n 4 -v
```
### Retry on failure
```bash
# Retry twice on failure
pytest tests/tests/test_chat_p0.py --reruns 2 -v
```
### Coverage report
```bash
pytest tests/tests/test_chat_p0.py --cov=src --cov-report=html -v
```
### Generate test data
```python
from faker import Faker
fake = Faker("en_US")
def test_with_generated_data(self, chat_page):
chat_page.open()
chat_page.send_message(fake.sentence())
chat_page.wait_for_ai_response()
```
## References
- [Playwright docs](https://playwright.dev/python/)
- [pytest docs](https://docs.pytest.org/)
- [Page Object Pattern](https://playwright.dev/python/docs/test-pom)
- [Allure reports](https://docs.qameta.io/allure/)
## Maintainers
- QA Assistant
- Last updated: 2026-04-13