English:
../TESTING.md
Genasis 변경을 push 하기 전에 안전성을 검증하는 방법. 10초짜리
cargo fmt 부터 풀 Plane + Mattermost docker 스택을 띄우는 10분짜리
실서버 스모크까지, 프로젝트가 제공하는 모든 테스트 계층을 다루며 어떤
변경에 어느 계층을 돌려야 하는지 안내합니다.
| 변경 대상 | push 전 실행 |
|---|---|
| Rust 코드 (모든 crate) | cargo fmt --all && cargo test --workspace |
crates/genasis-providers/ |
+ scripts/nightly-e2e.sh |
crates/genasis-cli/ (init / attach 라이프사이클) |
+ scripts/nightly-e2e.sh |
servers/docker-compose.yml |
+ scripts/nightly-e2e.sh |
trial-app/ (프론트엔드) |
cd trial-app && npm run typecheck && npm run build && npm run e2e |
docs/ko/ 외부 *.md |
scripts/check-i18n-drift.sh --warn |
crates/genasis-i18n/locales/*.yml |
scripts/i18n-extract-keys.sh |
tests/golden/** 픽스처 |
BLESS=1 cargo test -p genasis-overlay 후 diff 확인 |
CI 가 돌리는 것과 동일한 단일 명령:
cargo fmt --all -- --check && \
cargo clippy --workspace --all-targets && \
cargo test --workspace --all-targets
Genasis 는 10개 계층의 회귀 검증을 제공합니다. CI 는 매 push 마다 L1–L3 + L8 을 자동 수행합니다. 나머지 계층은 로컬에서 — 무료 CI 러너에서 돌리기엔 너무 무겁거나 (L9 는 전체 Plane 스택 필요), 개발자 환경의 자격 증명이 필요하기 (L7) 때문에 — 실행됩니다.
| 계층 | 내용 | 실행 시점 | 소요 | CI? |
|---|---|---|---|---|
| L1 fmt + lint | cargo fmt --check, cargo clippy |
매 commit | ~10 s | ✅ ci.yml :: test |
| L2 단위 + 통합 | cargo test --workspace --all-targets |
매 PR | ~60 s | ✅ ci.yml :: test |
| L3 i18n drift | check-i18n-drift.sh, i18n-extract-keys.sh |
docs/template 변경 시 | ~5 s | ✅ ci.yml :: lint-i18n (PR 에서 warn-only) |
| L4 trial-app 빌드 | npm run typecheck && npm run build |
trial-app/ 변경 시 |
~30 s | ❌ |
| L5 trial-app E2E | npm run e2e |
trial-app/ 변경 시 |
~5 분 | ❌ |
| L6 README parity | cargo test -p genasis-e2e |
CLI 표면 변경 시 | ~30 s | ✅ L2 에 포함 |
| L7 실서버 | scripts/e2e-test.sh |
릴리즈 전 | ~10 분 | ❌ |
| L8 커버리지 | cargo llvm-cov |
정보 제공 | ~80 s | ✅ ci.yml :: coverage → Codecov |
| L9 실서버 스모크 | scripts/nightly-e2e.sh |
provider / init / servers 변경 시 | ~10 분 | ❌ — 의도적 로컬 전용 |
| L10 소스 빌드 | ./build.sh |
릴리즈 검증 | ~3 분 | (릴리즈 파이프라인) |
cargo fmt --check + cargo clippy검출 대상: 스타일 drift, 비-관용적 Rust, 흔한 버그 패턴.
cargo fmt --all -- --check
cargo clippy --workspace --all-targets
실패 예시:
Diff in crates/genasis-cli/src/cmd_init.rs:195
복구: cargo fmt --all (--check 빼고) 후 다시 stage. push 전에
둘 다 통과해야 합니다 — ci.yml :: test 가 어떤 테스트보다 먼저 이
둘을 돌리므로, fmt 실패는 CI 전체를 단락시킵니다.
cargo test --workspace --all-targets검출 대상: 10 개 workspace crate 어디든 회귀 + tests/e2e
라이프사이클 하네스 + golden fixture drift.
cargo test --workspace --all-targets
# 또는 더 빠르게, lib + integration 만 돌리려면 --all-targets 생략
cargo test --workspace
현재 floor: 10 crate 에 걸친 245 개 테스트.
흔한 실패:
crates/genasis-core/src/config.rs 와 해당
test module 확인.tests/e2e/ 의 통합 테스트 실패 → `cargo test -p genasis-e2e
Genasis 는 엄격한 이중언어 프로젝트입니다 (CLAUDE.md §Bilingual Mirror Policy). 두 스크립트가 parity 를 강제합니다:
scripts/check-i18n-drift.sh --warn # drift 출력, warn 모드는 exit 0
scripts/check-i18n-drift.sh # drift 출력, 있으면 exit 1
scripts/i18n-extract-keys.sh # en.yml ↔ ko.yml 키 parity 보장
CI 는 PR 에서 둘 다 --warn 모드로 돌리지만, release-prep 에서는
drift 가 hard-fail 합니다. drift 해결 방법:
progress.{md,ko.md} 에 기록.영어 소스 파일에 한국어 거부: CI 는 docs/ko/ 외부의 *.md,
*.tera, *.rs, *.sh, *.yml 에서 [가–] 을 grep 합니다. 영어
소스에 한글이 섞이면 CI 가 즉시 실패합니다.
cd trial-app
npm install # 첫 회만
npm run typecheck # tsc --noEmit
npm run build # next build
검출 대상: TypeScript 타입 오류, 깨진 Next.js 15 SSR / hydration, 누락된 의존성.
trial-app/ 은 브라우저에서 도는 Plane + Mattermost 시뮬레이터입니다
(docs/TUTORIAL.md 참조). cargo workspace 에 속하지 않으므로 CI 의
cargo test 는 절대 건드리지 않습니다 — TypeScript / React / Tailwind
코드 변경 시 L4 + L5 를 직접 돌려야 합니다.
cd trial-app
npx playwright install chromium # 첫 회만
npm run e2e # headless
npm run e2e:ui # 인터랙티브 UI 모드
trial-webapp PRD 의 US-001..US-022 (M21) 을 다루는 23 개 spec.
Spec 위치는 trial-app/e2e/:
smoke.spec.ts — 부팅 + 네비게이션 (M21.1)demo.spec.ts — 스크립트 8단계 데모 스프린트 (M21.2)signup.spec.ts — 호스팅 트라이얼 신청 폼 (M21.3)live.spec.ts — 라이브 trial-bridge 라운드트립 (M21.4)npm run e2e 가 “starting webServer” 에서 멈추면 playwright.config.ts
의 dev server 설정이 3000 포트에서 다른 프로세스와 충돌하는 것 — kill
후 재시도.
tests/e2e/)cargo test -p genasis-e2e
검출 대상: README.md / README.ko.md 가 광고하는 모든 명령
(genasis init, genasis attach, genasis doctor 등) 에 대한 스모크
테스트가 tests/e2e/tests/ 에 있습니다. CLI 명령을 추가하거나
플래그 동작을 바꿀 때 여기에 매칭되는 테스트를 추가해, README 와
코드가 절대 drift 하지 않도록 보장합니다.
이 crate 는 workspace 에 속하므로 cargo test --workspace (L2) 가
이미 돌립니다. 별도로 호출하는 건 단일 실패 명령을 디버깅할 때
유용합니다.
scripts/e2e-test.sh)# Mock 모드 — 라이브 서비스 불필요 (~30 초)
scripts/e2e-test.sh --mock
# Quick 모드 — Plane 프로비저닝 건너뜀 (~5 분)
scripts/e2e-test.sh --quick
# 전체 라이프사이클을 라이브 서비스에 (~10 분)
scripts/e2e-test.sh
라이브 모드 전제 조건:
target/release/genasis (먼저 cargo build --release 실행)agents-pool/.env.e2e (agents-pool submodule 의 비공개 파일)
또는 다음 환경변수 export:
PLANE_URL, PLANE_API_KEY, PLANE_WORKSPACE_SLUGMM_URL, MM_ADMIN_TOKEN, MM_TEAM_ID결과는 test-results/e2e-<timestamp>.log 에 기록되고 최신 요약은
test-results/e2e-latest.json 에 저장됩니다. --mock 모드는 실
서비스 안 건드리고 스크립트 plumbing 검증할 때 유용합니다 — API
호출은 단락하지만 와이어링은 그대로 실행됩니다.
cargo llvm-cov → Codecov)cargo install cargo-llvm-cov # 첫 회만
cargo llvm-cov --workspace --lcov --output-path lcov.info
CI 는 main 으로 push 마다 lcov.info 를 Codecov 에 업로드합니다.
README 의
뱃지가 최신 결과를 반영합니다. 강제 floor 는 없으며 — 커버리지는
정보 제공이지 게이트가 아닙니다.
업로드 없이 로컬에서 확인:
cargo llvm-cov --workspace --html --open
scripts/nightly-e2e.sh)가장 무거운 계층. servers/docker-compose.yml 에서 전체 Plane +
Mattermost docker 스택을 부팅하고 genasis init --probe-only 로
프로빙합니다. 의도적으로 로컬 전용 — GitHub 무료 러너 (7 GB RAM,
2 vCPU) 는 풀 Plane 스택을 안정적으로 호스팅할 수 없기 때문입니다
(postgres + redis + minio + rabbitmq + plane-api/web/space/admin/live
# 전체 (~10 분): 빌드 → 부팅 → cargo test (release) → probe → tear down
scripts/nightly-e2e.sh
# 더 빠르게 (~3 분): 부팅 + probe 만, cargo test 건너뜀
scripts/nightly-e2e.sh --skip-test
# 검사 모드: probe 후 docker 스택 그대로 유지
scripts/nightly-e2e.sh --no-down
# 끝나고 직접 정리:
( cd servers && docker compose down -v --remove-orphans )
# 인라인 도움말
scripts/nightly-e2e.sh --help
전제 조건:
docker + docker compose v2 플러그인cargo (stable toolchain)스크립트는 EXIT trap 으로 docker 스택을 항상 다시 내립니다 (단,
--no-down 을 주면 예외).
실행 시점:
crates/genasis-providers/ (실서버 flavor 로직) push 전crates/genasis-cli/ (init / attach 라이프사이클) push 전servers/docker-compose.yml push 전다른 변경 (프론트엔드, agent overlay, 문서) 은 cargo test
--workspace 만으로 충분합니다 — L9 는 과합니다.
./build.sh)./build.sh
README 가 광고하는 install 경로를 검증 — Rust 미설치 시 설치, release
바이너리 빌드, ~/.local/bin/genasis 로 복사. 릴리즈 cut 전에
fresh-machine install 이 여전히 작동하는지 확인할 때 유용.
| 변경 대상 | 최소 게이트 | 신뢰도 부스트 (선택) |
|---|---|---|
| genasis-core 의 Rust 함수 1개 | L1 + L2 | — |
| genasis-providers 어디든 | L1 + L2 | L9 |
cmd_init.rs / cmd_attach.rs |
L1 + L2 + L6 | L9 |
새 [[humans]] 류 config 필드 |
L1 + L2 + golden 픽스처 | L9 |
Agent overlay .tera 템플릿 |
L2 + L3 | — |
새 t!() 키 |
L2 + L3 (i18n 키 parity) | — |
docs/** 만 (코드 무관) |
L3 | — |
trial-app/app/** (프론트엔드) |
L4 + L5 | — |
servers/docker-compose.yml |
L9 | — |
| GitHub workflow 파일 | (없음 — push 후 관찰) | — |
| 릴리즈 준비 | L1 + L2 + L6 + L7 + L9 + L10 | — |
CI (.github/workflows/ci.yml) 는 싸고 빠른 루프입니다. 매 push /
PR 마다 ~50 초 소요. 흔한 실패 클래스를 잡도록 튜닝됨: fmt, clippy,
깨진 테스트, 누락된 번역, 커버리지 하락. 의도적으로 무거운 계층은
돌리지 않습니다 — 이유:
이 계층들은 개발자 워크스테이션에서 돌립니다 — 그곳에서는:
이 분리는 의도적이며 CONTRIBUTING.md 에 codify 되어 있습니다.
코드 옆 #[cfg(test)] mod tests 블록에 추가. CI 의 L2 가 자동
픽업.
tests/e2e/tests/ 아래에 새 #[test] 함수 추가, tests/e2e/src/lib.rs
의 헬퍼 사용 (harness 모듈이 spawn_genasis() 등 노출). CI 의 L2
가 자동 픽업.
tests/golden/<name>/input/ 생성tests/golden/<name>/README.md 작성BLESS=1 cargo test -p genasis-overlay 로
tests/golden/<name>/expected/ 생성BLESS=1 없이 다시 돌려 픽스처가
안정적인지 확인trial-app/e2e/ 아래 .spec.ts 파일 추가. 인터랙티브 디버깅은
npm run e2e -- --ui.
crate 간 공유 헬퍼는 tests/e2e/src/lib.rs. tests/unit/ 디렉터리는
특정 crate 에 맞지 않는 작은 유틸리티 테스트용.
cargo test 가 느림 (>5 분)cargo test -p <crate-name> 로 다른 9 crate 건너뜀.cargo test --no-run 으로 컴파일만 하고 단일 테스트만 반복:
cargo test --no-fail-fast <test_name>.nightly-e2e.sh 에서 Mattermost health 체크 timeoutMattermost 컨테이너는 cold boot 에 첫-실행 스키마 마이그레이션 (~2-3
분) 을 합니다. 스크립트는 총 15 분 대기. 계속 timeout 되면
( cd servers && docker compose logs mm ) 으로 무엇이 막혔는지 확인.
npm run e2e 가 “starting webServer” 에서 멈춤3000 포트 충돌. 잔여 Next.js dev server 를 kill:
lsof -i :3000
kill <pid>
CODECOV_TOKEN repo secret 누락 또는 최근 push 가 Rust 파일을
건드리지 않아 커버리지 재업로드 안 됨. ci.yml 수동 트리거 또는
cargo 관련 변경 push.
BLESS=1 픽스처 재생성이 노이즈 발생일부 픽스처는 timestamp 나 임시 경로를 포함. genasis-overlay
crate 의 golden 하네스는 비교 전 정규화하지만, 의도하지 않은 diff
가 보이면 crates/genasis-overlay/tests/golden_helpers.rs 의
정규화 룰 확인.
flavor=trial 경로가 왜 L9 를 대체할 수 없는지