Uses Collision ^7.0

This commit is contained in:
Nuno Maduro
2022-09-15 01:07:15 +01:00
parent eab944023c
commit 3ff95faaaa
47 changed files with 646 additions and 308 deletions

View File

@ -9,7 +9,6 @@ it('has plugin')->assertTrue(class_exists(CoveragePlugin::class));
it('adds coverage if --coverage exist', function () {
$plugin = new CoveragePlugin(new ConsoleOutput());
$testSuite = TestSuite::getInstance();
expect($plugin->coverage)->toBeFalse();
$arguments = $plugin->handleArguments([]);

View File

@ -28,23 +28,23 @@ it('sets closures', function () {
yield [1];
});
expect(DatasetsRepository::resolve('foo', ['foo']))->toBe(['foo with (1)' => [1]]);
expect(DatasetsRepository::resolve('foo', ['foo']))->toBe(['(1)' => [1]]);
});
it('sets arrays', function () {
DatasetsRepository::set('bar', [[2]]);
expect(DatasetsRepository::resolve('bar', ['bar']))->toBe(['bar with (2)' => [2]]);
expect(DatasetsRepository::resolve('bar', ['bar']))->toBe(['(2)' => [2]]);
});
it('gets bound to test case object', function () {
it('gets bound to test case object', function ($value) {
$this->assertTrue(true);
})->with([['a'], ['b']]);
test('it truncates the description', function () {
expect(true)->toBe(true);
// it gets tested by the integration test
})->with([str_repeat('Fooo', 10000000)]);
})->with([str_repeat('Fooo', 10)]);
$state = new stdClass();
$state->text = '';
@ -233,8 +233,12 @@ test('more than two datasets did the job right', function () use ($state) {
it('can resolve a dataset after the test case is available', function ($result) {
expect($result)->toBe('bar');
})->with([
function () { return $this->foo; },
[function () { return $this->foo; }],
function () {
return $this->foo;
},
[function () {
return $this->foo;
}],
]);
it('can resolve a dataset after the test case is available with shared yield sets', function ($result) {
@ -249,38 +253,54 @@ it('resolves a potential bound dataset logically', function ($foo, $bar) {
expect($foo)->toBe('foo');
expect($bar())->toBe('bar');
})->with([
['foo', function () { return 'bar'; }], // This should be passed as a closure because we've passed multiple arguments
['foo', function () {
return 'bar';
}], // This should be passed as a closure because we've passed multiple arguments
]);
it('resolves a potential bound dataset logically even when the closure comes first', function ($foo, $bar) {
expect($foo())->toBe('foo');
expect($bar)->toBe('bar');
})->with([
[function () { return 'foo'; }, 'bar'], // This should be passed as a closure because we've passed multiple arguments
[function () {
return 'foo';
}, 'bar'], // This should be passed as a closure because we've passed multiple arguments
]);
it('will not resolve a closure if it is type hinted as a closure', function (Closure $data) {
expect($data())->toBeString();
})->with([
function () { return 'foo'; },
function () { return 'bar'; },
function () {
return 'foo';
},
function () {
return 'bar';
},
]);
it('will not resolve a closure if it is type hinted as a callable', function (callable $data) {
expect($data())->toBeString();
})->with([
function () { return 'foo'; },
function () { return 'bar'; },
function () {
return 'foo';
},
function () {
return 'bar';
},
]);
it('can correctly resolve a bound dataset that returns an array', function (array $data) {
expect($data)->toBe(['foo', 'bar', 'baz']);
})->with([
function () { return ['foo', 'bar', 'baz']; },
function () {
return ['foo', 'bar', 'baz'];
},
]);
it('can correctly resolve a bound dataset that returns an array but wants to be spread', function (string $foo, string $bar, string $baz) {
expect([$foo, $bar, $baz])->toBe(['foo', 'bar', 'baz']);
})->with([
function () { return ['foo', 'bar', 'baz']; },
function () {
return ['foo', 'bar', 'baz'];
},
]);

View File

@ -32,7 +32,9 @@ it('not catch exceptions if given condition is false', function () {
it('catch exceptions if given condition is true', function () {
throw new Exception('Something bad happened');
})->throwsIf(function () { return true; }, Exception::class);
})->throwsIf(function () {
return true;
}, Exception::class);
it('catch exceptions and messages if given condition is true', function () {
throw new Exception('Something bad happened');

View File

@ -40,8 +40,12 @@ it('works inside of each', function () {
it('works with sequence', function () {
expect(new HasMethods())
->books()->sequence(
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
function ($book) {
$book->title->toEqual('Foo')->cost->toEqual(20);
},
function ($book) {
$book->title->toEqual('Bar')->cost->toEqual(30);
},
);
});
@ -54,8 +58,12 @@ it('can compose complex expectations', function () {
->attributes()->toBeArray()
->books()->toBeArray->each->not->toBeEmpty
->books()->sequence(
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
function ($book) {
$book->title->toEqual('Foo')->cost->toEqual(20);
},
function ($book) {
$book->title->toEqual('Bar')->cost->toEqual(30);
},
);
});

View File

@ -9,8 +9,12 @@ it('can access methods and properties', function () {
})->books()->toBeArray()
->posts->toBeArray->each->not->toBeEmpty
->books()->sequence(
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
function ($book) {
$book->title->toEqual('Foo')->cost->toEqual(20);
},
function ($book) {
$book->title->toEqual('Bar')->cost->toEqual(30);
},
);
});
@ -53,7 +57,9 @@ it('can start a new higher order expectation using the and syntax without nestin
->toBeInstanceOf(HasMethodsAndProperties::class)
->meta
->sequence(
function ($value, $key) { $value->toBeArray()->and($key)->toBe('foo'); },
function ($value, $key) {
$value->toBeArray()->and($key)->toBe('foo');
},
);
});

View File

@ -35,8 +35,12 @@ it('works inside of each', function () {
it('works with sequence', function () {
expect(['books' => [['title' => 'Foo', 'cost' => 20], ['title' => 'Bar', 'cost' => 30]]])
->books->sequence(
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
function ($book) {
$book->title->toEqual('Foo')->cost->toEqual(20);
},
function ($book) {
$book->title->toEqual('Bar')->cost->toEqual(30);
},
);
});
@ -51,10 +55,16 @@ it('can compose complex expectations', function () {
it('works with objects', function () {
expect(new HasProperties())
->name->toEqual('foo')->not->toEqual('world')
->posts->toHaveCount(2)->each(function ($post) { $post->is_published->toBeTrue(); })
->posts->toHaveCount(2)->each(function ($post) {
$post->is_published->toBeTrue();
})
->posts->sequence(
function ($post) { $post->title->toEqual('Foo'); },
function ($post) { $post->title->toEqual('Bar'); },
function ($post) {
$post->title->toEqual('Foo');
},
function ($post) {
$post->title->toEqual('Bar');
},
);
});

View File

@ -9,17 +9,17 @@ beforeEach(function () {
it('pass', function () {
expect('baz')
->match('foo', [
'bar' => function ($value) {
$this->matched = 'bar';
'bar' => function ($value) {
$this->matched = 'bar';
return $value->toEqual('bar');
},
'foo' => function ($value) {
$this->matched = 'baz';
return $value->toEqual('bar');
},
'foo' => function ($value) {
$this->matched = 'baz';
return $value->toEqual('baz');
},
]
return $value->toEqual('baz');
},
]
)
->toEqual($this->matched);
@ -29,30 +29,30 @@ it('pass', function () {
it('failures', function () {
expect(true)
->match('foo', [
'bar' => function ($value) {
return $value->toBeTrue();
},
'foo' => function ($value) {
return $value->toBeFalse();
},
]
'bar' => function ($value) {
return $value->toBeTrue();
},
'foo' => function ($value) {
return $value->toBeFalse();
},
]
);
})->throws(ExpectationFailedException::class, 'true is false');
it('runs with truthy', function () {
expect('foo')
->match(1, [
'bar' => function ($value) {
$this->matched = 'bar';
'bar' => function ($value) {
$this->matched = 'bar';
return $value->toEqual('bar');
},
true => function ($value) {
$this->matched = 'foo';
return $value->toEqual('bar');
},
true => function ($value) {
$this->matched = 'foo';
return $value->toEqual('foo');
},
]
return $value->toEqual('foo');
},
]
)
->toEqual($this->matched);
@ -62,17 +62,17 @@ it('runs with truthy', function () {
it('runs with falsy', function () {
expect('foo')
->match(false, [
'bar' => function ($value) {
$this->matched = 'bar';
'bar' => function ($value) {
$this->matched = 'bar';
return $value->toEqual('bar');
},
false => function ($value) {
$this->matched = 'foo';
return $value->toEqual('bar');
},
false => function ($value) {
$this->matched = 'foo';
return $value->toEqual('foo');
},
]
return $value->toEqual('foo');
},
]
)
->toEqual($this->matched);
@ -82,7 +82,9 @@ it('runs with falsy', function () {
it('runs with truthy closure condition', function () {
expect('foo')
->match(
function () { return '1'; }, [
function () {
return '1';
}, [
'bar' => function ($value) {
$this->matched = 'bar';
@ -103,7 +105,9 @@ it('runs with truthy closure condition', function () {
it('runs with falsy closure condition', function () {
expect('foo')
->match(
function () { return '0'; }, [
function () {
return '0';
}, [
'bar' => function ($value) {
$this->matched = 'bar';
@ -124,9 +128,9 @@ it('runs with falsy closure condition', function () {
it('can be passed non-callable values', function () {
expect('foo')
->match('pest', [
'bar' => 'foo',
'pest' => 'baz',
]
'bar' => 'foo',
'pest' => 'baz',
]
);
})->throws(ExpectationFailedException::class, 'two strings are equal');
@ -137,7 +141,9 @@ it('fails with unhandled match', function () {
it('can be used in higher order tests')
->expect(true)
->match(
function () { return true; }, [
function () {
return true;
}, [
false => function ($value) {
return $value->toBeFalse();
},

View File

@ -36,7 +36,8 @@ class Symbol
class State
{
public array $runCount = [];
public array $runCount = [];
public array $appliedCount = [];
public function __construct()
@ -132,16 +133,16 @@ test('pipe is applied and can stop pipeline', function () use ($state) {
expect($char)->toBe(new Char('A'))
->and($state)
->runCount->toMatchArray([
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
])
->appliedCount->toMatchArray([
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
]);
});
@ -151,16 +152,16 @@ test('pipe is run and can let the pipeline keep going', function () use ($state)
expect(3)->toBe(3)
->and($state)
->runCount->toMatchArray([
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 1,
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 1,
])
->appliedCount->toMatchArray([
'char' => 0,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
'char' => 0,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
]);
});
@ -172,16 +173,16 @@ test('pipe works with negated expectation', function () use ($state) {
expect($char)->not->toBe(new Char('B'))
->and($state)
->runCount->toMatchArray([
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
])
->appliedCount->toMatchArray([
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
'char' => 1,
'number' => 0,
'wildcard' => 0,
'symbol' => 0,
]);
});
@ -204,16 +205,16 @@ test('interceptor stops the pipeline', function () use ($state) {
expect($number)->toBe(new Number(1))
->and($state)
->runCount->toMatchArray([
'char' => 1,
'number' => 1,
'wildcard' => 0,
'symbol' => 0,
'char' => 1,
'number' => 1,
'wildcard' => 0,
'symbol' => 0,
])
->appliedCount->toMatchArray([
'char' => 0,
'number' => 1,
'wildcard' => 0,
'symbol' => 0,
'char' => 0,
'number' => 1,
'wildcard' => 0,
'symbol' => 0,
]);
});

View File

@ -9,9 +9,15 @@ test('an exception is thrown if the the type is not iterable', function () {
test('allows for sequences of checks to be run on iterable data', function () {
expect([1, 2, 3])
->sequence(
function ($expectation) { $expectation->toBeInt()->toEqual(1); },
function ($expectation) { $expectation->toBeInt()->toEqual(2); },
function ($expectation) { $expectation->toBeInt()->toEqual(3); },
function ($expectation) {
$expectation->toBeInt()->toEqual(1);
},
function ($expectation) {
$expectation->toBeInt()->toEqual(2);
},
function ($expectation) {
$expectation->toBeInt()->toEqual(3);
},
);
expect(static::getCount())->toBe(6);
@ -20,9 +26,15 @@ test('allows for sequences of checks to be run on iterable data', function () {
test('loops back to the start if it runs out of sequence items', function () {
expect([1, 2, 3, 1, 2, 3, 1, 2])
->sequence(
function ($expectation) { $expectation->toBeInt()->toEqual(1); },
function ($expectation) { $expectation->toBeInt()->toEqual(2); },
function ($expectation) { $expectation->toBeInt()->toEqual(3); },
function ($expectation) {
$expectation->toBeInt()->toEqual(1);
},
function ($expectation) {
$expectation->toBeInt()->toEqual(2);
},
function ($expectation) {
$expectation->toBeInt()->toEqual(3);
},
);
expect(static::getCount())->toBe(16);
@ -31,9 +43,15 @@ test('loops back to the start if it runs out of sequence items', function () {
test('fails if the number of iterable items is greater than the number of expectations', function () {
expect([1, 2])
->sequence(
function ($expectation) { $expectation->toBeInt()->toEqual(1); },
function ($expectation) { $expectation->toBeInt()->toEqual(2); },
function ($expectation) { $expectation->toBeInt()->toEqual(3); },
function ($expectation) {
$expectation->toBeInt()->toEqual(1);
},
function ($expectation) {
$expectation->toBeInt()->toEqual(2);
},
function ($expectation) {
$expectation->toBeInt()->toEqual(3);
},
);
})->throws(ExpectationFailedException::class);
@ -60,7 +78,9 @@ test('it can be passed non-callable values', function () {
test('it can be passed a mixture of value types', function () {
expect(['foo', 'bar', 'baz'])->sequence(
'foo',
function ($expectation) { $expectation->toEqual('bar')->toBeString(); },
function ($expectation) {
$expectation->toEqual('bar')->toBeString();
},
'baz'
);

View File

@ -3,7 +3,8 @@
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(function () {})->toBeCallable();
expect(function () {
})->toBeCallable();
expect(null)->not->toBeCallable();
});
@ -14,5 +15,7 @@ test('failures', function () {
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(function () { return 42; })->not->toBeCallable();
expect(function () {
return 42;
})->not->toBeCallable();
})->throws(ExpectationFailedException::class);

View File

@ -3,10 +3,10 @@
use PHPUnit\Framework\ExpectationFailedException;
$test_array = [
'a' => 1,
'a' => 1,
'b',
'c' => 'world',
'd' => [
'c' => 'world',
'd' => [
'e' => 'hello',
],
'key.with.dots' => false,

View File

@ -19,7 +19,8 @@ test('pass', function () {
test('pass with class', function () {
expect(new class() {
public $name = 'Nuno';
public $name = 'Nuno';
public $email = 'enunomaduro@gmail.com';
})->toMatchObject([
'name' => 'Nuno',

View File

@ -3,60 +3,98 @@
use PHPUnit\Framework\ExpectationFailedException;
test('passes', function () {
expect(function () { throw new RuntimeException(); })->toThrow(RuntimeException::class);
expect(function () { throw new RuntimeException(); })->toThrow(Exception::class);
expect(function () { throw new RuntimeException(); })->toThrow(function (RuntimeException $e) {});
expect(function () { throw new RuntimeException('actual message'); })->toThrow(function (Exception $e) {
expect(function () {
throw new RuntimeException();
})->toThrow(RuntimeException::class);
expect(function () {
throw new RuntimeException();
})->toThrow(Exception::class);
expect(function () {
throw new RuntimeException();
})->toThrow(function (RuntimeException $e) {
});
expect(function () {
throw new RuntimeException('actual message');
})->toThrow(function (Exception $e) {
expect($e->getMessage())->toBe('actual message');
});
expect(function () {})->not->toThrow(Exception::class);
expect(function () { throw new RuntimeException('actual message'); })->toThrow('actual message');
expect(function () { throw new Exception(); })->not->toThrow(RuntimeException::class);
expect(function () { throw new RuntimeException('actual message'); })->toThrow(RuntimeException::class, 'actual message');
expect(function () { throw new RuntimeException('actual message'); })->toThrow(function (RuntimeException $e) {}, 'actual message');
expect(function () {
})->not->toThrow(Exception::class);
expect(function () {
throw new RuntimeException('actual message');
})->toThrow('actual message');
expect(function () {
throw new Exception();
})->not->toThrow(RuntimeException::class);
expect(function () {
throw new RuntimeException('actual message');
})->toThrow(RuntimeException::class, 'actual message');
expect(function () {
throw new RuntimeException('actual message');
})->toThrow(function (RuntimeException $e) {
}, 'actual message');
});
test('failures 1', function () {
expect(function () {})->toThrow(RuntimeException::class);
expect(function () {
})->toThrow(RuntimeException::class);
})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.');
test('failures 2', function () {
expect(function () {})->toThrow(function (RuntimeException $e) {});
expect(function () {
})->toThrow(function (RuntimeException $e) {
});
})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.');
test('failures 3', function () {
expect(function () { throw new Exception(); })->toThrow(function (RuntimeException $e) {});
expect(function () {
throw new Exception();
})->toThrow(function (RuntimeException $e) {
});
})->throws(ExpectationFailedException::class, 'Failed asserting that Exception Object');
test('failures 4', function () {
expect(function () { throw new Exception('actual message'); })
expect(function () {
throw new Exception('actual message');
})
->toThrow(function (Exception $e) {
expect($e->getMessage())->toBe('expected message');
});
})->throws(ExpectationFailedException::class, 'Failed asserting that two strings are identical');
test('failures 5', function () {
expect(function () { throw new Exception('actual message'); })->toThrow('expected message');
expect(function () {
throw new Exception('actual message');
})->toThrow('expected message');
})->throws(ExpectationFailedException::class, 'Failed asserting that \'actual message\' contains "expected message".');
test('failures 6', function () {
expect(function () {})->toThrow('actual message');
expect(function () {
})->toThrow('actual message');
})->throws(ExpectationFailedException::class, 'Exception with message "actual message" not thrown');
test('failures 7', function () {
expect(function () { throw new RuntimeException('actual message'); })->toThrow(RuntimeException::class, 'expected message');
expect(function () {
throw new RuntimeException('actual message');
})->toThrow(RuntimeException::class, 'expected message');
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(function () { throw new RuntimeException(); })->not->toThrow(RuntimeException::class);
expect(function () {
throw new RuntimeException();
})->not->toThrow(RuntimeException::class);
})->throws(ExpectationFailedException::class);
test('closure missing parameter', function () {
expect(function () {})->toThrow(function () {});
expect(function () {
})->toThrow(function () {
});
})->throws(InvalidArgumentException::class, 'The given closure must have a single parameter type-hinted as the class string.');
test('closure missing type-hint', function () {
expect(function () {})->toThrow(function ($e) {});
expect(function () {
})->toThrow(function ($e) {
});
})->throws(InvalidArgumentException::class, 'The given closure\'s parameter must be type-hinted as the class string.');
it('can handle a non-defined exception', function () {

View File

@ -67,7 +67,9 @@ it('skips with falsy', function () {
it('runs with truthy closure condition', function () {
expect($this->unlessObject)
->unless(
function () { return '0'; },
function () {
return '0';
},
function ($value) {
return $value->trueValue->toBeTrue();
}
@ -80,7 +82,9 @@ it('runs with truthy closure condition', function () {
it('skips with falsy closure condition', function () {
expect($this->unlessObject)
->unless(
function () { return '1'; },
function () {
return '1';
},
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
@ -93,7 +97,9 @@ it('skips with falsy closure condition', function () {
it('can be used in higher order tests')
->expect(true)
->unless(
function () { return false; },
function () {
return false;
},
function ($value) {
return $value->toBeFalse();
}

View File

@ -67,7 +67,9 @@ it('skips with falsy', function () {
it('runs with truthy closure condition', function () {
expect($this->whenObject)
->when(
function () { return '1'; },
function () {
return '1';
},
function ($value) {
return $value->trueValue->toBeTrue();
}
@ -80,7 +82,9 @@ it('runs with truthy closure condition', function () {
it('skips with falsy closure condition', function () {
expect($this->whenObject)
->when(
function () { return '0'; },
function () {
return '0';
},
function ($value) {
return $value->trueValue->toBeFalse(); // fails
}
@ -93,7 +97,9 @@ it('skips with falsy closure condition', function () {
it('can be used in higher order tests')
->expect(false)
->when(
function () { return true; },
function () {
return true;
},
function ($value) {
return $value->toBeTrue();
}

View File

@ -11,7 +11,9 @@ it('is capable doing multiple assertions')
->assertFalse(false);
it('resolves expect callables correctly')
->expect(function () { return 'foo'; })
->expect(function () {
return 'foo';
})
->toBeString()
->toBe('foo')
->and('bar')
@ -23,24 +25,38 @@ test('does not treat method names as callables')
it('can defer a method until after test setup')
->expect('foo')->toBeString()
->defer(function () { expect($this)->toBeInstanceOf(TestCase::class); })
->defer(function () {
expect($this)->toBeInstanceOf(TestCase::class);
})
->toBe('foo')
->and('hello world')->toBeString();
it('can pass datasets into the expect callables')
->with([[1, 2, 3]])
->expect(function (...$numbers) { return $numbers; })->toBe([1, 2, 3])
->and(function (...$numbers) { return $numbers; })->toBe([1, 2, 3]);
->expect(function (...$numbers) {
return $numbers;
})->toBe([1, 2, 3])
->and(function (...$numbers) {
return $numbers;
})->toBe([1, 2, 3]);
it('can pass datasets into the defer callable')
->with([[1, 2, 3]])
->defer(function (...$numbers) { expect($numbers)->toBe([1, 2, 3]); });
->defer(function (...$numbers) {
expect($numbers)->toBe([1, 2, 3]);
});
it('can pass shared datasets into callables')
->with('numbers.closure.wrapped')
->expect(function ($value) { return $value; })
->and(function ($value) { return $value; })
->defer(function ($value) { expect($value)->toBeInt(); })
->expect(function ($value) {
return $value;
})
->and(function ($value) {
return $value;
})
->defer(function ($value) {
expect($value)->toBeInt();
})
->toBeInt();
afterEach()->assertTrue(true);

View File

@ -21,11 +21,15 @@ it('skips with message')
->assertTrue(false);
it('skips with truthy closure condition')
->skip(function () { return '1'; })
->skip(function () {
return '1';
})
->assertTrue(false);
it('do not skips with falsy closure condition')
->skip(function () { return false; })
->skip(function () {
return false;
})
->assertTrue(true);
it('skips with condition and message')
@ -37,10 +41,16 @@ it('skips when skip after assertion')
->skip();
it('can use something in the test case as a condition')
->skip(function () { return $this->shouldSkip; }, 'This test was skipped')
->skip(function () {
return $this->shouldSkip;
}, 'This test was skipped')
->assertTrue(false);
it('can user higher order callables and skip')
->skip(function () { return $this->shouldSkip; })
->expect(function () { return $this->shouldSkip; })
->skip(function () {
return $this->shouldSkip;
})
->expect(function () {
return $this->shouldSkip;
})
->toBeFalse();