
# Testes

Greph é validado com três camadas de testes:

1. **Testes unitários** para componentes isolados (analisadores, percorredores, codecs, opções).
2. **Corpus de regressão do oráculo** que compara a saída de Greph com os binários canônicos `grep`, `ripgrep` e `ast-grep` em um conjunto fixo de cenários.
3. **Matriz de recursos orientada por sondagens** que verifica a superfície confirmada dos wrappers `rg` e `sg`.

O CI é executado a cada push para `main` e a cada pull request (`.github/workflows/ci.yml`). Ele executa verificações de padrões de código (`composer cs`), análise estática (`composer analyse`), os conjuntos de testes unitários e de integração de PHPUnit (`composer test`) e `composer audit` em PHP 8.4. O corpus do oráculo (`composer test:oracle`) não faz parte do CI, e a matriz de recursos é gerada manualmente com `php bin/feature-matrix`. O conjunto PHPUnit inclui um teste que gera a matriz com `rg` e `sg` upstream marcados como indisponíveis e verifica o formato do relatório, para que o teste não falhe quando uma única sondagem apresenta regressão.

## Trabalhar a partir de um clone

Tudo nesta página exige um clone do repositório. Como desde 0.2.3 o pacote Composer contém apenas `src/` e os quatro executáveis de runtime, `tests/`, `scenarios/`, `benchmarks/` e os scripts de desenvolvimento em `bin/` não são incluídos nele.

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

## Executar os testes

```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` é o requisito para qualquer lançamento. Se não passar, a alteração não está concluída.

## O modelo do oráculo

Greph segue um modelo de verificação orientado por oráculo. Para cada cenário, três comandos são executados:

1. **Oráculo**: `grep`, `ripgrep` ou `ast-grep`, capturado para o corpus de cenários.
2. **Resultado real**: Greph, capturado para o mesmo corpus.
3. **Comparador**: uma comparação estruturada que verifica a equivalência linha a linha ou semântica.

Se Greph divergir do oráculo, Greph está errado. Se `grep` e `rg` divergirem entre si, o cenário registra a divergência em `oracle_disagreement`, identifica a ferramenta que Greph segue em `greph_follows` e define a comparação com a outra ferramenta como `skip`. As duas direções ocorrem no corpus.

Os cenários de texto são comparados com `grep` e `rg`; os cenários de AST e reescrita, com `sg`. A saída do oráculo é capturada uma vez e enviada ao diretório `oracle/` de cada cenário, então uma execução normal precisa apenas de PHP; as ferramentas externas só são necessárias para capturar ou atualizar a saída do oráculo.

A implementação fica em `tests/Oracle/` e os cenários ficam em `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` e `scenarios/edge/`.

## Estrutura dos cenários

Cada cenário é um diretório independente:

```
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` declara o padrão, as flags e o caminho de pesquisa. Um objeto `expectations` opcional define o modo de comparação por oráculo (`exact`, `semantic` ou `skip`); sem ele, os cenários de texto comparam `grep` e `rg` exatamente e o `rg` JSON semanticamente, enquanto os cenários de AST e reescrita comparam com `sg`.

## Executar um único cenário

O repositório tem um pequeno conjunto de CLIs para trabalhar com cenários individuais. São ferramentas de desenvolvimento, não pontos de entrada do runtime: ficam junto aos binários de runtime em `bin/`, mas não fazem parte do pacote Composer. Cada uma recebe o nome do cenário relativo a `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
```

## Executar o conjunto completo de regressão

```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
```

Os cenários são sempre executados um de cada vez. `--jobs N` é aceito e exibido na linha de resumo, mas não executa nada em paralelo ([#7](https://github.com/inline0/greph/issues/7)). Em um clone novo, `text/no-ignore` e `text/explicit-file-input` falham, porque os arquivos de fixture em `setup/vendor/` não estão incluídos no repositório ([#6](https://github.com/inline0/greph/issues/6)).

O conjunto de regressão é o critério para novos comportamentos. Uma nova flag, um novo caso-limite ou uma correção de bug exige um cenário que registre o comportamento esperado em relação a um oráculo.

## Relatórios de conformidade

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

`verify-compliance` não executa nada por conta própria. Ele lê os arquivos do oráculo, de resultados reais e de relatórios deixados pelas últimas execuções de cenários e informa quais cenários passaram, quais falharam e quais ainda não têm relatório. Execute `./bin/test-regression` primeiro. `--output report.json` também grava o relatório como JSON. É o comando certo para saber "a ramificação atual está pronta para lançamento?".

## Fluxo de trabalho de desenvolvimento orientado por testes

Ao adicionar um recurso:

1. Escreva um diretório de cenário com o corpus e as flags que exercitam o novo comportamento.
2. Execute `./bin/oracle <scenario>` para capturar a saída da ferramenta canônica.
3. Implemente o recurso em `src/`.
4. Execute `./bin/test-scenario <scenario>` para verificar se Greph corresponde ao oráculo.
5. Execute `./bin/test-regression --fast` para garantir que nada mais regrediu.
6. Execute `composer verify` antes de fazer o commit.

Ao corrigir um bug:

1. Registre a entrada que falha como um cenário.
2. Confirme que o oráculo produz a saída esperada.
3. Confirme que Greph não produz essa saída.
4. Corrija o bug.
5. Confirme que Greph agora corresponde ao oráculo.
6. Execute `composer verify`.

O cenário permanece no corpus permanentemente, para que o bug não volte sem que `composer test:oracle` (e `composer verify`) falhe.
