用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ViewWay/MiniHES --skill webapp-testing命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | webapp-testing |
| description | MiniHES 前后端测试。当用户需要编写测试、运行测试、调试测试失败、 或提到 pytest、vitest、playwright 时激活。 涵盖后端单元测试、前端组件测试、E2E 测试。 |
需要测试什么?
├── 后端 API / Service / Model
│ ├── 单函数逻辑 → pytest 单元测试
│ ├── API 端到端 → pytest + httpx AsyncClient
│ └── 数据库操作 → pytest + 真实数据库 / SQLite 内存
│
├── 前端组件 / 页面
│ ├── 组件逻辑 → vitest + Vue Test Utils
│ └── 样式快照 → vitest
│
└── 前后端集成
└── 用户流程 → Playwright E2E
backend/tests/
├── backend/
│ ├── conftest.py # fixtures
│ ├── factories.py # 测试数据工厂
│ ├── unit/ # 单元测试(无外部依赖)
│ │ ├── test_services/
│ │ └── test_utils/
│ └── api/ # API 集成测试
│ ├── test_auth.py
│ ├── test_meters.py
│ └── test_tasks.py
# conftest.py
import pytest
from httpx import AsyncClient, ASGITransport
from app.main import app
@pytest.fixture
async def client():
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as c:
yield c
@pytest.fixture
async def auth_client(client):
# 登录获取 token
response = await client.post("/api/v1/auth/login", json={...})
token = response.json()["access_token"]
client.headers["Authorization"] = f"Bearer {token}"
yield client
import pytest
@pytest.mark.asyncio
async def test_create_meter(client, auth_client):
"""测试创建电表"""
# Arrange
data = {"serial_number": "TEST001", "meter_name": "测试电表"}
# Act
response = await auth_client.post("/api/v1/meters", json=data)
# Assert
assert response.status_code == 201
assert response.json()["serial_number"] == "TEST001"
cd backend
# 全部
uv run pytest
# 指定文件
uv run pytest tests/backend/api/test_meters.py
# 带覆盖率
uv run pytest --cov=app --cov-report=term-missing
# 只运行失败的
uv run pytest --lf
# 详细输出
uv run pytest -v
apps/web-antd/src/
├── views/
│ └── devices/
│ ├── MeterList.vue
│ └── __tests__/
│ └── MeterList.test.ts
├── components/
│ └── __tests__/
└── api/
└── __tests__/
import { describe, it, expect, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import MeterStatusTag from '../MeterStatusTag.vue';
describe('MeterStatusTag', () => {
it('renders online status', () => {
const wrapper = mount(MeterStatusTag, {
props: { status: 'online' },
});
expect(wrapper.text()).toContain('在线');
});
});
cd frontend
# 全部
pnpm run test
# 监听模式
pnpm run test:watch
# 覆盖率
pnpm run test:coverage
# UI 模式
pnpm run test:ui
tests/e2e/
├── playwright.config.ts
├── fixtures/
│ └── auth.ts
└── specs/
├── login.spec.ts
├── meter-management.spec.ts
└── task-scheduling.spec.ts
import { test, expect } from '@playwright/test';
test('创建新电表', async ({ page }) => {
// 登录
await page.goto('http://localhost:5666/login');
await page.fill('[placeholder="用户名"]', 'admin');
await page.fill('[placeholder="密码"]', 'password');
await page.click('button[type="submit"]');
// 导航到设备管理
await page.click('text=设备管理');
await page.click('text=电表列表');
// 创建电表
await page.click('text=新增');
await page.fill('[label="序列号"]', 'E2E-TEST-001');
await page.fill('[label="电表名称"]', 'E2E测试电表');
await page.click('text=确定');
// 验证
await expect(page.locator('text=E2E-TEST-001')).toBeVisible();
});
# 全部浏览器
cd frontend && pnpm run test:e2e
# UI 模式
pnpm run test:e2e-ui
# 指定文件
npx playwright test specs/meter-management.spec.ts
# 调试模式
npx playwright test --debug
| 层 | 目标 |
|---|---|
| 后端 Service | 80%+ |
| 后端 API | 70%+ |
| 前端组件 | 60%+ |
| E2E | 关键流程 100% |