- Implement optimistic locking for deposit balance updates - Prevent race conditions in concurrent deposit requests - Add automatic retry with exponential backoff (max 3 attempts) - Add version column to user_deposits table - Improve type safety across codebase - Add explicit types for Namecheap API responses - Add typed function arguments (ManageDepositArgs, etc.) - Remove `any` types from deposit-agent and tool files - Add reconciliation job for balance integrity verification - Compare user_deposits.balance vs SUM(confirmed transactions) - Alert admin on discrepancy detection - Set up test environment with Vitest + Miniflare - Add 50+ test cases for deposit system - Add helper functions for test data creation - Update documentation - Add migration guide for version columns - Document optimistic locking patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
Unit Tests for telegram-bot-workers
이 디렉토리는 Cloudflare Workers 환경에서 실행되는 Telegram Bot의 단위 테스트를 포함합니다.
테스트 프레임워크
- Vitest: 빠르고 현대적인 테스트 프레임워크
- Miniflare: Cloudflare Workers 로컬 시뮬레이터 (D1, KV 지원)
- Coverage: V8 Coverage Provider
설치
npm install
필요한 의존성:
vitest- 테스트 러너miniflare- Workers 환경 시뮬레이션@cloudflare/vitest-pool-workers- Vitest Workers 통합@vitest/coverage-v8- 커버리지 리포트
실행
# 모든 테스트 실행
npm test
# Watch 모드 (파일 변경 감지)
npm run test:watch
# 커버리지 리포트 생성
npm run test:coverage
테스트 파일
deposit-agent.test.ts
예치금 시스템 (deposit-agent.ts) 테스트
커버리지:
- ✅ get_balance: 신규 사용자 0원, 기존 잔액 조회
- ✅ get_account_info: 은행 계좌 정보 반환
- ✅ request_deposit: 음수/0원 거부, 7글자 매칭, 자동/수동 처리
- ✅ get_transactions: 거래 내역 조회, 정렬, LIMIT 처리
- ✅ cancel_transaction: 본인/관리자 권한, 상태 검증
- ✅ confirm_deposit: 잔액 증가, Batch 실패 처리
- ✅ reject_deposit: 거래 거절
- ✅ get_pending_list: 관리자 전용
- ✅ Concurrency: 동시 요청 처리, Race condition
- ✅ Edge Cases: 큰 금액, 특수문자, 짧은 이름
테스트 수: 50+개
setup.ts
테스트 환경 초기화 및 헬퍼 함수
기능:
- D1 Database 스키마 초기화 (in-memory SQLite)
- 각 테스트 후 데이터 정리 (스키마 유지)
- 테스트 데이터 생성 헬퍼 함수
헬퍼 함수:
createTestUser(telegramId, username)
createBankNotification(depositorName, amount)
createDepositTransaction(userId, amount, status, depositorName?)
getTestDB()
테스트 작성 가이드
기본 구조
import { describe, it, expect, beforeEach } from 'vitest';
import { executeDepositFunction } from '../src/deposit-agent';
import { createTestUser, getTestDB } from './setup';
describe('Feature Name', () => {
let testUserId: number;
beforeEach(async () => {
testUserId = await createTestUser('123456789', 'testuser');
});
it('should do something', async () => {
const result = await executeDepositFunction('function_name', {
param: 'value'
}, {
userId: testUserId,
telegramUserId: '123456789',
isAdmin: false,
db: getTestDB()
});
expect(result).toHaveProperty('success', true);
});
});
Mock 전략
D1 Database: Miniflare가 자동으로 in-memory SQLite 제공
환경 변수: vitest.config.ts에서 설정
environmentOptions: {
bindings: {
BOT_TOKEN: 'test-bot-token',
WEBHOOK_SECRET: 'test-webhook-secret',
DEPOSIT_ADMIN_ID: '999999999',
}
}
외부 API Mock: vi.fn() 사용
const mockFetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ data: 'mocked' })
});
Batch 실패 시뮬레이션
const originalBatch = testContext.db.batch;
testContext.db.batch = vi.fn().mockResolvedValue([
{ success: true, meta: { changes: 1 } },
{ success: false, meta: { changes: 0 } }, // 실패
]);
await expect(someFunction()).rejects.toThrow('처리 실패');
// 복원
testContext.db.batch = originalBatch;
디버깅
Verbose 모드
npm test -- --reporter=verbose
특정 테스트만 실행
# 파일명으로 필터링
npm test deposit-agent
# 테스트 설명으로 필터링
npm test -- -t "should reject negative amounts"
로그 출력
테스트 내에서 console.log 사용 가능:
it('debugging test', async () => {
console.log('Debug info:', result);
expect(result).toBeDefined();
});
CI/CD 통합
GitHub Actions 예시:
- name: Run tests
run: npm test
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
향후 계획
openai-service.ts- Function Calling 도구 테스트summary-service.ts- 프로필 시스템 테스트- Integration Tests - 전체 워크플로우 테스트
- E2E Tests - Telegram Bot API 통합 테스트
문제 해결
"Cannot find module" 에러
npm install
D1 스키마 초기화 실패
setup.ts에서 schema.sql 경로 확인:
const schemaPath = join(__dirname, '../schema.sql');
Miniflare 버전 충돌
package.json에서 버전 확인:
{
"miniflare": "^3.20231030.0",
"@cloudflare/vitest-pool-workers": "^0.1.0"
}
테스트 타임아웃
vitest.config.ts에서 타임아웃 증가:
test: {
testTimeout: 10000, // 기본 5초 → 10초
}