[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -2,128 +2,178 @@
id: wiki-2026-0508-test-automation-pyramid
title: Test Automation Pyramid
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: []
aliases: [Test Pyramid, 테스트 피라미드, Cohn Pyramid]
duplicate_of: none
source_trust_level: A
confidence_score: 0.92
tags: [uncategorized]
verification_status: applied
tags: [testing, architecture, pyramid, automation]
raw_sources: []
last_reinforced: 2026-05-08
last_reinforced: 2026-05-10
github_commit: pending
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
tech_stack:
language: unspecified
framework: unspecified
language: TypeScript
framework: Vitest/Playwright
---
# [[Test Automation Pyramid]]
# Test Automation Pyramid
## 📌 Brief 마이크 요약
Test Automation Pyramid(테스트 자동화 피라미드)는 소프트웨어 테스트를 입도(Granularity)에 따라 여러 계층으로 그룹화하고, 각 계층에서 얼마나 많은 테스트를 작성해야 하는지를 시각적으로 나타낸 메타포입니다 [1]. 이 원칙은 가장 빠르고 독립적인 단위 테스트(Unit Tests)를 피라미드의 하단에 가장 많이 배치하고, 상위 수준인 통합 테스트와 엔드 투 엔드(E2E) 테스트로 갈수록 그 수를 줄일 것을 권장합니다 [2, 3]. 이를 통해 리팩토링과 같은 코드 구조 변경 시 즉각적이고 신뢰할 수 있는 피드백을 제공하는 빠르고 유지보수 가능한 테스트 스위트를 구축할 수 있습니다 [3, 4].
## 매 한 줄
> **"매 unit test 가 base, e2e 가 tip"**. Mike Cohn 의 2009 Succeeding with Agile 에서 origin — slow/expensive UI test 의 over-reliance 의 anti-pattern. 매 2026 modern stack 은 unit + integration + contract + e2e 의 4-layer 의 evolution.
## 📖 구조화된 지식 (Synthesized Content)
* **개념의 기원 및 기본 원칙:** 마이크 콘(Mike Cohn)이 고안한 이 개념은 테스트를 다양한 입도로 작성하되, 상위 수준(High-level)으로 갈수록 테스트의 수를 적게 유지하라는 두 가지 핵심 원칙을 제시합니다 [1, 3].
* **단위 테스트 (Unit Tests - 피라미드 하단):** 전체 자동화 테스트의 약 70%를 차지해야 하는 기반 계층입니다 [5]. 밀리초 단위로 매우 빠르게 실행되며, 개별 컴포넌트나 함수 수준의 동작을 격리하여 검증합니다 [5]. 리팩토링 중 실수가 발생했을 때 가장 빠르고 정확한 피드백 루프를 제공합니다 [4, 6].
* **통합 테스트 (Integration Tests - 피라미드 중간):** 약 20%를 차지하며, 단위 테스트로는 잡을 수 없는 컴포넌트 간의 상호작용(데이터베이스, 외부 API 등)의 결함을 찾아냅니다 [7-9].
* **엔드 투 엔드 테스트 (End-to-End Tests - 피라미드 상단):** 10% 정도로 유지해야 합니다 [10]. 사용자 인터페이스부터 백엔드 서비스까지 전체 워크플로우를 실제 사용자 여정에 맞춰 검증하지만, 구축 비용이 가장 비싸고, 실행 속도가 매우 느리며, 유지보수가 까다롭습니다(brittle) [4, 10].
* **테스트 중복 제거와 하향 이동 (Push Tests Down):** 테스트 스위트의 비대화를 막기 위해, 상위 수준 테스트에서 오류를 발견했는데 하위 수준 테스트가 실패하지 않았다면 반드시 하위 수준(단위 테스트 등)에 테스트를 추가해야 합니다 [11]. 가능한 한 모든 테스트는 피라미드의 가장 아래 계층에서 검증하도록 내려보내야 합니다 [11].
## 매 핵심
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
* **역 피라미드 및 아이스크림 콘 안티 패턴 (Inverted Pyramid / Ice-Cream Cone):** UI 기반의 E2E 테스트 위주로 하향식(Top-down) 자동화를 시도하면 '역 테스트 피라미드'가 형성됩니다 [3, 10]. 이 경우 테스트 스위트 실행에 수 시간이 걸리고 거짓 실패(False failures)가 잦아져, 팀이 자동화 테스트를 불신하고 결과를 무시하게 되는 부작용이 발생합니다 [10, 12].
* **계층 명칭의 모호성과 시대적 한계:** 원본 피라미드가 제시한 'Service Test'나 'UI Test'라는 명칭은 현대 개발 환경(예: React, Angular 등 SPA 프레임워크)에서는 오해를 살 수 있습니다 [3]. SPA 환경에서는 UI 자체도 최상단이 아닌 단위 테스트 수준에서 검증할 수 있기 때문입니다 [3].
* **신뢰성과 실행 속도의 트레이드오프:** 피라미드 상단으로 갈수록 사용자의 실제 사용 환경과 유사해져 비즈니스적 확신(Confidence)은 높아지지만, 실행 시간(Speed)과 유지보수(Maintainability) 비용이 급증합니다 [10, 13]. 따라서 커버리지, 속도, 신뢰성의 균형을 시스템 전체 관점에서 조율해야 합니다 [14].
### 매 layers (bottom-up)
- **Unit (70%)**: pure function, 단일 class, <10ms, in-memory.
- **Integration (20%)**: DB, HTTP client, 매 real adapter, 100ms-1s.
- **Contract (5-10%)**: provider/consumer 매 Pact / OpenAPI schema.
- **E2E (5%)**: 매 full user journey, Playwright/Cypress, 10s+.
## 🔗 지식 연결 (Graph)
### Related Concepts
### 매 anti-shapes
- **Ice cream cone**: 매 e2e heavy, unit 부족 — slow CI, flaky.
- **Hourglass**: 매 unit + e2e 만, integration 의 gap — production bug 의 source.
- **Cupcake**: manual test layer 의 추가 — automation 의 의미 상실.
#### [구현/테스트 전략]
- [[단위 테스트 (Unit Tests)]]
- 연결 이유: 테스트 피라미드의 근간을 이루며 전체 테스트의 대다수를 차지하는 핵심 요소이기 때문입니다 [5, 15].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 리팩토링 진행 시 기존 기능이 깨지지 않았음을 밀리초 단위로 확인해 주는 가장 강력한 '안전망'의 역할을 이해할 수 있습니다 [4].
- [[테스트 주도 개발 (TDD)]]
- 연결 이유: 피라미드 하단의 단위 테스트를 작성하는 주요 기법(Red-Green-Refactor)으로, 리팩토링의 필수 전제 조건이기 때문입니다 [5, 16].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 테스트를 먼저 작성하여 소프트웨어의 동작을 보호하고, 이후 리팩토링을 통해 코드의 내부 구조를 안전하게 개선하는 흐름을 배울 수 있습니다 [16, 17].
### 매 응용
1. CI pipeline tier — unit on every commit, e2e on merge to main.
2. Bug 발견 시 lowest-level test 의 추가 (root cause level).
3. Test budget 분배 결정 (시간 / 신뢰도 trade-off).
#### [아키텍처/기반 기술]
- [[지속적 통합 (CI) 및 지속적 배포 (CD)]]
- 연결 이유: 테스트 피라미드가 올바르게 구축되어야 CI/CD 파이프라인에서 병목 없이 소프트웨어를 지속적으로 배포할 수 있기 때문입니다 [2, 18, 19].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 리팩토링 후 코드가 커밋될 때마다 빠른 피드백을 제공하여, 지속 가능한 애자일 개발과 DevOps 문화를 유지하는 아키텍처적 기반을 이해할 수 있습니다 [6, 19].
- [[레거시 코드 (Legacy Code)]]
- 연결 이유: "테스트가 없는 코드"로 정의되는 레거시 코드를 안전하게 리팩토링하려면, 점진적으로 테스트 피라미드를 구축해야 하기 때문입니다 [20, 21].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 의존성이 강하게 결합된 코드에서 '접점(Seams)'을 찾아내어 단위 테스트를 추가하고, 리팩토링을 수행할 수 있는 상태로 만드는 기법을 파악할 수 있습니다 [22, 23].
## 💻 패턴
### Deeper Research Questions
- 테스트 피라미드의 단위 테스트와 통합 테스트의 경계는 어떻게 정의되며, 테스트 대역(Mock, Stub)을 사용해야 하는 정확한 기준과 범위는 무엇인가?
- UI 및 E2E 테스트에 편중된 '역 테스트 피라미드(아이스크림 콘)' 형태의 레거시 시스템을 정상적인 피라미드 구조로 마이그레이션하기 위한 점진적 전략은 무엇인가?
- SPA(Single Page Application) 및 마이크로서비스 아키텍처 환경에서 기존 테스트 피라미드의 계층(Service, UI) 개념은 어떻게 현대적으로 재해석되어야 하는가?
- 리팩토링 시 상위 수준(E2E) 테스트는 통과하지만 하위 수준(Unit) 테스트만 깨지는 경우, 이를 어떻게 처리하고 테스트 스위트를 재구성해야 하는가?
- 계약 테스트(Consumer-Driven Contract Tests)는 테스트 피라미드의 어느 계층에 위치하며, 마이크로서비스 간의 통합 테스트를 어떻게 효율적으로 대체하거나 보완하는가?
### Vitest unit test
```typescript
import { describe, it, expect } from 'vitest';
import { calculateDiscount } from './pricing';
### Practical Application Contexts
- **Implementation:** 개발자는 새로운 기능을 추가하거나 기존 코드를 수정할 때, TDD를 활용하여 빠르고 고립된 단위 테스트를 최우선으로 작성해야 합니다 [5].
- **System Design:** 아키텍처 설계 시 각 컴포넌트가 독립적으로 테스트될 수 있도록 의존성 분리(Decoupling)를 고려하여 단위 테스트 작성이 용이한 모듈식 구조를 설계해야 합니다 [24].
- **Operation / Maintenance:** CI 파이프라인의 실행 속도를 유지하기 위해 유지보수가 힘든 E2E 테스트 비중은 최소화하고, 단위 및 통합 테스트 중심으로 회귀 버그를 탐지하는 운영 프로세스를 확립해야 합니다 [5, 10, 19].
- **Learning Path:** TDD 및 Mocking 프레임워크 학습 -> 단위 및 통합 테스트 구축 방법 습득 -> 테스트 피라미드 원리에 따른 테스트 포트폴리오 최적화 -> CI 파이프라인 통합 및 안전한 리팩토링 실습 순으로 역량을 키워나갑니다.
- **My Project Relevance:** 현재 진행 중인 프로젝트가 느리고 깨지기 쉬운 E2E 테스트에만 의존하고 있지 않은지 점검하고, 리팩토링을 두려움 없이 수행할 수 있도록 하위 수준의 단위 테스트 커버리지를 두텁게 확보하는 리팩토링 전략의 핵심 근거로 활용됩니다.
describe('calculateDiscount', () => {
it('applies 10% for VIP customer', () => {
expect(calculateDiscount(100, 'VIP')).toBe(90);
});
### Adjacent Topics
- [[소비자 주도 계약 테스트 (Consumer-Driven Contract Tests, CDC)]]
- 확장 방향: 마이크로서비스 환경에서 통합 테스트의 비용을 줄이고, 서비스 간 API 인터페이스(계약)가 깨지지 않았는지 독립적으로 검증하는 기법으로 테스트 피라미드 전략을 확장할 수 있습니다 [25, 26].
---
*Last updated: 2026-05-03*
## 📌 한 줄 통찰 (The Karpathy Summary)
> *(TODO: 한 문장으로 핵심 통찰을 작성. "X는 Y 조건에서 Z 효과를 낸다" 구조 권장.)*
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
**언제 이 지식을 쓰는가:**
- *(TODO)*
**언제 쓰면 안 되는가:**
- *(TODO)*
## 🧪 검증 상태 (Validation)
- **정보 상태:** needs_review
- **출처 신뢰도:** A
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
## 🧬 중복 검사 (Duplicate Check)
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
- **처리 방식:** UPDATE (자동 정규화)
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
## 🕓 변경 이력 (Changelog)
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|------|-----------|-----------|--------|
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
## 💻 코드 패턴 (Code Patterns)
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
```text
# TODO
it('returns full price for standard customer', () => {
expect(calculateDiscount(100, 'STANDARD')).toBe(100);
});
});
```
## 🤔 의사결정 기준 (Decision Criteria)
### Integration test (real Postgres via testcontainers)
```typescript
import { PostgreSqlContainer } from '@testcontainers/postgresql';
**선택 A를 써야 할 때:**
- *(TODO)*
let container: StartedTestContainer;
beforeAll(async () => {
container = await new PostgreSqlContainer('postgres:16').start();
process.env.DATABASE_URL = container.getConnectionUri();
});
**선택 B를 써야 할 때:**
- *(TODO)*
it('persists user', async () => {
const repo = new UserRepository();
await repo.save({ id: '1', name: 'Alice' });
const found = await repo.findById('1');
expect(found?.name).toBe('Alice');
});
```
**기본값:**
> *(TODO)*
### Contract test (Pact consumer)
```typescript
import { PactV3, MatchersV3 } from '@pact-foundation/pact';
## ❌ 안티패턴 (Anti-Patterns)
const provider = new PactV3({ consumer: 'web', provider: 'api' });
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
provider
.uponReceiving('a request for user')
.withRequest({ method: 'GET', path: '/users/1' })
.willRespondWith({
status: 200,
body: { id: MatchersV3.string('1'), name: MatchersV3.string('Alice') }
});
```
### Playwright E2E
```typescript
import { test, expect } from '@playwright/test';
test('user can checkout', async ({ page }) => {
await page.goto('/products/42');
await page.getByRole('button', { name: 'Add to cart' }).click();
await page.goto('/cart');
await page.getByRole('button', { name: 'Checkout' }).click();
await expect(page).toHaveURL(/\/orders\/\w+/);
});
```
### Test pyramid CI distribution (GitHub Actions)
```yaml
jobs:
unit:
runs-on: ubuntu-latest
steps:
- run: pnpm test:unit # <30s, every push
integration:
needs: unit
steps:
- run: pnpm test:integration # <5min, every PR
e2e:
needs: integration
if: github.ref == 'refs/heads/main'
steps:
- run: pnpm test:e2e # <20min, main only
```
### Coverage budget enforcement
```typescript
// vitest.config.ts
export default {
test: {
coverage: {
thresholds: {
lines: 80,
functions: 80,
branches: 75,
statements: 80,
},
},
},
};
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Pure logic, no I/O | Unit test |
| DB query / external HTTP | Integration with testcontainers |
| Microservice boundary | Contract test (Pact) |
| Critical user journey | E2E (smoke only, 5-10 tests) |
| Visual regression | Playwright trace + screenshot |
**기본값**: 70/20/10 split (unit/integration/e2e), 매 contract test 는 microservice 환경에서만.
## 🔗 Graph
- 부모: [[Test-Driven_Development]] · [[Testability_Architecture]]
- 변형: [[Testing Trophy]] (Kent C. Dodds) · [[Test Honeycomb]]
- 응용: [[Continuous Integration]] · [[CI_CD_Pipeline]]
- Adjacent: [[Mock Objects (가짜 객체)]] · [[Property-Based Testing]]
## 🤖 LLM 활용
**언제**: test strategy 설계, CI tier 분배 결정, anti-shape 진단.
**언제 X**: 매 specific test framework 의 deep API 질문 — 매 official docs 의 우선.
## ❌ 안티패턴
- **All e2e**: 매 30분 CI, flaky retry hell.
- **No integration**: unit pass + production fail (mock drift).
- **Test pyramid as goal**: 매 ratio 의 obsession — 매 actual confidence 가 metric.
- **100% coverage**: meaningless — 매 critical path coverage 가 진짜.
## 🧪 검증 / 중복
- Verified (Mike Cohn, *Succeeding with Agile* 2009; Martin Fowler 2012 update).
- 신뢰도 A.
- 중복: [[Test Pyramid (테스트 피라미드)]] redirect.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — full canonical content with 4-layer modern pyramid |