Skip to content

Commit

Permalink
Remove common prefixes and suffixes from actual and expected single-l…
Browse files Browse the repository at this point in the history
…ine strings
  • Loading branch information
staabm committed Oct 29, 2024
1 parent 5ef523a commit dc7b864
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/ScalarComparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0,
}

if ($expectedToCompare !== $actualToCompare && is_string($expected) && is_string($actual)) {
[$expected, $actual] = StringUtil::removeOverlongCommonPrefix($expected, $actual);

throw new ComparisonFailure(
$expected,
$actual,
Expand Down
55 changes: 55 additions & 0 deletions src/StringUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php declare(strict_types=1);
/*
* This file is part of sebastian/comparator.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Comparator;

use function str_replace;
use function strlen;
use function substr;

/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class StringUtil
{
private const OVERLONG_PREFIX_THRESHOLD = 40;
private const KEEP_PREFIX_CHARS = 15;

/**
* @return array{string, string}
*/
public static function removeOverlongCommonPrefix(string $string1, string $string2): array
{
$commonPrefix = self::findCommonPrefix($string1, $string2);

if (strlen($commonPrefix) > self::OVERLONG_PREFIX_THRESHOLD) {
$string1 = str_replace(substr($commonPrefix, 0, -self::KEEP_PREFIX_CHARS), '...', $string1);
$string2 = str_replace(substr($commonPrefix, 0, -self::KEEP_PREFIX_CHARS), '...', $string2);
}

return [$string1, $string2];
}

private static function findCommonPrefix(string $string1, string $string2): string
{
$prefix = '';

for ($i = 0; $i < strlen($string1); $i++) {
if (!isset($string2[$i]) || $string1[$i] != $string2[$i]) {
break;
}

$prefix .= $string1[$i];
}

return $prefix;
}
}
56 changes: 56 additions & 0 deletions tests/unit/ArrayComparatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,41 @@ public static function assertEqualsFailsProvider(): array
];
}

/**
* @return non-empty-list<array{0: string, 1: array, 2: array, 3?: float, 4?: bool}>
*/
public static function assertEqualsFailsWithDiffProvider(): array
{
return [
[
"
--- Expected
+++ Actual
@@ @@
Array (
- 0 => 'Too short to cut XYZ'
+ 0 => 'Too short to cut HERE'
)
",
['Too short to cut XYZ'],
['Too short to cut HERE'],
],
[
"
--- Expected
+++ Actual
@@ @@
Array (
- 0 => '...important clue XYZ and more behind'
+ 0 => '...important clue HERE and more behind'
)
",
['Some really long string that just keeps going and going and going but contains important clue XYZ and more behind'],
['Some really long string that just keeps going and going and going but contains important clue HERE and more behind'],
],
];
}

protected function setUp(): void
{
$this->comparator = new ArrayComparator;
Expand Down Expand Up @@ -178,4 +213,25 @@ public function testAssertEqualsFails(array $expected, array $actual, float $del

$this->comparator->assertEquals($expected, $actual, $delta, $canonicalize);
}

/**
* @param array<mixed> $expected
* @param array<mixed> $actual
*/
#[DataProvider('assertEqualsFailsWithDiffProvider')]
public function testAssertEqualsFailsWithDiff(
string $expectedDiff,
array $expected,
array $actual,
float $delta = 0.0,
bool $canonicalize = false
): void {
try {
$this->comparator->assertEquals($expected, $actual, $delta, $canonicalize);
$this->fail('Expected ComparisonFailure not thrown');
} catch (ComparisonFailure $e) {
$this->assertEquals('Failed asserting that two arrays are equal.', $e->getMessage());
$this->assertEquals($expectedDiff, $e->getDiff());
}
}
}
54 changes: 54 additions & 0 deletions tests/unit/ScalarComparatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,48 @@ public static function assertEqualsFailsProvider(): array
];
}

/**
* @return non-empty-list<array{0: string, 1: string, 2: string}>
*/
public static function assertEqualsFailsWithDiffProvider(): array
{
return [
[
"
--- Expected
+++ Actual
@@ @@
-'string'
+'other string'
",
'string',
'other string',
],
[
"
--- Expected
+++ Actual
@@ @@
-'...ch will be cut HERE some trailer'
+'...ch will be cut XYZ some trailer'
",
'too too too long string which will be cut HERE some trailer',
'too too too long string which will be cut XYZ some trailer',
],
[
"
--- Expected
+++ Actual
@@ @@
-'...ch will be cut HERE some llooooooooonnng llooooooooonnng llooooooooonnng llooooooooonnng trailer'
+'...ch will be cut XYZ some llooooooooonnng llooooooooonnng llooooooooonnng llooooooooonnng trailer'
",
'too too too long string which will be cut HERE some llooooooooonnng llooooooooonnng llooooooooonnng llooooooooonnng trailer',
'too too too long string which will be cut XYZ some llooooooooonnng llooooooooonnng llooooooooonnng llooooooooonnng trailer',
],
];
}

#[DataProvider('acceptsSucceedsProvider')]
public function testAcceptsSucceeds(mixed $expected, mixed $actual): void
{
Expand Down Expand Up @@ -160,4 +202,16 @@ public function testAssertEqualsFails(mixed $expected, mixed $actual, string $me

(new ScalarComparator)->assertEquals($expected, $actual);
}

#[DataProvider('assertEqualsFailsWithDiffProvider')]
public function testAssertEqualsFailsWithDiff(string $expectedDiff, string $expected, string $actual): void
{
try {
(new ScalarComparator)->assertEquals($expected, $actual);
$this->fail('Expected ComparisonFailure not thrown');
} catch (ComparisonFailure $e) {
$this->assertEquals('Failed asserting that two strings are equal.', $e->getMessage());
$this->assertEquals($expectedDiff, $e->getDiff());
}
}
}

0 comments on commit dc7b864

Please sign in to comment.