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
4 changes: 1 addition & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ jobs:
run: composer test

- name: Database drivers
run: |
vendor/bin/phpunit -c resources/phpunit.mysql.xml
vendor/bin/phpunit -c resources/phpunit.pgsql.xml
run: php bin/talon run mysql pgsql

# Runtime-independent: run once on a single (v5) cell rather than all ten.
- name: Static analysis, coding standard, layout
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

### Changed

- The repo dogfoods its own runner: `composer test`/`test-coverage`/`test-coverage-html` and the CI database step now route through `bin/talon` (`php bin/talon run mysql pgsql` replaces the two explicit PHPUnit invocations). Infection still drives PHPUnit directly by design; the raw `vendor/bin/phpunit -c ...` invocations keep working as a fallback. [#5](https://github.com/phalcon/talon/issues/5)

### Added

- `talon` CLI runner: `vendor/bin/talon run [suites...] [-- passthrough]` fronts PHPUnit per mapped suite, `talon suites` lists the map. Suites come from a root `talon.php` (per-suite `config`/`php`/`env`/`args`, global `php`/`env` merged in) or, with zero config, from discovered `phpunit*.xml` files (`phpunit.mysql.xml` -> `mysql`; `phpunit.xml.dist` -> `unit`, the default). Options forward to PHPUnit starting at the first option talon does not recognize (everything after `--` always forwards verbatim); the reserved name `all` runs every suite sequentially with a `max()` exit code; subprocess re-exec keeps per-suite ini flags (e.g. `extension=phalcon.so`) and env vars possible. Adds `phalcon/cli-options-parser` (^2.0) as a runtime dependency. [#5](https://github.com/phalcon/talon/issues/5)
- Infection mutation testing: `infection/infection` (^0.29) as a dev dependency, configured via `resources/infection.json5` (source `src/`, `@default` mutators, logs and temp files under `tests/_output/infection/`), with a `composer test-mutation` script and a report-only step in the CI coverage job. The suite was hardened until the mutation score plateaued at 99% MSI / 99% covered MSI under the ext-phalcon (v5) test image - the five surviving mutants are provider-specific and are killed under the phalcon/phalcon (v6) provider the CI step runs on. Every config-level mutator ignore is individually justified in `resources/infection.json5`. [#7](https://github.com/phalcon/talon/issues/7)

### Fixed
Expand Down
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Stop the stack with `docker compose down`.

| Command | What it does |
|---------|--------------|
| `composer test` | the default suite (unit, functional, browser, sqlite) |
| `composer test` | the default suite (unit, functional, browser, sqlite) via `bin/talon` |
| `composer test-coverage` | Clover report → `tests/_output/coverage.xml` |
| `composer test-coverage-html` | HTML report → `tests/_output/coverage` |
| `composer test-mutation` | Infection mutation testing → `tests/_output/infection/` |
Expand All @@ -78,11 +78,13 @@ Stop the stack with `docker compose down`.
| `composer cs-fixer` | PHP-CS-Fixer (dry-run) |
| `composer cs-fixer-fix` | PHP-CS-Fixer (apply) |

The MySQL and PostgreSQL suites use dedicated configs:
The MySQL and PostgreSQL suites run through the repo's own runner (dogfooding
the CLI); raw PHPUnit remains available as a fallback:

```bash
docker compose run --rm app php bin/talon run mysql pgsql
# fallback, bypassing the runner:
docker compose run --rm app vendor/bin/phpunit -c resources/phpunit.mysql.xml
docker compose run --rm app vendor/bin/phpunit -c resources/phpunit.pgsql.xml
```

## Before opening a pull request
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,49 @@ Talon::boot(Settings::fromArray([
]));
```

## Command line runner

`vendor/bin/talon` fronts PHPUnit per mapped suite:

```bash
vendor/bin/talon run # default suite (unit)
vendor/bin/talon run mysql
vendor/bin/talon run mysql pgsql
vendor/bin/talon run all # every mapped suite, sequentially
vendor/bin/talon suites # list mapped suites
```

With zero configuration, suites are discovered from `phpunit*.xml` files in the project
root and `resources/` (`phpunit.mysql.xml` becomes `mysql`; `phpunit.xml.dist` becomes
`unit`, the default). Projects that need php ini flags or env vars declare a `talon.php`
at the project root:

```php
return [
'php' => ['extension=ext/modules/phalcon.so'], // global ini flags, optional
'suites' => [
'unit' => ['config' => 'resources/phpunit.xml.dist'],
'mysql' => ['config' => 'resources/phpunit.mysql.xml'],
'pgsql' => ['config' => 'resources/phpunit.pgsql.xml'],
'sqlite' => ['config' => 'resources/phpunit.sqlite.xml'],
],
'default' => 'unit',
];
```

Per-suite keys: `config` (required), `php` (extra ini flags), `env` (extra env vars) and
`args` (default PHPUnit arguments) — suite entries merge over the global `php`/`env`.
Options are forwarded to PHPUnit starting at the first option talon does not recognize
itself, and everything after `--` is always forwarded verbatim:

```bash
vendor/bin/talon run unit -- --filter FooTest --testdox
```

Each suite runs as its own subprocess (per-suite extensions and env vars work), a single
suite's exit code is forwarded verbatim, and multiple suites exit with the maximum code
after a per-suite summary.

## Beyond PHPUnit

The traits are the core public API and carry no PHPUnit base-class requirement for their
Expand Down
31 changes: 31 additions & 0 deletions bin/talon
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php

/**
* This file is part of the Phalcon Talon.
*
* (c) Phalcon Team <team@phalcon.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

use Phalcon\Talon\Cli\Kernel;

// Dev checkout: bin/../vendor; installed dependency: vendor/phalcon/talon/bin -> vendor.
foreach ([dirname(__DIR__) . '/vendor/autoload.php', dirname(__DIR__, 3) . '/autoload.php'] as $autoload) {
if (file_exists($autoload)) {
require $autoload;

break;
}
}

if (!class_exists(Kernel::class)) {
fwrite(STDERR, 'talon: could not locate the composer autoloader.' . PHP_EOL);
exit(1);
}

exit((new Kernel())->handle($_SERVER['argv'] ?? []));
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"keywords": ["phalcon", "testing", "phpunit", "test", "harness"],
"require": {
"php": "^8.1",
"phalcon/cli-options-parser": "^2.0",
"symfony/browser-kit": "^6.4 || ^7.0",
"symfony/dom-crawler": "^6.4 || ^7.0"
},
Expand Down Expand Up @@ -34,6 +35,7 @@
"autoload-dev": {
"psr-4": { "Phalcon\\Talon\\Tests\\": "tests/" }
},
"bin": ["bin/talon"],
"config": {
"sort-packages": true,
"allow-plugins": {
Expand All @@ -49,9 +51,9 @@
"cs-fix": "phpcbf --standard=resources/phpcs.xml",
"cs-fixer": "php-cs-fixer fix --config=resources/php-cs-fixer.php --dry-run --diff",
"cs-fixer-fix": "php-cs-fixer fix --config=resources/php-cs-fixer.php",
"test": "phpunit -c resources/phpunit.xml.dist",
"test-coverage": "phpunit -c resources/phpunit.xml.dist --coverage-clover tests/_output/coverage.xml",
"test-coverage-html": "phpunit -c resources/phpunit.xml.dist --coverage-html tests/_output/coverage",
"test": "@php bin/talon run",
"test-coverage": "@php bin/talon run unit -- --coverage-clover tests/_output/coverage.xml",
"test-coverage-html": "@php bin/talon run unit -- --coverage-html tests/_output/coverage",
"test-mutation": "infection --configuration=resources/infection.json5 --threads=max"
}
}
82 changes: 81 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions resources/infection.json5
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,28 @@
},
"mutators": {
"@default": true,
"ArrayItemRemoval": {
// STDIN in the descriptor spec is interactive TTY passthrough; a
// self-hosted test cannot observe it without owning the parent's
// stdio, which PHPUnit does.
"ignore": ["Phalcon\\Talon\\Cli\\ProcessRunner::open"]
},
"CastBool": {
"ignore": [
// Allowlisted flags parse to boolean true and the fallback is
// a bool literal; the cast is defensive only.
"Phalcon\\Talon\\Cli\\Input::wantsHelp",
"Phalcon\\Talon\\Cli\\Input::wantsVersion"
]
},
"CastString": {
"ignore": [
// Discovered suite names are non-numeric filename stems and
// preg_replace with a fixed valid pattern never returns null;
// these casts only satisfy static analysis. Method-scoped:
// each method's only cast is the defensive one.
"Phalcon\\Talon\\Cli\\SuiteMap::discover",
"Phalcon\\Talon\\Cli\\SuiteMap::suiteNameFor",
// The (string) cast result is only used as an array key; PHP
// normalizes numeric-string keys back to int, so it is a no-op.
"Phalcon\\Talon\\Settings::sectionOfArrays",
Expand All @@ -28,6 +48,19 @@
"Phalcon\\Talon\\Browser\\Client::normalizeResponse::160"
]
},
"Coalesce": {
"ignore": [
// The long/short option keys are only ever true or absent,
// so the coalesce order is unobservable.
"Phalcon\\Talon\\Cli\\Input::wantsHelp",
"Phalcon\\Talon\\Cli\\Input::wantsVersion"
]
},
"DecrementInteger": {
// The suite list is never empty and exit codes are >= 0, so
// any negative initial max() seed is unobservable.
"ignore": ["Phalcon\\Talon\\Cli\\Command\\RunCommand::execute::66"]
},
"FunctionCallRemoval": {
// xdebug is not loaded in the test images (pcov is);
// ini_set('xdebug.*') is a silent no-op there, so whether any
Expand Down
1 change: 1 addition & 0 deletions resources/phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<arg value="-colors"/>
<arg name="extensions" value="php"/>
<rule ref="PSR12"/>
<file>../bin</file>
<file>../src</file>
<file>../tests</file>
<!-- Mutation runs leave crash debris here that breaks traversal. -->
Expand Down
Loading
Loading