Compare commits

...

19 Commits

Author SHA1 Message Date
3205b571b0 Merge branch 'master' of https://github.com/pestphp/pest 2021-05-14 10:51:54 +01:00
2c4aef5272 release: 1.2.1 2021-05-14 10:51:50 +01:00
4a45a7cc6b Merge pull request #297 from owenvoke/bugfix/laravel-commands
fix: resolve test directory before function call
2021-05-14 10:17:51 +01:00
ea8ab88056 style: apply fixes from PHPStan 2021-05-14 10:05:16 +01:00
564a21badd style: apply fixes from php-cs-fixer 2021-05-14 10:00:53 +01:00
41ce87450f fix: resolve test directory before function call 2021-05-14 09:33:52 +01:00
fb0eef4200 release: 1.2.0 2021-05-13 00:37:55 +01:00
819da37b89 Merge pull request #292 from shuvroroy/patch-1
Remove unused import
2021-05-12 21:21:59 +01:00
8eb9c408a9 Merge pull request #296 from pestphp/feature/php-cs-fixer-3
chore: migrate to PHP-CS-Fixer 3.x
2021-05-12 15:14:06 +01:00
1f10b46402 chore: migrate to PHP-CS-Fixer 3.x 2021-05-12 11:26:09 +01:00
7bb12b73e8 Merge pull request #288 from gregorip02/master
Ignore the absence of the tests folder
2021-05-11 08:19:14 +01:00
b8103697c9 Remove unused import 2021-05-07 12:45:55 +06:00
ca3f8b5702 Merge pull request #291 from olivernybroe/feat-junit
Add Junit support
2021-05-05 17:13:58 +01:00
daa01ea44b Merge pull request #283 from faustbrian/test-directory-config
make test directory configurable
2021-05-05 11:07:10 +01:00
26d577f9c5 separate directory and path by / 2021-05-05 05:07:17 +03:00
43fb711251 Merge branch 'master' into master 2021-05-03 11:47:36 -04:00
567af55a19 make test directory configurable 2021-05-03 18:28:20 +03:00
1440637e41 Add Junit support 2021-05-02 11:22:19 +02:00
d048d60d04 Ignore the absence of the tests folder 2021-04-10 11:51:13 -04:00
23 changed files with 543 additions and 80 deletions

30
.gitattributes vendored
View File

@ -1,16 +1,14 @@
/art export-ignore
/docs export-ignore
/tests export-ignore
/scripts export-ignore
/.github export-ignore
/.php_cs export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
phpstan.neon export-ignore
rector.yaml export-ignore
phpunit.xml export-ignore
CHANGELOG.md export-ignore
CONTRIBUTING.md export-ignore
README.md export-ignore
/art export-ignore
/docs export-ignore
/tests export-ignore
/scripts export-ignore
/.github export-ignore
/.php-cs-fixer.dist.php export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
phpstan.neon export-ignore
phpunit.xml export-ignore
CHANGELOG.md export-ignore
CONTRIBUTING.md export-ignore
README.md export-ignore

5
.gitignore vendored
View File

@ -4,8 +4,9 @@ composer.lock
/vendor/
coverage.xml
.phpunit.result.cache
.php_cs.cache
/.php-cs-fixer.php
.php-cs-fixer.cache
.temp/coverage.php
*.swp
*.swo
.vscode/
.vscode/

View File

@ -6,7 +6,7 @@ $finder = PhpCsFixer\Finder::create()
->in(__DIR__ . DIRECTORY_SEPARATOR . 'scripts')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'stubs')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'src')
->append(['.php_cs']);
->append(['.php-cs-fixer.dist.php']);
$rules = [
'@Symfony' => true,
@ -25,7 +25,7 @@ $rules = [
$rules['increment_style'] = ['style' => 'post'];
return PhpCsFixer\Config::create()
return (new PhpCsFixer\Config())
->setUsingCache(true)
->setRules($rules)
->setFinder($finder);

View File

@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [v1.2.1 (2021-05-14)](https://github.com/pestphp/pest/compare/v1.2.0...v1.2.1)
### Fixed
- Laravel commands failing with new `--test-directory` option ([#297](https://github.com/pestphp/pest/pull/297))
## [v1.2.0 (2021-05-13)](https://github.com/pestphp/pest/compare/v1.1.0...v1.2.0)
### Added
- Adds JUnit / Infection support ([#291](https://github.com/pestphp/pest/pull/291))
- `--test-directory` command line option ([#283](https://github.com/pestphp/pest/pull/283))
## [v1.1.0 (2021-05-02)](https://github.com/pestphp/pest/compare/v1.0.5...v1.1.0)
### Added
- Possibility of "hooks" being added using the "uses" function ([#282](https://github.com/pestphp/pest/pull/282))

View File

@ -28,11 +28,12 @@ use Symfony\Component\Console\Output\OutputInterface;
(new Provider())->register();
// get $rootPath based on $autoloadPath
$rootPath = dirname($autoloadPath, 2);
$rootPath = dirname($autoloadPath, 2);
$argv = new ArgvInput();
$testSuite = TestSuite::getInstance($rootPath);
$testSuite = TestSuite::getInstance($rootPath, $argv->getParameterOption('--test-directory', 'tests'));
$isDecorated = (new ArgvInput())->getParameterOption('--colors', 'always') !== 'never';
$isDecorated = $argv->getParameterOption('--colors', 'always') !== 'never';
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);
$container = Container::getInstance();
@ -41,5 +42,14 @@ use Symfony\Component\Console\Output\OutputInterface;
ValidatesEnvironment::in($testSuite);
// lets remove any arguments that PHPUnit does not understand
if ($argv->hasParameterOption('--test-directory')) {
foreach ($_SERVER['argv'] as $key => $value) {
if (strpos($value, '--test-directory') !== false) {
unset($_SERVER['argv'][$key]);
}
}
}
exit($container->get(Command::class)->run($_SERVER['argv']));
})();

View File

@ -22,10 +22,13 @@ parameters:
- "#Method Pest\\\\Support\\\\Reflection::getParameterClassName\\(\\) has a nullable return type declaration.#"
-
message: '#Call to an undefined method PHPUnit\\Framework\\Test::getName\(\)#'
path: src/TeamCity.php
path: src/Logging
-
message: '#invalid typehint type Pest\\Concerns\\TestCase#'
path: src/TeamCity.php
path: src/Logging
-
message: '#is not subtype of native type PHPUnit\\Framework\\Test#'
path: src/TeamCity.php
path: src/Logging
-
message: '#Call to an undefined method PHPUnit\\Framework\\Test::getPrintableTestCaseName\(\)#'
path: src/Logging

View File

@ -5,7 +5,8 @@ declare(strict_types=1);
namespace Pest\Actions;
use NunoMaduro\Collision\Adapters\Phpunit\Printer;
use Pest\TeamCity;
use Pest\Logging\JUnit;
use Pest\Logging\TeamCity;
use PHPUnit\TextUI\DefaultResultPrinter;
/**
@ -32,6 +33,14 @@ final class AddsDefaults
$arguments[self::PRINTER] = new TeamCity($arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS);
}
// Load our junit logger instead.
if (array_key_exists('junitLogfile', $arguments)) {
$arguments['listeners'][] = new JUnit(
$arguments['junitLogfile']
);
unset($arguments['junitLogfile']);
}
return $arguments;
}
}

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Pest\Actions;
use Pest\Support\Str;
use PHPUnit\TextUI\Configuration\Configuration;
use function Pest\testDirectory;
use PHPUnit\Util\FileLoader;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
@ -33,7 +33,7 @@ final class LoadStructure
*/
public static function in(string $rootPath): void
{
$testsPath = $rootPath . DIRECTORY_SEPARATOR . 'tests';
$testsPath = $rootPath . DIRECTORY_SEPARATOR . testDirectory();
$load = function ($filename): bool {
return file_exists($filename) && (bool) FileLoader::checkAndLoad($filename);

View File

@ -9,7 +9,6 @@ use Pest\Support\ChainableClosure;
use Pest\Support\ExceptionTrace;
use Pest\TestSuite;
use PHPUnit\Framework\ExecutionOrderDependency;
use PHPUnit\Util\Test;
use Throwable;
/**

View File

@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Pest\Exceptions;
use InvalidArgumentException;
use NunoMaduro\Collision\Contracts\RenderlessEditor;
use NunoMaduro\Collision\Contracts\RenderlessTrace;
use Symfony\Component\Console\Exception\ExceptionInterface;
/**
* @internal
*/
final class InvalidUsesPath extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{
/**
* Creates a new instance of invalid uses path.
*/
public function __construct(string $target)
{
parent::__construct(sprintf('The path `%s` is not valid.', $target));
}
}

View File

@ -8,6 +8,8 @@ use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Pest\Exceptions\InvalidConsoleArgument;
use function Pest\testDirectory;
use Pest\TestSuite;
/**
* @internal
@ -19,7 +21,8 @@ final class PestDatasetCommand extends Command
*
* @var string
*/
protected $signature = 'pest:dataset {name : The name of the dataset}';
protected $signature = 'pest:dataset {name : The name of the dataset}
{--test-directory=tests : The name of the tests directory}';
/**
* The console command description.
@ -33,10 +36,13 @@ final class PestDatasetCommand extends Command
*/
public function handle(): void
{
/* @phpstan-ignore-next-line */
TestSuite::getInstance(base_path(), $this->option('test-directory'));
/** @var string $name */
$name = $this->argument('name');
$relativePath = sprintf('tests/Datasets/%s.php', ucfirst($name));
$relativePath = sprintf(testDirectory('Datasets/%s.php'), ucfirst($name));
/* @phpstan-ignore-next-line */
$target = base_path($relativePath);

View File

@ -8,6 +8,8 @@ use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Pest\Console\Thanks;
use Pest\Exceptions\InvalidConsoleArgument;
use function Pest\testDirectory;
use Pest\TestSuite;
/**
* @internal
@ -19,7 +21,7 @@ final class PestInstallCommand extends Command
*
* @var string
*/
protected $signature = 'pest:install';
protected $signature = 'pest:install {--test-directory=tests : The name of the tests directory}';
/**
* The console command description.
@ -34,7 +36,10 @@ final class PestInstallCommand extends Command
public function handle(): void
{
/* @phpstan-ignore-next-line */
$pest = base_path('tests/Pest.php');
TestSuite::getInstance(base_path(), $this->option('test-directory'));
/* @phpstan-ignore-next-line */
$pest = base_path(testDirectory('Pest.php'));
$stubs = 'stubs/Laravel';
if (File::exists($pest)) {

View File

@ -8,6 +8,8 @@ use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Pest\Exceptions\InvalidConsoleArgument;
use Pest\Support\Str;
use function Pest\testDirectory;
use Pest\TestSuite;
/**
* @internal
@ -19,7 +21,7 @@ final class PestTestCommand extends Command
*
* @var string
*/
protected $signature = 'pest:test {name : The name of the file} {--unit : Create a unit test} {--dusk : Create a Dusk test}';
protected $signature = 'pest:test {name : The name of the file} {--unit : Create a unit test} {--dusk : Create a Dusk test} {--test-directory=tests : The name of the tests directory}';
/**
* The console command description.
@ -33,12 +35,16 @@ final class PestTestCommand extends Command
*/
public function handle(): void
{
/* @phpstan-ignore-next-line */
TestSuite::getInstance(base_path(), $this->option('test-directory'));
/** @var string $name */
$name = $this->argument('name');
$type = ((bool) $this->option('unit')) ? 'Unit' : (((bool) $this->option('dusk')) ? 'Browser' : 'Feature');
$relativePath = sprintf('tests/%s/%s.php',
$relativePath = sprintf(
testDirectory('%s/%s.php'),
$type,
ucfirst($name)
);

430
src/Logging/JUnit.php Normal file
View File

@ -0,0 +1,430 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (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 Pest\Logging;
use function class_exists;
use DOMDocument;
use DOMElement;
use Exception;
use function get_class;
use function method_exists;
use Pest\Concerns\TestCase;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\ExceptionWrapper;
use PHPUnit\Framework\SelfDescribing;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestFailure;
use PHPUnit\Framework\TestListener;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\Warning;
use PHPUnit\Util\Filter;
use PHPUnit\Util\Printer;
use PHPUnit\Util\Xml;
use ReflectionClass;
use ReflectionException;
use function sprintf;
use function str_replace;
use Throwable;
use function trim;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class JUnit extends Printer implements TestListener
{
/**
* @var DOMDocument
*/
private $document;
/**
* @var DOMElement
*/
private $root;
/**
* @var DOMElement[]
*/
private $testSuites = [];
/**
* @var int[]
*/
private $testSuiteTests = [0];
/**
* @var int[]
*/
private $testSuiteAssertions = [0];
/**
* @var int[]
*/
private $testSuiteErrors = [0];
/**
* @var int[]
*/
private $testSuiteWarnings = [0];
/**
* @var int[]
*/
private $testSuiteFailures = [0];
/**
* @var int[]
*/
private $testSuiteSkipped = [0];
/**
* @var int[]|float[]
*/
private $testSuiteTimes = [0];
/**
* @var int
*/
private $testSuiteLevel = 0;
/**
* @var DOMElement|null
*/
private $currentTestCase;
public function __construct(string $out)
{
$this->document = new DOMDocument('1.0', 'UTF-8');
$this->document->formatOutput = true;
$this->root = $this->document->createElement('testsuites');
$this->document->appendChild($this->root);
parent::__construct($out);
}
/**
* Flush buffer and close output.
*/
public function flush(): void
{
$this->write($this->getXML());
parent::flush();
}
/**
* An error occurred.
*/
public function addError(Test $test, Throwable $t, float $time): void
{
$this->doAddFault($test, $t, 'error');
$this->testSuiteErrors[$this->testSuiteLevel]++;
}
/**
* A warning occurred.
*/
public function addWarning(Test $test, Warning $e, float $time): void
{
$this->doAddFault($test, $e, 'warning');
$this->testSuiteWarnings[$this->testSuiteLevel]++;
}
/**
* A failure occurred.
*/
public function addFailure(Test $test, AssertionFailedError $e, float $time): void
{
$this->doAddFault($test, $e, 'failure');
$this->testSuiteFailures[$this->testSuiteLevel]++;
}
/**
* Incomplete test.
*/
public function addIncompleteTest(Test $test, Throwable $t, float $time): void
{
$this->doAddSkipped();
}
/**
* Risky test.
*/
public function addRiskyTest(Test $test, Throwable $t, float $time): void
{
}
/**
* Skipped test.
*/
public function addSkippedTest(Test $test, Throwable $t, float $time): void
{
$this->doAddSkipped();
}
/** @phpstan-ignore-next-line */
public function startTestSuite(TestSuite $suite): void
{
$testSuite = $this->document->createElement('testsuite');
$testSuite->setAttribute('name', $suite->getName());
if (class_exists($suite->getName(), false)) {
try {
$class = new ReflectionClass($suite->getName());
if ($class->hasMethod('__getFileName')) {
$fileName = $class->getMethod('__getFileName')->invoke(null);
} else {
$fileName = $class->getFileName();
}
$testSuite->setAttribute('file', $fileName);
} catch (ReflectionException $e) {
// @ignoreException
}
}
if ($this->testSuiteLevel > 0) {
$this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);
} else {
$this->root->appendChild($testSuite);
}
$this->testSuiteLevel++;
$this->testSuites[$this->testSuiteLevel] = $testSuite;
$this->testSuiteTests[$this->testSuiteLevel] = 0;
$this->testSuiteAssertions[$this->testSuiteLevel] = 0;
$this->testSuiteErrors[$this->testSuiteLevel] = 0;
$this->testSuiteWarnings[$this->testSuiteLevel] = 0;
$this->testSuiteFailures[$this->testSuiteLevel] = 0;
$this->testSuiteSkipped[$this->testSuiteLevel] = 0;
$this->testSuiteTimes[$this->testSuiteLevel] = 0;
}
/** @phpstan-ignore-next-line */
public function endTestSuite(TestSuite $suite): void
{
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'tests',
(string) $this->testSuiteTests[$this->testSuiteLevel]
);
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'assertions',
(string) $this->testSuiteAssertions[$this->testSuiteLevel]
);
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'errors',
(string) $this->testSuiteErrors[$this->testSuiteLevel]
);
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'warnings',
(string) $this->testSuiteWarnings[$this->testSuiteLevel]
);
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'failures',
(string) $this->testSuiteFailures[$this->testSuiteLevel]
);
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'skipped',
(string) $this->testSuiteSkipped[$this->testSuiteLevel]
);
$this->testSuites[$this->testSuiteLevel]->setAttribute(
'time',
sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel])
);
if ($this->testSuiteLevel > 1) {
$this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel];
$this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel];
$this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel];
$this->testSuiteWarnings[$this->testSuiteLevel - 1] += $this->testSuiteWarnings[$this->testSuiteLevel];
$this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel];
$this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel];
$this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel];
}
$this->testSuiteLevel--;
}
/**
* A test started.
*
* @param Test|TestCase $test
*/
public function startTest(Test $test): void
{
$usesDataprovider = false;
if (method_exists($test, 'usesDataProvider')) {
$usesDataprovider = $test->usesDataProvider();
}
$testCase = $this->document->createElement('testcase');
$testCase->setAttribute('name', $test->getName());
try {
$class = new ReflectionClass($test);
// @codeCoverageIgnoreStart
} catch (ReflectionException $e) {
// @phpstan-ignore-next-line
throw new Exception($e->getMessage(), (int) $e->getCode(), $e);
}
// @codeCoverageIgnoreEnd
$methodName = $test->getName(!$usesDataprovider);
if ($class->hasMethod($methodName)) {
try {
$method = $class->getMethod($methodName);
// @codeCoverageIgnoreStart
} catch (ReflectionException $e) {
// @phpstan-ignore-next-line
throw new Exception($e->getMessage(), (int) $e->getCode(), $e);
}
// @codeCoverageIgnoreEnd
$testCase->setAttribute('class', $class->getName());
$testCase->setAttribute('classname', str_replace('\\', '.', $class->getName()));
$fileName = $class->getFileName();
if ($fileName !== false) {
$testCase->setAttribute('file', $fileName);
}
$testCase->setAttribute('line', (string) $method->getStartLine());
}
if (TeamCity::isPestTest($test)) {
$testCase->setAttribute('class', $test->getPrintableTestCaseName());
$testCase->setAttribute('classname', str_replace('\\', '.', $test->getPrintableTestCaseName()));
// @phpstan-ignore-next-line
$testCase->setAttribute('file', $test->__getFileName());
}
$this->currentTestCase = $testCase;
}
/**
* A test ended.
*/
public function endTest(Test $test, float $time): void
{
$numAssertions = 0;
if (method_exists($test, 'getNumAssertions')) {
$numAssertions = $test->getNumAssertions();
}
$this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions;
if ($this->currentTestCase !== null) {
$this->currentTestCase->setAttribute(
'assertions',
(string) $numAssertions
);
$this->currentTestCase->setAttribute(
'time',
sprintf('%F', $time)
);
$this->testSuites[$this->testSuiteLevel]->appendChild(
$this->currentTestCase
);
}
$this->testSuiteTests[$this->testSuiteLevel]++;
$this->testSuiteTimes[$this->testSuiteLevel] += $time;
$testOutput = '';
if (method_exists($test, 'hasOutput') && method_exists($test, 'getActualOutput')) {
$testOutput = $test->hasOutput() ? $test->getActualOutput() : '';
}
if ($testOutput !== '') {
$systemOut = $this->document->createElement(
'system-out',
Xml::prepareString($testOutput)
);
if ($this->currentTestCase !== null) {
$this->currentTestCase->appendChild($systemOut);
}
}
$this->currentTestCase = null;
}
/**
* Returns the XML as a string.
*/
public function getXML(): string
{
$xml = $this->document->saveXML();
if ($xml === false) {
return '';
}
return $xml;
}
private function doAddFault(Test $test, Throwable $t, string $type): void
{
if ($this->currentTestCase === null) {
return;
}
if ($test instanceof SelfDescribing) {
$buffer = $test->toString() . "\n";
} else {
$buffer = '';
}
$buffer .= trim(
TestFailure::exceptionToString($t) . "\n" .
Filter::getFilteredStacktrace($t)
);
$fault = $this->document->createElement(
$type,
Xml::prepareString($buffer)
);
if ($t instanceof ExceptionWrapper) {
$fault->setAttribute('type', $t->getClassName());
} else {
$fault->setAttribute('type', get_class($t));
}
$this->currentTestCase->appendChild($fault);
}
private function doAddSkipped(): void
{
if ($this->currentTestCase === null) {
return;
}
$skipped = $this->document->createElement('skipped');
$this->currentTestCase->appendChild($skipped);
$this->testSuiteSkipped[$this->testSuiteLevel]++;
}
}

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Pest;
namespace Pest\Logging;
use function getmypid;
use Pest\Concerns\TestCase;
@ -121,7 +121,7 @@ final class TeamCity extends DefaultResultPrinter
$this->printEvent('testStarted', [
self::NAME => $test->getName(),
/* @phpstan-ignore-next-line */
// @phpstan-ignore-next-line
self::LOCATION_HINT => self::PROTOCOL . $test->toString(),
]);
}
@ -203,7 +203,7 @@ final class TeamCity extends DefaultResultPrinter
return (int) round($time * 1000);
}
private static function isPestTest(Test $test): bool
public static function isPestTest(Test $test): bool
{
/** @var array<string, string> $uses */
$uses = class_uses($test);

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Pest\PendingObjects;
use Closure;
use Pest\Exceptions\InvalidUsesPath;
use Pest\TestSuite;
/**
@ -92,14 +91,13 @@ final class UsesCall
]);
}, $targets);
$this->targets = array_map(function ($target): string {
$isValid = is_dir($target) || file_exists($target);
if (!$isValid) {
throw new InvalidUsesPath($target);
$this->targets = array_reduce($targets, function (array $accumulator, string $target): array {
if (is_dir($target) || file_exists($target)) {
$accumulator[] = (string) realpath($target);
}
return (string) realpath($target);
}, $targets);
return $accumulator;
}, []);
}
/**

View File

@ -6,5 +6,10 @@ namespace Pest;
function version(): string
{
return '1.1.0';
return '1.2.1';
}
function testDirectory(string $file = ''): string
{
return TestSuite::getInstance()->testPath . '/' . $file;
}

View File

@ -22,7 +22,7 @@ final class Plugin
public static function uses(string ...$traits): void
{
self::$callables[] = function () use ($traits): void {
uses(...$traits)->in(TestSuite::getInstance()->rootPath . DIRECTORY_SEPARATOR . 'tests');
uses(...$traits)->in(TestSuite::getInstance()->rootPath . DIRECTORY_SEPARATOR . testDirectory());
};
}
}

View File

@ -12,7 +12,6 @@ use ReflectionException;
use ReflectionFunction;
use ReflectionNamedType;
use ReflectionParameter;
use ReflectionProperty;
/**
* @internal

View File

@ -66,6 +66,13 @@ final class TestSuite
*/
public $rootPath;
/**
* Holds the test path.
*
* @var string
*/
public $testPath;
/**
* Holds an instance of the test suite.
*
@ -76,7 +83,7 @@ final class TestSuite
/**
* Creates a new instance of the test suite.
*/
public function __construct(string $rootPath)
public function __construct(string $rootPath, string $testPath)
{
$this->beforeAll = new BeforeAllRepository();
$this->beforeEach = new BeforeEachRepository();
@ -85,15 +92,16 @@ final class TestSuite
$this->afterAll = new AfterAllRepository();
$this->rootPath = (string) realpath($rootPath);
$this->testPath = $testPath;
}
/**
* Returns the current instance of the test suite.
*/
public static function getInstance(string $rootPath = null): TestSuite
public static function getInstance(string $rootPath = null, string $testPath = null): TestSuite
{
if (is_string($rootPath)) {
self::$instance = new TestSuite($rootPath);
if (is_string($rootPath) && is_string($testPath)) {
self::$instance = new TestSuite($rootPath, $testPath);
foreach (Plugin::$callables as $callable) {
$callable();

View File

@ -18,7 +18,7 @@ test('default php unit tests', function () {
$testSuite->addTest($phpUnitTestCase);
expect($testSuite->tests())->toHaveCount(1);
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd()));
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd(), 'tests'));
expect($testSuite->tests())->toHaveCount(1);
});
@ -27,6 +27,6 @@ it('removes warnings', function () {
$warningTestCase = new WarningTestCase('No tests found in class "Pest\TestCase".');
$testSuite->addTest($warningTestCase);
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd()));
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd(), 'tests'));
expect($testSuite->tests())->toHaveCount(0);
});

View File

@ -38,6 +38,7 @@ it('creates an instance and resolves also sub parameters', function () {
it('can resolve builtin value types', function () {
$this->container->add('rootPath', getcwd());
$this->container->add('testPath', 'tests');
$instance = $this->container->get(TestSuite::class);
expect($instance)->toBeInstanceOf(TestSuite::class);

View File

@ -4,7 +4,7 @@ use Pest\Exceptions\TestAlreadyExist;
use Pest\TestSuite;
it('does not allow to add the same test description twice', function () {
$testSuite = new TestSuite(getcwd());
$testSuite = new TestSuite(getcwd(), 'tests');
$test = function () {};
$testSuite->tests->set(new \Pest\Factories\TestCaseFactory(__FILE__, 'foo', $test));
$this->expectException(TestAlreadyExist::class);