
# 테스트

Greph은 세 단계의 테스트로 검증합니다.

1. **단위 테스트**: 파서, 워커, 코덱, 옵션 등 개별 구성 요소를 테스트합니다.
2. **오라클 회귀 테스트 코퍼스**: 고정된 시나리오 세트에서 Greph의 출력을 표준 `grep`, `ripgrep` 및 `ast-grep` 바이너리의 출력과 비교합니다.
3. **프로브 기반 기능 매트릭스**: `rg` 및 `sg` 래퍼에서 검증된 기능 범위를 확인합니다.

CI는 `main`에 푸시할 때마다, 그리고 모든 풀 리퀘스트(`.github/workflows/ci.yml`)에서 실행됩니다. 코딩 표준(`composer cs`), 정적 분석(`composer analyse`), PHPUnit 단위 및 통합 테스트 모음(`composer test`), 그리고 PHP 8.4에서 `composer audit`을 실행합니다. 오라클 코퍼스(`composer test:oracle`)는 CI에 포함되지 않으며, 기능 매트릭스는 `php bin/feature-matrix`로 수동 재생성합니다. PHPUnit 테스트 모음에는 업스트림 `rg` 및 `sg`을 사용할 수 없는 것으로 표시한 상태에서 매트릭스를 생성하고 보고서의 형식을 확인하는 테스트가 포함되어 있으므로, 프로브 하나가 회귀해도 실패하지 않습니다.

## 클론에서 작업하기

이 페이지의 모든 작업에는 저장소 클론이 필요합니다. 0.2.3 Composer 패키지에는 `src/` 및 네 가지 런타임 실행 파일만 포함되므로, `tests/`, `scenarios/`, `benchmarks/` 및 `bin/`의 개발 스크립트는 패키지에서 제외됩니다.

```bash
git clone https://github.com/inline0/greph
cd greph
composer install
```

## 테스트 실행하기

```bash
# PHPUnit unit and integration suites
composer test

# Oracle regression corpus
composer test:oracle

# Static analysis
composer analyse

# Coding standards
composer cs
composer cs:fix

# Full release-grade verification (analyse + cs + test + test:oracle)
composer verify
```

모든 릴리스는 `composer verify`을 통과해야 합니다. 통과하지 못하면 변경 작업은 완료된 것이 아닙니다.

## 오라클 모델

Greph은 오라클 기반 검증 모델을 따릅니다. 각 시나리오에서 세 가지 명령을 실행합니다.

1. **오라클**: 시나리오 코퍼스를 기준으로 캡처한 `grep`, `ripgrep` 또는 `ast-grep`입니다.
2. **실제 결과**: 동일한 코퍼스를 기준으로 캡처한 Greph입니다.
3. **비교기**: 줄 단위 또는 의미상 동일성을 확인하는 구조화된 비교입니다.

Greph이 오라클과 일치하지 않으면 Greph이 잘못된 것입니다. `grep`와 `rg`이 서로 일치하지 않으면 시나리오는 `oracle_disagreement`에 불일치를 기록하고, `greph_follows`에서 Greph이 따르는 도구를 명시하며, 다른 도구와의 비교를 `skip`로 설정합니다. 코퍼스에는 두 방향의 경우가 모두 있습니다.

텍스트 시나리오는 `grep` 및 `rg`과 비교하고, AST 및 재작성 시나리오는 `sg`와 비교합니다. 오라클 출력은 한 번 캡처해 각 시나리오의 `oracle/` 디렉터리에 커밋하므로, 일반 실행에는 PHP만 필요합니다. 외부 도구는 오라클 출력을 캡처하거나 새로 고칠 때만 필요합니다.

구현은 `tests/Oracle/`에 있고 시나리오는 `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` 및 `scenarios/edge/`에 있습니다.

## 시나리오 구성

각 시나리오는 독립된 디렉터리입니다.

```
scenarios/text/literal-simple/
├── scenario.json     # name, category, pattern, flags, path
├── setup/            # corpus to search through
├── oracle/           # captured oracle output (grep.txt, rg.txt, rg.json, ...)
├── actual/           # captured greph output (generated, git-ignored)
└── reports/          # comparison results (generated, git-ignored)
```

`scenario.json`에는 패턴, 플래그 및 검색 경로를 선언합니다. 선택적 `expectations` 객체는 오라클(`exact`, `semantic` 또는 `skip`)별 비교 모드를 설정합니다. 이 객체가 없으면 텍스트 시나리오는 `grep` 및 `rg`을 정확히 비교하고 `rg` JSON은 의미상 비교하며, AST 및 재작성 시나리오는 `sg`와 비교합니다.

## 단일 시나리오 실행하기

저장소에는 개별 시나리오를 다루기 위한 소규모 CLI 모음이 있습니다. 이는 런타임 진입점이 아니라 개발 도구입니다. `bin/`의 런타임 바이너리와 함께 있지만 Composer 패키지에는 포함되지 않습니다. 각 도구에는 `scenarios/` 기준 상대 경로로 시나리오 이름을 지정합니다.

```bash
# Capture oracle output for a scenario (needs grep and rg, or sg)
./bin/oracle text/literal-simple

# Run greph against a scenario, capture its output
./bin/actual text/literal-simple

# Diff oracle vs actual
./bin/compare text/literal-simple

# Full pipeline: oracle (only if missing) -> actual -> compare
./bin/test-scenario text/literal-simple

# Recapture the oracle output first
./bin/test-scenario text/literal-simple --refresh
```

## 전체 회귀 테스트 모음 실행하기

```bash
# All scenarios (the same as composer test:oracle)
./bin/test-regression

# Filter by category
./bin/test-regression --category text
./bin/test-regression --category ast
./bin/test-regression --category rewrite
./bin/test-regression --category edge

# Print only failures and the summary
./bin/test-regression --fast

# Recapture every oracle before comparing
./bin/test-regression --refresh
```

시나리오는 항상 한 번에 하나씩 실행됩니다. `--jobs N`은 허용되며 요약 행에 표시되지만, 병렬로 실행되는 작업은 없습니다([#7](https://github.com/inline0/greph/issues/7)). 새로 클론한 저장소에서는 `text/no-ignore` 및 `text/explicit-file-input`가 실패합니다. `setup/vendor/`에 있는 픽스처 파일이 커밋되지 않았기 때문입니다([#6](https://github.com/inline0/greph/issues/6)).

회귀 테스트 모음은 새로운 동작을 추가할 때 통과해야 하는 기준입니다. 새 플래그, 새 예외 사례 또는 새 버그 수정에는 오라클을 기준으로 기대 동작을 기록한 시나리오가 필요합니다.

## 규정 준수 보고

```bash
./bin/verify-compliance
```

`verify-compliance`은 자체적으로 어떤 작업도 실행하지 않습니다. 마지막 시나리오 실행에서 남긴 오라클, 실제 결과 및 보고서 파일을 읽어 통과한 시나리오, 실패한 시나리오, 아직 보고서가 없는 시나리오를 출력합니다. 먼저 `./bin/test-regression`을 실행하세요. `--output report.json`는 보고서를 JSON로도 작성합니다. 현재 브랜치가 릴리스할 준비가 되었는지 확인하려면 이 명령을 실행하세요.

## 테스트 주도 개발 워크플로우

기능을 추가할 때:

1. 새 동작을 실행하는 코퍼스와 플래그를 포함한 시나리오 디렉터리를 작성합니다.
2. `./bin/oracle <scenario>`을 실행해 표준 도구의 출력을 캡처합니다.
3. `src/`에서 기능을 구현합니다.
4. `./bin/test-scenario <scenario>`를 실행해 Greph가 오라클과 일치하는지 확인합니다.
5. `./bin/test-regression --fast`를 실행해 다른 부분에 회귀가 없는지 확인합니다.
6. 커밋하기 전에 `composer verify`를 실행합니다.

버그를 수정할 때:

1. 실패하는 입력을 시나리오로 캡처합니다.
2. 오라클이 예상 출력을 생성하는지 확인합니다.
3. Greph이 예상 출력을 생성하지 않는지 확인합니다.
4. 버그를 수정합니다.
5. Greph이 이제 오라클과 일치하는지 확인합니다.
6. `composer verify`를 실행합니다.

시나리오는 코퍼스에 영구히 남으므로 `composer test:oracle`(및 `composer verify`)이 실패하지 않는 한 버그가 다시 발생할 수 없습니다.
