ahmed-bhs/pyra
最新稳定版本:v0.1.0-beta.2
Composer 安装命令:
composer require --dev ahmed-bhs/pyra
包简介
Standalone CLI that validates the shape of your test pyramid (unit/integration/e2e ratios) for any PHP project.
README 文档
README
Pyra looks at your tests and answers two questions: is the overall pyramid the right shape, and for the code you just changed on a branch, was it tested at the level it should be.
It works on any PHP project (Symfony, Laravel or plain PHP) as long as the tests are
written with PHPUnit (methods test* / #[Test]) or Gherkin scenarios. Pest is
not supported yet, so a project whose tests are written only in Pest will report zero
tests.
It does not boot your app. It reads files and a YAML config, so it runs the same everywhere.
Why
The test pyramid (Mike Cohn) says: lots of small, fast, isolated unit tests at the bottom; fewer slow, costly end-to-end tests at the top. The Practical Test Pyramid boils it down to two rules worth keeping:
- Write tests with different granularity
- The more high-level you get the fewer tests you should have
Most teams agree with this and then drift away from it one change at a time: a feature ships with an end-to-end test and no unit test, a "unit" test quietly spins up the database. Pyra is there to notice.
Install
composer require --dev ahmed-bhs/pyra
The two commands
pyra check looks at the whole suite: how many tests live at each level, whether the
ratios and ordering still make a pyramid, and whether any "unit" test is really an
integration test in disguise (it depends on something like an EntityManager).
pyra diff looks at what changed on your branch against a base ref. For every class you
changed, it checks the test levels that area is expected to have. It searches the whole
test suite, not just the files in the diff, so a test you wrote three months ago still
counts and you do not get nagged about a class that is already covered.
vendor/bin/pyra check --strict
vendor/bin/pyra diff --base origin/main --strict
vendor/bin/pyra diff --base origin/main --coverage build/clover.xml
vendor/bin/pyra diff --base origin/main --format=github # inline annotations
--base is any git ref: a branch (origin/main), a tag, or a commit. You do not need an
open pull request; a local branch is enough.
With --strict, a violation exits 1 (for CI). Without it, violations are printed but
the command still exits 0. diff can render as a table (default), json, or
github annotations. See docs/github-actions.md for a
ready-to-use workflow.
Config
Pyra reads a pyra.yaml at the project root. The shortest config that does something
useful:
pyra: levels: unit: paths: [tests/Unit] forbidden_dependencies: - Doctrine\ORM\EntityManagerInterface integration: paths: [tests/Integration] e2e: paths: [features] counter: gherkin
Every key (levels, percentages, counters, the diff block, ready-to-copy Symfony and
Laravel examples) is documented in docs/configuration.md.
What it actually catches
- A class you changed that has no test at the level its area expects.
- A unit test that pulls in an integration-only dependency.
- A pyramid that has tipped over (more integration than unit), compared within one counting style.
- If you pass
--coverage, the changed lines that no test executes.
Where it stops
A few things worth knowing before you trust the output:
- Without a coverage file it can only tell you a test looks missing, never that
coverage is low. "Coverage" is only ever reported from a clover/cobertura XML you pass
in with
--coverage. - There is no notion of a "feature": the unit of work is the changed class, summed up over the branch.
- The class-to-test matching is by name. A test that mentions a class without really exercising it is a false positive; a class hit only through a collaborator (or reflection, or the container) without being named is a false negative. Coverage is how you close that gap.
- A
.featurefile names no PHP class, so e2e cannot be name-matched. Only the path rules or coverage reach it. - Telling coverage apart per level needs one coverage run per suite; a single merged file cannot say which level hit a line.
- It counts PHPUnit (
test*/#[Test]) and Gherkin scenarios. Pest is not counted yet. - It classifies tests by directory. You map folders to levels; a folder that mixes unit and integration tests in the same place cannot be split (a project like api-platform/core, which groups tests by component rather than by level, is only as precise as your paths). Per-test level markers are a possible future addition.
License
MIT
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-09