Skip to content
This repository was archived by the owner on Feb 14, 2023. It is now read-only.

Commit e9653f9

Browse files
staabmclxmstaab
andauthored
added CrossOsAgnosticComparator (#11)
Co-authored-by: Markus Staab <[email protected]>
1 parent 71f100c commit e9653f9

File tree

6 files changed

+258
-10
lines changed

6 files changed

+258
-10
lines changed

README.md

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,137 @@
11
# PHPUnit Tools to ease cross operating system Testing
22

3-
## make `assertEquals*` comparisons end-of-line (aka `PHP_EOL`) character agnostic
3+
## non-invasive method
4+
5+
A method which makes cross-os assertions obvious.
6+
7+
### make `assertEquals*` comparisons end-of-line (aka `PHP_EOL`) character agnostic
8+
9+
Make use of [`CrossOsAgnosticComparator`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/CrossOsAgnosticComparator.php) to make your regular `assert*`-calls aware of [`EolAgnosticString`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/EolAgnosticString.php) as a expected type.
10+
11+
```php
12+
use SebastianBergmann\Comparator\Factory;
13+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticComparator;
14+
use staabm\PHPUnitCrossOs\Comparator\EolAgnosticString;
15+
16+
final class MyTestCase extends TestCase {
17+
18+
/**
19+
* @var CrossOsAgnosticComparator
20+
*/
21+
private $comparator;
22+
23+
public function setUp(): void
24+
{
25+
$this->comparator = new CrossOsAgnosticComparator();
26+
27+
$factory = Factory::getInstance();
28+
$factory->register($this->comparator);
29+
}
30+
31+
public function tearDown(): void
32+
{
33+
$factory = Factory::getInstance();
34+
$factory->unregister($this->comparator);
35+
}
36+
37+
public function testStringsAreEqual() {
38+
// this assertion will be considered successfull
39+
self::assertEquals(new EolAgnosticString("hello\nworld"), "hello\r\nworld");
40+
// works also for assertEquals* variants
41+
self::assertEqualsIgnoringCase(new EolAgnosticString("hello\nworld"), "hello\r\nWORLD");
42+
}
43+
44+
}
45+
```
46+
47+
### make `assertEquals*` comparisons directory-separator (aka `DIRECTORY_SEPARATOR`) character agnostic
48+
49+
Make use of [`CrossOsAgnosticComparator`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/CrossOsAgnosticComparator.php) to make your regular `assert*`-calls aware of [`DirSeparatorAgnosticString`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/DirSeparatorAgnosticString.php) as a expected type.
50+
51+
```php
52+
use SebastianBergmann\Comparator\Factory;
53+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticComparator;
54+
use staabm\PHPUnitCrossOs\Comparator\DirSeparatorAgnosticString;
55+
56+
final class MyTestCase extends TestCase {
57+
58+
/**
59+
* @var CrossOsAgnosticComparator
60+
*/
61+
private $comparator;
62+
63+
public function setUp(): void
64+
{
65+
$this->comparator = new CrossOsAgnosticComparator();
66+
67+
$factory = Factory::getInstance();
68+
$factory->register($this->comparator);
69+
}
70+
71+
public function tearDown(): void
72+
{
73+
$factory = Factory::getInstance();
74+
$factory->unregister($this->comparator);
75+
}
76+
77+
public function testStringsAreEqual() {
78+
// this assertion will be considered successfull
79+
self::assertEquals(new DirSeparatorAgnosticString("hello\\world"), "hello/world");
80+
// works also for assertEquals* variants
81+
self::assertEqualsIgnoringCase(new DirSeparatorAgnosticString("hello\\world"), "hello/WORLD");
82+
}
83+
84+
}
85+
```
86+
87+
88+
### make `assertEquals*` comparisons cross os agnostic
89+
90+
Make use of [`CrossOsAgnosticComparator`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/CrossOsAgnosticComparator.php) to make your regular `assert*`-calls aware of [`CrossOsAgnosticString`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/CrossOsAgnosticString.php) as a expected type.
91+
92+
```php
93+
use SebastianBergmann\Comparator\Factory;
94+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticComparator;
95+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticString;
96+
97+
final class MyTestCase extends TestCase {
98+
99+
/**
100+
* @var CrossOsAgnosticComparator
101+
*/
102+
private $comparator;
103+
104+
public function setUp(): void
105+
{
106+
$this->comparator = new CrossOsAgnosticComparator();
107+
108+
$factory = Factory::getInstance();
109+
$factory->register($this->comparator);
110+
}
111+
112+
public function tearDown(): void
113+
{
114+
$factory = Factory::getInstance();
115+
$factory->unregister($this->comparator);
116+
}
117+
118+
public function testStringsAreEqual() {
119+
// this assertion will be considered successfull
120+
self::assertEquals(new CrossOsAgnosticString("hello\\world"), "hello/world");
121+
// works also for assertEquals* variants
122+
self::assertEqualsIgnoringCase(new CrossOsAgnosticString("hello\\world"), "hello/WORLD");
123+
}
124+
125+
}
126+
```
127+
128+
129+
## invasive method
130+
131+
A method to test cross-os related stuff using php builtin assertions.
132+
You may not like it, because it makes your test feels kind of magical as your `assertEquals()` calls will behave differently based on the given parameters.
133+
134+
### make `assertEquals*` comparisons end-of-line (aka `PHP_EOL`) character agnostic
4135

5136
Make use of [`EolAgnosticStringComparator`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/EolAgnosticStringComparator.php) to make your regular `assert*`-calls succeed even if the compared string differ in end-of-line characters:
6137

@@ -39,7 +170,7 @@ final class MyTestCase extends TestCase {
39170
}
40171
```
41172

42-
## make `assertEquals*` comparisons directory-separator (aka `DIRECTORY_SEPARATOR`) character agnostic
173+
### make `assertEquals*` comparisons directory-separator (aka `DIRECTORY_SEPARATOR`) character agnostic
43174

44175
Make use of [`DirSeparatorAgnosticStringComparator.php`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/DirSeparatorAgnosticStringComparator.php.php) to make your regular `assert*`-calls succeed even if the compared string differ in directory-separation characters:
45176

@@ -79,7 +210,7 @@ final class MyTestCase extends TestCase {
79210
```
80211

81212

82-
## make `assertEquals*` comparisons cross os agnostic
213+
### make `assertEquals*` comparisons cross os agnostic
83214

84215
Make use of [`CrossOsAgnosticStringComparatorFunctionalTest.php`](https://github.com/staabm/phpunit-cross-os/blob/main/lib/Comparator/CrossOsAgnosticStringComparatorFunctionalTest.php.php) to make your regular `assert*`-calls succeed even if the compared string differ in directory-separation and/or end-of-line characters:
85216

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace staabm\PHPUnitCrossOs\Comparator;
4+
5+
use function PHPUnit\Framework\assertIsString;
6+
use function PHPUnit\Framework\assertTrue;
7+
use SebastianBergmann\Comparator\Comparator;
8+
use SebastianBergmann\Comparator\ComparisonFailure;
9+
10+
final class CrossOsAgnosticComparator extends Comparator
11+
{
12+
public function accepts($expected, $actual)
13+
{
14+
return ($expected instanceof CrossOsAgnosticString || $expected instanceof EolAgnosticString || $expected instanceof DirSeparatorAgnosticString) && \is_string($actual);
15+
}
16+
17+
/**
18+
* @return void
19+
*/
20+
public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false)
21+
{
22+
assertTrue($expected instanceof CrossOsAgnosticString || $expected instanceof EolAgnosticString || $expected instanceof DirSeparatorAgnosticString);
23+
assertIsString($actual);
24+
25+
$expected = $expected->getNormalized();
26+
$actual = new CrossOsAgnosticString($actual);
27+
$actual = $actual->getNormalized();
28+
29+
if ($ignoreCase) {
30+
if (0 !== strcasecmp($expected, $actual)) {
31+
throw new ComparisonFailure($expected, $actual, $expected, $actual);
32+
}
33+
} else {
34+
if (0 !== strcmp($expected, $actual)) {
35+
throw new ComparisonFailure($expected, $actual, $expected, $actual);
36+
}
37+
}
38+
}
39+
}

lib/Comparator/CrossOsAgnosticString.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@ public function __construct(string $string)
1414
$this->string = $string;
1515
}
1616

17-
public function getNormalized():string
17+
public function getNormalized(): string
1818
{
19-
$s = str_replace('\\', '/', $this->string);
20-
$s = str_replace("\r\n", "\n", $s);
21-
22-
return $s;
19+
return str_replace(["\r\n", '\\'], ["\n", '/'], $this->string);
2320
}
2421
}

lib/Comparator/DirSeparatorAgnosticString.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public function __construct(string $string)
1414
$this->string = $string;
1515
}
1616

17-
public function getNormalized():string
17+
public function getNormalized(): string
1818
{
1919
return str_replace('\\', '/', $this->string);
2020
}

lib/Comparator/EolAgnosticString.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public function __construct(string $string)
1414
$this->string = $string;
1515
}
1616

17-
public function getNormalized():string
17+
public function getNormalized(): string
1818
{
1919
return str_replace("\r\n", "\n", $this->string);
2020
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace staabm\Tests\PHPUnitCrossOs\Comparator;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use SebastianBergmann\Comparator\ComparisonFailure;
7+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticComparator;
8+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticString;
9+
use staabm\PHPUnitCrossOs\Comparator\CrossOsAgnosticStringComparator;
10+
use staabm\PHPUnitCrossOs\Comparator\DirSeparatorAgnosticString;
11+
use staabm\PHPUnitCrossOs\Comparator\DirSeparatorAgnosticStringComparator;
12+
use staabm\PHPUnitCrossOs\Comparator\EolAgnosticString;
13+
14+
final class CrossOsAgnosticComparatorTest extends TestCase {
15+
public function dataEqualProvider() {
16+
$eolTest = new EolAgnosticStringComparatorTest();
17+
$dirSepTest = new DirSeparatorAgnosticStringComparatorTest();
18+
19+
foreach($eolTest->dataEqualProvider() as $data) {
20+
[$expected, $actual, $ignoreCase] = $data;
21+
$expected = new EolAgnosticString($expected);
22+
yield [$expected, $actual, $ignoreCase];
23+
}
24+
foreach($dirSepTest->dataEqualProvider() as $data) {
25+
[$expected, $actual, $ignoreCase] = $data;
26+
$expected = new DirSeparatorAgnosticString($expected);
27+
yield [$expected, $actual, $ignoreCase];
28+
}
29+
30+
foreach($eolTest->dataEqualProvider() as $data) {
31+
[$expected, $actual, $ignoreCase] = $data;
32+
$expected = new CrossOsAgnosticString($expected);
33+
yield [$expected, $actual, $ignoreCase];
34+
}
35+
foreach($dirSepTest->dataEqualProvider() as $data) {
36+
[$expected, $actual, $ignoreCase] = $data;
37+
$expected = new CrossOsAgnosticString($expected);
38+
yield [$expected, $actual, $ignoreCase];
39+
}
40+
41+
yield [new CrossOsAgnosticString("hello\r\nworld/subdir"),"hello\nworld\\subdir", false];
42+
}
43+
44+
/**
45+
* @dataProvider dataEqualProvider
46+
*/
47+
public function testEqualComparator($expected, $actual, bool $ignoreCase) {
48+
$comparator = new CrossOsAgnosticComparator();
49+
self::assertTrue($comparator->accepts($expected, $actual));
50+
$comparator->assertEquals($expected, $actual, 0.0, false, $ignoreCase);
51+
}
52+
53+
public function dataComparisonFailure() {
54+
$eolTest = new EolAgnosticStringComparatorTest();
55+
$dirSepTest = new DirSeparatorAgnosticStringComparatorTest();
56+
57+
foreach([CrossOsAgnosticString::class, EolAgnosticString::class, DirSeparatorAgnosticString::class] as $stringClass) {
58+
foreach($eolTest->dataComparisonFailure() as $data) {
59+
[$expected, $actual, $ignoreCase] = $data;
60+
$expected = new $stringClass($expected);
61+
yield [$expected, $actual, $ignoreCase];
62+
}
63+
foreach($dirSepTest->dataComparisonFailure() as $data) {
64+
[$expected, $actual, $ignoreCase] = $data;
65+
$expected = new $stringClass($expected);
66+
yield [$expected, $actual, $ignoreCase];
67+
}
68+
}
69+
}
70+
71+
/**
72+
* @dataProvider dataComparisonFailure
73+
*/
74+
public function testComparisonFailure($expected, $actual, bool $ignoreCase) {
75+
self::expectException(ComparisonFailure::class);
76+
77+
$comparator = new CrossOsAgnosticComparator();
78+
self::assertTrue($comparator->accepts($expected, $actual));
79+
$comparator->assertEquals($expected, $actual, 0.0, false, $ignoreCase);
80+
}
81+
}

0 commit comments

Comments
 (0)