Skip to content

Commit

Permalink
Increase test coverage
Browse files Browse the repository at this point in the history
* Removed matcher-checks for phpspec 2
* Improved performance by limiting `debug_backtrace`
  • Loading branch information
jaylinski committed Jan 20, 2021
1 parent 72f7ad2 commit 218bcad
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 57 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/coverage
/vendor
.phpunit.result.cache
composer.lock
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
],
"autoload": {
"files": [
"expect.php"
"src/expect.php"
],
"psr-4": {
"FriendsOfPhpSpec\\PhpSpec\\Expect\\": "src/"
Expand All @@ -27,8 +27,9 @@
"squizlabs/php_codesniffer": "^3.5"
},
"scripts": {
"lint": "phpcs --standard=PSR12 src expect.php",
"test": "phpunit"
"lint": "phpcs --standard=PSR12 src",
"test": "phpunit",
"coverage": "phpunit --coverage-html coverage --coverage-filter src"
},
"config": {
"sort-packages": true
Expand Down
16 changes: 5 additions & 11 deletions expect.php → src/expect.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function expect($sus): Subject
$reflectionFactory = new ReflectionFactory();
$exampleNode = new ExampleNode('expect', new \ReflectionFunction(__FUNCTION__));

$matchers = new MatcherManager($presenter);
$matchers = new MatcherManager($presenter);
$matchers->add(new Matcher\IdentityMatcher($presenter));
$matchers->add(new Matcher\ComparisonMatcher($presenter));
$matchers->add(new Matcher\ThrowMatcher($unwrapper, $presenter, $reflectionFactory));
Expand All @@ -56,17 +56,11 @@ function expect($sus): Subject
$matchers->add(new Matcher\StringEndMatcher($presenter));
$matchers->add(new Matcher\StringRegexMatcher($presenter));
$matchers->add(new Matcher\StringContainMatcher($presenter));
if (class_exists('PhpSpec\Matcher\TriggerMatcher')) {
$matchers->add(new Matcher\TriggerMatcher($unwrapper));
}
if (class_exists('PhpSpec\Matcher\IterateAsMatcher')) {
$matchers->add(new Matcher\IterateAsMatcher($presenter));
}
if (class_exists('PhpSpec\Matcher\ApproximatelyMatcher')) {
$matchers->add(new Matcher\ApproximatelyMatcher($presenter));
}
$matchers->add(new Matcher\TriggerMatcher($unwrapper));
$matchers->add(new Matcher\IterateAsMatcher($presenter));
$matchers->add(new Matcher\ApproximatelyMatcher($presenter));

$trace = debug_backtrace();
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
if (isset($trace[1]['object'])) {
$object = $trace[1]['object'];

Expand Down
135 changes: 92 additions & 43 deletions tests/ExpectTest.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
<?php

include __DIR__ . '/Foo.php';
include __DIR__ . '/FooMatcher.php';

use PhpSpec\Exception\Exception as PhpSpecException;
use PhpSpec\Matcher\MatchersProvider;
use PHPUnit\Framework\TestCase;

class ExpectTest extends TestCase
class ExpectTest extends TestCase implements MatchersProvider
{
private $addInvalidMatcher;

function setUp(): void
{
$this->addInvalidMatcher = false;
}

/**
* @test
* @dataProvider correctExpectations
Expand All @@ -27,30 +36,62 @@ function it_throws_when_expectation_is_not_met($expectation)
$expectation();
}

/**
* @test
*/
function it_throws_when_custom_matcher_does_not_implement_correct_interface()
{
$this->expectException(RuntimeException::class);
$this->addInvalidMatcher = true;
expect(1)->toBe(1);
}

/**
* @test
*/
function it_can_be_deactivated()
{
// Active by default
$this->assertTrue(e710d4e7_friends_of_phpspec_use_expect());

putenv('PHPSPEC_DISABLE_EXPECT=1');
$this->assertFalse(e710d4e7_friends_of_phpspec_use_expect());

putenv('PHPSPEC_DISABLE_EXPECT=');
$this->assertTrue(e710d4e7_friends_of_phpspec_use_expect());

define('PHPSPEC_DISABLE_EXPECT', true);
$this->assertFalse(e710d4e7_friends_of_phpspec_use_expect());
}

/**
* Cases that should evaluate without an exception
*/
function correctExpectations()
{
return [
[ function () { expect(5)->toBe(5); } ],
[ function () { expect(5)->toBeLike('5'); } ],
[ function () { expect((new Foo()))->toHaveType('Foo'); } ],
[ function () { expect((new Foo()))->toHaveCount(1); } ],
[ function () { expect((new Foo()))->toBeFoo(); } ],
[ function () { expect((new Foo())->getArray())->toBeArray(); } ],
[ function () { expect((new Foo())->getString())->toBeString(); } ],
[ function () { expect(['foo'])->toContain('foo'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKey('foo'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKeyWithValue('foo','bar'); } ],
[ function () { expect('foo bar')->toContain('bar'); } ],
[ function () { expect('foo bar')->toStartWith('foo'); } ],
[ function () { expect('foo bar')->toEndWith('bar'); } ],
[ function () { expect('foo bar')->toMatch('/bar/'); } ],
[ function () { expect((new Foo()))->toThrow('InvalidArgumentException')->duringThrowException(); } ],
[ function () { method_exists(expect(''), 'toTrigger') && expect((new Foo()))->toTrigger(E_USER_DEPRECATED)->duringTriggerError(); } ],
[ function () { method_exists(expect(''), 'toBeApproximately') && expect(1.444447777)->toBeApproximately(1.444447777, 1.0e-9); } ],
[ function () { method_exists(expect(''), 'toIterateAs') && expect((new Foo())->getIterator())->toIterateAs(new \ArrayIterator(['Foo', 'Bar'])); } ],
[ function () { expect(5)->toBe(5); } ],
[ function () { expect(5)->notToBe(1); } ],
[ function () { expect(5)->toBeLike('5'); } ],
[ function () { expect((new Foo()))->toHaveType('Foo'); } ],
[ function () { expect((new Foo()))->toHaveCount(1); } ],
[ function () { expect((new Foo()))->toBeFoo(); } ],
[ function () { expect((new Foo())->getArray())->toBeArray(); } ],
[ function () { expect((new Foo())->getString())->toBeString(); } ],
[ function () { expect(['foo'])->toContain('foo'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKey('foo'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKeyWithValue('foo','bar'); } ],
[ function () { expect('foo bar')->toContain('bar'); } ],
[ function () { expect('foo bar')->toStartWith('foo'); } ],
[ function () { expect('foo bar')->toEndWith('bar'); } ],
[ function () { expect('foo bar')->toMatch('/bar/'); } ],
[ function () { expect((new Foo()))->toThrow('InvalidArgumentException')->duringThrowException(); } ],
[ function () { expect((new Foo()))->toTrigger(E_USER_DEPRECATED)->duringTriggerError(); } ],
[ function () { expect(1.444447777)->toBeApproximately(1.444447777, 1.0e-9); } ],
[ function () { expect((new Foo())->getIterator())->toIterateAs(new \ArrayIterator(['Foo', 'Bar'])); } ],
// Custom matchers
[ function () { expect(['foo' => 'bar'])->toHaveKey('foo'); } ],
[ function () { expect(1)->toHaveFoo(1); } ],
];
}

Expand All @@ -59,31 +100,39 @@ function correctExpectations()
*/
function incorrectExpectations()
{
$incorrectExpectations = [
[ function () { expect(6)->toBe(5); } ],
[ function () { expect(6)->toBeLike('5'); } ],
[ function () { expect((new Foo()))->toHaveType('Bar'); } ],
[ function () { expect((new Foo()))->toHaveCount(2); } ],
[ function () { expect((new Foo()))->toBeBar(); } ],
[ function () { expect((new Foo())->getString())->toBeArray(); } ],
[ function () { expect((new Foo())->getArray())->toBeString(); } ],
[ function () { expect(['foo'])->toContain('bar'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKey('bar'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKeyWithValue('foo','foo'); } ],
[ function () { expect('foo bar')->toContain('baz'); } ],
[ function () { expect('foo bar')->toStartWith('baz'); } ],
[ function () { expect('foo bar')->toEndWith('baz'); } ],
[ function () { expect('foo bar')->toMatch('/baz/'); } ],
[ function () { expect((new Foo()))->toThrow('AnotherException')->duringThrowException(); } ]
return [
[ function () { expect(6)->toBe(5); } ],
[ function () { expect(6)->notToBe(6); } ],
[ function () { expect(6)->toBeLike('5'); } ],
[ function () { expect((new Foo()))->toHaveType('Bar'); } ],
[ function () { expect((new Foo()))->toHaveCount(2); } ],
[ function () { expect((new Foo()))->toBeBar(); } ],
[ function () { expect((new Foo())->getString())->toBeArray(); } ],
[ function () { expect((new Foo())->getArray())->toBeString(); } ],
[ function () { expect(['foo'])->toContain('bar'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKey('bar'); } ],
[ function () { expect(['foo' => 'bar'])->toHaveKeyWithValue('foo','foo'); } ],
[ function () { expect('foo bar')->toContain('baz'); } ],
[ function () { expect('foo bar')->toStartWith('baz'); } ],
[ function () { expect('foo bar')->toEndWith('baz'); } ],
[ function () { expect('foo bar')->toMatch('/baz/'); } ],
[ function () { expect((new Foo()))->toThrow('AnotherException')->duringThrowException(); } ],
[ function () { expect(1.444447777)->toBeApproximately(1.444447778, 1.0e-9); } ],
[ function () { expect((new Foo())->getIterator())->toIterateAs(new \ArrayIterator(['Bar', 'Foo'])); } ],
];
}

if (method_exists(expect(''), 'toBeApproximately')) {
$incorrectExpectations[] = [function () { expect(1.444447777)->toBeApproximately(1.444447778, 1.0e-9); }];
}
if (method_exists(expect(''), 'toIterateAs')) {
$incorrectExpectations = [ function () { expect((new Foo())->getIterator())->toIterateAs(new \ArrayIterator(['Bar', 'Foo'])); } ];
}

return $incorrectExpectations;
/**
* Provide custom matchers
*
* @return array
*/
public function getMatchers(): array
{
return [
'haveKey' => function ($subject, $key) { return array_key_exists($key, $subject); },
'haveFoo' => new FooMatcher(),
'haveBar' => $this->addInvalidMatcher ? new stdClass() : new FooMatcher(),
];
}
}
30 changes: 30 additions & 0 deletions tests/FooMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

use PhpSpec\Exception\Example\FailureException;
use PhpSpec\Matcher\BasicMatcher;

/**
* Test fixture used in ExpectTest
*/
class FooMatcher extends BasicMatcher
{
public function supports(string $name, $subject, array $arguments): bool
{
return 'haveFoo' === $name;
}

protected function matches($subject, array $arguments): bool
{
return $subject === $arguments[0];
}

protected function getFailureException(string $name, $subject, array $arguments): FailureException
{
return new FailureException();
}

protected function getNegativeFailureException(string $name, $subject, array $arguments): FailureException
{
return new FailureException();
}
}

0 comments on commit 218bcad

Please sign in to comment.