mcpField
Q
qa-engineer

qa-engineer

github.com/anyprotoテスト・品質9.0k59 回インストール5 日前に更新
リポジトリ

qa-engineer について

qa-engineer は、anytype-ts の最近の変更を分析し、`../anytype-desktop-suite` リポジトリに Playwright の E2E テストを生成するスキルです。変更に関係するユーザー向け動作に絞り、既存のテストパターン、翻訳キー、セレクター規則に従います。

主な機能

  1. 01変更に基づくテスト範囲
  2. 02ユーザー向け動作の整理
  3. 03Playwright E2E テスト生成
  4. 04既存カバレッジとページオブジェクトの調査
  5. 05翻訳キーとセレクターの規則
  6. 06テスト計画とページオブジェクトの案内

活用シーン

  1. 01機能変更後のテスト追加
  2. 02コンポーネント編集後の UI 動作確認
  3. 03E2E テストのカバレッジ不足の特定
  4. 04テストスイートの規則に沿ったテスト作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/anyproto/anytype-ts --skill qa-engineer

インストール後、Claude Code で/qa-engineerを入力して読み込まれたか確認します。

詳細

QA エンジニアスキル

anytype-ts の最近のコード変更を分析し、テスト可能なユーザー向けの動作に対応付けて、../anytype-desktop-suite リポジトリに Playwright E2E テストを生成します。

使用するタイミング

次の場合にこのスキルを有効にします。

  • 新機能の実装後、または既存機能の変更後
  • ユーザー操作に影響するエディター/コンポーネントの変更後
  • ユーザーが最近の変更に対するテストの追加を明示的に依頼した場合
  • CLAUDE.md の「QA Engineer」セクションに記載されたタスクの完了後

原則

  1. 変更主導 — 実際に変更された箇所だけをテストし、変更されていないコードのテストは生成しません
  2. ユーザー向け — 実装の詳細ではなく、観察可能な動作に焦点を当てます
  3. 互換性 — anytype-desktop-suite の既存のテストパターンに厳密に従います
  4. 最小限 — 機能領域ごとにテストファイルを1つ作成し、過剰なテストは行いません
  5. 翻訳を考慮 — UI テキストは必ず翻訳キーを使い、ハードコードしません

プロセス

フェーズ 1:変更の分析
  1. 変更点を特定する — git diff をベースブランチ(または最近のコミット)に対して実行し、変更されたファイルを確認します
  2. 変更を分類する — ユーザー向けの変更と内部リファクタリングを判別します
  3. 機能に対応付ける — コード変更をテスト可能なユーザーフローに結び付けます。
    • コンポーネントの変更 → 検証する UI 操作
    • ストアの変更 → テストする状態遷移
    • メニュー/ポップアップの変更 → 開く/閉じる/操作するフロー
    • エディターの変更 → ブロックの作成、編集、選択
    • API の変更 → データフローとエラー処理

ユーザー向けの影響がない、内部のみの変更(型のリファクタリング、ユーティリティの抽出、純粋なスタイル変更)はスキップします。

フェーズ 2:既存のカバレッジを調査
  1. 既存のテストを確認する — ../anytype-desktop-suite/tests/ を検索し、変更された機能領域をすでにカバーするテストがあるか確認します
  2. 既存のページオブジェクトを確認する — ../anytype-desktop-suite/src/pages/ を検索し、影響を受けるコンポーネントを操作するページオブジェクトがあるか確認します
  3. テスト計画を確認する — ../anytype-desktop-suite/specs/ を検索し、その領域を対象とする既存の計画があるか確認します
  4. 不足箇所を特定する — まだカバーされていない内容を判別します
フェーズ 3:テスト計画を作成

次の形式に従って、../anytype-desktop-suite/specs/ にテスト計画を記述します。

# Feature Area — Test Plan

**Source changes:** List of changed files in anytype-ts
**Date:** YYYY-MM-DD

## Prerequisites
- Seed: `tests/seed.spec.ts` (creates account, opens vault)
- Any additional setup needed

### 1. Test Group Name
**Seed:** `tests/seed.spec.ts`

#### 1.1 Scenario Name
**Steps:**
1. Step description
2. Step description
**Expected:** What should happen

#### 1.2 Another Scenario
...
フェーズ 4:テストファイルを生成

次の厳格な規約に従って、../anytype-desktop-suite/tests/ にテストファイルを作成します。

ファイル構造
// spec: specs/plan-name.md
// seed: tests/seed.spec.ts

import { test, expect } from '../../src/fixtures';
import { restartGrpcServer } from '../../src/helpers/test-server';
// Import relevant page objects
import { SidebarPage } from '../../src/pages/main/sidebar.page';

test.describe('Feature Area', () => {
  test.describe.configure({ mode: 'serial' });

  test.beforeAll(async () => {
    await restartGrpcServer();
  });

  test('should do the expected behavior', async ({ page, translations }) => {
    const sidebar = new SidebarPage(page, translations);
    await sidebar.waitForReady();

    // Step: Description of what we're doing
    await page.getByText(translations.someTranslationKey).click();

    // Verify: Expected outcome
    await expect(page.locator('#some-element')).toBeVisible();
  });
});
規則
  1. 翻訳 — UI テキストには必ず translations.keyName を使用します。キーは ../anytype-ts/dist/lib/json/lang/en-US.json または ../anytype-ts/src/json/text.json で確認します
  2. ページオブジェクト — ../anytype-desktop-suite/src/pages/ の既存のページオブジェクトを使用します。新しいオブジェクトは必要な場合にのみ作成します
  3. 待機 — await expect(locator).toBeVisible() または waitFor({ state: 'visible' }) を使用します。setTimeout、networkidle、固定時間の待機は使用しません
  4. セレクター — ロールベース > テスト ID > テキスト > CSS セレクターの順に優先します
  5. 分離 — 各テストファイルは beforeAll で gRPC サーバーを再起動します。ファイル内のテストでは serial モードを使って状態を共有できます
  6. 命名 — ファイル名は機能名に合わせたケバブケースにします:feature-name.spec.ts
  7. ディレクトリ — 機能領域に対応するサブディレクトリに配置します:tests/editor/、tests/blocks/ など
フェーズ 5:ページオブジェクトを作成(必要な場合)

変更された機能で、既存のページオブジェクトでは対応できない新しいページ操作が必要な場合は、新しいページオブジェクトを作成します。

import { BasePage } from '../base.page';

export class FeaturePage extends BasePage {
  // Locators
  get someButton() {
    return this.page.locator('#some-button');
  }

  get someText() {
    return this.page.getByText(this.t('translationKey'));
  }

  // Actions
  async waitForReady() {
    await this.someButton.waitFor({ state: 'visible' });
  }

  async doSomething() {
    await this.someButton.click();
    await expect(this.someText).toBeVisible();
  }
}

ページオブジェクトは、適切なサブディレクトリの ../anytype-desktop-suite/src/pages/ に配置します。

フェーズ 6:概要を出力

テストを生成した後、概要を提示します。

## QA Engineer Summary

### Changes Analyzed
- file1.tsx — description of change
- file2.tsx — description of change

### Tests Generated
- `tests/feature/scenario-name.spec.ts` — what it tests
- `specs/feature-plan.md` — test plan

### New Page Objects
- `src/pages/main/feature.page.ts` — (if created)

### Coverage Notes
- What's covered by new tests
- What's NOT covered and why (e.g., requires manual testing, backend-only change)

### Run Tests
```bash
cd ../anytype-desktop-suite && npm test -- tests/feature/scenario-name.spec.ts

## Finding Translation Keys

To map UI text to translation keys:

1. Search `../anytype-ts/src/json/text.json` for the English text
2. The key is the JSON property name (e.g., `"authSelectSignup": "Create new vault"` → use `translations.authSelectSignup`)
3. For dynamic text with parameters, check how the component calls `translate()` with substitution params

## Finding Selectors

To find stable selectors for elements:

1. Search the component source in `../anytype-ts/src/ts/component/` for `id=`, `data-`, `className`
2. Check for block IDs: blocks typically have `#block-{id}` selectors
3. Check for menu IDs: menus use `#menu{Type}` pattern
4. Check for popup IDs: popups use `#popup{Type}` pattern
5. The sidebar uses `#sidebarPage{Section}` pattern

## Test Areas Mapping

| anytype-ts Area | Test Directory | Page Objects |
|---|---|---|
| `component/block/text.tsx` | `tests/editor/` | `pages/main/editor.page.ts` |
| `component/block/dataview.tsx` | `tests/dataview/` | `pages/main/dataview.page.ts` |
| `component/menu/` | `tests/menus/` | (inline or new page object) |
| `component/popup/` | `tests/popups/` | `pages/components/modal.component.ts` |
| `component/sidebar/` | `tests/sidebar/` | `pages/main/sidebar.page.ts` |
| `component/widget/` | `tests/widgets/` | `pages/main/widget.page.ts` |
| `component/page/main/graph.tsx` | `tests/graph/` | (new page object) |
| `component/page/auth/` | `tests/auth/` | `pages/auth/*.page.ts` |
| `store/` | (test via UI) | (use existing page objects) |

## What NOT to Test

- Pure TypeScript type changes
- Internal utility refactors with no UI impact
- CSS-only changes (unless they affect element visibility/layout)
- Backend (anytype-heart) changes — those have their own tests
- Build/config changes

コメント