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
10 changes: 10 additions & 0 deletions Tests/Fixtures/TestCaseTrait/configTestData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

return [
'test_data' => [
[
'input' => 'foo',
'expected' => 'bar',
],
],
];
10 changes: 10 additions & 0 deletions Tests/Fixtures/TestCaseTrait/loadTestDataConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

return [
'structure' => [
'foo' => 'bar',
],
'test_data' => [
'baz' => 'qux',
],
];
18 changes: 18 additions & 0 deletions Tests/Unit/TestCaseTrait/TestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace WPMedia\PHPUnit\Tests\Unit\TestCaseTrait;

use WPMedia\PHPUnit\Unit\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase {
}

/**
* Concrete class declared in this file on purpose: {@see \WPMedia\PHPUnit\TestCaseTrait::loadTestDataConfig()}
* resolves the fixture path from the class's own file location, and no `TestCase.php` fixture exists under
* `Tests/Fixtures/TestCaseTrait/`. Used by `Test_LoadTestDataConfig` to cover the "no matching fixture" case.
*/
class NoFixtureTestCase extends TestCase {
}
45 changes: 45 additions & 0 deletions Tests/Unit/TestCaseTrait/configTestData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace WPMedia\PHPUnit\Tests\Unit\TestCaseTrait;

/**
* @covers \WPMedia\PHPUnit\TestCaseTrait::configTestData
* @group TestCaseTrait
*/
class Test_ConfigTestData extends TestCase {

public function testShouldReturnTestDataKeyWhenPresentInFixture() {
$this->assertSame(
[
[
'input' => 'foo',
'expected' => 'bar',
],
],
$this->configTestData()
);
}

public function testShouldReturnWholeConfigWhenTestDataKeyIsAbsent() {
$this->config = [
'foo' => 'bar',
];

$this->assertSame( [ 'foo' => 'bar' ], $this->configTestData() );
}

public function testShouldNotReloadConfigWhenAlreadyPopulated() {
// First call: lazily loads the fixture.
$this->configTestData();

// Overwrite with a sentinel value that has no `test_data` key.
$this->config = [
'sentinel' => true,
];

// Second call must not reload from the fixture, since $config is no longer empty.
$this->assertSame( [ 'sentinel' => true ], $this->configTestData() );
}
}
37 changes: 37 additions & 0 deletions Tests/Unit/TestCaseTrait/loadTestDataConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace WPMedia\PHPUnit\Tests\Unit\TestCaseTrait;

/**
* @covers \WPMedia\PHPUnit\TestCaseTrait::loadTestDataConfig
* @group TestCaseTrait
*/
class Test_LoadTestDataConfig extends TestCase {

public function testShouldPopulateConfigFromMatchingFixture() {
$this->loadTestDataConfig();

$this->assertSame(
[
'structure' => [
'foo' => 'bar',
],
'test_data' => [
'baz' => 'qux',
],
],
$this->config
);
}

public function testShouldSetEmptyConfigWhenNoMatchingFixtureFileExists() {
$target = new NoFixtureTestCase();

$method = $this->get_reflective_method( 'loadTestDataConfig', NoFixtureTestCase::class );
$method->invoke( $target );

$this->assertSame( [], $this->getNonPublicPropertyValue( 'config', NoFixtureTestCase::class, $target ) );
}
}
33 changes: 33 additions & 0 deletions src/TestCaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionObject;
use ReflectionProperty;

trait TestCaseTrait {
Expand All @@ -33,6 +34,38 @@ protected function getTestData( $dir, $filename ) { // phpcs:ignore WordPress.Na
: [];
}

/**
* Structure + test data configuration, lazily loaded by {@see configTestData()}.
*
* @var array
*/
protected $config = [];

/**
* Test Data Provider that uses the `'test_data'` key of the config file matching the test class,
* lazily loading it on first use.
*
* @return array
*/
public function configTestData() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid -- Public API method; renaming would be a breaking change for consumers.
if ( empty( $this->config ) ) {
$this->loadTestDataConfig();
}

return $this->config['test_data'] ?? $this->config;
}

/**
* Loads the test data config file matching the current test class name and location.
*
* @return void
*/
protected function loadTestDataConfig() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid -- Public API method; renaming would be a breaking change for consumers.
$file = ( new ReflectionObject( $this ) )->getFileName();

$this->config = $this->getTestData( dirname( $file ), basename( $file, '.php' ) );
}

/**
* Get reflective access to the private/protected method.
*
Expand Down
Loading