Compare commits

...

13 Commits

Author SHA1 Message Date
436b20857d docs: updates changelog 2023-06-02 22:46:07 +01:00
82b0adf5ae release: v2.6.2 2023-06-02 22:43:42 +01:00
a0041f139c chore: bumps phpunit dependency 2023-06-02 22:40:46 +01:00
b25bc7ee05 docs: updates changelog 2023-05-12 09:23:13 +01:00
faafedd55c release: v2.6.1 2023-05-12 09:22:02 +01:00
c99325275a chore: bumps dependencies 2023-05-12 09:16:45 +01:00
37a7583755 Merge pull request #809 from gehrisandro/fix-teamcity-output
fix teamcity output for tests throwing an exception before the first assertion
2023-05-11 22:52:26 +01:00
a851b5ed70 fix teamcity output for tests throwing an exception before the first assertion 2023-05-11 22:27:43 +02:00
983659f8e8 chore: bumps paratest 2023-05-06 11:52:05 +01:00
3e1cef296f chore: updates snapshots 2023-05-06 11:51:58 +01:00
cada5c5136 Merge pull request #804 from titantwentyone/2.x
Allow traits to be covered
2023-05-06 11:49:41 +01:00
477492fdd2 Adding tests 2023-05-06 08:43:19 +01:00
963b7f43ab Allow traits to be covered 2023-05-05 17:59:52 +01:00
14 changed files with 155 additions and 59 deletions

View File

@ -2,6 +2,25 @@
## Unreleased
## [v2.6.2 (2023-06-02)](https://github.com/pestphp/pest/compare/v2.6.1...v2.6.2)
### Chore
- Bumps PHPUnit to `^10.2.0` ([a0041f1](https://github.com/pestphp/pest/commit/a0041f139cba94fe5d15318c38e275f2e2fb3350))
## [v2.6.1 (2023-04-12)](https://github.com/pestphp/pest/compare/v2.6.0...v2.6.1)
### Fixes
- PHPStorm issue output problem for tests throwing an exception before the first assertion ([#809](https://github.com/pestphp/pest/pull/809))
- Allow traits to be covered ([#804](https://github.com/pestphp/pest/pull/804))
### Chore
- Bumps PHPUnit to `^10.1.3` ([c993252](https://github.com/pestphp/pest/commit/c99325275acf1fd3759b487b93ec50473f706709))
## [v2.6.0 (2023-04-05)](https://github.com/pestphp/pest/compare/v2.5.2...v2.6.0)
### Adds
- Allows `toThrow` to be used against an exception instance ([#797](https://github.com/pestphp/pest/pull/797))
## [v2.5.2 (2023-04-19)](https://github.com/pestphp/pest/compare/v2.5.1...v2.5.2)
### Chore

View File

@ -18,16 +18,16 @@
],
"require": {
"php": "^8.1.0",
"brianium/paratest": "^7.1.3",
"brianium/paratest": "^7.1.4",
"nunomaduro/collision": "^7.5.2",
"nunomaduro/termwind": "^1.15.1",
"pestphp/pest-plugin": "^2.0.1",
"pestphp/pest-plugin-arch": "^2.1.2",
"phpunit/phpunit": "^10.1.2"
"phpunit/phpunit": "^10.2.0"
},
"conflict": {
"webmozart/assert": "<1.11.0",
"phpunit/phpunit": ">10.1.2"
"phpunit/phpunit": ">10.2.0"
},
"autoload": {
"psr-4": {
@ -49,8 +49,8 @@
]
},
"require-dev": {
"pestphp/pest-dev-tools": "^2.8.0",
"symfony/process": "^6.2.10"
"pestphp/pest-dev-tools": "^2.9.0",
"symfony/process": "^6.3.0"
},
"minimum-stability": "stable",
"config": {

View File

@ -11,6 +11,12 @@ use Pest\Support\Str;
use PHPUnit\Event\Code\Test;
use PHPUnit\Event\Code\TestMethod;
use PHPUnit\Event\Code\Throwable;
use PHPUnit\Event\Test\BeforeFirstTestMethodErrored;
use PHPUnit\Event\Test\ConsideredRisky;
use PHPUnit\Event\Test\Errored;
use PHPUnit\Event\Test\Failed;
use PHPUnit\Event\Test\MarkedIncomplete;
use PHPUnit\Event\Test\Skipped;
use PHPUnit\Event\TestSuite\TestSuite;
use PHPUnit\Framework\Exception as FrameworkException;
use PHPUnit\TestRunner\TestResult\TestResult as PhpUnitTestResult;
@ -188,12 +194,30 @@ final class Converter
*/
public function getStateFromResult(PhpUnitTestResult $result): State
{
$numberOfPassedTests = $result->numberOfTestsRun()
- $result->numberOfTestErroredEvents()
- $result->numberOfTestFailedEvents()
- $result->numberOfTestSkippedEvents()
- $result->numberOfTestsWithTestConsideredRiskyEvents()
- $result->numberOfTestMarkedIncompleteEvents();
$events = [
...$result->testErroredEvents(),
...$result->testFailedEvents(),
...$result->testSkippedEvents(),
...array_merge(...array_values($result->testConsideredRiskyEvents())),
...$result->testMarkedIncompleteEvents(),
];
$numberOfNotPassedTests = count(
array_unique(
array_map(
function (BeforeFirstTestMethodErrored|Errored|Failed|Skipped|ConsideredRisky|MarkedIncomplete $event): string {
if ($event instanceof BeforeFirstTestMethodErrored) {
return $event->testClassName();
}
return $this->getTestCaseLocation($event->test());
},
$events
)
)
);
$numberOfPassedTests = $result->numberOfTestsRun() - $numberOfNotPassedTests;
return $this->stateGenerator->fromPhpUnitTestResult($numberOfPassedTests, $result);
}

View File

@ -16,6 +16,7 @@ use Pest\Logging\TeamCity\Subscriber\TestPreparedSubscriber;
use Pest\Logging\TeamCity\Subscriber\TestSkippedSubscriber;
use Pest\Logging\TeamCity\Subscriber\TestSuiteFinishedSubscriber;
use Pest\Logging\TeamCity\Subscriber\TestSuiteStartedSubscriber;
use PHPUnit\Event\Code\Test;
use PHPUnit\Event\EventFacadeIsSealedException;
use PHPUnit\Event\Facade;
use PHPUnit\Event\Telemetry\Duration;
@ -47,6 +48,11 @@ final class TeamCityLogger
private bool $isSummaryTestCountPrinted = false;
/**
* @var array<string, bool>
*/
private array $testEvents = [];
/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
@ -108,12 +114,14 @@ final class TeamCityLogger
public function testSkipped(Skipped $event): void
{
$message = ServiceMessage::testIgnored(
$this->converter->getTestCaseMethodName($event->test()),
'This test was ignored.'
);
$this->whenFirstEventForTest($event->test(), function () use ($event): void {
$message = ServiceMessage::testIgnored(
$this->converter->getTestCaseMethodName($event->test()),
'This test was ignored.'
);
$this->output($message);
$this->output($message);
});
}
/**
@ -122,17 +130,19 @@ final class TeamCityLogger
*/
public function testErrored(Errored $event): void
{
$testName = $this->converter->getTestCaseMethodName($event->test());
$message = $this->converter->getExceptionMessage($event->throwable());
$details = $this->converter->getExceptionDetails($event->throwable());
$this->whenFirstEventForTest($event->test(), function () use ($event): void {
$testName = $this->converter->getTestCaseMethodName($event->test());
$message = $this->converter->getExceptionMessage($event->throwable());
$details = $this->converter->getExceptionDetails($event->throwable());
$message = ServiceMessage::testFailed(
$testName,
$message,
$details,
);
$message = ServiceMessage::testFailed(
$testName,
$message,
$details,
);
$this->output($message);
$this->output($message);
});
}
/**
@ -141,28 +151,30 @@ final class TeamCityLogger
*/
public function testFailed(Failed $event): void
{
$testName = $this->converter->getTestCaseMethodName($event->test());
$message = $this->converter->getExceptionMessage($event->throwable());
$details = $this->converter->getExceptionDetails($event->throwable());
$this->whenFirstEventForTest($event->test(), function () use ($event): void {
$testName = $this->converter->getTestCaseMethodName($event->test());
$message = $this->converter->getExceptionMessage($event->throwable());
$details = $this->converter->getExceptionDetails($event->throwable());
if ($event->hasComparisonFailure()) {
$comparison = $event->comparisonFailure();
$message = ServiceMessage::comparisonFailure(
$testName,
$message,
$details,
$comparison->actual(),
$comparison->expected()
);
} else {
$message = ServiceMessage::testFailed(
$testName,
$message,
$details,
);
}
if ($event->hasComparisonFailure()) {
$comparison = $event->comparisonFailure();
$message = ServiceMessage::comparisonFailure(
$testName,
$message,
$details,
$comparison->actual(),
$comparison->expected()
);
} else {
$message = ServiceMessage::testFailed(
$testName,
$message,
$details,
);
}
$this->output($message);
$this->output($message);
});
}
/**
@ -171,12 +183,14 @@ final class TeamCityLogger
*/
public function testConsideredRisky(ConsideredRisky $event): void
{
$message = ServiceMessage::testIgnored(
$this->converter->getTestCaseMethodName($event->test()),
$event->message()
);
$this->whenFirstEventForTest($event->test(), function () use ($event): void {
$message = ServiceMessage::testIgnored(
$this->converter->getTestCaseMethodName($event->test()),
$event->message()
);
$this->output($message);
$this->output($message);
});
}
public function testFinished(Finished $event): void
@ -264,4 +278,14 @@ final class TeamCityLogger
ServiceMessage::setFlowId($this->flowId);
}
private function whenFirstEventForTest(Test $test, callable $callback): void
{
$testIdentifier = $this->converter->getTestCaseLocation($test);
if (! isset($this->testEvents[$testIdentifier])) {
$this->testEvents[$testIdentifier] = true;
$callback();
}
}
}

View File

@ -227,7 +227,7 @@ final class TestCall
public function covers(string ...$classesOrFunctions): self
{
foreach ($classesOrFunctions as $classOrFunction) {
$isClass = class_exists($classOrFunction);
$isClass = class_exists($classOrFunction) || trait_exists($classOrFunction);
$isMethod = function_exists($classOrFunction);
if (! $isClass && ! $isMethod) {

View File

@ -6,7 +6,7 @@ namespace Pest;
function version(): string
{
return '2.6.0';
return '2.6.2';
}
function testDirectory(string $file = ''): string

View File

@ -1,5 +1,5 @@
##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='file://tests/.tests/Failure.php' flowId='1234']
##teamcity[testCount count='6' flowId='1234']
##teamcity[testCount count='8' flowId='1234']
##teamcity[testStarted name='it can fail with comparison' locationHint='pest_qn://tests/.tests/Failure.php::it can fail with comparison' flowId='1234']
##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at src/Mixins/Expectation.php:343|nat src/Support/ExpectationPipeline.php:75|nat src/Support/ExpectationPipeline.php:79|nat src/Expectation.php:300|nat tests/.tests/Failure.php:6|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:302|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:302|nat src/Concerns/Testable.php:221|nat src/Kernel.php:86' type='comparisonFailure' actual='true' expected='false' flowId='1234']
##teamcity[testFinished name='it can fail with comparison' duration='100000' flowId='1234']
@ -12,14 +12,19 @@
##teamcity[testStarted name='it can fail' locationHint='pest_qn://tests/.tests/Failure.php::it can fail' flowId='1234']
##teamcity[testFailed name='it can fail' message='oh noo' details='at tests/.tests/Failure.php:18|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:302|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:302|nat src/Concerns/Testable.php:221|nat src/Kernel.php:86' flowId='1234']
##teamcity[testFinished name='it can fail' duration='100000' flowId='1234']
##teamcity[testStarted name='it throws exception' locationHint='pest_qn://tests/.tests/Failure.php::it throws exception' flowId='1234']
##teamcity[testFailed name='it throws exception' message='Exception: test error' details='at tests/.tests/Failure.php:22|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:302|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:302|nat src/Concerns/Testable.php:221|nat src/Kernel.php:86' flowId='1234']
##teamcity[testFinished name='it throws exception' duration='100000' flowId='1234']
##teamcity[testStarted name='it is not done yet' locationHint='pest_qn://tests/.tests/Failure.php::it is not done yet' flowId='1234']
##teamcity[testIgnored name='it is not done yet' message='This test was ignored.' details='' flowId='1234']
##teamcity[testFinished name='it is not done yet' duration='100000' flowId='1234']
##teamcity[testStarted name='build this one.' locationHint='pest_qn://tests/.tests/Failure.php::build this one.' flowId='1234']
##teamcity[testIgnored name='build this one.' message='This test was ignored.' details='' flowId='1234']
##teamcity[testFinished name='build this one.' duration='100000' flowId='1234']
##teamcity[testStarted name='it is passing' locationHint='pest_qn://tests/.tests/Failure.php::it is passing' flowId='1234']
##teamcity[testFinished name='it is passing' duration='100000' flowId='1234']
##teamcity[testSuiteFinished name='Tests/tests/Failure' flowId='1234']
Tests: 2 failed, 1 risky, 2 todos, 1 skipped (2 assertions)
Tests: 3 failed, 1 risky, 2 todos, 1 skipped, 1 passed (3 assertions)
Duration: 1.00s

View File

@ -1,5 +1,5 @@
Pest Testing Framework 2.6.0.
Pest Testing Framework 2.6.2.
USAGE: pest <file> [options]

View File

@ -49,6 +49,7 @@
✓ it uses the correct PHPUnit attribute for function
✓ it removes duplicated attributes
✓ it guesses if the given argument is a class or function
✓ it uses the correct PHPUnit attribute for trait
✓ it appends CoversNothing to method attributes
✓ it does not append CoversNothing to other methods
✓ it throws exception if no class nor method has been found
@ -169,7 +170,7 @@
DEPR Tests\Features\Deprecated
! deprecated → str_contains(): Passing null to parameter #1 ($haystack) of type string is deprecated // tests/Features/Deprecated.php:6
user deprecated
! user deprecated → Since foo 1.0: This is a deprecation description // vendor/symfony/deprecation-contracts/function.php:25
PASS Tests\Features\Exceptions
✓ it gives access the the underlying expectException
@ -1034,4 +1035,4 @@
PASS Tests\Visual\Version
✓ visual snapshot of help command output
Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 17 skipped, 715 passed (1727 assertions)
Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 17 skipped, 715 passed (1729 assertions)

View File

@ -1,3 +1,3 @@
Pest Testing Framework 2.6.0.
Pest Testing Framework 2.6.2.

View File

@ -18,9 +18,17 @@ it('can fail', function () {
$this->fail("oh noo");
});
it('throws exception', function () {
throw new Exception('test error');
});
it('is not done yet', function () {
})->todo();
todo("build this one.");
it('is passing', function () {
expect(true)->toEqual(true);
});

View File

@ -6,6 +6,7 @@ use PHPUnit\Framework\Attributes\CoversClass;
use Tests\Fixtures\Covers\CoversClass1;
use Tests\Fixtures\Covers\CoversClass2;
use Tests\Fixtures\Covers\CoversClass3;
use Tests\Fixtures\Covers\CoversTrait;
$runCounter = 0;
@ -43,6 +44,13 @@ it('guesses if the given argument is a class or function', function () {
expect($attributes[3]->getArguments()[0])->toBe(CoversClass3::class);
})->covers(CoversClass3::class, 'testCoversFunction');
it('uses the correct PHPUnit attribute for trait', function () {
$attributes = (new ReflectionClass($this))->getAttributes();
expect($attributes[4]->getName())->toBe('PHPUnit\Framework\Attributes\CoversClass');
expect($attributes[4]->getArguments()[0])->toBe('Tests\Fixtures\Covers\CoversTrait');
})->coversClass(CoversTrait::class);
it('appends CoversNothing to method attributes', function () {
$phpDoc = (new ReflectionClass($this))->getMethod($this->name());

View File

@ -0,0 +1,7 @@
<?php
namespace Tests\Fixtures\Covers;
trait CoversTrait
{
}

View File

@ -18,7 +18,7 @@ $run = function () {
test('parallel', function () use ($run) {
expect($run('--exclude-group=integration'))
->toContain('Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 14 skipped, 703 passed (1712 assertions)')
->toContain('Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 14 skipped, 704 passed (1714 assertions)')
->toContain('Parallel: 3 processes');
})->skipOnWindows();