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
38 changes: 38 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Tests

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']

name: PHP ${{ matrix.php }} - ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip
coverage: none

- name: Install xmlstarlet
run: sudo apt-get update && sudo apt-get install -y xmlstarlet

- name: Install dependencies
run: composer update --prefer-dist --no-progress

- name: Run test suite
run: ./vendor/bin/phpunit --testdox
32 changes: 32 additions & 0 deletions .github/workflows/update-changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "Update Changelog"

on:
release:
types: [released]

permissions:
contents: write

jobs:
update:
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: main

- name: Update Changelog
uses: stefanzweifel/changelog-updater-action@v1
with:
latest-version: ${{ github.event.release.name }}
release-notes: ${{ github.event.release.body }}

- name: Commit updated CHANGELOG
uses: stefanzweifel/git-auto-commit-action@v7
with:
branch: main
commit_message: Update CHANGELOG
file_pattern: CHANGELOG.md
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
vendor
.phpunit.cache
composer.lock
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ For XmlStarlet on other platforms, see [here](http://xmlstar.sourceforge.net/doc
./vendor/bin/phpunit-failed-runner
```

## Testing

This package includes a comprehensive test suite that demonstrates the incremental test-fixing workflow.

Run the test suite:

```bash
composer test
```

### Changelog

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
Expand Down
18 changes: 15 additions & 3 deletions bin/phpunit-failed-runner
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,30 @@ else
runner="./vendor/bin/phpunit"
fi

# Determine XSL path - check if we're in the package itself or using it as a dependency
if [ -f "./prune.xsl" ]; then
# We're in the package root
xsl_path="."
elif [ -f "./vendor/chrisdicarlo/phpunit-failed-runner/prune.xsl" ]; then
# We're using the package as a dependency
xsl_path="./vendor/chrisdicarlo/phpunit-failed-runner"
else
echo "Error: Cannot find XSL transformation files"
exit 1
fi

if test -f "$logfile"; then
echo -e "Logfile found. Searching for previously failing tests... \U23F3"

count_failed_tests="$(xmlstarlet tr ./vendor/chrisdicarlo/phpunit-failed-runner/prune.xsl junit.xml | xmlstarlet tr --omit-decl ./vendor/chrisdicarlo/phpunit-failed-runner/count-failed.xsl)"
count_failed_tests="$(xmlstarlet tr "$xsl_path/prune.xsl" junit.xml | xmlstarlet tr --omit-decl "$xsl_path/count-failed.xsl")"

if [ "$count_failed_tests" = "0" ]; then
echo -e "No failed tests! Great job! \U1F44D \U1F389"
rm "$logfile"
exit 0
else
echo -e "Found $count_failed_tests previously failing tests, filtering... \U1F97A"
filter=$(xmlstarlet tr ./vendor/chrisdicarlo/phpunit-failed-runner/prune.xsl junit.xml | xmlstarlet tr --omit-decl ./vendor/chrisdicarlo/phpunit-failed-runner/failed-tests.xsl); "$runner" --filter "$filter" --log-junit junit.xml
filter=$(xmlstarlet tr "$xsl_path/prune.xsl" junit.xml | xmlstarlet tr --omit-decl "$xsl_path/failed-tests.xsl"); "$runner" --filter "$filter" --log-junit junit.xml
fi
else
echo -e "Logfile not found. Running the test suite... \U1F91E"
Expand All @@ -29,7 +41,7 @@ else
fi

if test -f "$logfile"; then
count_failed_tests="$(xmlstarlet tr ./vendor/chrisdicarlo/phpunit-failed-runner/prune.xsl junit.xml | xmlstarlet tr --omit-decl ./vendor/chrisdicarlo/phpunit-failed-runner/count-failed.xsl)"
count_failed_tests="$(xmlstarlet tr "$xsl_path/prune.xsl" junit.xml | xmlstarlet tr --omit-decl "$xsl_path/count-failed.xsl")"

if [ "$count_failed_tests" = "0" ]; then
echo -e "No failed tests! Great job! \U1F44D \U1F389"
Expand Down
13 changes: 12 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,16 @@
],
"bin": [
"bin/phpunit-failed-runner"
]
],
"require-dev": {
"phpunit/phpunit": "^8.5|^9.6|^10.5|^11.0"
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"test": "phpunit"
}
}
21 changes: 21 additions & 0 deletions phpunit-integration-fixtures.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
failOnRisky="true"
failOnWarning="true"
cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="Fixture Tests for Integration Testing">
<file>tests/AlwaysPassingTest.php</file>
<file>tests/InitiallyFailingTest.php</file>
<file>tests/AnotherFailingTest.php</file>
</testsuite>
</testsuites>
<source>
<include>
<directory>bin</directory>
</include>
</source>
</phpunit>
20 changes: 20 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
failOnRisky="true"
failOnWarning="true"
cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="Test Suite">
<directory>tests</directory>
<exclude>tests/Fixtures</exclude>
</testsuite>
</testsuites>
<source>
<include>
<directory>bin</directory>
</include>
</source>
</phpunit>
26 changes: 26 additions & 0 deletions tests/AlwaysPassingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Tests;

use PHPUnit\Framework\TestCase;
use Tests\Fixtures\AlwaysPassingFixture;

class AlwaysPassingTest extends TestCase
{
public function test_always_passing_fixture_returns_true(): void
{
$fixture = new AlwaysPassingFixture();

$this->assertTrue(
$fixture->success(),
'AlwaysPassingFixture should always return true'
);
}

public function test_another_always_passing_test(): void
{
$fixture = new AlwaysPassingFixture();

$this->assertTrue($fixture->success());
}
}
19 changes: 19 additions & 0 deletions tests/AnotherFailingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Tests;

use PHPUnit\Framework\TestCase;
use Tests\Fixtures\AnotherFailingFixture;

class AnotherFailingTest extends TestCase
{
public function test_another_failing_fixture(): void
{
$fixture = new AnotherFailingFixture();

$this->assertTrue(
$fixture->success(),
'This test will also fail initially'
);
}
}
14 changes: 14 additions & 0 deletions tests/Fixtures/AlwaysPassingFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Tests\Fixtures;

/**
* Fixture class that always passes
*/
class AlwaysPassingFixture
{
public function success(): bool
{
return true;
}
}
16 changes: 16 additions & 0 deletions tests/Fixtures/AnotherFailingFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Tests\Fixtures;

/**
* Another fixture class that initially fails
* Change the return value from false to true to simulate fixing the test
*/
class AnotherFailingFixture
{
public function success(): bool
{
// CHANGEME: false = failing test, true = passing test
return true;
}
}
16 changes: 16 additions & 0 deletions tests/Fixtures/InitiallyFailingFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Tests\Fixtures;

/**
* Fixture class that initially fails but can be "fixed"
* Change the return value from false to true to simulate fixing the test
*/
class InitiallyFailingFixture
{
public function success(): bool
{
// CHANGEME: false = failing test, true = passing test
return true;
}
}
29 changes: 29 additions & 0 deletions tests/InitiallyFailingTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Tests;

use PHPUnit\Framework\TestCase;
use Tests\Fixtures\InitiallyFailingFixture;

class InitiallyFailingTest extends TestCase
{
public function test_initially_failing_fixture(): void
{
$fixture = new InitiallyFailingFixture();

$this->assertTrue(
$fixture->success(),
'This test will fail initially but pass after the fixture is fixed'
);
}

public function test_another_initially_failing_test(): void
{
$fixture = new InitiallyFailingFixture();

$this->assertTrue(
$fixture->success(),
'Another test that depends on the same fixture'
);
}
}
Loading