CtrlK
BlogDocsLog inGet started
Tessl Logo

qa-interaction

QA Interaction Agent. 사용자 인터랙션 테스트 계획 및 Playwright E2E 테스트 작성을 담당합니다. UX/UI 명세 기반의 상세한 테스트 시나리오를 설계합니다.

Install with Tessl CLI

npx tessl i github:shaul1991/shaul-agents-plugin --skill qa-interaction
What are skills?

Overall
score

61%

Does it follow best practices?

Validation for skill structure

SKILL.md
Review
Evals

QA Interaction Agent

역할

사용자 인터랙션을 중심으로 테스트를 계획하고, Playwright를 사용하여 E2E 테스트를 작성/실행합니다.

담당 업무

1. 사용자 인터랙션 테스트 계획

  • UX/UI 명세 기반 테스트 시나리오
  • 사용자 플로우별 테스트 케이스
  • 상태 전환 테스트

2. Playwright E2E 테스트 작성

  • 페이지 네비게이션 테스트
  • 폼 입력 및 제출 테스트
  • 인터랙션 테스트 (클릭, 호버, 드래그)

3. 접근성 테스트

  • 키보드 네비게이션
  • 스크린 리더 호환성
  • WCAG 준수 확인

테스트 시나리오 템플릿

사용자 플로우 테스트

## 테스트 시나리오: [플로우명]

### 전제 조건
- [ ] 사용자 로그인 상태
- [ ] 필요한 데이터 준비

### 테스트 단계
| # | 동작 | 예상 결과 | 검증 방법 |
|---|------|----------|----------|
| 1 | 페이지 접근 | 페이지 로드 완료 | URL, 제목 확인 |
| 2 | 버튼 클릭 | 모달 표시 | 요소 visibility |
| 3 | 폼 입력 | 유효성 통과 | 에러 메시지 없음 |
| 4 | 제출 | 성공 메시지 | 토스트/알림 |

### 엣지 케이스
- [ ] 네트워크 오류 시
- [ ] 타임아웃 발생 시
- [ ] 동시 요청 시

Playwright 테스트 패턴

기본 페이지 테스트

import { test, expect } from '@playwright/test';

test.describe('User Profile Page', () => {
  test.beforeEach(async ({ page }) => {
    // 로그인 및 페이지 접근
    await page.goto('/login');
    await page.fill('[data-testid="email"]', 'test@example.com');
    await page.fill('[data-testid="password"]', 'password123');
    await page.click('[data-testid="login-button"]');
    await page.waitForURL('/dashboard');
  });

  test('should display user profile', async ({ page }) => {
    await page.goto('/profile');

    await expect(page.locator('[data-testid="user-name"]')).toBeVisible();
    await expect(page.locator('[data-testid="user-email"]')).toBeVisible();
  });

  test('should edit profile successfully', async ({ page }) => {
    await page.goto('/profile');

    // 편집 모드 진입
    await page.click('[data-testid="edit-button"]');

    // 이름 변경
    await page.fill('[data-testid="name-input"]', 'New Name');

    // 저장
    await page.click('[data-testid="save-button"]');

    // 성공 확인
    await expect(page.locator('[data-testid="success-toast"]')).toBeVisible();
    await expect(page.locator('[data-testid="user-name"]')).toHaveText('New Name');
  });
});

폼 인터랙션 테스트

test.describe('Registration Form', () => {
  test('should validate required fields', async ({ page }) => {
    await page.goto('/register');

    // 빈 폼 제출
    await page.click('[data-testid="submit-button"]');

    // 에러 메시지 확인
    await expect(page.locator('[data-testid="email-error"]')).toHaveText('이메일을 입력하세요');
    await expect(page.locator('[data-testid="password-error"]')).toHaveText('비밀번호를 입력하세요');
  });

  test('should show password strength indicator', async ({ page }) => {
    await page.goto('/register');

    // 약한 비밀번호
    await page.fill('[data-testid="password"]', '123');
    await expect(page.locator('[data-testid="strength-weak"]')).toBeVisible();

    // 강한 비밀번호
    await page.fill('[data-testid="password"]', 'StrongP@ss123!');
    await expect(page.locator('[data-testid="strength-strong"]')).toBeVisible();
  });

  test('should handle form submission', async ({ page }) => {
    await page.goto('/register');

    await page.fill('[data-testid="email"]', 'new@example.com');
    await page.fill('[data-testid="password"]', 'SecureP@ss123');
    await page.fill('[data-testid="confirm-password"]', 'SecureP@ss123');
    await page.check('[data-testid="terms-checkbox"]');

    await page.click('[data-testid="submit-button"]');

    // 성공 페이지로 리다이렉트
    await page.waitForURL('/register/success');
    await expect(page.locator('h1')).toHaveText('가입 완료');
  });
});

상태 전환 테스트

test.describe('Shopping Cart', () => {
  test('should update cart count on add', async ({ page }) => {
    await page.goto('/products');

    // 초기 카트 수량
    await expect(page.locator('[data-testid="cart-count"]')).toHaveText('0');

    // 상품 추가
    await page.click('[data-testid="add-to-cart-1"]');

    // 카트 수량 업데이트
    await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');
  });

  test('should show loading state during checkout', async ({ page }) => {
    await page.goto('/cart');

    await page.click('[data-testid="checkout-button"]');

    // 로딩 상태 확인
    await expect(page.locator('[data-testid="loading-spinner"]')).toBeVisible();

    // 완료 후 리다이렉트
    await page.waitForURL('/checkout/success');
  });
});

접근성 테스트

test.describe('Accessibility', () => {
  test('should be keyboard navigable', async ({ page }) => {
    await page.goto('/');

    // Tab 키로 네비게이션
    await page.keyboard.press('Tab');
    await expect(page.locator(':focus')).toHaveAttribute('data-testid', 'nav-home');

    await page.keyboard.press('Tab');
    await expect(page.locator(':focus')).toHaveAttribute('data-testid', 'nav-products');

    // Enter 키로 활성화
    await page.keyboard.press('Enter');
    await page.waitForURL('/products');
  });

  test('should have proper ARIA labels', async ({ page }) => {
    await page.goto('/');

    // 주요 영역 ARIA 확인
    await expect(page.locator('nav')).toHaveAttribute('aria-label', 'Main navigation');
    await expect(page.locator('main')).toHaveAttribute('role', 'main');
    await expect(page.locator('footer')).toHaveAttribute('role', 'contentinfo');
  });
});

반응형 테스트

test.describe('Responsive Design', () => {
  test('should show mobile menu on small screens', async ({ page }) => {
    // 모바일 뷰포트
    await page.setViewportSize({ width: 375, height: 667 });
    await page.goto('/');

    // 햄버거 메뉴 표시
    await expect(page.locator('[data-testid="mobile-menu-button"]')).toBeVisible();
    await expect(page.locator('[data-testid="desktop-nav"]')).not.toBeVisible();

    // 메뉴 열기
    await page.click('[data-testid="mobile-menu-button"]');
    await expect(page.locator('[data-testid="mobile-nav"]')).toBeVisible();
  });

  test('should show desktop nav on large screens', async ({ page }) => {
    // 데스크톱 뷰포트
    await page.setViewportSize({ width: 1280, height: 720 });
    await page.goto('/');

    await expect(page.locator('[data-testid="desktop-nav"]')).toBeVisible();
    await expect(page.locator('[data-testid="mobile-menu-button"]')).not.toBeVisible();
  });
});

테스트 명령어

# Playwright 테스트 실행
npx playwright test

# 특정 파일 실행
npx playwright test user-profile.spec.ts

# UI 모드로 실행
npx playwright test --ui

# 디버그 모드
npx playwright test --debug

# 특정 브라우저
npx playwright test --project=chromium

# 리포트 생성
npx playwright show-report

테스트 계획 문서 구조

# [기능명] 인터랙션 테스트 계획

## 1. 테스트 범위
### 포함
### 제외

## 2. 테스트 환경
- 브라우저: Chrome, Firefox, Safari
- 디바이스: Desktop, Tablet, Mobile

## 3. 사용자 플로우별 테스트
### 플로우 1: [플로우명]
### 플로우 2: [플로우명]

## 4. 엣지 케이스

## 5. 성능 기준
- 페이지 로드: < 3초
- 인터랙션 응답: < 100ms

## 6. 접근성 요구사항
- WCAG 2.1 Level AA

## 7. 테스트 데이터

산출물 위치

  • 테스트 계획: docs/features/<기능명>/test-plans/interaction-tests.md
  • E2E 테스트: e2e/**/*.spec.ts
  • 테스트 리포트: playwright-report/
  • 스크린샷: test-results/
Repository
github.com/shaul1991/shaul-agents-plugin
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.