Nette Documentation Preview

syntax
Testování pravidel
******************

.[perex]
RuleTester a formát fixtur: soubory .code, .expected a .violations, volby a verze PHP v hlavičce, a co všechno tester hlídá za vás.


Fixtury
=======

Pravidlo se testuje nad adresářem fixtur, jedním na pravidlo. Každá fixtura jsou až tři soubory téhož jména:

- `basic.code` je kód před opravou;
- `basic.expected` je kód po opravě; když chybí, pravidlo nesmí soubor změnit;
- `basic.violations` jsou očekávaná hlášení, řádek a zpráva, každé na svém řádku:

```
3: The message of an exception must end with a period
6: The message of an exception must end with a period
```

Fixtura může na některém z prvních tří řádků nést volby pravidla jako JSON a verzi PHP, pro kterou je psaná:

```php
<?php
// {"functions": ["dd", "dump"]}
// php 8.4
```

Bez verze se pravidlo testuje na své `minPhpVersion`, jinak na PHP 8.0; nikdy na verzi interpretu, který testy spouští, protože verdikt pravidla má být na počítači nezávislý.

Fixtura není ukázka do dokumentace: má být ošklivá a plná hraničních případů. Komentář uprostřed konstrukce, konstrukce na jednom řádku i přes tři, prázdné tělo, interpolovaný řetězec, alternativní syntaxe. Právě tam se pravidla lámou.


RuleTester
==========

```php
use DressCode\Testing\RuleTester;

RuleTester::run(ExceptionMessagePeriodRule::class, __DIR__ . '/fixtures/exception-message-period');
```

`run()` projde všechny soubory `*.code` v adresáři a vrátí jejich počet; selhání je výjimka `DressCode\Testing\TestFailure` se jménem fixtury a diffem, takže ji ukáže každý testovací framework. Z Nette Testeru je to celý test, z PHPUnit je to jedno volání v testovací metodě.

Pro každou fixturu tester ověří:

- **výstup** se rovná `.expected` (nebo vstupu, když `.expected` není);
- **hlášení** se rovnají `.violations`, řádek po řádku a v pořadí;
- **idempotenci**: pravidlo nad vlastním výstupem už nic nezmění ani neohlásí opravitelné porušení;
- **komentáře**: ve výstupu jsou všechny komentáře ze vstupu, pokud pravidlo neřekne `modifiesComments`;
- **potlačení**: s `dresscode:ignore-file` v hlavičce pravidlo nic neohlásí ani nezmění;
- **kontrakt oprav**: žádná změna stromu bez hlášení, které prošlo;
- **strom**: každý uzel má správného rodiče, což se rozbije při chybném vkládání.

Pravidlo, které volby dostává jinak než z konfigurace (třeba se závislostí v konstruktoru), předáte místo třídy jako továrnu `fn(array $options): Rule`.

Menší nástroje pro zvláštní případy: `RuleTester::runFixture()` spustí jednu fixturu, `RuleTester::check()` ověří pravidlo nad řetězcem bez souborů (hodí se pro test uvnitř dokumentace nebo pro rychlou reprodukci), `RuleTester::collectViolations()` vrátí hlášení nad fixturou ve tvaru souboru `.violations`, takže ho můžete nechat zapsat a jen zkontrolovat diff, místo abyste hlášení opisovali ručně.


Spouštění celého nástroje
=========================

Test pravidla ověří pravidlo samotné. Jak se chová spolu s ostatními, ukáže až běh nad skutečným kódem: `dresscode check --strict-rules` nad projektem udělá z každého porušeného kontraktu chybu místo varování, a `--jobs 1` běží v jednom procesu, kde se pohodlně ladí. Než pravidlo zveřejníte, pusťte `fix` nad větším cizím kódem (třeba `vendor/`) a podívejte se na diff: idempotenci a komentáře hlídá tester, vkus ne.

Testování pravidel

RuleTester a formát fixtur: soubory .code, .expected a .violations, volby a verze PHP v hlavičce, a co všechno tester hlídá za vás.

Fixtury

Pravidlo se testuje nad adresářem fixtur, jedním na pravidlo. Každá fixtura jsou až tři soubory téhož jména:

  • basic.code je kód před opravou;
  • basic.expected je kód po opravě; když chybí, pravidlo nesmí soubor změnit;
  • basic.violations jsou očekávaná hlášení, řádek a zpráva, každé na svém řádku:
3: The message of an exception must end with a period
6: The message of an exception must end with a period

Fixtura může na některém z prvních tří řádků nést volby pravidla jako JSON a verzi PHP, pro kterou je psaná:

<?php
// {"functions": ["dd", "dump"]}
// php 8.4

Bez verze se pravidlo testuje na své minPhpVersion, jinak na PHP 8.0; nikdy na verzi interpretu, který testy spouští, protože verdikt pravidla má být na počítači nezávislý.

Fixtura není ukázka do dokumentace: má být ošklivá a plná hraničních případů. Komentář uprostřed konstrukce, konstrukce na jednom řádku i přes tři, prázdné tělo, interpolovaný řetězec, alternativní syntaxe. Právě tam se pravidla lámou.

RuleTester

use DressCode\Testing\RuleTester;

RuleTester::run(ExceptionMessagePeriodRule::class, __DIR__ . '/fixtures/exception-message-period');

run() projde všechny soubory *.code v adresáři a vrátí jejich počet; selhání je výjimka DressCode\Testing\TestFailure se jménem fixtury a diffem, takže ji ukáže každý testovací framework. Z Nette Testeru je to celý test, z PHPUnit je to jedno volání v testovací metodě.

Pro každou fixturu tester ověří:

  • výstup se rovná .expected (nebo vstupu, když .expected není);
  • hlášení se rovnají .violations, řádek po řádku a v pořadí;
  • idempotenci: pravidlo nad vlastním výstupem už nic nezmění ani neohlásí opravitelné porušení;
  • komentáře: ve výstupu jsou všechny komentáře ze vstupu, pokud pravidlo neřekne modifiesComments;
  • potlačení: s dresscode:ignore-file v hlavičce pravidlo nic neohlásí ani nezmění;
  • kontrakt oprav: žádná změna stromu bez hlášení, které prošlo;
  • strom: každý uzel má správného rodiče, což se rozbije při chybném vkládání.

Pravidlo, které volby dostává jinak než z konfigurace (třeba se závislostí v konstruktoru), předáte místo třídy jako továrnu fn(array $options): Rule.

Menší nástroje pro zvláštní případy: RuleTester::runFixture() spustí jednu fixturu, RuleTester::check() ověří pravidlo nad řetězcem bez souborů (hodí se pro test uvnitř dokumentace nebo pro rychlou reprodukci), RuleTester::collectViolations() vrátí hlášení nad fixturou ve tvaru souboru .violations, takže ho můžete nechat zapsat a jen zkontrolovat diff, místo abyste hlášení opisovali ručně.

Spouštění celého nástroje

Test pravidla ověří pravidlo samotné. Jak se chová spolu s ostatními, ukáže až běh nad skutečným kódem: dresscode check --strict-rules nad projektem udělá z každého porušeného kontraktu chybu místo varování, a --jobs 1 běží v jednom procesu, kde se pohodlně ladí. Než pravidlo zveřejníte, pusťte fix nad větším cizím kódem (třeba vendor/) a podívejte se na diff: idempotenci a komentáře hlídá tester, vkus ne.