diff --git a/itdoc-doc/docs/guides/test-framework-migration.mdx b/itdoc-doc/docs/guides/test-framework-migration.mdx
new file mode 100644
index 0000000..17099b6
--- /dev/null
+++ b/itdoc-doc/docs/guides/test-framework-migration.mdx
@@ -0,0 +1,574 @@
+---
+sidebar_position: 4
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Migration Guide from Your E2E Tests
+
+> **This guide explains how to migrate existing Mocha or Jest test cases to Itdoc format.**
+
+## Why Migrate to Itdoc?
+
+Itdoc blends API testing with automatic documentation, so migrating your existing test cases gives you:
+
+- **Automated OpenAPI Generation**: Test runs output OpenAPI specs plus matching Markdown and HTML docs
+- **Self-Documenting Tests**: API metadata stays next to the assertions, keeping code and docs aligned
+- **Framework Compatibility**: Keep running Mocha or Jest while layering the Itdoc DSL on top
+- **Better API Visibility**: Structured tags, descriptions, and examples make your endpoints easier to explore
+
+## Key Differences
+
+### Traditional Test Frameworks vs Itdoc
+
+| Feature | Mocha/Jest | Itdoc |
+|------------------------|---------------------------|---------------------------------------------------------|
+| Test grouping | `describe('API', ...)` | `describeAPI(HttpMethod.GET, '/path', {...}, app, ...)` |
+| Test case | `it('test name', ...)` | `itDoc('test name', ...)` |
+| API metadata | Comments or external docs | Structured `summary`, `description`, `tags` |
+| Request/Response specs | Manual assertions | Builder pattern with `field()` helpers |
+| Documentation | Manual or separate tools | Auto-generated OpenAPI, Markdown, HTML |
+
+## Migration Process
+
+### Step 1: Understand the Structure
+
+Itdoc uses two main functions that replace the standard test framework functions:
+
+1. **`describeAPI()`**: Replaces `describe()` for API endpoint testing
+2. **`itDoc()`**: Replaces `it()` for individual test cases
+
+### Step 2: Identify API Tests to Migrate
+
+Not all tests need migration. Itdoc is designed for **API endpoint testing**. Consider migrating:
+
+- ✅ Integration tests for REST APIs
+- ✅ E2E tests for HTTP endpoints
+- ✅ API contract tests
+
+Don't migrate:
+
+- ❌ Pure unit tests (functions, utilities, services)
+- ❌ Tests without HTTP requests
+- ❌ Internal logic tests
+
+### Step 3: Convert Test Structure
+
+## Mocha to Itdoc Conversion
+
+### Before: Standard Mocha Test
+
+
+
+ ```js
+ const request = require('supertest');
+ const app = require('./app');
+ const { expect } = require('chai');
+
+ describe('User API', () => {
+ describe('POST /users', () => {
+ it('should create a new user', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ username: 'johndoe',
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(201);
+ expect(response.body).to.have.property('id');
+ expect(response.body).to.have.property('username', 'johndoe');
+ });
+
+ it('should return 400 when username is missing', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(400);
+ expect(response.body.error).to.equal('Username is required');
+ });
+ });
+ });
+ ```
+
+
+ ```ts
+ import request from 'supertest';
+ import app from './app';
+ import { expect } from 'chai';
+
+ describe('User API', () => {
+ describe('POST /users', () => {
+ it('should create a new user', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ username: 'johndoe',
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(201);
+ expect(response.body).to.have.property('id');
+ expect(response.body).to.have.property('username', 'johndoe');
+ });
+
+ it('should return 400 when username is missing', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(400);
+ expect(response.body.error).to.equal('Username is required');
+ });
+ });
+ });
+ ```
+
+
+
+### After: Itdoc Format
+
+
+
+ ```js
+ const app = require('./app');
+ const { describeAPI, itDoc, HttpMethod, HttpStatus, field } = require('itdoc');
+
+ describeAPI(
+ HttpMethod.POST,
+ '/users',
+ {
+ summary: 'User Creation API',
+ description: 'Creates a new user with username and email',
+ tags: ['Users']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should create a new user', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ username: field('Username for the new user', 'johndoe'),
+ email: field('User email address', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.CREATED)
+ .body({
+ id: field('Unique user identifier', 1),
+ username: field('Username', 'johndoe'),
+ email: field('Email address', 'john@example.com')
+ });
+ });
+
+ itDoc('should return 400 when username is missing', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ email: field('User email address', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.BAD_REQUEST)
+ .body({
+ error: field('Error message', 'Username is required')
+ });
+ });
+ }
+ );
+ ```
+
+
+ ```ts
+ import app from './app';
+ import { describeAPI, itDoc, HttpMethod, HttpStatus, field } from 'itdoc';
+
+ describeAPI(
+ HttpMethod.POST,
+ '/users',
+ {
+ summary: 'User Creation API',
+ description: 'Creates a new user with username and email',
+ tags: ['Users']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should create a new user', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ username: field('Username for the new user', 'johndoe'),
+ email: field('User email address', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.CREATED)
+ .body({
+ id: field('Unique user identifier', 1),
+ username: field('Username', 'johndoe'),
+ email: field('Email address', 'john@example.com')
+ });
+ });
+
+ itDoc('should return 400 when username is missing', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ email: field('User email address', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.BAD_REQUEST)
+ .body({
+ error: field('Error message', 'Username is required')
+ });
+ });
+ }
+ );
+ ```
+
+
+
+## Jest to Itdoc Conversion
+
+### Before: Standard Jest Test
+
+
+
+ ```js
+ const request = require('supertest');
+ const app = require('./app');
+
+ describe('Product API', () => {
+ describe('GET /products/:id', () => {
+ it('should return product details', async () => {
+ const response = await request(app)
+ .get('/products/123')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(200);
+ expect(response.body.id).toBe(123);
+ expect(response.body.name).toBe('Test Product');
+ expect(response.body.price).toBe(99.99);
+ });
+
+ it('should return 404 for non-existent product', async () => {
+ const response = await request(app)
+ .get('/products/999')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(404);
+ expect(response.body.error).toBe('Product not found');
+ });
+ });
+ });
+ ```
+
+
+ ```ts
+ import request from 'supertest';
+ import app from './app';
+
+ describe('Product API', () => {
+ describe('GET /products/:id', () => {
+ it('should return product details', async () => {
+ const response = await request(app)
+ .get('/products/123')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(200);
+ expect(response.body.id).toBe(123);
+ expect(response.body.name).toBe('Test Product');
+ expect(response.body.price).toBe(99.99);
+ });
+
+ it('should return 404 for non-existent product', async () => {
+ const response = await request(app)
+ .get('/products/999')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(404);
+ expect(response.body.error).toBe('Product not found');
+ });
+ });
+ });
+ ```
+
+
+
+### After: Itdoc Format
+
+
+
+ ```js
+ const app = require('./app');
+ const { describeAPI, itDoc, HttpMethod, HttpStatus, field, header } = require('itdoc');
+
+ describeAPI(
+ HttpMethod.GET,
+ '/products/:id',
+ {
+ summary: 'Get Product Details',
+ description: 'Retrieves detailed information about a specific product by ID',
+ tags: ['Products']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should return product details', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer authentication token', 'Bearer token123')
+ })
+ .params({
+ id: field('Product ID', '123')
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ id: field('Product ID', 123),
+ name: field('Product name', 'Test Product'),
+ price: field('Product price', 99.99)
+ });
+ });
+
+ itDoc('should return 404 for non-existent product', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer authentication token', 'Bearer token123')
+ })
+ .params({
+ id: field('Product ID', '999')
+ })
+ .res()
+ .status(HttpStatus.NOT_FOUND)
+ .body({
+ error: field('Error message', 'Product not found')
+ });
+ });
+ }
+ );
+ ```
+
+
+ ```ts
+ import app from './app';
+ import { describeAPI, itDoc, HttpMethod, HttpStatus, field, header } from 'itdoc';
+
+ describeAPI(
+ HttpMethod.GET,
+ '/products/:id',
+ {
+ summary: 'Get Product Details',
+ description: 'Retrieves detailed information about a specific product by ID',
+ tags: ['Products']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should return product details', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer authentication token', 'Bearer token123')
+ })
+ .params({
+ id: field('Product ID', '123')
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ id: field('Product ID', 123),
+ name: field('Product name', 'Test Product'),
+ price: field('Product price', 99.99)
+ });
+ });
+
+ itDoc('should return 404 for non-existent product', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer authentication token', 'Bearer token123')
+ })
+ .params({
+ id: field('Product ID', '999')
+ })
+ .res()
+ .status(HttpStatus.NOT_FOUND)
+ .body({
+ error: field('Error message', 'Product not found')
+ });
+ });
+ }
+ );
+ ```
+
+
+
+## Migration Checklist
+
+### 1. Replace Test Functions
+
+- [ ] Replace `describe()` with `describeAPI(method, url, options, app, callback)`
+- [ ] Replace `it()` with `itDoc(description, testFn)`
+- [ ] Remove manual `supertest` imports (ITDoc handles this internally)
+
+### 2. Add API Metadata
+
+- [ ] Add `summary` (required): Brief API name
+- [ ] Add `description` (optional): Detailed API explanation
+- [ ] Add `tags` (optional): Array of categories for grouping APIs
+
+### 3. Convert Request Specifications
+
+- [ ] Replace `.send()` with `.req().body({})`
+- [ ] Replace `.set()` with `.req().headers({})`
+- [ ] Replace `.query()` with `.req().query({})`
+- [ ] Add URL parameters with `.req().params({})`
+
+### 4. Convert Response Assertions
+
+- [ ] Replace `expect(response.status)` with `.res().status(HttpStatus.XXX)`
+- [ ] Replace body assertions with `.res().body({})`
+- [ ] Replace header assertions with `.res().headers({})`
+
+### 5. Use Field Helpers
+
+- [ ] Wrap all request/response fields with `field(description, example)`
+- [ ] Wrap headers with `header(description, example)`
+- [ ] Set `required` flag: `field(description, example, false)` for optional fields
+
+## Common Patterns
+
+### Optional Fields
+
+```js
+// Third parameter controls if field is required (default: true)
+field('Optional description', 'example', false) // Optional field
+field('Required description', 'example') // Required field (default)
+field('Required description', 'example', true) // Explicitly required
+```
+
+### Nullable Fields
+
+```js
+// ITDoc supports null values as examples
+field('Nullable field', null) // Required nullable field
+field('Optional nullable', null, false) // Optional nullable field
+```
+
+### Query Parameters
+
+```js
+itDoc('should filter by status', () => {
+ return apiDoc
+ .test()
+ .req()
+ .query({
+ status: field('Filter by status', 'active'),
+ page: field('Page number', 1, false) // Optional parameter
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ items: field('List of filtered items', [])
+ });
+});
+```
+
+### Path Parameters
+
+```js
+describeAPI(
+ HttpMethod.GET,
+ '/users/:userId/posts/:postId',
+ { summary: 'Get User Post' },
+ app,
+ (apiDoc) => {
+ itDoc('should return specific post', () => {
+ return apiDoc
+ .test()
+ .req()
+ .params({
+ userId: field('User ID', '123'),
+ postId: field('Post ID', '456')
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ post: field('Post content', 'Hello World')
+ });
+ });
+ }
+);
+```
+
+### Authentication Headers
+
+```js
+import { header } from 'itdoc';
+
+itDoc('should require authentication', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer token', 'Bearer eyJhbGc...'),
+ 'X-API-Key': header('API Key', 'api-key-12345', false) // Optional header
+ })
+ .res()
+ .status(HttpStatus.OK);
+});
+```
+
+## Troubleshooting
+
+### Issue: Tests pass but documentation is not generated
+
+**Solution**: Ensure you have configured the test runner integration. See [Integration with Test Runner](integration-test-runner) guide.
+
+### Issue: `Cannot find module 'itdoc'`
+
+**Solution**: Install Itdoc in your project:
+```bash
+npm install itdoc --save-dev
+```
+
+### Issue: TypeScript type errors with `app` parameter
+
+**Solution**: Cast your Express app to `any` or use type assertion:
+```ts
+import { Application } from 'express';
+
+describeAPI(
+ HttpMethod.GET,
+ '/api',
+ { summary: 'API' },
+ app as Application, // Type assertion
+ (apiDoc) => { /* ... */ }
+);
+```
+
+### Issue: Global `describe` or `it` is undefined
+
+**Solution**: Make sure your test framework (Mocha or Jest) is properly configured and the test file is being run through the test runner.
+
+## Next Steps
+
+After migrating your tests:
+
+1. **Run your tests** to verify they still pass
+2. **Check the generated documentation** in the `output/` directory
+3. **Review the OpenAPI spec** (`output/oas.json`)
+4. **View the HTML documentation** (`output/redoc.html`)
+5. **Customize the output** using [Configuration Guide](./configuration)
diff --git a/itdoc-doc/i18n/ko/docusaurus-plugin-content-docs/current/guides/test-framework-migration.mdx b/itdoc-doc/i18n/ko/docusaurus-plugin-content-docs/current/guides/test-framework-migration.mdx
new file mode 100644
index 0000000..9d3bd89
--- /dev/null
+++ b/itdoc-doc/i18n/ko/docusaurus-plugin-content-docs/current/guides/test-framework-migration.mdx
@@ -0,0 +1,574 @@
+---
+sidebar_position: 4
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# 기존 E2E 테스트 마이그레이션 가이드
+
+> **이 가이드는 기존 Mocha 또는 Jest 테스트 케이스를 Itdoc 형식으로 마이그레이션하는 방법을 설명합니다.**
+
+## 왜 Itdoc으로 마이그레이션해야 하나요?
+
+Itdoc은 API 테스트와 자동 문서화를 하나의 흐름으로 묶어 줍니다. 기존 테스트를 옮기면 다음과 같은 이점을 얻습니다.
+
+- **자동 OpenAPI 생성**: 테스트 실행만으로 OpenAPI 스펙과 연동된 Markdown, HTML 문서를 자동 생성합니다
+- **자체 문서화 테스트**: 테스트 검증 옆에 API 메타데이터를 유지해 코드와 문서가 함께 바뀝니다
+- **프레임워크 호환성**: 기존에 사용하던 Mocha 또는 Jest 러너 위에 Itdoc DSL을 바로 얹을 수 있습니다
+- **향상된 API 가시성**: 태그, 설명, 예제 등 구조화된 정보로 엔드포인트를 더 쉽게 탐색할 수 있습니다
+
+## 주요 차이점
+
+### 기존 테스트 프레임워크 vs Itdoc
+
+| 기능 | Mocha/Jest | Itdoc |
+|-----------|------------------------|---------------------------------------------------------|
+| 테스트 그룹화 | `describe('API', ...)` | `describeAPI(HttpMethod.GET, '/path', {...}, app, ...)` |
+| 테스트 케이스 | `it('test name', ...)` | `itDoc('test name', ...)` |
+| API 메타데이터 | 주석 또는 외부 문서 | 구조화된 `summary`, `description`, `tags` |
+| 요청/응답 스펙 | 수동 검증 | `field()` 헬퍼를 사용한 빌더 패턴 |
+| 문서화 | 수동 또는 별도 도구 | 자동 생성된 OpenAPI, Markdown, HTML |
+
+## 마이그레이션 프로세스
+
+### 1단계: 구조 이해하기
+
+Itdoc은 표준 테스트 프레임워크 함수를 대체하는 두 가지 주요 함수를 사용합니다:
+
+1. **`describeAPI()`**: API 엔드포인트 테스트를 위해 `describe()`를 대체
+2. **`itDoc()`**: 개별 테스트 케이스를 위해 `it()`를 대체
+
+### 2단계: 마이그레이션할 API 테스트 식별
+
+모든 테스트를 마이그레이션할 필요는 없습니다. Itdoc은 **API 엔드포인트 테스팅**을 위해 설계되었습니다. 다음 테스트를 마이그레이션하는 것을 고려하세요:
+
+- ✅ REST API를 위한 통합 테스트
+- ✅ HTTP 엔드포인트를 위한 E2E 테스트
+- ✅ API 계약 테스트
+
+마이그레이션하지 말아야 할 테스트:
+
+- ❌ 순수 단위 테스트 (함수, 유틸리티, 서비스)
+- ❌ HTTP 요청이 없는 테스트
+- ❌ 내부 로직 테스트
+
+### 3단계: 테스트 구조 변환
+
+## Mocha에서 Itdoc으로 변환
+
+### 변환 전: 표준 Mocha 테스트
+
+
+
+ ```js
+ const request = require('supertest');
+ const app = require('./app');
+ const { expect } = require('chai');
+
+ describe('User API', () => {
+ describe('POST /users', () => {
+ it('should create a new user', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ username: 'johndoe',
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(201);
+ expect(response.body).to.have.property('id');
+ expect(response.body).to.have.property('username', 'johndoe');
+ });
+
+ it('should return 400 when username is missing', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(400);
+ expect(response.body.error).to.equal('Username is required');
+ });
+ });
+ });
+ ```
+
+
+ ```ts
+ import request from 'supertest';
+ import app from './app';
+ import { expect } from 'chai';
+
+ describe('User API', () => {
+ describe('POST /users', () => {
+ it('should create a new user', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ username: 'johndoe',
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(201);
+ expect(response.body).to.have.property('id');
+ expect(response.body).to.have.property('username', 'johndoe');
+ });
+
+ it('should return 400 when username is missing', async () => {
+ const response = await request(app)
+ .post('/users')
+ .send({
+ email: 'john@example.com'
+ });
+
+ expect(response.status).to.equal(400);
+ expect(response.body.error).to.equal('Username is required');
+ });
+ });
+ });
+ ```
+
+
+
+### 변환 후: Itdoc 형식
+
+
+
+ ```js
+ const app = require('./app');
+ const { describeAPI, itDoc, HttpMethod, HttpStatus, field } = require('itdoc');
+
+ describeAPI(
+ HttpMethod.POST,
+ '/users',
+ {
+ summary: '사용자 생성 API',
+ description: '사용자 이름과 이메일로 새 사용자를 생성합니다',
+ tags: ['Users']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should create a new user', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ username: field('새 사용자의 사용자 이름', 'johndoe'),
+ email: field('사용자 이메일 주소', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.CREATED)
+ .body({
+ id: field('고유 사용자 식별자', 1),
+ username: field('사용자 이름', 'johndoe'),
+ email: field('이메일 주소', 'john@example.com')
+ });
+ });
+
+ itDoc('should return 400 when username is missing', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ email: field('사용자 이메일 주소', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.BAD_REQUEST)
+ .body({
+ error: field('에러 메시지', 'Username is required')
+ });
+ });
+ }
+ );
+ ```
+
+
+ ```ts
+ import app from './app';
+ import { describeAPI, itDoc, HttpMethod, HttpStatus, field } from 'itdoc';
+
+ describeAPI(
+ HttpMethod.POST,
+ '/users',
+ {
+ summary: '사용자 생성 API',
+ description: '사용자 이름과 이메일로 새 사용자를 생성합니다',
+ tags: ['Users']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should create a new user', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ username: field('새 사용자의 사용자 이름', 'johndoe'),
+ email: field('사용자 이메일 주소', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.CREATED)
+ .body({
+ id: field('고유 사용자 식별자', 1),
+ username: field('사용자 이름', 'johndoe'),
+ email: field('이메일 주소', 'john@example.com')
+ });
+ });
+
+ itDoc('should return 400 when username is missing', () => {
+ return apiDoc
+ .test()
+ .req()
+ .body({
+ email: field('사용자 이메일 주소', 'john@example.com')
+ })
+ .res()
+ .status(HttpStatus.BAD_REQUEST)
+ .body({
+ error: field('에러 메시지', 'Username is required')
+ });
+ });
+ }
+ );
+ ```
+
+
+
+## Jest에서 Itdoc으로 변환
+
+### 변환 전: 표준 Jest 테스트
+
+
+
+ ```js
+ const request = require('supertest');
+ const app = require('./app');
+
+ describe('Product API', () => {
+ describe('GET /products/:id', () => {
+ it('should return product details', async () => {
+ const response = await request(app)
+ .get('/products/123')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(200);
+ expect(response.body.id).toBe(123);
+ expect(response.body.name).toBe('Test Product');
+ expect(response.body.price).toBe(99.99);
+ });
+
+ it('should return 404 for non-existent product', async () => {
+ const response = await request(app)
+ .get('/products/999')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(404);
+ expect(response.body.error).toBe('Product not found');
+ });
+ });
+ });
+ ```
+
+
+ ```ts
+ import request from 'supertest';
+ import app from './app';
+
+ describe('Product API', () => {
+ describe('GET /products/:id', () => {
+ it('should return product details', async () => {
+ const response = await request(app)
+ .get('/products/123')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(200);
+ expect(response.body.id).toBe(123);
+ expect(response.body.name).toBe('Test Product');
+ expect(response.body.price).toBe(99.99);
+ });
+
+ it('should return 404 for non-existent product', async () => {
+ const response = await request(app)
+ .get('/products/999')
+ .set('Authorization', 'Bearer token123');
+
+ expect(response.status).toBe(404);
+ expect(response.body.error).toBe('Product not found');
+ });
+ });
+ });
+ ```
+
+
+
+### 변환 후: Itdoc 형식
+
+
+
+ ```js
+ const app = require('./app');
+ const { describeAPI, itDoc, HttpMethod, HttpStatus, field, header } = require('itdoc');
+
+ describeAPI(
+ HttpMethod.GET,
+ '/products/:id',
+ {
+ summary: '상품 상세 조회',
+ description: 'ID로 특정 상품의 상세 정보를 조회합니다',
+ tags: ['Products']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should return product details', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer 인증 토큰', 'Bearer token123')
+ })
+ .params({
+ id: field('상품 ID', '123')
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ id: field('상품 ID', 123),
+ name: field('상품명', 'Test Product'),
+ price: field('상품 가격', 99.99)
+ });
+ });
+
+ itDoc('should return 404 for non-existent product', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer 인증 토큰', 'Bearer token123')
+ })
+ .params({
+ id: field('상품 ID', '999')
+ })
+ .res()
+ .status(HttpStatus.NOT_FOUND)
+ .body({
+ error: field('에러 메시지', 'Product not found')
+ });
+ });
+ }
+ );
+ ```
+
+
+ ```ts
+ import app from './app';
+ import { describeAPI, itDoc, HttpMethod, HttpStatus, field, header } from 'itdoc';
+
+ describeAPI(
+ HttpMethod.GET,
+ '/products/:id',
+ {
+ summary: '상품 상세 조회',
+ description: 'ID로 특정 상품의 상세 정보를 조회합니다',
+ tags: ['Products']
+ },
+ app,
+ (apiDoc) => {
+ itDoc('should return product details', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer 인증 토큰', 'Bearer token123')
+ })
+ .params({
+ id: field('상품 ID', '123')
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ id: field('상품 ID', 123),
+ name: field('상품명', 'Test Product'),
+ price: field('상품 가격', 99.99)
+ });
+ });
+
+ itDoc('should return 404 for non-existent product', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer 인증 토큰', 'Bearer token123')
+ })
+ .params({
+ id: field('상품 ID', '999')
+ })
+ .res()
+ .status(HttpStatus.NOT_FOUND)
+ .body({
+ error: field('에러 메시지', 'Product not found')
+ });
+ });
+ }
+ );
+ ```
+
+
+
+## 마이그레이션 체크리스트
+
+### 1. 테스트 함수 교체
+
+- [ ] `describe()`를 `describeAPI(method, url, options, app, callback)`로 교체
+- [ ] `it()`를 `itDoc(description, testFn)`로 교체
+- [ ] 수동 `supertest` import 제거 (ITDoc이 내부적으로 처리)
+
+### 2. API 메타데이터 추가
+
+- [ ] `summary` 추가 (필수): 간단한 API 이름
+- [ ] `description` 추가 (선택): 상세한 API 설명
+- [ ] `tags` 추가 (선택): API 그룹화를 위한 카테고리 배열
+
+### 3. 요청 명세 변환
+
+- [ ] `.send()`를 `.req().body({})`로 교체
+- [ ] `.set()`을 `.req().headers({})`로 교체
+- [ ] `.query()`를 `.req().query({})`로 교체
+- [ ] `.req().params({})`로 URL 파라미터 추가
+
+### 4. 응답 검증 변환
+
+- [ ] `expect(response.status)`를 `.res().status(HttpStatus.XXX)`로 교체
+- [ ] body 검증을 `.res().body({})`로 교체
+- [ ] header 검증을 `.res().headers({})`로 교체
+
+### 5. Field 헬퍼 사용
+
+- [ ] 모든 요청/응답 필드를 `field(description, example)`로 감싸기
+- [ ] 헤더를 `header(description, example)`로 감싸기
+- [ ] `required` 플래그 설정: 선택적 필드는 `field(description, example, false)`
+
+## 일반적인 패턴
+
+### 선택적 필드
+
+```js
+// 세 번째 파라미터로 필드가 필수인지 제어 (기본값: true)
+field('선택적 설명', 'example', false) // 선택적 필드
+field('필수 설명', 'example') // 필수 필드 (기본값)
+field('필수 설명', 'example', true) // 명시적으로 필수
+```
+
+### Nullable 필드
+
+```js
+// ITDoc은 null 값을 예제로 지원합니다
+field('Nullable 필드', null) // 필수 nullable 필드
+field('선택적 nullable', null, false) // 선택적 nullable 필드
+```
+
+### 쿼리 파라미터
+
+```js
+itDoc('should filter by status', () => {
+ return apiDoc
+ .test()
+ .req()
+ .query({
+ status: field('상태로 필터링', 'active'),
+ page: field('페이지 번호', 1, false) // 선택적 파라미터
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ items: field('필터링된 항목 목록', [])
+ });
+});
+```
+
+### 경로 파라미터
+
+```js
+describeAPI(
+ HttpMethod.GET,
+ '/users/:userId/posts/:postId',
+ { summary: '사용자 게시물 조회' },
+ app,
+ (apiDoc) => {
+ itDoc('should return specific post', () => {
+ return apiDoc
+ .test()
+ .req()
+ .params({
+ userId: field('사용자 ID', '123'),
+ postId: field('게시물 ID', '456')
+ })
+ .res()
+ .status(HttpStatus.OK)
+ .body({
+ post: field('게시물 내용', 'Hello World')
+ });
+ });
+ }
+);
+```
+
+### 인증 헤더
+
+```js
+import { header } from 'itdoc';
+
+itDoc('should require authentication', () => {
+ return apiDoc
+ .test()
+ .req()
+ .headers({
+ Authorization: header('Bearer 토큰', 'Bearer eyJhbGc...'),
+ 'X-API-Key': header('API 키', 'api-key-12345', false) // 선택적 헤더
+ })
+ .res()
+ .status(HttpStatus.OK);
+});
+```
+
+## 문제 해결
+
+### 문제: 테스트는 통과하지만 문서가 생성되지 않음
+
+**해결방법**: 테스트 러너 통합을 구성했는지 확인하세요. [테스트 러너와의 통합](integration-test-runner) 가이드를 참고하세요.
+
+### 문제: `Cannot find module 'itdoc'`
+
+**해결방법**: 프로젝트에 Itdoc을 설치하세요:
+```bash
+npm install itdoc --save-dev
+```
+
+### 문제: `app` 파라미터에서 TypeScript 타입 에러
+
+**해결방법**: Express app을 `any`로 캐스팅하거나 타입 단언을 사용하세요:
+```ts
+import { Application } from 'express';
+
+describeAPI(
+ HttpMethod.GET,
+ '/api',
+ { summary: 'API' },
+ app as Application, // 타입 단언
+ (apiDoc) => { /* ... */ }
+);
+```
+
+### 문제: 전역 `describe` 또는 `it`가 정의되지 않음
+
+**해결방법**: 테스트 프레임워크(Mocha 또는 Jest)가 올바르게 구성되어 있고 테스트 파일이 테스트 러너를 통해 실행되고 있는지 확인하세요.
+
+## 다음 단계
+
+테스트 마이그레이션 후:
+
+1. **테스트 실행**하여 여전히 통과하는지 확인
+2. **생성된 문서 확인** (`output/` 디렉토리)
+3. **OpenAPI 스펙 검토** (`output/oas.json`)
+4. **HTML 문서 보기** (`output/redoc.html`)
+5. [설정 가이드](./configuration)를 사용하여 **출력 사용자 정의**