Skip to content

Commit fd04b2b

Browse files
committed
feat(tests): Add TestSupport trait and corresponding test suite for inaccessible properties and methods.
1 parent b5613ed commit fd04b2b

File tree

4 files changed

+86
-65
lines changed

4 files changed

+86
-65
lines changed

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
- Invoke inaccessible methods to expand testing coverage.
2929

3030
**Cross-Platform String Assertions**
31-
- Eliminate false positives/negatives caused by Windows vs. Unix line-ending differences.
31+
- Eliminate false positives/negatives caused by windows vs. unix line ending differences.
3232
- Normalize line endings for consistent string comparisons across platforms.
3333

3434
**File System Test Management**
@@ -73,6 +73,33 @@ composer update
7373

7474
## Basic Usage
7575

76+
### Using TestSupport trait
77+
78+
```php
79+
<?php
80+
81+
declare(strict_types=1);
82+
83+
use PHPForge\Support\TestSupport;
84+
use PHPUnit\Framework\TestCase;
85+
86+
final class MyTest extends TestCase
87+
{
88+
use TestSupport;
89+
90+
public function testInaccessibleProperty()
91+
{
92+
$object = new class () {
93+
private string $secretValue = 'hidden';
94+
};
95+
96+
$value = $this->inaccessibleProperty($object, 'secretValue');
97+
98+
self::assertSame('hidden', $value);
99+
}
100+
}
101+
```
102+
76103
### Accessing private properties
77104

78105
```php

composer.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "php-forge/support",
33
"type": "library",
4-
"description": "Support library tests for PHP",
4+
"description": "Support utilities for enhanced testing capabilities.",
55
"keywords": [
66
"php",
77
"php-forge",
@@ -11,16 +11,16 @@
1111
],
1212
"license": "BSD-3-Clause",
1313
"require": {
14-
"php": "^8.1",
15-
"phpunit/phpunit": "^10.5"
14+
"php": "^8.1"
1615
},
1716
"require-dev": {
1817
"infection/infection": "^0.27|^0.31",
1918
"maglnet/composer-require-checker": "^4.7",
20-
"phpstan/phpstan-strict-rules": "^2.0.3",
21-
"symplify/easy-coding-standard": "^12.5",
2219
"phpstan/phpstan": "^2.1",
23-
"rector/rector": "^2.1"
20+
"phpstan/phpstan-strict-rules": "^2.0.3",
21+
"phpunit/phpunit": "^10.5",
22+
"rector/rector": "^2.1",
23+
"symplify/easy-coding-standard": "^12.5"
2424
},
2525
"autoload": {
2626
"psr-4": {

src/Assert.php renamed to src/TestSupport.php

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,20 @@
2020
use function unlink;
2121

2222
/**
23-
* Assertion utility class for advanced test introspection and manipulation.
23+
* Trait providing utilities for testing inaccessible properties, methods, and filesystem cleanup.
2424
*
25-
* Provides static helper methods for accessing and modifying inaccessible properties and methods invoking parent class
26-
* logic, and performing file system cleanup in test environments.
25+
* Supplies static helper methods for normalizing line endings, accessing or modifying private/protected properties and
26+
* methods (including those inherited from parent classes), invoking inaccessible methods, and recursively removing
27+
* files from directories.
2728
*
28-
* Extends {@see \PHPUnit\Framework\Assert} to offer additional capabilities for testing private/protected members and
29-
* for managing test artifacts, supporting robust and isolated unit tests.
29+
* These utilities are designed to facilitate comprehensive unit testing by enabling assertions and manipulations that
30+
* would otherwise be restricted by visibility constraints or platform differences.
3031
*
31-
* Key features.
32-
* - Access and modify inaccessible (private/protected) properties and methods via reflection.
33-
* - Invoke parent class methods and properties for testing inheritance scenarios.
34-
* - Normalize line endings for cross-platform string assertions.
35-
* - Remove files and directories recursively for test environment cleanup.
36-
*
37-
* @copyright Copyright (C) 2025 PHPForge.
32+
* @copyright Copyright (C) 2025 Terabytesoftw.
3833
* @license https://opensource.org/license/bsd-3-clause BSD 3-Clause License.
3934
*/
40-
final class Assert extends \PHPUnit\Framework\Assert
35+
trait TestSupport
4136
{
42-
/**
43-
* Asserts that two strings are equal after normalizing line endings to unix style ('\n').
44-
*
45-
* Replaces all windows style ('\r\n') line endings with unix style ('\n') in both the expected and actual strings
46-
* before performing the equality assertion.
47-
*
48-
* This ensures cross-platform consistency in string comparisons where line ending differences may otherwise cause
49-
* `false` negatives.
50-
*
51-
* @param string $expected Expected string value, with any line endings.
52-
* @param string $actual Actual string value, with any line endings.
53-
* @param string $message Optional failure message to display if the assertion fails. Default is an empty string.
54-
*/
55-
public static function equalsWithoutLE(string $expected, string $actual, string $message = ''): void
56-
{
57-
$expected = str_replace("\r\n", "\n", $expected);
58-
$actual = str_replace("\r\n", "\n", $actual);
59-
60-
self::assertEquals($expected, $actual, $message);
61-
}
62-
6337
/**
6438
* Retrieves the value of an inaccessible property from a parent class instance.
6539
*
@@ -185,6 +159,23 @@ public static function invokeParentMethod(
185159
return $result ?? null;
186160
}
187161

162+
/**
163+
* Normalizes line endings to unix style ('\n') for cross-platform string assertions.
164+
*
165+
* Converts windows style ('\r\n') line endings to unix style ('\n') to ensure consistent string comparisons across
166+
* different operating systems during testing.
167+
*
168+
* This method is useful for eliminating false negatives in assertions caused by platform-specific line endings.
169+
*
170+
* @param string $line Input string potentially containing windows style line endings.
171+
*
172+
* @return string String with normalized unix style line endings.
173+
*/
174+
public static function normalizeLineEndings(string $line): string
175+
{
176+
return str_replace("\r\n", "\n", $line);
177+
}
178+
188179
/**
189180
* Removes all files and directories recursively from the specified base path, excluding '.gitignore' and
190181
* '.gitkeep'.
Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,35 @@
44

55
namespace PHPForge\Support\Tests;
66

7-
use PHPForge\Support\Assert;
87
use PHPForge\Support\Tests\Stub\{TestBaseClass, TestClass};
8+
use PHPForge\Support\TestSupport;
99
use PHPUnit\Framework\TestCase;
1010
use ReflectionException;
1111
use RuntimeException;
1212

1313
/**
14-
* Test suite for {@see Assert} utility methods and reflection helpers.
14+
* Test suite for {@see TestSupport} trait utility methods.
1515
*
16-
* Verifies the behavior of assertion and reflection-based utility methods for testing inaccessible properties, parent
17-
* properties, and methods, as well as file system operations for test directories.
16+
* Verifies the behavior of utility methods provided by the {@see TestSupport} trait for testing inaccessible
17+
* properties, parent properties, and methods, as well as file system operations for test directories.
1818
*
1919
* These tests ensure correct access and mutation of private/protected members, invocation of inaccessible methods, and
2020
* robust file removal logic, including error handling for non-existent directories.
2121
*
22-
* Test coverage.
22+
* Test coverage:
2323
* - Accessing and asserting values of inaccessible properties and parent properties.
2424
* - Ensuring correct exception handling for invalid operations.
2525
* - Invoking inaccessible methods and parent methods.
26+
* - Normalizing line endings.
2627
* - Removing files from directories and handling missing directories.
2728
* - Setting values for inaccessible properties and parent properties.
2829
*
2930
* @copyright Copyright (C) 2025 Terabytesoftw.
3031
* @license https://opensource.org/license/bsd-3-clause BSD 3-Clause License.
3132
*/
32-
final class AssertTest extends TestCase
33+
final class TestSupportTest extends TestCase
3334
{
34-
public function testEqualsWithoutLEReturnsTrueWhenStringsAreIdenticalWithLineEndings(): void
35-
{
36-
Assert::equalsWithoutLE(
37-
"foo\r\nbar",
38-
"foo\r\nbar",
39-
"Should return 'true' when both strings are identical including line endings.",
40-
);
41-
}
35+
use TestSupport;
4236

4337
/**
4438
* @throws ReflectionException
@@ -47,7 +41,7 @@ public function testInaccessibleParentPropertyReturnsExpectedValue(): void
4741
{
4842
self::assertSame(
4943
'valueParent',
50-
Assert::inaccessibleParentProperty(
44+
self::inaccessibleParentProperty(
5145
new TestClass(),
5246
TestBaseClass::class,
5347
'propertyParent',
@@ -56,6 +50,15 @@ public function testInaccessibleParentPropertyReturnsExpectedValue(): void
5650
);
5751
}
5852

53+
public function testNormalizeLineEndingsWhenStringsAreIdenticalWithLineEndings(): void
54+
{
55+
self::assertSame(
56+
self::normalizeLineEndings("foo\r\nbar"),
57+
self::normalizeLineEndings("foo\r\nbar"),
58+
"Should return 'true' when both strings are identical including line endings.",
59+
);
60+
}
61+
5962
public function testRemoveFilesFromDirectoryRemovesAllFiles(): void
6063
{
6164
$dir = dirname(__DIR__) . '/runtime';
@@ -64,7 +67,7 @@ public function testRemoveFilesFromDirectoryRemovesAllFiles(): void
6467
touch("{$dir}/test.txt");
6568
touch("{$dir}/subdir/test.txt");
6669

67-
Assert::removeFilesFromDirectory($dir);
70+
self::removeFilesFromDirectory($dir);
6871

6972
$this->assertFileDoesNotExist(
7073
"{$dir}/test.txt",
@@ -83,7 +86,7 @@ public function testReturnInaccessiblePropertyValueWhenPropertyIsPrivate(): void
8386
{
8487
self::assertSame(
8588
'value',
86-
Assert::inaccessibleProperty(new TestClass(), 'property'),
89+
self::inaccessibleProperty(new TestClass(), 'property'),
8790
"Should return the value of the private property 'property' when accessed via reflection.",
8891
);
8992
}
@@ -95,7 +98,7 @@ public function testReturnValueWhenInvokingInaccessibleMethod(): void
9598
{
9699
$this->assertSame(
97100
'value',
98-
Assert::invokeMethod(new TestClass(), 'inaccessibleMethod'),
101+
self::invokeMethod(new TestClass(), 'inaccessibleMethod'),
99102
"Should return 'value' when invoking the inaccessible method 'inaccessibleParentMethod' on 'TestClass' " .
100103
'via reflection.',
101104
);
@@ -108,7 +111,7 @@ public function testReturnValueWhenInvokingInaccessibleParentMethod(): void
108111
{
109112
$this->assertSame(
110113
'valueParent',
111-
Assert::invokeParentMethod(
114+
self::invokeParentMethod(
112115
new TestClass(),
113116
TestBaseClass::class,
114117
'inaccessibleParentMethod',
@@ -125,11 +128,11 @@ public function testSetInaccessibleParentProperty(): void
125128
{
126129
$object = new TestClass();
127130

128-
Assert::setInaccessibleParentProperty($object, TestBaseClass::class, 'propertyParent', 'foo');
131+
self::setInaccessibleParentProperty($object, TestBaseClass::class, 'propertyParent', 'foo');
129132

130133
$this->assertSame(
131134
'foo',
132-
Assert::inaccessibleParentProperty($object, TestBaseClass::class, 'propertyParent'),
135+
self::inaccessibleParentProperty($object, TestBaseClass::class, 'propertyParent'),
133136
"Should return 'foo' after setting the parent property 'propertyParent' via " .
134137
"'setInaccessibleParentProperty' method.",
135138
);
@@ -142,11 +145,11 @@ public function testSetInaccessiblePropertySetsValueCorrectly(): void
142145
{
143146
$object = new TestClass();
144147

145-
Assert::setInaccessibleProperty($object, 'property', 'foo');
148+
self::setInaccessibleProperty($object, 'property', 'foo');
146149

147150
$this->assertSame(
148151
'foo',
149-
Assert::inaccessibleProperty($object, 'property'),
152+
self::inaccessibleProperty($object, 'property'),
150153
"Should return 'foo' after setting the private property 'property' via 'setInaccessibleProperty' method.",
151154
);
152155
}
@@ -156,6 +159,6 @@ public function testThrowRuntimeExceptionWhenRemoveFilesFromDirectoryNonExisting
156159
$this->expectException(RuntimeException::class);
157160
$this->expectExceptionMessage('Unable to open directory: non-existing-directory');
158161

159-
Assert::removeFilesFromDirectory(__DIR__ . '/non-existing-directory');
162+
self::removeFilesFromDirectory(__DIR__ . '/non-existing-directory');
160163
}
161164
}

0 commit comments

Comments
 (0)