Compare commits

...

114 Commits

Author SHA1 Message Date
4855987ba8 chore: update changelog 2020-09-30 13:03:23 +01:00
4f677a6cc2 Merge pull request #193 from owenvoke/feature/dependencies
chore(composer): add support for PHPUnit 9.3.11
2020-09-24 12:12:03 +01:00
228f2deb64 chore(composer): add support for PHPUnit 9.3.11 2020-09-24 10:45:19 +01:00
0fadf9a02c chore: update changelog 2020-09-21 20:31:32 +01:00
2b138ad76b Merge pull request #191 from owenvoke/feature/assert-regex
feat(expectations): add toMatch
2020-09-21 20:28:42 +01:00
e3e4815b55 chore(expectations): rename 'toMatchRegEx' to 'toMatch' 2020-09-21 20:20:21 +01:00
f76f353c32 chore: update snapshots 2020-09-21 20:19:01 +01:00
16b9f54dc3 feat(expectations): add toMatchRegEx 2020-09-21 20:18:58 +01:00
281166475e Merge pull request #190 from owenvoke/feature/assert-constraint
feat(expectations): add toMatchConstraint
2020-09-21 20:14:39 +01:00
23805cb5d6 chore: update snapshots 2020-09-16 19:03:21 +01:00
76d0f9cfc1 feat(expectations): add toMatchConstraint 2020-09-16 19:02:33 +01:00
5b083e4eb1 chore: update changelog 2020-09-16 10:35:43 +01:00
f48694b18a Merge pull request #187 from owenvoke/feature/assert-string
feat: add 'toStartWith' and 'toEndWith' expectations
2020-09-16 10:33:00 +01:00
8fa59ddbf0 Merge pull request #189 from owenvoke/feature/changelog-workflow
chore: don't run changelog workflow on forks
2020-09-16 09:26:17 +01:00
2619db4026 chore: don't run changelog workflow on forks 2020-09-16 08:26:49 +01:00
f3a71fb100 chore: update snapshots 2020-09-16 08:22:35 +01:00
04fafe742c feat(expectations): add toEndWith 2020-09-16 08:21:46 +01:00
cad8a41e6d feat(expectations): add toStartWith 2020-09-16 08:20:00 +01:00
1567923cda docs: updates changelog 2020-09-15 21:57:50 +02:00
c7116afcae tests: updates snapshots 2020-09-15 21:56:39 +02:00
4e184b2f90 Adds toMatchObject 2020-09-15 21:53:25 +02:00
9b5f664f00 Merge pull request #185 from owenvoke/feature/stubs
chore: update PHPUnit config stubs
2020-09-15 13:06:33 +02:00
0e89525ea8 chore: fix PHPUnit config 2020-09-15 10:45:17 +01:00
0b6cdf8f02 chore: fix PHPUnit config stubs 2020-09-15 10:44:59 +01:00
5f63d959e1 docs: updates changelog 2020-09-13 15:35:49 +02:00
be7fe41179 docs: updates changelog 2020-09-13 15:16:38 +02:00
204f343831 feat: adds toHaveKeys expectation 2020-09-13 15:15:37 +02:00
aa230a1716 docs: updates changelog 2020-09-12 23:46:45 +02:00
97f98569bc feat: adds support to PHPUnit 9.3.9 || 9.3.10 2020-09-12 23:45:22 +02:00
1318bf9830 Merge pull request #141 from olivernybroe/feat-teamcity
feat(teamcity): Add basic teamcity output format
2020-09-11 09:14:33 +01:00
3b58f946f1 Adds Scout APM as premium sponsor 2020-09-11 00:19:43 +02:00
dfc2470764 Merge pull request #179 from owenvoke/feature/badge
docs: fix GitHub Actions badge in README
2020-09-07 12:15:42 +02:00
f650978dd0 docs: fix GitHub Actions badge in README 2020-09-07 11:12:20 +01:00
c6ba469e68 release: version 2020-08-29 23:55:28 +02:00
3a9997f9af docs: updates changelog 2020-08-29 23:55:05 +02:00
fb6cb891be Merge pull request #174 from pestphp/phpunit-upgrade
Allow phpunit 9.3.8 too
2020-08-29 22:59:51 +02:00
76beda74c9 Allow phpunit 9.3.8 too 2020-08-28 16:40:17 +01:00
0398d4223b docs: updates changelog 2020-08-27 22:47:10 +02:00
360eeb4c7d Merge pull request #173 from owenvoke/feature/collision-stable
chore: update to use stable Collision 5
2020-08-26 11:00:43 +01:00
79b4224a35 chore: update to use stable Collision 5 2020-08-26 10:49:46 +01:00
3c79c893c9 Merge pull request #169 from felixdorn/forwards-calls-to-helpers
Forward TestCase bad method calls to global functions
2020-08-25 22:44:57 +02:00
a11f507191 Merge pull request #172 from owenvoke/feature/phpunit-9.3
chore: update PHPUnit configuration for coverage
2020-08-25 22:44:38 +02:00
6413f7040f chore: update PHPUnit configuration for coverage 2020-08-25 21:41:05 +01:00
278af4b835 forward bad TestCase method calls to global functions 2020-08-25 13:45:55 +02:00
fe885fbfb6 Merge pull request #170 from owenvoke/bugfix/snapshot-time
fix: update snapshot generation to strip time
2020-08-25 10:25:23 +02:00
61b2c426e4 fix: update snapshot generation to strip time 2020-08-24 21:29:56 +01:00
4272d49fb7 Merge pull request #165 from owenvoke/bugfix/decoration
fix: don't decorate output if --colors=never is set
2020-08-19 20:28:57 +01:00
014ab3b957 Merge pull request #166 from owenvoke/feature/version
chore: indicate 0.3 dev in version
2020-08-19 20:27:51 +01:00
09a0a64f20 tests: update to use version() in test 2020-08-19 16:56:40 +01:00
bf79f7c63f chore: indicate 0.3 dev in version 2020-08-19 16:48:20 +01:00
36b879f97d fix: don't decorate output if --colors=never is set 2020-08-19 13:46:07 +01:00
bcc206d183 chore(teamcity): static analysis fix 2020-08-18 14:10:32 +02:00
1e7b6a0396 Merge branch 'master' of https://github.com/pestphp/pest into feat-teamcity
 Conflicts:
	phpstan.neon
2020-08-15 08:30:46 +02:00
57a1ccd213 Merge pull request #162 from owenvoke/feature/file-expectations
feat(expectations): add file assertions
2020-08-13 10:15:37 +01:00
708b4b1d49 tests: fix snapshots 2020-08-13 10:03:23 +01:00
3695736b3a tests: update snapshots 2020-08-13 10:03:23 +01:00
8cc9580253 tests(expectations): add tests for file assertions 2020-08-13 10:03:23 +01:00
e1fbf56f3d tests(expectations): fix method in test file 2020-08-13 10:03:23 +01:00
50cd1056eb feat(expectations): add file assertions 2020-08-13 10:03:23 +01:00
cfe6a6728f Merge pull request #163 from owenvoke/feature/rector-php
build: update Rector config to PHP
2020-08-12 15:29:15 +01:00
38344c99f1 style: apply Rector changes 2020-08-12 14:45:55 +01:00
98ed779424 build: update Rector config to PHP 2020-08-12 13:03:15 +01:00
943707cbcd Merge pull request #161 from pestphp/phpunit
Require PHPUnit 9.3.7
2020-08-12 12:13:23 +01:00
940e246f27 Require PHPUnit 7.3.7 2020-08-12 11:39:57 +01:00
439ebcdcaf feat(expectation-api): adds failed assertations on not methods 2020-08-09 19:08:27 +01:00
d2db71bb78 tests: update snapshots 2020-08-09 18:31:08 +01:00
d85432933c Merge pull request #128 from GrahamCampbell/php8
feat: adds support to phpunit 9.3 and php 8.0
2020-08-08 22:53:24 +01:00
3cfadee2bb PHP 8 and PHPUnit 9.3 support 2020-08-07 11:23:45 +01:00
051ca73cae Merge pull request #156 from voyula/patch-2
Add yaml file extension support
2020-08-04 11:19:41 +01:00
50a273f1f1 Add Yaml Support
For: https://github.com/pestphp/pest/blob/master/rector.yaml
2020-08-04 12:54:49 +03:00
ffe5dde7f0 Merge pull request #151 from GrahamCampbell/patch-1
Added additional rector sets
2020-08-04 07:33:54 +01:00
7e1747a364 Merge pull request #150 from innocenzi/fix/command-interactions
Avoid command interactions when the `--no-interaction` flag is given
2020-08-03 21:26:11 +01:00
356b9c01c7 Added additional rector sets 2020-08-03 21:03:17 +01:00
4009177e56 style: fix unary_operator_space 2020-08-03 21:49:09 +02:00
46d1d46384 Merge branch 'master' of https://github.com/pestphp/pest 2020-08-03 20:48:52 +01:00
128ff1006f chore: removes broken rector set 2020-08-03 20:48:45 +01:00
64bb853720 fix: correctly avoid interactions 2020-08-03 21:39:58 +02:00
330dafa294 Merge pull request #145 from AlexMartinFR/patch-2
Update globals.php
2020-08-02 22:53:32 +01:00
a51c354268 Update globals.php
Typo.
2020-08-02 19:25:54 +02:00
cc1abe7f06 fix(teamcity): Fixed a bug when running phpunit tests together with pest tests 2020-07-31 10:25:23 +02:00
0c16942d37 refactor(teamcity): Small cleanup 2020-07-28 11:14:10 +02:00
fa413aafbb style(teamcity): fix styling 2020-07-28 10:51:57 +02:00
75f17bb118 feat(teamcity): Add basic team city output format 2020-07-28 09:11:30 +02:00
19ce733207 Merge pull request #139 from AlexMartinFR/expectations
Polishing Expectation API
2020-07-27 08:47:33 +02:00
7529d44f81 Polishing Expectation API 2020-07-26 17:20:58 +02:00
e4e4eb0a57 chore: bumps deps 2020-07-24 21:54:00 +02:00
c8eb1397b4 Merge pull request #123 from pestphp/feat/expect
feat: add `expect` function
2020-07-18 19:04:37 +02:00
c4c768dcaa tests: update snapshots 2020-07-18 18:57:14 +02:00
8c60a9fff5 Merge pull request #129 from ceceppa/feat/expect
Feat/expect
2020-07-18 18:29:32 +02:00
206e613711 Merge pull request #130 from GrahamCampbell/patch-1
Cleanup actions static analysis
2020-07-16 19:40:49 +02:00
5fb81e9eb4 Update static.yml 2020-07-16 18:36:58 +01:00
d130a1aea0 Cleanup actions static analysis 2020-07-16 18:22:17 +01:00
03201cb8b7 feat(expect): add more methods 2020-07-16 07:57:05 +01:00
46e900e8d2 feat(expect): add more methods 2020-07-16 07:35:31 +01:00
f0f79ab244 feat(expect): add more methods 2020-07-16 07:34:43 +01:00
1e61144cd2 feat(expect): handle property calls to opposite expectations 2020-07-15 01:05:36 +02:00
2751bc9674 feat(expect): fixes to contain with strings 2020-07-15 00:57:31 +02:00
e2deaae6c9 feat(expect): makes expect work with pending higher order tests 2020-07-15 00:34:59 +02:00
1aec8bac55 feat(expect): adds toHaveProperty 2020-07-14 23:37:02 +02:00
32ef377284 feat(expect): removes ignore cases related assertions 2020-07-14 23:21:51 +02:00
ab017e17e2 feat(expect): removes assertions api 2020-07-14 23:15:29 +02:00
832882160f feat(expect): updates test suite to use expectation api 2020-07-14 23:15:14 +02:00
e03d015120 Merge pull request #125 from ceceppa/feat/expect
Feat/expect
2020-07-14 21:13:42 +02:00
819825bdd2 feat(expect): add more methods 2020-07-14 08:08:13 +01:00
d29c789788 feat(expect): add more methods 2020-07-13 17:57:18 +01:00
b4c45af785 feat(expect): add more methods 2020-07-13 17:49:19 +01:00
b4bf799d75 feat(expect): add more methods 2020-07-13 17:38:09 +01:00
9f62f2d483 feat(expect): add more methods 2020-07-13 17:27:55 +01:00
679082e805 feat(expect): add more methods 2020-07-10 07:53:45 +01:00
42f0bd052e feat(expect): add more methods 2020-07-10 07:47:34 +01:00
01b9bab55f feat(expect): adds toBe 2020-07-06 00:32:12 +02:00
3eb0a95955 Merge pull request #121 from owenvoke/feature/changelog-hr
Add 'hr' tag to separate link
2020-07-02 11:20:32 +02:00
d11157f7b2 Add 'hr' tag to separate link 2020-07-02 10:15:48 +01:00
1f2ec74d6c docs: updates changelog 2020-07-02 10:04:29 +01:00
107 changed files with 2259 additions and 2179 deletions

View File

@ -14,5 +14,5 @@ trim_trailing_whitespace = true
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[*.yml] [*.{yml,yaml}]
indent_size = 2 indent_size = 2

View File

@ -13,6 +13,8 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'pestphp/pest'
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Checkout website repository - name: Checkout website repository
@ -39,6 +41,8 @@ jobs:
--- ---
${{ steps.package.outputs.content }} ${{ steps.package.outputs.content }}
----
Next section: [Upgrade Guide →](/docs/upgrade-guide) Next section: [Upgrade Guide →](/docs/upgrade-guide)
write-mode: overwrite write-mode: overwrite
- name: Copy CHANGELOG to website repository - name: Copy CHANGELOG to website repository

View File

@ -1,46 +0,0 @@
name: Formats
on: ['push', 'pull_request']
jobs:
ci:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest]
php: [7.4]
dependency-version: [prefer-lowest, prefer-stable]
name: Formats P${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cache dependencies
uses: actions/cache@v1
with:
path: ~/.composer/cache/files
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, mbstring, zip
tools: prestissimo
coverage: pcov
- name: Install Composer dependencies
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist
- name: Coding Style Checks
run: |
vendor/bin/rector process src --dry-run
vendor/bin/php-cs-fixer fix -v --dry-run
- name: Type Checks
run: vendor/bin/phpstan analyse --ansi

54
.github/workflows/static.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: Static Analysis
on: ['push', 'pull_request']
jobs:
cs:
runs-on: ubuntu-latest
name: Code Style
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
tools: composer:v2
coverage: none
- name: Install Dependencies
run: composer update --no-interaction --no-progress
- name: Run Rector
run: vendor/bin/rector process src --dry-run
- name: Run PHP-CS-Fixer
run: vendor/bin/php-cs-fixer fix -v --allow-risky=yes --dry-run
phpstan:
runs-on: ubuntu-latest
strategy:
matrix:
dependency-version: [prefer-lowest, prefer-stable]
name: PHPStan ${{ matrix.dependency-version }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
tools: composer:v2
coverage: none
- name: Install Dependencies
run: composer update --prefer-stable --no-interaction --no-progress
- name: Run PHPStan
run: vendor/bin/phpstan analyse --no-progress

View File

@ -6,43 +6,39 @@ jobs:
ci: ci:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: true
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
php: [7.3, 7.4] php: ['7.3', '7.4', '8.0']
dependency-version: [prefer-lowest, prefer-stable] dependency-version: [prefer-lowest, prefer-stable]
name: Tests P${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }} name: PHP ${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Cache dependencies
uses: actions/cache@v1
with:
path: ~/.composer/cache/files
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
- name: Setup PHP - name: Setup PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
with: with:
php-version: ${{ matrix.php }} php-version: ${{ matrix.php }}
extensions: dom, mbstring, zip tools: composer:v2
coverage: none coverage: none
- name: Install Composer dependencies - name: Setup Problem Matches
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Install PHP 7 dependencies
run: composer update --${{ matrix.dependency-version }} --no-interaction --no-progress
if: "matrix.php < 8"
- name: Install PHP 8 dependencies
run: composer update --${{ matrix.dependency-version }} --ignore-platform-req=php --no-interaction --no-progress
if: "matrix.php >= 8"
- name: Unit Tests - name: Unit Tests
run: php bin/pest --colors=always --exclude-group=integration run: php bin/pest --colors=always --exclude-group=integration
- name: Integration Tests - name: Integration Tests
run: php bin/pest --colors=always --group=integration run: php bin/pest --colors=always --group=integration
- name: Setup problem matchers for PHP
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
- name: Setup problem matchers for Pest
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

View File

@ -3,7 +3,6 @@
$finder = PhpCsFixer\Finder::create() $finder = PhpCsFixer\Finder::create()
->in(__DIR__ . DIRECTORY_SEPARATOR . 'tests') ->in(__DIR__ . DIRECTORY_SEPARATOR . 'tests')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'bin') ->in(__DIR__ . DIRECTORY_SEPARATOR . 'bin')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'compiled')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'scripts') ->in(__DIR__ . DIRECTORY_SEPARATOR . 'scripts')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'stubs') ->in(__DIR__ . DIRECTORY_SEPARATOR . 'stubs')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'src') ->in(__DIR__ . DIRECTORY_SEPARATOR . 'src')

View File

@ -5,6 +5,46 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased] ## [Unreleased]
## [v0.3.7 (2020-09-30)](https://github.com/pestphp/pest/compare/v0.3.6...v0.3.7)
### Added
- Add support for PHPUnit 9.3.11 ([#193](https://github.com/pestphp/pest/pull/193))
## [v0.3.6 (2020-09-21)](https://github.com/pestphp/pest/compare/v0.3.5...v0.3.6)
### Added
- `toMatch` expectation ([#191](https://github.com/pestphp/pest/pull/191))
- `toMatchConstraint` expectation ([#190](https://github.com/pestphp/pest/pull/190))
## [v0.3.5 (2020-09-16)](https://github.com/pestphp/pest/compare/v0.3.4...v0.3.5)
### Added
- `toStartWith` and `toEndWith` expectations ([#187](https://github.com/pestphp/pest/pull/187))
## [v0.3.4 (2020-09-15)](https://github.com/pestphp/pest/compare/v0.3.3...v0.3.4)
### Added
- `toMatchObject` expectation ([4e184b2](https://github.com/pestphp/pest/commit/4e184b2f906c318a5e9cd38fe693cdab5c48d8a2))
## [v0.3.3 (2020-09-13)](https://github.com/pestphp/pest/compare/v0.3.2...v0.3.3)
### Added
- `toHaveKeys` expectation ([204f343](https://github.com/pestphp/pest/commit/204f343831adc17bb3734553c24fac92d02f27c7))
## [v0.3.2 (2020-09-12)](https://github.com/pestphp/pest/compare/v0.3.1...v0.3.2)
### Added
- Support to PHPUnit 9.3.9, and 9.3.10 ([1318bf9](https://github.com/pestphp/pest/commit/97f98569bc86e8b87f8cde963fe7b4bf5399623b))
## [v0.3.1 (2020-08-29)](https://github.com/pestphp/pest/compare/v0.3.0...v0.3.1)
### Added
- Support to PHPUnit 9.3.8 ([#174](https://github.com/pestphp/pest/pull/174))
## [v0.3.0 (2020-08-27)](https://github.com/pestphp/pest/compare/v0.2.3...v0.3.0)
### Added
- Expectation API (TODO)
- PHPUnit 9.3 and PHP 8 support ([#128](https://github.com/pestphp/pest/pull/128))
- Fowards `$this` calls to globals ([#169](https://github.com/pestphp/pest/pull/169))
### Fixed
- don't decorate output if --colors=never is set ([36b879f](https://github.com/pestphp/pest/commit/36b879f97d7b187c87a94eb60af5b7d3b7253d56))
## [v0.2.3 (2020-07-01)](https://github.com/pestphp/pest/compare/v0.2.2...v0.2.3)
### Added ### Added
- `--init` and `pest:install` artisan command output changes ([#118](https://github.com/pestphp/pest/pull/118), [db7c4b1](https://github.com/pestphp/pest/commit/db7c4b174f0974969450dda71dcd649ef0c073a3)) - `--init` and `pest:install` artisan command output changes ([#118](https://github.com/pestphp/pest/pull/118), [db7c4b1](https://github.com/pestphp/pest/commit/db7c4b174f0974969450dda71dcd649ef0c073a3))
- `--version` option to view the current version of Pest ([9ea51ca](https://github.com/pestphp/pest/commit/9ea51caf3f74569debb1e465992e9ea916cb80fe)) - `--version` option to view the current version of Pest ([9ea51ca](https://github.com/pestphp/pest/commit/9ea51caf3f74569debb1e465992e9ea916cb80fe))

View File

@ -1,7 +1,7 @@
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/pestphp/art/master/readme.png" width="600" alt="PEST"> <img src="https://raw.githubusercontent.com/pestphp/art/master/readme.png" width="600" alt="PEST">
<p align="center"> <p align="center">
<a href="https://github.com/pestphp/pest/actions"><img alt="GitHub Workflow Status (master)" src="https://img.shields.io/github/workflow/status/pestphp/pest/Continuous Integration/master"></a> <a href="https://github.com/pestphp/pest/actions"><img alt="GitHub Workflow Status (master)" src="https://img.shields.io/github/workflow/status/pestphp/pest/Tests/master"></a>
<a href="https://packagist.org/packages/pestphp/pest"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/pestphp/pest"></a> <a href="https://packagist.org/packages/pestphp/pest"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/pestphp/pest"></a>
<a href="https://packagist.org/packages/pestphp/pest"><img alt="Latest Version" src="https://img.shields.io/packagist/v/pestphp/pest"></a> <a href="https://packagist.org/packages/pestphp/pest"><img alt="Latest Version" src="https://img.shields.io/packagist/v/pestphp/pest"></a>
<a href="https://packagist.org/packages/pestphp/pest"><img alt="License" src="https://img.shields.io/packagist/l/pestphp/pest"></a> <a href="https://packagist.org/packages/pestphp/pest"><img alt="License" src="https://img.shields.io/packagist/l/pestphp/pest"></a>
@ -15,4 +15,12 @@
- Follow us on Twitter: **[@pestphp »](https://twitter.com/pestphp)** - Follow us on Twitter: **[@pestphp »](https://twitter.com/pestphp)**
- Join us on the Discord Server: **[discord.gg/bMAJv82 »](https://discord.gg/bMAJv82)** - Join us on the Discord Server: **[discord.gg/bMAJv82 »](https://discord.gg/bMAJv82)**
## Pest Sponsors
We would like to extend our thanks to the following sponsors for funding Pest development. If you are interested in becoming a sponsor, please visit the Nuno Maduro's [Sponsors page](https://github.com/sponsors/nunomaduro).
### Premium Sponsors
- **[Scout APM](https://github.com/scoutapp)**
Pest was created by **[Nuno Maduro](https://twitter.com/enunomaduro)** under the **[Sponsorware license](https://github.com/sponsorware/docs)**. It got open-sourced and is now licensed under the **[MIT license](https://opensource.org/licenses/MIT)**. Pest was created by **[Nuno Maduro](https://twitter.com/enunomaduro)** under the **[Sponsorware license](https://github.com/sponsorware/docs)**. It got open-sourced and is now licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.

View File

@ -6,6 +6,7 @@ use Pest\Actions\ValidatesEnvironment;
use Pest\Console\Command; use Pest\Console\Command;
use Pest\Support\Container; use Pest\Support\Container;
use Pest\TestSuite; use Pest\TestSuite;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -27,7 +28,9 @@ use Symfony\Component\Console\Output\OutputInterface;
$rootPath = getcwd(); $rootPath = getcwd();
$testSuite = TestSuite::getInstance($rootPath); $testSuite = TestSuite::getInstance($rootPath);
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, true);
$isDecorated = (new ArgvInput())->getParameterOption('--colors', 'always') !== 'never';
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);
$container = Container::getInstance(); $container = Container::getInstance();
$container->add(TestSuite::class, $testSuite); $container->add(TestSuite::class, $testSuite);

View File

File diff suppressed because it is too large Load Diff

View File

@ -17,13 +17,12 @@
} }
], ],
"require": { "require": {
"php": "^7.3", "php": "^7.3 || ^8.0",
"nunomaduro/collision": "^5.0.0-BETA3", "nunomaduro/collision": "^5.0",
"pestphp/pest-plugin": "^0.2", "pestphp/pest-plugin": "^0.3",
"pestphp/pest-plugin-coverage": "^0.2", "pestphp/pest-plugin-coverage": "^0.3",
"pestphp/pest-plugin-init": "^0.2", "pestphp/pest-plugin-init": "^0.3",
"phpunit/phpunit": "^9.1.4", "phpunit/phpunit": ">= 9.3.7 <= 9.3.11"
"sebastian/environment": "^5.1"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -31,8 +30,7 @@
}, },
"files": [ "files": [
"src/globals.php", "src/globals.php",
"src/Pest.php", "src/Pest.php"
"compiled/globals.php"
] ]
}, },
"autoload-dev": { "autoload-dev": {
@ -44,16 +42,10 @@
] ]
}, },
"require-dev": { "require-dev": {
"ergebnis/phpstan-rules": "^0.15.0",
"friendsofphp/php-cs-fixer": "^2.16.3",
"illuminate/console": "^7.16.1", "illuminate/console": "^7.16.1",
"illuminate/support": "^7.16.1", "illuminate/support": "^7.16.1",
"mockery/mockery": "^1.4.0", "mockery/mockery": "^1.4.1",
"phpstan/phpstan": "^0.12.30", "pestphp/pest-dev-tools": "dev-master"
"phpstan/phpstan-strict-rules": "^0.12.2",
"rector/rector": "^0.7.37",
"symfony/var-dumper": "^5.1.2",
"thecodingmachine/phpstan-strict-rules": "^0.12.0"
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true, "prefer-stable": true,
@ -65,7 +57,6 @@
"bin/pest" "bin/pest"
], ],
"scripts": { "scripts": {
"compile": "@php ./scripts/compile.php",
"lint": "rector process src && php-cs-fixer fix -v", "lint": "rector process src && php-cs-fixer fix -v",
"test:lint": "php-cs-fixer fix -v --dry-run && rector process src --dry-run", "test:lint": "php-cs-fixer fix -v --dry-run && rector process src --dry-run",
"test:types": "phpstan analyse --ansi --memory-limit=0", "test:types": "phpstan analyse --ansi --memory-limit=0",
@ -81,7 +72,7 @@
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "0.2.x-dev" "dev-master": "0.4.x-dev"
}, },
"pest": { "pest": {
"plugins": [ "plugins": [

View File

@ -21,3 +21,13 @@ parameters:
- "# with null as default value#" - "# with null as default value#"
- "#has parameter \\$closure with default value.#" - "#has parameter \\$closure with default value.#"
- "#has parameter \\$description with default value.#" - "#has parameter \\$description with default value.#"
- "#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
-
message: '#invalid typehint type Pest\\Concerns\\TestCase#'
path: src/TeamCity.php
-
message: '#is not subtype of native type PHPUnit\\Framework\\Test#'
path: src/TeamCity.php

View File

@ -8,9 +8,9 @@
<directory suffix=".php">./tests</directory> <directory suffix=".php">./tests</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <coverage processUncoveredFiles="true">
<whitelist processUncoveredFilesFromWhitelist="true"> <include>
<directory suffix=".php">./src</directory> <directory suffix=".php">./src</directory>
</whitelist> </include>
</filter> </coverage>
</phpunit> </phpunit>

35
rector.php Normal file
View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
$parameters->set(Option::SETS, [
SetList::ACTION_INJECTION_TO_CONSTRUCTOR_INJECTION,
SetList::ARRAY_STR_FUNCTIONS_TO_STATIC_CALL,
SetList::CODE_QUALITY,
SetList::PHP_53,
SetList::PHP_54,
SetList::PHP_56,
SetList::PHP_70,
SetList::PHP_71,
SetList::PHP_72,
SetList::PHP_73,
SetList::PHPSTAN,
SetList::PHPUNIT_CODE_QUALITY,
SetList::SOLID,
]);
$parameters->set(Option::PATHS, [__DIR__ . '/src', __DIR__ . '/tests']);
$parameters->set(Option::EXCLUDE_RECTORS, [
StaticCallOnNonStaticToInstanceCallRector::class,
]);
};

View File

@ -1,16 +0,0 @@
# rector.yaml
parameters:
sets:
- 'action-injection-to-constructor-injection'
- 'array-str-functions-to-static-call'
- 'celebrity'
- 'doctrine'
- 'phpstan'
- 'phpunit-code-quality'
- 'solid'
- 'early-return'
- 'doctrine-code-quality'
- 'code-quality'
- 'php71'
- 'php72'
- 'php73'

View File

@ -5,12 +5,16 @@ declare(strict_types=1);
namespace Pest\Actions; namespace Pest\Actions;
use NunoMaduro\Collision\Adapters\Phpunit\Printer; use NunoMaduro\Collision\Adapters\Phpunit\Printer;
use Pest\TeamCity;
use PHPUnit\TextUI\DefaultResultPrinter;
/** /**
* @internal * @internal
*/ */
final class AddsDefaults final class AddsDefaults
{ {
private const PRINTER = 'printer';
/** /**
* Adds default arguments to the given `arguments` array. * Adds default arguments to the given `arguments` array.
* *
@ -20,8 +24,12 @@ final class AddsDefaults
*/ */
public static function to(array $arguments): array public static function to(array $arguments): array
{ {
if (!array_key_exists('printer', $arguments)) { if (!array_key_exists(self::PRINTER, $arguments)) {
$arguments['printer'] = new Printer(null, $arguments['verbose'] ?? false, $arguments['colors'] ?? 'always'); $arguments[self::PRINTER] = new Printer(null, $arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS);
}
if ($arguments[self::PRINTER] === \PHPUnit\Util\Log\TeamCity::class) {
$arguments[self::PRINTER] = new TeamCity($arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS);
} }
return $arguments; return $arguments;

View File

@ -6,8 +6,7 @@ namespace Pest\Actions;
use Pest\Exceptions\AttributeNotSupportedYet; use Pest\Exceptions\AttributeNotSupportedYet;
use Pest\Exceptions\FileOrFolderNotFound; use Pest\Exceptions\FileOrFolderNotFound;
use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\XmlConfiguration\Loader;
use PHPUnit\TextUI\Configuration\Registry;
/** /**
* @internal * @internal
@ -30,9 +29,7 @@ final class ValidatesConfiguration
throw new FileOrFolderNotFound('phpunit.xml'); throw new FileOrFolderNotFound('phpunit.xml');
} }
$configuration = Registry::getInstance() $configuration = (new Loader())->load($arguments[self::CONFIGURATION_KEY])->phpunit();
->get($arguments[self::CONFIGURATION_KEY])
->phpunit();
if ($configuration->processIsolation()) { if ($configuration->processIsolation()) {
throw new AttributeNotSupportedYet('processIsolation', 'true'); throw new AttributeNotSupportedYet('processIsolation', 'true');

View File

@ -5,9 +5,11 @@ declare(strict_types=1);
namespace Pest\Concerns; namespace Pest\Concerns;
use Closure; use Closure;
use Pest\Expectation;
use Pest\Support\ExceptionTrace; use Pest\Support\ExceptionTrace;
use Pest\TestSuite; use Pest\TestSuite;
use PHPUnit\Util\Test; use PHPUnit\Util\Test;
use Throwable;
/** /**
* To avoid inheritance conflicts, all the fields related * To avoid inheritance conflicts, all the fields related
@ -63,6 +65,11 @@ trait TestCase
return $this->__description; return $this->__description;
} }
public static function __getFileName(): string
{
return self::$__filename;
}
/** /**
* This method is called before the first test of this test class is run. * This method is called before the first test of this test class is run.
*/ */
@ -87,6 +94,16 @@ trait TestCase
parent::tearDownAfterClass(); parent::tearDownAfterClass();
} }
/**
* Creates a new expectation.
*
* @param mixed $value
*/
public function expect($value): Expectation
{
return new Expectation($value);
}
/** /**
* Gets executed before the test. * Gets executed before the test.
*/ */
@ -132,7 +149,7 @@ trait TestCase
* *
* @return mixed * @return mixed
* *
* @throws \Throwable * @throws Throwable
*/ */
public function __test() public function __test()
{ {
@ -142,7 +159,7 @@ trait TestCase
/** /**
* @return mixed * @return mixed
* *
* @throws \Throwable * @throws Throwable
*/ */
private function __callClosure(Closure $closure, array $arguments) private function __callClosure(Closure $closure, array $arguments)
{ {

538
src/Expectation.php Normal file
View File

@ -0,0 +1,538 @@
<?php
declare(strict_types=1);
namespace Pest;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\Constraint\Constraint;
/**
* @internal
*
* @property Expectation $not Creates the opposite expectation.
*/
final class Expectation
{
/**
* The expectation value.
*
* @readonly
*
* @var mixed
*/
public $value;
/**
* Creates a new expectation.
*
* @param mixed $value
*/
public function __construct($value)
{
$this->value = $value;
}
/**
* Creates a new expectation.
*
* @param mixed $value
*/
public function and($value): Expectation
{
return new self($value);
}
/**
* Creates the opposite expectation for the value.
*/
public function not(): OppositeExpectation
{
return new OppositeExpectation($this);
}
/**
* Asserts that two variables have the same type and
* value. Used on objects, it asserts that two
* variables reference the same object.
*
* @param mixed $expected
*/
public function toBe($expected): Expectation
{
Assert::assertSame($expected, $this->value);
return $this;
}
/**
* Asserts that the value is empty.
*/
public function toBeEmpty(): Expectation
{
Assert::assertEmpty($this->value);
return $this;
}
/**
* Asserts that the value is true.
*/
public function toBeTrue(): Expectation
{
Assert::assertTrue($this->value);
return $this;
}
/**
* Asserts that the value is false.
*/
public function toBeFalse(): Expectation
{
Assert::assertFalse($this->value);
return $this;
}
/**
* Asserts that the value is greater than $expected.
*
* @param int|float $expected
*/
public function toBeGreaterThan($expected): Expectation
{
Assert::assertGreaterThan($expected, $this->value);
return $this;
}
/**
* Asserts that the value is greater than or equal to $expected.
*
* @param int|float $expected
*/
public function toBeGreaterThanOrEqual($expected): Expectation
{
Assert::assertGreaterThanOrEqual($expected, $this->value);
return $this;
}
/**
* Asserts that the value is less than or equal to $expected.
*
* @param int|float $expected
*/
public function toBeLessThan($expected): Expectation
{
Assert::assertLessThan($expected, $this->value);
return $this;
}
/**
* Asserts that the value is less than $expected.
*
* @param int|float $expected
*/
public function toBeLessThanOrEqual($expected): Expectation
{
Assert::assertLessThanOrEqual($expected, $this->value);
return $this;
}
/**
* Asserts that $needle is an element of the value.
*
* @param mixed $needle
*/
public function toContain($needle): Expectation
{
if (is_string($this->value)) {
Assert::assertStringContainsString($needle, $this->value);
} else {
Assert::assertContains($needle, $this->value);
}
return $this;
}
/**
* Asserts that the value starts with $expected.
*/
public function toStartWith(string $expected): Expectation
{
Assert::assertStringStartsWith($expected, $this->value);
return $this;
}
/**
* Asserts that the value ends with $expected.
*/
public function toEndWith(string $expected): Expectation
{
Assert::assertStringEndsWith($expected, $this->value);
return $this;
}
/**
* Asserts that $count matches the number of elements of the value.
*/
public function toHaveCount(int $count): Expectation
{
Assert::assertCount($count, $this->value);
return $this;
}
/**
* Asserts that the value contains the property $name.
*
* @param mixed $value
*/
public function toHaveProperty(string $name, $value = null): Expectation
{
$this->toBeObject();
Assert::assertTrue(property_exists($this->value, $name));
if (func_num_args() > 1) {
/* @phpstan-ignore-next-line */
Assert::assertEquals($value, $this->value->{$name});
}
return $this;
}
/**
* Asserts that two variables have the same value.
*
* @param mixed $expected
*/
public function toEqual($expected): Expectation
{
Assert::assertEquals($expected, $this->value);
return $this;
}
/**
* Asserts that two variables have the same value.
* The contents of $expected and the $this->value are
* canonicalized before they are compared. For instance, when the two
* variables $expected and $this->value are arrays, then these arrays
* are sorted before they are compared. When $expected and $this->value
* are objects, each object is converted to an array containing all
* private, protected and public attributes.
*
* @param mixed $expected
*/
public function toEqualCanonicalizing($expected): Expectation
{
Assert::assertEqualsCanonicalizing($expected, $this->value);
return $this;
}
/**
* Asserts that the absolute difference between the value and $expected
* is lower than $delta.
*
* @param mixed $expected
*/
public function toEqualWithDelta($expected, float $delta): Expectation
{
Assert::assertEqualsWithDelta($expected, $this->value, $delta);
return $this;
}
/**
* Asserts that the value is infinite.
*/
public function toBeInfinite(): Expectation
{
Assert::assertInfinite($this->value);
return $this;
}
/**
* Asserts that the value is an instance of $class.
*
* @param string $class
*/
public function toBeInstanceOf($class): Expectation
{
/* @phpstan-ignore-next-line */
Assert::assertInstanceOf($class, $this->value);
return $this;
}
/**
* Asserts that the value is an array.
*/
public function toBeArray(): Expectation
{
Assert::assertIsArray($this->value);
return $this;
}
/**
* Asserts that the value is of type bool.
*/
public function toBeBool(): Expectation
{
Assert::assertIsBool($this->value);
return $this;
}
/**
* Asserts that the value is of type callable.
*/
public function toBeCallable(): Expectation
{
Assert::assertIsCallable($this->value);
return $this;
}
/**
* Asserts that the value is of type float.
*/
public function toBeFloat(): Expectation
{
Assert::assertIsFloat($this->value);
return $this;
}
/**
* Asserts that the value is of type int.
*/
public function toBeInt(): Expectation
{
Assert::assertIsInt($this->value);
return $this;
}
/**
* Asserts that the value is of type iterable.
*/
public function toBeIterable(): Expectation
{
Assert::assertIsIterable($this->value);
return $this;
}
/**
* Asserts that the value is of type numeric.
*/
public function toBeNumeric(): Expectation
{
Assert::assertIsNumeric($this->value);
return $this;
}
/**
* Asserts that the value is of type object.
*/
public function toBeObject(): Expectation
{
Assert::assertIsObject($this->value);
return $this;
}
/**
* Asserts that the value is of type resource.
*/
public function toBeResource(): Expectation
{
Assert::assertIsResource($this->value);
return $this;
}
/**
* Asserts that the value is of type scalar.
*/
public function toBeScalar(): Expectation
{
Assert::assertIsScalar($this->value);
return $this;
}
/**
* Asserts that the value is of type string.
*/
public function toBeString(): Expectation
{
Assert::assertIsString($this->value);
return $this;
}
/**
* Asserts that the value is NAN.
*/
public function toBeNan(): Expectation
{
Assert::assertNan($this->value);
return $this;
}
/**
* Asserts that the value is null.
*/
public function toBeNull(): Expectation
{
Assert::assertNull($this->value);
return $this;
}
/**
* Asserts that the value array has the provided $key.
*
* @param string|int $key
*/
public function toHaveKey($key): Expectation
{
Assert::assertArrayHasKey($key, $this->value);
return $this;
}
/**
* Asserts that the value array has the provided $keys.
*
* @param array<int, int|string> $keys
*/
public function toHaveKeys(array $keys): Expectation
{
foreach ($keys as $key) {
$this->toHaveKey($key);
}
return $this;
}
/**
* Asserts that the value is a directory.
*/
public function toBeDirectory(): Expectation
{
Assert::assertDirectoryExists($this->value);
return $this;
}
/**
* Asserts that the value is a directory and is readable.
*/
public function toBeReadableDirectory(): Expectation
{
Assert::assertDirectoryIsReadable($this->value);
return $this;
}
/**
* Asserts that the value is a directory and is writable.
*/
public function toBeWritableDirectory(): Expectation
{
Assert::assertDirectoryIsWritable($this->value);
return $this;
}
/**
* Asserts that the value is a file.
*/
public function toBeFile(): Expectation
{
Assert::assertFileExists($this->value);
return $this;
}
/**
* Asserts that the value is a file and is readable.
*/
public function toBeReadableFile(): Expectation
{
Assert::assertFileIsReadable($this->value);
return $this;
}
/**
* Asserts that the value is a file and is writable.
*/
public function toBeWritableFile(): Expectation
{
Assert::assertFileIsWritable($this->value);
return $this;
}
/**
* Asserts that the value object matches a subset
* of the properties of an given object.
*
* @param array<string, mixed>|object $object
*/
public function toMatchObject($object): Expectation
{
foreach ((array) $object as $property => $value) {
$this->toHaveProperty($property, $value);
}
return $this;
}
/**
* Asserts that the value matches a regular expression.
*/
public function toMatch(string $expression): Expectation
{
Assert::assertMatchesRegularExpression($expression, $this->value);
return $this;
}
/**
* Asserts that the value matches a constraint.
*/
public function toMatchConstraint(Constraint $constraint): Expectation
{
Assert::assertThat($this->value, $constraint);
return $this;
}
/**
* Dynamically calls methods on the class without any arguments.
*
* @return Expectation
*/
public function __get(string $name)
{
/* @phpstan-ignore-next-line */
return $this->{$name}();
}
}

View File

@ -157,8 +157,15 @@ final class TestCaseFactory
} }
/** /**
* Makes a fully qualified class name * Makes a fully qualified class name from the current filename.
* from the given filename. */
public function getClassName(): string
{
return $this->makeClassFromFilename($this->filename);
}
/**
* Makes a fully qualified class name from the given filename.
*/ */
public function makeClassFromFilename(string $filename): string public function makeClassFromFilename(string $filename): string
{ {

View File

@ -61,7 +61,8 @@ final class PestDatasetCommand extends Command
$element = Str::singular($name); $element = Str::singular($name);
$contents = str_replace('{dataset_element}', $element, $contents); $contents = str_replace('{dataset_element}', $element, $contents);
File::put($target, str_replace('{dataset_name}', $name, $contents)); File::put($target, str_replace('{dataset_name}', $name, $contents));
$message = sprintf('`%s` created successfully.', $relativePath);
$this->output->success(sprintf('`%s` created successfully.', $relativePath)); $this->output->success($message);
} }
} }

View File

@ -6,6 +6,7 @@ namespace Pest\Laravel\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Pest\Console\Thanks;
use Pest\Exceptions\InvalidConsoleArgument; use Pest\Exceptions\InvalidConsoleArgument;
use Pest\Support\Str; use Pest\Support\Str;
@ -60,7 +61,9 @@ final class PestInstallCommand extends Command
$this->output->success('`tests/Pest.php` created successfully.'); $this->output->success('`tests/Pest.php` created successfully.');
$this->output->success('`tests/Helpers.php` created successfully.'); $this->output->success('`tests/Helpers.php` created successfully.');
(new \Pest\Console\Thanks($this->output))(); if (!(bool) $this->option('no-interaction')) {
(new Thanks($this->output))();
}
} }
/** /**

View File

@ -64,7 +64,8 @@ final class PestTestCommand extends Command
$name = Str::endsWith($name, 'test') ? mb_substr($name, 0, -4) : $name; $name = Str::endsWith($name, 'test') ? mb_substr($name, 0, -4) : $name;
File::put($target, str_replace('{name}', $name, $contents)); File::put($target, str_replace('{name}', $name, $contents));
$message = sprintf('`%s` created successfully.', $relativePath);
$this->output->success(sprintf('`%s` created successfully.', $relativePath)); $this->output->success($message);
} }
} }

100
src/OppositeExpectation.php Normal file
View File

@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace Pest;
use PHPUnit\Framework\ExpectationFailedException;
use SebastianBergmann\Exporter\Exporter;
/**
* @internal
*
* @mixin Expectation
*/
final class OppositeExpectation
{
/**
* @var Expectation
*/
private $original;
/**
* Creates a new opposite expectation.
*/
public function __construct(Expectation $original)
{
$this->original = $original;
}
/**
* Asserts that the value array not has the provided $keys.
*
* @param array<int, int|string> $keys
*/
public function toHaveKeys(array $keys): Expectation
{
foreach ($keys as $key) {
try {
$this->original->toHaveKey($key);
} catch (ExpectationFailedException $e) {
continue;
}
$this->throwExpectationFailedExpection('toHaveKey', [$key]);
}
return $this->original;
}
/**
* Handle dynamic method calls into the original expectation.
*
* @param array<int, mixed> $arguments
*/
public function __call(string $name, array $arguments): Expectation
{
try {
/* @phpstan-ignore-next-line */
$this->original->{$name}(...$arguments);
} catch (ExpectationFailedException $e) {
return $this->original;
}
// @phpstan-ignore-next-line
$this->throwExpectationFailedExpection($name, $arguments);
}
/**
* Handle dynamic properties gets into the original expectation.
*/
public function __get(string $name): Expectation
{
try {
/* @phpstan-ignore-next-line */
$this->original->{$name};
} catch (ExpectationFailedException $e) {
return $this->original;
}
// @phpstan-ignore-next-line
$this->throwExpectationFailedExpection($name);
}
/**
* Creates a new expectation failed exception
* with a nice readable message.
*
* @param array<int, mixed> $arguments
*/
private function throwExpectationFailedExpection(string $name, array $arguments = []): void
{
$exporter = new Exporter();
$toString = function ($argument) use ($exporter): string {
return $exporter->shortenedExport($argument);
};
throw new ExpectationFailedException(sprintf('Expecting %s not %s %s.', $toString($this->original->value), strtolower((string) preg_replace('/(?<!\ )[A-Z]/', ' $0', $name)), implode(' ', array_map(function ($argument) use ($toString): string { return $toString($argument); }, $arguments))));
}
}

View File

@ -9,9 +9,12 @@ use Pest\Factories\TestCaseFactory;
use Pest\Support\Backtrace; use Pest\Support\Backtrace;
use Pest\Support\NullClosure; use Pest\Support\NullClosure;
use Pest\TestSuite; use Pest\TestSuite;
use PHPUnit\Framework\ExecutionOrderDependency;
use SebastianBergmann\Exporter\Exporter; use SebastianBergmann\Exporter\Exporter;
/** /**
* @method \Pest\Expectation expect(mixed $value)
*
* @internal * @internal
*/ */
final class TestCall final class TestCall
@ -89,6 +92,12 @@ final class TestCall
*/ */
public function depends(string ...$tests): TestCall public function depends(string ...$tests): TestCall
{ {
$className = $this->testCaseFactory->getClassName();
$tests = array_map(function (string $test) use ($className): ExecutionOrderDependency {
return ExecutionOrderDependency::createFromDependsAnnotation($className, $test);
}, $tests);
$this->testCaseFactory $this->testCaseFactory
->factoryProxies ->factoryProxies
->add(Backtrace::file(), Backtrace::line(), 'setDependencies', [$tests]); ->add(Backtrace::file(), Backtrace::line(), 'setDependencies', [$tests]);

View File

@ -6,5 +6,5 @@ namespace Pest;
function version(): string function version(): string
{ {
return '0.2.2'; return '0.3.6';
} }

View File

@ -11,6 +11,7 @@ use Pest\Exceptions\TestCaseClassOrTraitNotFound;
use Pest\Factories\TestCaseFactory; use Pest\Factories\TestCaseFactory;
use Pest\Support\Str; use Pest\Support\Str;
use Pest\TestSuite; use Pest\TestSuite;
use PHPUnit\Framework\TestCase;
/** /**
* @internal * @internal
@ -52,7 +53,7 @@ final class TestRepository
if ((!is_dir($path) && $filename === $path) || (is_dir($path) && $startsWith($filename, $path))) { if ((!is_dir($path) && $filename === $path) || (is_dir($path) && $startsWith($filename, $path))) {
foreach ($classOrTraits as $class) { foreach ($classOrTraits as $class) {
if (class_exists($class)) { if (class_exists($class)) {
if ($testCase->class !== \PHPUnit\Framework\TestCase::class) { if ($testCase->class !== TestCase::class) {
throw new TestCaseAlreadyInUse($testCase->class, $class, $filename); throw new TestCaseAlreadyInUse($testCase->class, $class, $filename);
} }
$testCase->class = $class; $testCase->class = $class;

View File

@ -75,14 +75,15 @@ final class Container
if ($constructor !== null) { if ($constructor !== null) {
$params = array_map( $params = array_map(
function (ReflectionParameter $param) use ($id) { function (ReflectionParameter $param) use ($id) {
$candidate = null; $candidate = Reflection::getParameterClassName($param);
if ($param->getType() !== null && $param->getType()->isBuiltin()) { if ($candidate === null) {
$candidate = $param->getName(); $type = $param->getType();
} elseif ($param->getClass() !== null) { if ($type !== null && $type->isBuiltin()) {
$candidate = $param->getClass()->getName(); $candidate = $param->getName();
} else { } else {
throw ShouldNotHappen::fromMessage(sprintf('The type of `$%s` in `%s` cannot be determined.', $id, $param->getName())); throw ShouldNotHappen::fromMessage(sprintf('The type of `$%s` in `%s` cannot be determined.', $id, $param->getName()));
}
} }
return $this->get($candidate); return $this->get($candidate);

View File

@ -20,7 +20,7 @@ final class ExceptionTrace
* *
* @return mixed * @return mixed
* *
* @throws \Throwable * @throws Throwable
*/ */
public static function ensure(Closure $closure) public static function ensure(Closure $closure)
{ {

View File

@ -76,8 +76,8 @@ final class HigherOrderMessage
Reflection::setPropertyValue($throwable, 'file', $this->filename); Reflection::setPropertyValue($throwable, 'file', $this->filename);
Reflection::setPropertyValue($throwable, 'line', $this->line); Reflection::setPropertyValue($throwable, 'line', $this->line);
if ($throwable->getMessage() === sprintf(self::UNDEFINED_METHOD, $this->methodName)) { if ($throwable->getMessage() === self::getUndefinedMethodMessage($target, $this->methodName)) {
/** @var \ReflectionClass $reflection */ /** @var ReflectionClass $reflection */
$reflection = new ReflectionClass($target); $reflection = new ReflectionClass($target);
/* @phpstan-ignore-next-line */ /* @phpstan-ignore-next-line */
$reflection = $reflection->getParentClass() ?: $reflection; $reflection = $reflection->getParentClass() ?: $reflection;
@ -87,4 +87,13 @@ final class HigherOrderMessage
throw $throwable; throw $throwable;
} }
} }
private static function getUndefinedMethodMessage(object $target, string $methodName): string
{
if (\PHP_MAJOR_VERSION >= 8) {
return sprintf(sprintf(self::UNDEFINED_METHOD, sprintf('%s::%s()', get_class($target), $methodName)));
}
return sprintf(self::UNDEFINED_METHOD, $methodName);
}
} }

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Pest\Support; namespace Pest\Support;
use ReflectionClass; use ReflectionClass;
use Throwable;
/** /**
* @internal * @internal
@ -51,12 +52,12 @@ final class HigherOrderTapProxy
try { try {
// @phpstan-ignore-next-line // @phpstan-ignore-next-line
return $this->target->{$property}; return $this->target->{$property};
} catch (\Throwable $throwable) { } catch (Throwable $throwable) {
Reflection::setPropertyValue($throwable, 'file', Backtrace::file()); Reflection::setPropertyValue($throwable, 'file', Backtrace::file());
Reflection::setPropertyValue($throwable, 'line', Backtrace::line()); Reflection::setPropertyValue($throwable, 'line', Backtrace::line());
if (Str::startsWith($message = $throwable->getMessage(), self::UNDEFINED_PROPERTY)) { if (Str::startsWith($message = $throwable->getMessage(), self::UNDEFINED_PROPERTY)) {
/** @var \ReflectionClass $reflection */ /** @var ReflectionClass $reflection */
$reflection = (new ReflectionClass($this->target))->getParentClass(); $reflection = (new ReflectionClass($this->target))->getParentClass();
Reflection::setPropertyValue($throwable, 'message', sprintf('Undefined property %s::$%s', $reflection->getName(), $property)); Reflection::setPropertyValue($throwable, 'message', sprintf('Undefined property %s::$%s', $reflection->getName(), $property));
} }

View File

@ -6,9 +6,12 @@ namespace Pest\Support;
use Closure; use Closure;
use Pest\Exceptions\ShouldNotHappen; use Pest\Exceptions\ShouldNotHappen;
use Pest\TestSuite;
use ReflectionClass; use ReflectionClass;
use ReflectionException; use ReflectionException;
use ReflectionFunction; use ReflectionFunction;
use ReflectionNamedType;
use ReflectionParameter;
use ReflectionProperty; use ReflectionProperty;
/** /**
@ -38,6 +41,12 @@ final class Reflection
return $object->__call($method, $args); return $object->__call($method, $args);
} }
if (is_callable($method)) {
return Closure::fromCallable($method)->bindTo(
TestSuite::getInstance()->test
)(...$args);
}
throw $exception; throw $exception;
} }
} }
@ -117,4 +126,32 @@ final class Reflection
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($object, $value); $reflectionProperty->setValue($object, $value);
} }
/**
* Get the class name of the given parameter's type, if possible.
*
* @see https://github.com/laravel/framework/blob/v6.18.25/src/Illuminate/Support/Reflector.php
*/
public static function getParameterClassName(ReflectionParameter $parameter): ?string
{
$type = $parameter->getType();
if (!$type instanceof ReflectionNamedType || $type->isBuiltin()) {
return null;
}
$name = $type->getName();
if (($class = $parameter->getDeclaringClass()) instanceof ReflectionClass) {
if ($name === 'self') {
return $class->getName();
}
if ($name === 'parent' && ($parent = $class->getParentClass()) instanceof ReflectionClass) {
return $parent->getName();
}
}
return $name;
}
} }

235
src/TeamCity.php Normal file
View File

@ -0,0 +1,235 @@
<?php
declare(strict_types=1);
namespace Pest;
use function getmypid;
use Pest\Concerns\TestCase;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestResult;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\Warning;
use PHPUnit\TextUI\DefaultResultPrinter;
use function round;
use function str_replace;
use Throwable;
final class TeamCity extends DefaultResultPrinter
{
private const PROTOCOL = 'pest_qn://';
private const NAME = 'name';
private const LOCATION_HINT = 'locationHint';
private const DURATION = 'duration';
private const TEST_SUITE_STARTED = 'testSuiteStarted';
private const TEST_SUITE_FINISHED = 'testSuiteFinished';
private const TEST_FAILED = 'testFailed';
/** @var int */
private $flowId;
/** @var bool */
private $isSummaryTestCountPrinted = false;
/** @var \PHPUnit\Util\Log\TeamCity */
private $phpunitTeamCity;
public function __construct(bool $verbose, string $colors)
{
parent::__construct(null, $verbose, $colors, false, 80, false);
$this->phpunitTeamCity = new \PHPUnit\Util\Log\TeamCity(
null,
$verbose,
$colors,
false,
80,
false
);
}
public function printResult(TestResult $result): void
{
$this->printHeader($result);
$this->printFooter($result);
}
/** @phpstan-ignore-next-line */
public function startTestSuite(TestSuite $suite): void
{
$this->flowId = getmypid();
if (!$this->isSummaryTestCountPrinted) {
$this->printEvent(
'testCount',
['count' => $suite->count()]
);
$this->isSummaryTestCountPrinted = true;
}
$suiteName = $suite->getName();
if (file_exists($suiteName) || !method_exists($suiteName, '__getFileName')) {
$this->printEvent(
self::TEST_SUITE_STARTED, [
self::NAME => $suiteName,
self::LOCATION_HINT => self::PROTOCOL . $suiteName,
]);
return;
}
$fileName = $suiteName::__getFileName();
$this->printEvent(
self::TEST_SUITE_STARTED, [
self::NAME => substr($suiteName, 2),
self::LOCATION_HINT => self::PROTOCOL . $fileName,
]);
}
/** @phpstan-ignore-next-line */
public function endTestSuite(TestSuite $suite): void
{
$suiteName = $suite->getName();
if (file_exists($suiteName) || !method_exists($suiteName, '__getFileName')) {
$this->printEvent(
self::TEST_SUITE_FINISHED, [
self::NAME => $suiteName,
self::LOCATION_HINT => self::PROTOCOL . $suiteName,
]);
return;
}
$this->printEvent(
self::TEST_SUITE_FINISHED, [
self::NAME => substr($suiteName, 2),
]);
}
/**
* @param Test|TestCase $test
*/
public function startTest(Test $test): void
{
if (!TeamCity::isPestTest($test)) {
$this->phpunitTeamCity->startTest($test);
return;
}
$this->printEvent('testStarted', [
self::NAME => $test->getName(),
/* @phpstan-ignore-next-line */
self::LOCATION_HINT => self::PROTOCOL . $test->toString(),
]);
}
/**
* @param Test|TestCase $test
*/
public function endTest(Test $test, float $time): void
{
if (!TeamCity::isPestTest($test)) {
$this->phpunitTeamCity->endTest($test, $time);
return;
}
$this->printEvent('testFinished', [
self::NAME => $test->getName(),
self::DURATION => self::toMilliseconds($time),
]);
}
/**
* @param Test|TestCase $test
*/
public function addError(Test $test, Throwable $t, float $time): void
{
if (!TeamCity::isPestTest($test)) {
$this->phpunitTeamCity->addError($test, $t, $time);
return;
}
$this->printEvent(
self::TEST_FAILED, [
self::NAME => $test->getName(),
'message' => $t->getMessage(),
'details' => $t->getTraceAsString(),
self::DURATION => self::toMilliseconds($time),
]);
}
/**
* @phpstan-ignore-next-line
*
* @param Test|TestCase $test
*/
public function addWarning(Test $test, Warning $e, float $time): void
{
if (!TeamCity::isPestTest($test)) {
$this->phpunitTeamCity->addWarning($test, $e, $time);
return;
}
$this->printEvent(
self::TEST_FAILED, [
self::NAME => $test->getName(),
'message' => $e->getMessage(),
'details' => $e->getTraceAsString(),
self::DURATION => self::toMilliseconds($time),
]);
}
public function addFailure(Test $test, AssertionFailedError $e, float $time): void
{
$this->phpunitTeamCity->addFailure($test, $e, $time);
}
protected function writeProgress(string $progress): void
{
}
/**
* @param array<string, string|int> $params
*/
private function printEvent(string $eventName, array $params = []): void
{
$this->write("\n##teamcity[{$eventName}");
if ($this->flowId !== 0) {
$params['flowId'] = $this->flowId;
}
foreach ($params as $key => $value) {
$escapedValue = self::escapeValue((string) $value);
$this->write(" {$key}='{$escapedValue}'");
}
$this->write("]\n");
}
private static function escapeValue(string $text): string
{
return str_replace(
['|', "'", "\n", "\r", ']', '['],
['||', "|'", '|n', '|r', '|]', '|['],
$text
);
}
private static function toMilliseconds(float $time): int
{
return (int) round($time * 1000);
}
private static function isPestTest(Test $test): bool
{
return in_array(TestCase::class, class_uses($test), true);
}
}

View File

@ -10,6 +10,7 @@ use Pest\Repositories\AfterEachRepository;
use Pest\Repositories\BeforeAllRepository; use Pest\Repositories\BeforeAllRepository;
use Pest\Repositories\BeforeEachRepository; use Pest\Repositories\BeforeEachRepository;
use Pest\Repositories\TestRepository; use Pest\Repositories\TestRepository;
use PHPUnit\Framework\TestCase;
/** /**
* @internal * @internal
@ -19,7 +20,7 @@ final class TestSuite
/** /**
* Holds the current test case. * Holds the current test case.
* *
* @var \PHPUnit\Framework\TestCase|null * @var TestCase|null
*/ */
public $test; public $test;

View File

@ -3,6 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use Pest\Datasets; use Pest\Datasets;
use Pest\Expectation;
use Pest\PendingObjects\AfterEachCall; use Pest\PendingObjects\AfterEachCall;
use Pest\PendingObjects\BeforeEachCall; use Pest\PendingObjects\BeforeEachCall;
use Pest\PendingObjects\TestCall; use Pest\PendingObjects\TestCall;
@ -43,8 +44,8 @@ function dataset(string $name, $dataset): void
} }
/** /**
* The uses function adds the binds the * The uses function binds the given
* given arguments to test closures. * arguments to test closures.
*/ */
function uses(string ...$classAndTraits): UsesCall function uses(string ...$classAndTraits): UsesCall
{ {
@ -104,3 +105,15 @@ function afterAll(Closure $closure = null): void
{ {
TestSuite::getInstance()->afterAll->set($closure); TestSuite::getInstance()->afterAll->set($closure);
} }
/**
* Creates a new expectation.
*
* @param mixed $value the Value
*
* @return Expectation
*/
function expect($value)
{
return test()->expect($value);
}

View File

@ -12,10 +12,10 @@
<directory suffix="Test.php">./tests/Feature</directory> <directory suffix="Test.php">./tests/Feature</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <coverage processUncoveredFiles="true">
<whitelist processUncoveredFilesFromWhitelist="true"> <include>
<directory suffix=".php">./app</directory> <directory suffix=".php">./app</directory>
<directory suffix=".php">./src</directory> <directory suffix=".php">./src</directory>
</whitelist> </include>
</filter> </coverage>
</phpunit> </phpunit>

View File

@ -9,9 +9,9 @@
<directory suffix="Test.php">./tests</directory> <directory suffix="Test.php">./tests</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <coverage processUncoveredFiles="true">
<whitelist processUncoveredFilesFromWhitelist="true"> <include>
<directory suffix=".php">./app</directory> <directory suffix=".php">./app</directory>
</whitelist> </include>
</filter> </coverage>
</phpunit> </phpunit>

View File

@ -2,6 +2,221 @@
PASS Tests\CustomTestCase\ExecutedTest PASS Tests\CustomTestCase\ExecutedTest
✓ that gets executed ✓ that gets executed
PASS Tests\Expect\not
✓ not property calls
PASS Tests\Expect\toBe
✓ expect true → toBeTrue → and false → toBeFalse
✓ strict comparisons
✓ failures
✓ not failures
PASS Tests\Expect\toBeArray
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeBool
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeCallable
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeDirectory
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeEmpty
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeFalse
✓ strict comparisons
✓ failures
✓ not failures
PASS Tests\Expect\toBeFile
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeFloat
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeGreatherThan
✓ passes
✓ failures
✓ not failures
PASS Tests\Expect\toBeGreatherThanOrEqual
✓ passes
✓ failures
✓ not failures
PASS Tests\Expect\toBeInfinite
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeInstanceOf
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeInt
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeIterable
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeLessThan
✓ passes
✓ failures
✓ not failures
PASS Tests\Expect\toBeLessThanOrEqual
✓ passes
✓ failures
✓ not failures
PASS Tests\Expect\toBeNAN
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeNull
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeNumeric
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeObject
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeReadableDirectory
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeReadableFile
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeResource
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeScalar
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeString
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeTrue
✓ strict comparisons
✓ failures
✓ not failures
PASS Tests\Expect\toBeWritableDirectory
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toBeWritableFile
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toContain
✓ passes strings
✓ passes arrays
✓ failures
✓ not failures
PASS Tests\Expect\toEndWith
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toEqual
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toEqualCanonicalizing
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toEqualWithDelta
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toHaveCount
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toHaveKey
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toHaveKeys
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toHaveProperty
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toMatch
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toMatchConstraint
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toMatchObject
✓ pass
✓ failures
✓ not failures
PASS Tests\Expect\toStartWith
✓ pass
✓ failures
✓ not failures
PASS Tests\Features\AfterAll PASS Tests\Features\AfterAll
✓ deletes file after all ✓ deletes file after all
@ -49,14 +264,6 @@
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #3 ✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #3
✓ it creates unique test case names - count ✓ it creates unique test case names - count
PASS Tests\Features\Depends
✓ first
✓ second
✓ depends
✓ depends with ...params
✓ depends with defined arguments
✓ depends run test only once
PASS Tests\Features\Exceptions PASS Tests\Features\Exceptions
✓ it gives access the the underlying expectException ✓ it gives access the the underlying expectException
✓ it catch exceptions ✓ it catch exceptions
@ -67,6 +274,7 @@
✓ it throws error if property do not exist ✓ it throws error if property do not exist
✓ it allows to call underlying protected/private methods ✓ it allows to call underlying protected/private methods
✓ it throws error if method do not exist ✓ it throws error if method do not exist
✓ it can forward unexpected calls to any global function
PASS Tests\Features\HigherOrderTests PASS Tests\Features\HigherOrderTests
✓ it proxies calls to object ✓ it proxies calls to object
@ -83,8 +291,8 @@
✓ it has bar ✓ it has bar
PASS Tests\Features\PendingHigherOrderTests PASS Tests\Features\PendingHigherOrderTests
✓ get 'foo' → get 'bar' → assertTrue true ✓ get 'foo' → get 'bar' → expect true → toBeTrue
✓ get 'foo' → assertTrue true ✓ get 'foo' → expect true → toBeTrue
WARN Tests\Features\Skip WARN Tests\Features\Skip
✓ it do not skips ✓ it do not skips
@ -167,5 +375,13 @@
WARN Tests\Visual\Success WARN Tests\Visual\Success
- visual snapshot of test suite on success - visual snapshot of test suite on success
Tests: 6 skipped, 96 passed PASS Tests\Features\Depends
Time: 3.43s ✓ first
✓ second
✓ depends
✓ depends with ...params
✓ depends with defined arguments
✓ depends run test only once
Tests: 6 skipped, 226 passed

View File

@ -8,7 +8,7 @@ trait PluginTrait
{ {
public function assertPluginTraitGotRegistered(): void public function assertPluginTraitGotRegistered(): void
{ {
assertTrue(true); $this->assertTrue(true);
} }
} }
@ -16,9 +16,14 @@ trait SecondPluginTrait
{ {
public function assertSecondPluginTraitGotRegistered(): void public function assertSecondPluginTraitGotRegistered(): void
{ {
assertTrue(true); $this->assertTrue(true);
} }
} }
Pest\Plugin::uses(PluginTrait::class); Pest\Plugin::uses(PluginTrait::class);
Pest\Plugin::uses(SecondPluginTrait::class); Pest\Plugin::uses(SecondPluginTrait::class);
function _assertThat()
{
expect(true)->toBeTrue();
}

10
tests/Expect/not.php Normal file
View File

@ -0,0 +1,10 @@
<?php
test('not property calls', function () {
expect(true)
->toBeTrue()
->not()->toBeFalse()
->not->toBeFalse
->and(false)
->toBeFalse();
});

20
tests/Expect/toBe.php Normal file
View File

@ -0,0 +1,20 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
expect(true)->toBeTrue()->and(false)->toBeFalse();
test('strict comparisons', function () {
$nuno = new stdClass();
$dries = new stdClass();
expect($nuno)->toBe($nuno)->not->toBe($dries);
});
test('failures', function () {
expect(1)->toBe(2);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(1)->not->toBe(1);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect([1, 2, 3])->toBeArray();
expect('1, 2, 3')->not->toBeArray();
});
test('failures', function () {
expect(null)->toBeArray();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(['a', 'b', 'c'])->not->toBeArray();
})->throws(ExpectationFailedException::class);

16
tests/Expect/toBeBool.php Normal file
View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(true)->toBeBool();
expect(0)->not->toBeBool();
});
test('failures', function () {
expect(null)->toBeBool();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(false)->not->toBeBool();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,18 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(function () {})->toBeCallable();
expect(null)->not->toBeCallable();
});
test('failures', function () {
$hello = 5;
expect($hello)->toBeCallable();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(function () { return 42; })->not->toBeCallable();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,17 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
$temp = sys_get_temp_dir();
expect($temp)->toBeDirectory();
});
test('failures', function () {
expect('/random/path/whatever')->toBeDirectory();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect('.')->not->toBeDirectory();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,18 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect([])->toBeEmpty();
expect(null)->toBeEmpty();
});
test('failures', function () {
expect([1, 2])->toBeEmpty();
expect(' ')->toBeEmpty();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect([])->not->toBeEmpty();
expect(null)->not->toBeEmpty();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('strict comparisons', function () {
expect(false)->toBeFalse();
});
test('failures', function () {
expect('')->toBeFalse();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(false)->not->toBe(false);
})->throws(ExpectationFailedException::class);

23
tests/Expect/toBeFile.php Normal file
View File

@ -0,0 +1,23 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
beforeEach(function () {
touch($this->tempFile = sys_get_temp_dir() . '/fake.file');
});
afterEach(function () {
unlink($this->tempFile);
});
test('pass', function () {
expect($this->tempFile)->toBeFile();
});
test('failures', function () {
expect('/random/path/whatever.file')->toBeFile();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect($this->tempFile)->not->toBeFile();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(1.0)->toBeFloat();
expect(1)->not->toBeFloat();
});
test('failures', function () {
expect(42)->toBeFloat();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(log(3))->not->toBeFloat();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('passes', function () {
expect(42)->toBeGreaterThan(41);
expect(4)->toBeGreaterThan(3.9);
});
test('failures', function () {
expect(4)->toBeGreaterThan(4);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(5)->not->toBeGreaterThan(4);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('passes', function () {
expect(42)->toBeGreaterThanOrEqual(41);
expect(4)->toBeGreaterThanOrEqual(4);
});
test('failures', function () {
expect(4)->toBeGreaterThanOrEqual(4.1);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(5)->not->toBeGreaterThanOrEqual(5);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(log(0))->toBeInfinite();
expect(log(1))->not->toBeInfinite();
});
test('failures', function () {
expect(asin(2))->toBeInfinite();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(INF)->not->toBeInfinite();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(new Exception())->toBeInstanceOf(Exception::class);
expect(new Exception())->not->toBeInstanceOf(RuntimeException::class);
});
test('failures', function () {
expect(new Exception())->toBeInstanceOf(RuntimeException::class);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(new Exception())->not->toBeInstanceOf(Exception::class);
})->throws(ExpectationFailedException::class);

16
tests/Expect/toBeInt.php Normal file
View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(42)->toBeInt();
expect(42.0)->not->toBeInt();
});
test('failures', function () {
expect(42.0)->toBeInt();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(6 * 7)->not->toBeInt();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,23 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect([])->toBeIterable();
expect(null)->not->toBeIterable();
});
test('failures', function () {
expect(42)->toBeIterable();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
function gen(): iterable
{
yield 1;
yield 2;
yield 3;
}
expect(gen())->not->toBeIterable();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('passes', function () {
expect(41)->toBeLessThan(42);
expect(4)->toBeLessThan(5);
});
test('failures', function () {
expect(4)->toBeLessThan(4);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(5)->not->toBeLessThan(6);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('passes', function () {
expect(41)->toBeLessThanOrEqual(42);
expect(4)->toBeLessThanOrEqual(4);
});
test('failures', function () {
expect(4)->toBeLessThanOrEqual(3.9);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(5)->not->toBeLessThanOrEqual(5);
})->throws(ExpectationFailedException::class);

16
tests/Expect/toBeNAN.php Normal file
View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(asin(2))->toBeNan();
expect(log(0))->not->toBeNan();
});
test('failures', function () {
expect(1)->toBeNan();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(acos(1.5))->not->toBeNan();
})->throws(ExpectationFailedException::class);

16
tests/Expect/toBeNull.php Normal file
View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(null)->toBeNull();
expect('')->not->toBeNull();
});
test('failures', function () {
expect('hello')->toBeNull();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(null)->not->toBeNull();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(42)->toBeNumeric();
expect('A')->not->toBeNumeric();
});
test('failures', function () {
expect(null)->toBeNumeric();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(6 * 7)->not->toBeNumeric();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect((object) ['a' => 1])->toBeObject();
expect(['a' => 1])->not->toBeObject();
});
test('failures', function () {
expect(null)->toBeObject();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect((object) 'ciao')->not->toBeObject();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(sys_get_temp_dir())->toBeReadableDirectory();
});
test('failures', function () {
expect('/random/path/whatever')->toBeReadableDirectory();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(sys_get_temp_dir())->not->toBeReadableDirectory();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,23 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
beforeEach(function () {
touch($this->tempFile = sys_get_temp_dir() . '/fake.file');
});
afterEach(function () {
unlink($this->tempFile);
});
test('pass', function () {
expect($this->tempFile)->toBeReadableFile();
});
test('failures', function () {
expect('/random/path/whatever.file')->toBeReadableFile();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect($this->tempFile)->not->toBeReadableFile();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,22 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
$resource = tmpfile();
afterAll(function () use ($resource) {
fclose($resource);
});
test('pass', function () use ($resource) {
expect($resource)->toBeResource();
expect(null)->not->toBeResource();
});
test('failures', function () {
expect(null)->toBeResource();
})->throws(ExpectationFailedException::class);
test('not failures', function () use ($resource) {
expect($resource)->not->toBeResource();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(1.1)->toBeScalar();
});
test('failures', function () {
expect(null)->toBeScalar();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(42)->not->toBeScalar();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect('1.1')->toBeString();
expect(1.1)->not->toBeString();
});
test('failures', function () {
expect(null)->toBeString();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect('42')->not->toBeString();
})->throws(ExpectationFailedException::class);

15
tests/Expect/toBeTrue.php Normal file
View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('strict comparisons', function () {
expect(true)->toBeTrue();
});
test('failures', function () {
expect('')->toBeTrue();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(false)->not->toBe(false);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(sys_get_temp_dir())->toBeWritableDirectory();
});
test('failures', function () {
expect('/random/path/whatever')->toBeWritableDirectory();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(sys_get_temp_dir())->not->toBeWritableDirectory();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,23 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
beforeEach(function () {
touch($this->tempFile = sys_get_temp_dir() . '/fake.file');
});
afterEach(function () {
unlink($this->tempFile);
});
test('pass', function () {
expect($this->tempFile)->toBeWritableFile();
});
test('failures', function () {
expect('/random/path/whatever.file')->toBeWritableFile();
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect($this->tempFile)->not->toBeWritableFile();
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,19 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('passes strings', function () {
expect([1, 2, 42])->toContain(42);
});
test('passes arrays', function () {
expect('Nuno')->toContain('Nu');
});
test('failures', function () {
expect([1, 2, 42])->toContain(3);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect([1, 2, 42])->not->toContain(42);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect('username')->toEndWith('name');
});
test('failures', function () {
expect('username')->toEndWith('password');
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect('username')->not->toEndWith('name');
})->throws(ExpectationFailedException::class);

15
tests/Expect/toEqual.php Normal file
View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect('00123')->toEqual(123);
});
test('failures', function () {
expect(['a', 'b', 'c'])->toEqual(['a', 'b']);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect('042')->not->toEqual(42);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect([1, 2, 3])->toEqualCanonicalizing([3, 1, 2]);
expect(['g', 'a', 'z'])->not->toEqualCanonicalizing(['a', 'z']);
});
test('failures', function () {
expect([3, 2, 1])->toEqualCanonicalizing([1, 2]);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(['a', 'b', 'c'])->not->toEqualCanonicalizing(['b', 'a', 'c']);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(1.0)->toEqualWithDelta(1.3, .4);
});
test('failures', function () {
expect(1.0)->toEqualWithDelta(1.5, .1);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(1.0)->not->toEqualWithDelta(1.6, .7);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect([1, 2, 3])->toHaveCount(3);
});
test('failures', function () {
expect([1, 2, 3])->toHaveCount(4);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect([1, 2, 3])->not->toHaveCount(3);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(['a' => 1, 'b', 'c' => 'world'])->toHaveKey('c');
});
test('failures', function () {
expect(['a' => 1, 'b', 'c' => 'world'])->toHaveKey('hello');
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(['a' => 1, 'hello' => 'world', 'c'])->not->toHaveKey('hello');
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(['a' => 1, 'b', 'c' => 'world'])->toHaveKeys(['a', 'c']);
});
test('failures', function () {
expect(['a' => 1, 'b', 'c' => 'world'])->toHaveKeys(['a', 'd']);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(['a' => 1, 'hello' => 'world', 'c'])->not->toHaveKeys(['hello', 'c']);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,22 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
$obj = new stdClass();
$obj->foo = 'bar';
$obj->fooNull = null;
test('pass', function () use ($obj) {
expect($obj)->toHaveProperty('foo');
expect($obj)->toHaveProperty('foo', 'bar');
expect($obj)->toHaveProperty('fooNull');
expect($obj)->toHaveProperty('fooNull', null);
});
test('failures', function () use ($obj) {
expect($obj)->toHaveProperty('bar');
})->throws(ExpectationFailedException::class);
test('not failures', function () use ($obj) {
expect($obj)->not->toHaveProperty('foo');
})->throws(ExpectationFailedException::class);

15
tests/Expect/toMatch.php Normal file
View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect('Hello World')->toMatch('/^hello wo.*$/i');
});
test('failures', function () {
expect('Hello World')->toMatch('/^hello$/i');
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect('Hello World')->not->toMatch('/^hello wo.*$/i');
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,16 @@
<?php
use PHPUnit\Framework\Constraint\IsTrue;
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect(true)->toMatchConstraint(new IsTrue());
});
test('failures', function () {
expect(false)->toMatchConstraint(new IsTrue());
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect(true)->not->toMatchConstraint(new IsTrue());
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,31 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
beforeEach(function () {
$this->user = (object) [
'id' => 1,
'name' => 'Nuno',
'email' => 'enunomaduro@gmail.com',
];
});
test('pass', function () {
expect($this->user)->toMatchObject([
'name' => 'Nuno',
'email' => 'enunomaduro@gmail.com',
]);
});
test('failures', function () {
expect($this->user)->toMatchObject([
'name' => 'Not the same name',
'email' => 'enunomaduro@gmail.com',
]);
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect($this->user)->not->toMatchObject([
'id' => 1,
]);
})->throws(ExpectationFailedException::class);

View File

@ -0,0 +1,15 @@
<?php
use PHPUnit\Framework\ExpectationFailedException;
test('pass', function () {
expect('username')->toStartWith('user');
});
test('failures', function () {
expect('username')->toStartWith('password');
})->throws(ExpectationFailedException::class);
test('not failures', function () {
expect('username')->not->toStartWith('user');
})->throws(ExpectationFailedException::class);

View File

@ -8,8 +8,8 @@ afterAll(function () use ($file) {
test('deletes file after all', function () use ($file) { test('deletes file after all', function () use ($file) {
file_put_contents($file, 'foo'); file_put_contents($file, 'foo');
assertFileExists($file); $this->assertFileExists($file);
register_shutdown_function(function () use ($file) { register_shutdown_function(function () use ($file) {
assertFileNotExists($file); $this->assertFileNotExists($file);
}); });
}); });

View File

@ -11,10 +11,10 @@ afterEach(function () use ($state) {
}); });
it('does not get executed before the test', function () { it('does not get executed before the test', function () {
assertFalse(property_exists($this->state, 'bar')); expect($this->state)->not->toHaveProperty('bar');
}); });
it('gets executed after the test', function () { it('gets executed after the test', function () {
assertTrue(property_exists($this->state, 'bar')); expect($this->state)->toHaveProperty('bar');
assertEquals(2, $this->state->bar); expect($this->state->bar)->toBe(2);
}); });

View File

@ -8,11 +8,11 @@ beforeAll(function () use ($foo) {
}); });
it('gets executed before tests', function () use ($foo) { it('gets executed before tests', function () use ($foo) {
assertEquals($foo->bar, 1); expect($foo->bar)->toBe(1);
$foo->bar = 'changed'; $foo->bar = 'changed';
}); });
it('do not get executed before each test', function () use ($foo) { it('do not get executed before each test', function () use ($foo) {
assertEquals($foo->bar, 'changed'); expect($foo->bar)->toBe('changed');
}); });

View File

@ -5,11 +5,11 @@ beforeEach(function () {
}); });
it('gets executed before each test', function () { it('gets executed before each test', function () {
assertEquals($this->bar, 2); expect($this->bar)->toBe(2);
$this->bar = 'changed'; $this->bar = 'changed';
}); });
it('gets executed before each test once again', function () { it('gets executed before each test once again', function () {
assertEquals($this->bar, 2); expect($this->bar)->toBe(2);
}); });

View File

@ -23,13 +23,13 @@ it('sets closures', function () {
yield [1]; yield [1];
}); });
assertEquals([[1]], iterator_to_array(Datasets::get('foo')())); expect(iterator_to_array(Datasets::get('foo')()))->toBe([[1]]);
}); });
it('sets arrays', function () { it('sets arrays', function () {
Datasets::set('bar', [[2]]); Datasets::set('bar', [[2]]);
assertEquals([[2]], Datasets::get('bar')); expect(Datasets::get('bar'))->toBe([[2]]);
}); });
it('gets bound to test case object', function () { it('gets bound to test case object', function () {
@ -37,7 +37,7 @@ it('gets bound to test case object', function () {
})->with([['a'], ['b']]); })->with([['a'], ['b']]);
test('it truncates the description', function () { test('it truncates the description', function () {
assertTrue(true); expect(true)->toBe(true);
// it gets tested by the integration test // it gets tested by the integration test
})->with([str_repeat('Fooo', 10000000)]); })->with([str_repeat('Fooo', 10000000)]);
@ -48,51 +48,51 @@ $datasets = [[1], [2]];
test('lazy datasets', function ($text) use ($state, $datasets) { test('lazy datasets', function ($text) use ($state, $datasets) {
$state->text .= $text; $state->text .= $text;
assertTrue(in_array([$text], $datasets)); expect(in_array([$text], $datasets))->toBe(true);
})->with($datasets); })->with($datasets);
test('lazy datasets did the job right', function () use ($state) { test('lazy datasets did the job right', function () use ($state) {
assertEquals('12', $state->text); expect($state->text)->toBe('12');
}); });
$state->text = ''; $state->text = '';
test('eager datasets', function ($text) use ($state, $datasets) { test('eager datasets', function ($text) use ($state, $datasets) {
$state->text .= $text; $state->text .= $text;
assertTrue(in_array([$text], $datasets)); expect($datasets)->toContain([$text]);
})->with(function () use ($datasets) { })->with(function () use ($datasets) {
return $datasets; return $datasets;
}); });
test('eager datasets did the job right', function () use ($state) { test('eager datasets did the job right', function () use ($state) {
assertEquals('1212', $state->text); expect($state->text)->toBe('1212');
}); });
test('lazy registered datasets', function ($text) use ($state, $datasets) { test('lazy registered datasets', function ($text) use ($state, $datasets) {
$state->text .= $text; $state->text .= $text;
assertTrue(in_array([$text], $datasets)); expect($datasets)->toContain([$text]);
})->with('numbers.array'); })->with('numbers.array');
test('lazy registered datasets did the job right', function () use ($state) { test('lazy registered datasets did the job right', function () use ($state) {
assertEquals('121212', $state->text); expect($state->text)->toBe('121212');
}); });
test('eager registered datasets', function ($text) use ($state, $datasets) { test('eager registered datasets', function ($text) use ($state, $datasets) {
$state->text .= $text; $state->text .= $text;
assertTrue(in_array([$text], $datasets)); expect($datasets)->toContain([$text]);
})->with('numbers.closure'); })->with('numbers.closure');
test('eager registered datasets did the job right', function () use ($state) { test('eager registered datasets did the job right', function () use ($state) {
assertEquals('12121212', $state->text); expect($state->text)->toBe('12121212');
}); });
test('eager wrapped registered datasets', function ($text) use ($state, $datasets) { test('eager wrapped registered datasets', function ($text) use ($state, $datasets) {
$state->text .= $text; $state->text .= $text;
assertTrue(in_array([$text], $datasets)); expect($datasets)->toContain([$text]);
})->with('numbers.closure.wrapped'); })->with('numbers.closure.wrapped');
test('eager registered wrapped datasets did the job right', function () use ($state) { test('eager registered wrapped datasets did the job right', function () use ($state) {
assertEquals('1212121212', $state->text); expect($state->text)->toBe('1212121212');
}); });
class Bar class Bar
@ -105,13 +105,13 @@ $namedDatasets = [
]; ];
test('lazy named datasets', function ($text) use ($state, $datasets) { test('lazy named datasets', function ($text) use ($state, $datasets) {
assertTrue(true); expect(true)->toBeTrue();
})->with($namedDatasets); })->with($namedDatasets);
$counter = 0; $counter = 0;
it('creates unique test case names', function (string $name, Plugin $plugin, bool $bool) use (&$counter) { it('creates unique test case names', function (string $name, Plugin $plugin, bool $bool) use (&$counter) {
assertTrue(true); expect(true)->toBeTrue();
$counter++; $counter++;
})->with([ })->with([
['Name 1', new Plugin(), true], ['Name 1', new Plugin(), true],
@ -123,5 +123,5 @@ it('creates unique test case names', function (string $name, Plugin $plugin, boo
]); ]);
it('creates unique test case names - count', function () use (&$counter) { it('creates unique test case names - count', function () use (&$counter) {
assertEquals(6, $counter); expect($counter)->toBe(6);
}); });

View File

@ -3,38 +3,32 @@
$runCounter = 0; $runCounter = 0;
test('first', function () use (&$runCounter) { test('first', function () use (&$runCounter) {
assertTrue(true); expect(true)->toBeTrue();
$runCounter++; $runCounter++;
return 'first'; return 'first';
}); });
test('second', function () use (&$runCounter) { test('second', function () use (&$runCounter) {
assertTrue(true); expect(true)->toBeTrue();
$runCounter++; $runCounter++;
return 'second'; return 'second';
}); });
test('depends', function () { test('depends', function () {
assertEquals( expect(func_get_args())->toBe(['first', 'second']);
['first', 'second'],
func_get_args()
);
})->depends('first', 'second'); })->depends('first', 'second');
test('depends with ...params', function (string ...$params) { test('depends with ...params', function (string ...$params) {
assertEquals( expect(func_get_args())->toBe($params);
['first', 'second'],
$params
);
})->depends('first', 'second'); })->depends('first', 'second');
test('depends with defined arguments', function (string $first, string $second) { test('depends with defined arguments', function (string $first, string $second) {
assertEquals('first', $first); expect($first)->toBe('first');
assertEquals('second', $second); expect($second)->toBe('second');
})->depends('first', 'second'); })->depends('first', 'second');
test('depends run test only once', function () use (&$runCounter) { test('depends run test only once', function () use (&$runCounter) {
assertEquals(2, $runCounter); expect($runCounter)->toBe(2);
})->depends('first', 'second'); })->depends('first', 'second');

View File

@ -7,7 +7,7 @@ function addUser()
it('can set/get properties on $this', function () { it('can set/get properties on $this', function () {
addUser(); addUser();
assertEquals('nuno', $this->user); expect($this->user)->toBe('nuno');
}); });
it('throws error if property do not exist', function () { it('throws error if property do not exist', function () {
@ -27,17 +27,18 @@ function mockUser()
$mock = test()->createMock(User::class); $mock = test()->createMock(User::class);
$mock->method('getName') $mock->method('getName')
->willReturn('maduro'); ->willReturn('maduro');
return $mock; return $mock;
} }
it('allows to call underlying protected/private methods', function () { it('allows to call underlying protected/private methods', function () {
$user = mockUser(); $user = mockUser();
expect($user->getName())->toBe('maduro');
assertEquals('maduro', $user->getName());
}); });
it('throws error if method do not exist', function () { it('throws error if method do not exist', function () {
test()->name(); test()->name();
})->throws(\ReflectionException::class, 'Call to undefined method PHPUnit\Framework\TestCase::name()'); })->throws(\ReflectionException::class, 'Call to undefined method PHPUnit\Framework\TestCase::name()');
it('can forward unexpected calls to any global function')->_assertThat();

View File

@ -1,7 +1,7 @@
<?php <?php
it('is a test', function () { it('is a test', function () {
assertArrayHasKey('key', ['key' => 'foo']); $this->assertArrayHasKey('key', ['key' => 'foo']);
}); });
it('is a higher order message test')->assertTrue(true); it('is a higher order message test')->expect(true)->toBeTrue();

View File

@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase;
uses(Macroable::class); uses(Macroable::class);
beforeEach()->macro('bar', function () { beforeEach()->macro('bar', function () {
assertInstanceOf(TestCase::class, $this); expect($this)->toBeInstanceOf(TestCase::class);
}); });
it('can call chained macro method')->bar(); it('can call chained macro method')->bar();

View File

@ -1,11 +1,12 @@
<?php <?php
use Pest\PendingObjects\TestCall;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
uses(Gettable::class); uses(Gettable::class);
/** /**
* @return TestCase|Gettable * @return TestCase|TestCall|Gettable
*/ */
function get(string $route) function get(string $route)
{ {
@ -15,15 +16,15 @@ function get(string $route)
trait Gettable trait Gettable
{ {
/** /**
* @return TestCase|Gettable * @return TestCase|TestCall|Gettable
*/ */
public function get(string $route) public function get(string $route)
{ {
assertNotEmpty($route); expect($route)->not->toBeEmpty();
return $this; return $this;
} }
} }
get('foo')->get('bar')->assertTrue(true); get('foo')->get('bar')->expect(true)->toBeTrue();
get('foo')->assertTrue(true); get('foo')->expect(true)->toBeTrue();

View File

@ -1,7 +1,7 @@
<?php <?php
test('a test', function () { test('a test', function () {
assertArrayHasKey('key', ['key' => 'foo']); $this->assertArrayHasKey('key', ['key' => 'foo']);
}); });
test('higher order message test')->assertTrue(true); test('higher order message test')->expect(true)->toBeTrue();

View File

@ -1,5 +1,7 @@
<?php <?php
use function PHPUnit\Framework\assertFalse;
$foo = new stdClass(); $foo = new stdClass();
$foo->beforeAll = false; $foo->beforeAll = false;
$foo->beforeEach = false; $foo->beforeEach = false;

View File

@ -10,6 +10,6 @@ class CustomTestCaseInSubFolder extends TestCase
{ {
public function assertCustomInSubFolderTrue() public function assertCustomInSubFolderTrue()
{ {
assertTrue(true); $this->assertTrue(true);
} }
} }

View File

@ -12,7 +12,7 @@ class MyCustomClass extends PHPUnit\Framework\TestCase
{ {
public function assertTrueIsTrue() public function assertTrueIsTrue()
{ {
assertTrue(true); $this->assertTrue(true);
} }
} }

View File

@ -1,5 +1,5 @@
<?php <?php
test('basic', function () { test('basic', function () {
assertTrue(true); expect(true)->toBeTrue();
}); });

View File

@ -7,14 +7,14 @@ use PHPUnit\TextUI\DefaultResultPrinter;
it('sets defaults', function () { it('sets defaults', function () {
$arguments = AddsDefaults::to(['bar' => 'foo']); $arguments = AddsDefaults::to(['bar' => 'foo']);
assertInstanceOf(Printer::class, $arguments['printer']); expect($arguments['printer'])->toBeInstanceOf(Printer::class);
assertEquals($arguments['bar'], 'foo'); expect($arguments['bar'])->toBe('foo');
}); });
it('does not override options', function () { it('does not override options', function () {
$defaultResultPrinter = new DefaultResultPrinter(); $defaultResultPrinter = new DefaultResultPrinter();
assertEquals(AddsDefaults::to(['printer' => $defaultResultPrinter]), [ expect(AddsDefaults::to(['printer' => $defaultResultPrinter]))->tobe([
'printer' => $defaultResultPrinter, 'printer' => $defaultResultPrinter,
]); ]);
}); });

View File

@ -16,10 +16,10 @@ test('default php unit tests', function () {
$phpUnitTestCase = new class() extends PhpUnitTestCase { $phpUnitTestCase = new class() extends PhpUnitTestCase {
}; };
$testSuite->addTest($phpUnitTestCase); $testSuite->addTest($phpUnitTestCase);
assertCount(1, $testSuite->tests()); expect($testSuite->tests())->toHaveCount(1);
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd())); AddsTests::to($testSuite, new \Pest\TestSuite(getcwd()));
assertCount(1, $testSuite->tests()); expect($testSuite->tests())->toHaveCount(1);
}); });
it('removes warnings', function () use ($pestTestCase) { it('removes warnings', function () use ($pestTestCase) {
@ -28,5 +28,5 @@ it('removes warnings', function () use ($pestTestCase) {
$testSuite->addTest($warningTestCase); $testSuite->addTest($warningTestCase);
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd())); AddsTests::to($testSuite, new \Pest\TestSuite(getcwd()));
assertCount(0, $testSuite->tests()); expect($testSuite->tests())->toHaveCount(0);
}); });

Some files were not shown because too many files have changed in this diff Show More