mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
feat: note()
This commit is contained in:
11
bin/pest
11
bin/pest
@ -4,6 +4,7 @@
|
|||||||
use Pest\Kernel;
|
use Pest\Kernel;
|
||||||
use Pest\Panic;
|
use Pest\Panic;
|
||||||
use Pest\TestCaseFilters\GitDirtyTestCaseFilter;
|
use Pest\TestCaseFilters\GitDirtyTestCaseFilter;
|
||||||
|
use Pest\TestCaseMethodFilters\NotesTestCaseFilter;
|
||||||
use Pest\TestCaseMethodFilters\TodoTestCaseFilter;
|
use Pest\TestCaseMethodFilters\TodoTestCaseFilter;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
use Symfony\Component\Console\Input\ArgvInput;
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
@ -17,6 +18,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
|||||||
|
|
||||||
$dirty = false;
|
$dirty = false;
|
||||||
$todo = false;
|
$todo = false;
|
||||||
|
$notes = false;
|
||||||
|
|
||||||
foreach ($arguments as $key => $value) {
|
foreach ($arguments as $key => $value) {
|
||||||
if ($value === '--compact') {
|
if ($value === '--compact') {
|
||||||
@ -43,6 +45,11 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
|||||||
unset($arguments[$key]);
|
unset($arguments[$key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($value === '--notes') {
|
||||||
|
$notes = true;
|
||||||
|
unset($arguments[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
if (str_contains($value, '--teamcity')) {
|
if (str_contains($value, '--teamcity')) {
|
||||||
unset($arguments[$key]);
|
unset($arguments[$key]);
|
||||||
$arguments[] = '--no-output';
|
$arguments[] = '--no-output';
|
||||||
@ -81,6 +88,10 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
|||||||
$testSuite->tests->addTestCaseMethodFilter(new TodoTestCaseFilter());
|
$testSuite->tests->addTestCaseMethodFilter(new TodoTestCaseFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($notes) {
|
||||||
|
$testSuite->tests->addTestCaseMethodFilter(new NotesTestCaseFilter());
|
||||||
|
}
|
||||||
|
|
||||||
$isDecorated = $input->getParameterOption('--colors', 'always') !== 'never';
|
$isDecorated = $input->getParameterOption('--colors', 'always') !== 'never';
|
||||||
|
|
||||||
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);
|
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);
|
||||||
|
|||||||
@ -29,6 +29,11 @@ trait Testable
|
|||||||
*/
|
*/
|
||||||
private string $__description;
|
private string $__description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The test's notes.
|
||||||
|
*/
|
||||||
|
private static array $__latestNotes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test's latest description.
|
* The test's latest description.
|
||||||
*/
|
*/
|
||||||
@ -74,6 +79,18 @@ trait Testable
|
|||||||
*/
|
*/
|
||||||
private array $__snapshotChanges = [];
|
private array $__snapshotChanges = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new "note" to the Test Case.
|
||||||
|
*/
|
||||||
|
public function note(array|string $note): self
|
||||||
|
{
|
||||||
|
$note = is_array($note) ? $note : [$note];
|
||||||
|
|
||||||
|
self::$__latestNotes = array_merge(self::$__latestNotes, $note);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the test case static properties.
|
* Resets the test case static properties.
|
||||||
*/
|
*/
|
||||||
@ -95,6 +112,7 @@ trait Testable
|
|||||||
if ($test->hasMethod($name)) {
|
if ($test->hasMethod($name)) {
|
||||||
$method = $test->getMethod($name);
|
$method = $test->getMethod($name);
|
||||||
$this->__description = self::$__latestDescription = $method->description;
|
$this->__description = self::$__latestDescription = $method->description;
|
||||||
|
self::$__latestNotes = $method->notes;
|
||||||
$this->__describing = $method->describing;
|
$this->__describing = $method->describing;
|
||||||
$this->__test = $method->getClosure($this);
|
$this->__test = $method->getClosure($this);
|
||||||
}
|
}
|
||||||
@ -224,6 +242,7 @@ trait Testable
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->__description = self::$__latestDescription = $description;
|
$this->__description = self::$__latestDescription = $description;
|
||||||
|
self::$__latestNotes = $method->notes;
|
||||||
|
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
@ -405,4 +424,12 @@ trait Testable
|
|||||||
{
|
{
|
||||||
return self::$__latestDescription;
|
return self::$__latestDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The latest printable test case notes.
|
||||||
|
*/
|
||||||
|
public static function getPrintableTestCaseMethodNotes(): array
|
||||||
|
{
|
||||||
|
return self::$__latestNotes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,13 @@ final class TestCaseMethodFactory
|
|||||||
*/
|
*/
|
||||||
public bool $todo = false;
|
public bool $todo = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The test's notes.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
public array $notes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test's datasets.
|
* The test's datasets.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -364,6 +364,20 @@ final class TestCall
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a note to the test.
|
||||||
|
*
|
||||||
|
* @param array<int, string>|string $note
|
||||||
|
*/
|
||||||
|
public function note(array|string $note): self
|
||||||
|
{
|
||||||
|
$notes = is_array($note) ? $note : [$note];
|
||||||
|
|
||||||
|
$this->testCaseMethod->notes = array_merge($this->testCaseMethod->notes, $notes);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the covered classes or methods.
|
* Sets the covered classes or methods.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -123,6 +123,9 @@ final class Help implements HandlesArguments
|
|||||||
], [
|
], [
|
||||||
'arg' => '--todos',
|
'arg' => '--todos',
|
||||||
'desc' => 'Output to standard output the list of todos',
|
'desc' => 'Output to standard output the list of todos',
|
||||||
|
], [
|
||||||
|
'arg' => '--notes',
|
||||||
|
'desc' => 'Output to standard output tests with notes',
|
||||||
], [
|
], [
|
||||||
'arg' => '--retry',
|
'arg' => '--retry',
|
||||||
'desc' => 'Run non-passing tests first and stop execution upon first error or failure',
|
'desc' => 'Run non-passing tests first and stop execution upon first error or failure',
|
||||||
|
|||||||
@ -34,7 +34,7 @@ final class Parallel implements HandlesArguments
|
|||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
private const UNSUPPORTED_ARGUMENTS = ['--todo', '--todos', '--retry'];
|
private const UNSUPPORTED_ARGUMENTS = ['--todo', '--todos', '--retry', '--notes'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the given command line arguments indicate that the test suite should be run in parallel.
|
* Whether the given command line arguments indicate that the test suite should be run in parallel.
|
||||||
@ -42,6 +42,7 @@ final class Parallel implements HandlesArguments
|
|||||||
public static function isEnabled(): bool
|
public static function isEnabled(): bool
|
||||||
{
|
{
|
||||||
$argv = new ArgvInput();
|
$argv = new ArgvInput();
|
||||||
|
|
||||||
if ($argv->hasParameterOption('--parallel')) {
|
if ($argv->hasParameterOption('--parallel')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -118,7 +118,7 @@ final class TestRepository
|
|||||||
*/
|
*/
|
||||||
public function get(string $filename): ?TestCaseFactory
|
public function get(string $filename): ?TestCaseFactory
|
||||||
{
|
{
|
||||||
return $this->testCases[$filename];
|
return $this->testCases[$filename] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -31,7 +31,7 @@ final class ExceptionTrace
|
|||||||
$message = str_replace(self::UNDEFINED_METHOD, 'Call to undefined method ', $message);
|
$message = str_replace(self::UNDEFINED_METHOD, 'Call to undefined method ', $message);
|
||||||
|
|
||||||
if (class_exists((string) $class) && (is_countable(class_parents($class)) ? count(class_parents($class)) : 0) > 0 && array_values(class_parents($class))[0] === TestCase::class) { // @phpstan-ignore-line
|
if (class_exists((string) $class) && (is_countable(class_parents($class)) ? count(class_parents($class)) : 0) > 0 && array_values(class_parents($class))[0] === TestCase::class) { // @phpstan-ignore-line
|
||||||
$message .= '. Did you forget to use the [uses()] function? Read more at: https://pestphp.com/docs/configuring-tests';
|
$message .= '. Did you forget to use the [pest()->uses()] function? Read more at: https://pestphp.com/docs/configuring-tests';
|
||||||
}
|
}
|
||||||
|
|
||||||
Reflection::setPropertyValue($throwable, 'message', $message);
|
Reflection::setPropertyValue($throwable, 'message', $message);
|
||||||
|
|||||||
16
src/TestCaseMethodFilters/NotesTestCaseFilter.php
Normal file
16
src/TestCaseMethodFilters/NotesTestCaseFilter.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\TestCaseMethodFilters;
|
||||||
|
|
||||||
|
use Pest\Contracts\TestCaseMethodFilter;
|
||||||
|
use Pest\Factories\TestCaseMethodFactory;
|
||||||
|
|
||||||
|
final class NotesTestCaseFilter implements TestCaseMethodFilter
|
||||||
|
{
|
||||||
|
public function accept(TestCaseMethodFactory $factory): bool
|
||||||
|
{
|
||||||
|
return count($factory->notes) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
tests/Features/Note.php
Normal file
36
tests/Features/Note.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
$this->note('This is before each runtime note');
|
||||||
|
})->note('This is before each static note');
|
||||||
|
|
||||||
|
it('may have a static note', function () {
|
||||||
|
expect(true)->toBeTrue();
|
||||||
|
})->note('This is a note');
|
||||||
|
|
||||||
|
it('may have a runtime note', function () {
|
||||||
|
expect(true)->toBeTrue(true);
|
||||||
|
|
||||||
|
$this->note('This is a runtime note');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('may have static note and runtime note', function () {
|
||||||
|
expect(true)->toBeTrue(true);
|
||||||
|
|
||||||
|
$this->note('This is a runtime note');
|
||||||
|
})->note('This is a static note');
|
||||||
|
|
||||||
|
describe('nested', function () {
|
||||||
|
it('may have static note and runtime note', function () {
|
||||||
|
expect(true)->toBeTrue(true);
|
||||||
|
|
||||||
|
$this->note('This is a runtime note within describe');
|
||||||
|
})->note('This is a static note within describe');
|
||||||
|
})->note('This is describe static note');
|
||||||
|
|
||||||
|
test('multiple notes', function () {
|
||||||
|
$this->note([
|
||||||
|
'This is a runtime note',
|
||||||
|
'This is another runtime note',
|
||||||
|
]);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user