Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## Unreleased

- **Docs:** the READMEs and `llms.txt` now state what follows from driving the
engine through a single PHPUnit test method: `setUp()`/`tearDown()` and
`#[Before]`/`#[After]` run once per property rather than per run, test-double
expectations are verified after the last run (an unmet `once()` fails the
property as a whole and is never shrunk), and per-test coverage counts lines
reached only while shrinking. The Testo adapter does not share the first one.

## 1.0.0 — 2026-09-20

The stability release, in step with `rasuvaeff/property-testing-core` 1.0.0.
Expand Down
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,22 @@ would otherwise falsify every run without a word of explanation.
[`throws()`](#expected-exceptions-throws) instead, or assert on the
exception inside the body.
- `setUp()` runs once per test, not per generated input — a property is one
test method with one `check()`.
test method with one `check()`. So is `tearDown()`, and so are `#[Before]`
and `#[After]` hooks: state a run leaves behind is visible to the next run
and to every shrinking attempt. Build per-input fixtures inside the body.
- **Test double expectations are verified once per property.** PHPUnit
verifies the doubles it created when the test method ends, which is after
the last run. An unmet `once()` therefore fails the property as a whole:
it is not attributed to an input and it is not shrunk. A double that must
be checked per input has to be created and verified inside the body.
- **Code coverage counts shrinking attempts.** Every run — random phase,
corpus replay and each shrink trial — executes inside the one test method,
so per-test coverage includes lines reached only while shrinking.
- These three follow from driving the engine through a single test method,
which is what PHPUnit's extension points allow. The
[Testo adapter](https://github.com/rasuvaeff/property-testing-testo) does
not share the first one: there each run goes through the framework's
interceptor pipeline, so lifecycle hooks run per run.
- With a **data provider**, the corpus id carries the data set name
(`Class::method with data set "large"`), so the sets do not replay — and
prune — each other's regressions. The unstable-id warning is printed only
Expand Down
19 changes: 18 additions & 1 deletion README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,24 @@ $this->forAll(['width' => Gen::intBetween(1, 5000), 'minWidth' => Gen::intBetwee
прогона. Объявляйте ожидание через [`throws()`](#ожидаемые-исключения-throws)
или проверяйте исключение внутри тела.
- `setUp()` выполняется один раз на тест, а не на каждый вход — property это
один тестовый метод с одним `check()`.
один тестовый метод с одним `check()`. То же касается `tearDown()` и хуков
`#[Before]`/`#[After]`: состояние, оставленное прогоном, видно следующему
прогону и каждой попытке усадки. Фикстуры, нужные на каждый вход, стройте
внутри тела.
- **Ожидания тест-даблов проверяются один раз на свойство.** PHPUnit
верифицирует созданные им даблы в конце тестового метода — то есть после
последнего прогона. Невыполненный `once()` поэтому роняет свойство целиком:
он не привязывается к входу и не усаживается. Дабл, который должен
проверяться на каждый вход, нужно создавать и верифицировать внутри тела.
- **Покрытие учитывает попытки усадки.** Все прогоны — случайная фаза,
воспроизведение корпуса и каждая усадочная попытка — выполняются внутри
одного тестового метода, поэтому в покрытие теста попадают строки,
достигнутые только во время усадки.
- Эти три следствия вытекают из того, что движок работает внутри одного
тестового метода — так устроены точки расширения PHPUnit.
[Testo-адаптер](https://github.com/rasuvaeff/property-testing-testo) первого
из них лишён: там каждый прогон идёт через конвейер интерцепторов
фреймворка, поэтому хуки жизненного цикла выполняются на каждый прогон.
- С **data provider** id корпуса несёт имя набора (`Class::method with data
set "large"`), чтобы наборы не воспроизводили — и не удаляли — регрессии
друг друга. Предупреждение о нестабильном id печатается только при
Expand Down
8 changes: 8 additions & 0 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ Requires PHP 8.3–8.5, `phpunit/phpunit` `^11.5 || ^12.0 || ^13.0`
that returns normally or throws another class fails and shrinks. Skips and
`Assume::that()` discards are unaffected. A non-Throwable class string is
rejected with `InvalidArgumentException`.
- The engine drives ONE PHPUnit test method, so: `setUp()`/`tearDown()` and
`#[Before]`/`#[After]` run once per property, not per run (state leaks into
the next run and into every shrink attempt); test-double expectations are
verified after the last run, so an unmet `once()` fails the property as a
whole instead of being attributed to an input and shrunk; per-test coverage
includes lines reached only while shrinking. Per-input fixtures and doubles
belong inside the body. The Testo adapter runs each trial through the
framework's interceptor pipeline, so there lifecycle hooks DO run per run.
- Environment contract and corpus format are identical to the Testo adapter
and to frozen `rasuvaeff/property-testing` 2.8 — corpora interoperate.
- Generators, `Shrinkable`, `Assume`, `Classify`, `Gen::draw()`, state-machine
Expand Down
Loading