PHPUnit یک فریمورک یونیت تستینگ مبتنی بر معماری xUnit برای زبان برنامهنویسی پیاچپی است که توسط Sebastian Bergmann ابداع گردیده است به طوری که در این فریمورک، همچون بسیاری از دیگر فریمورکهای یونیت تستینگ، از مفهومی تحت عنوان Assertion به منظور نشان دادن صحت کارکرد یک بلوک از کد (Unit) استفاده میشود که در ادامهٔ این آموزش بیشتر در این باره بحث خواهیم کرد.
درآمدی بر Composer
کامپوزر یک پَکیج مَنِجر است بدان معنا که توسعهدهندگان زبان برنامهنویسی پیاچپی با استفاده از آن قادر خواهند بود تا به سادگی از طریق کامندلاین وابستگیهای پروژههای خود را مدیریت کنند که به منظور استفاده از فریمورک PHPUnit نیز نیاز به نصب این ابزار خواهیم داشت که در همین راستا و پیش از ادامهٔ این آموزش توصیه میشود به مقالات زیر از وبلاگ سکان آکادمی مراجعه نمایید:
- Composer چیست؟
- آموزش نصب Composer روی سیستمعامل گنو/لینوکس توزیع اوبونتو
لازم به یادآوری است که در این دورهٔ آموزشی از سیستمعامل گنو/لینوکس توزیع اوبونتو استفاده خواهیم کرد اما در عین نکات آموزشی قابلپیادهسازی در سایر پلتفرمها نیز میباشند.
برای شروع، در مسیر var/www/
پوشهای تحت عنوان phpunit
ساخته و پس از ورود به آن، کامند زیر را اجرا میکنیم:
/var/www/phpunit$ composer require --dev phpunit/phpunit
آنچه در کامند فوق نیاز به توضیح دارد اینکه آپشن dev--
حاکی از آن است که این پکیج صرفاً در محیط توسعه نصب خواهد شد. چنانچه کامند فوق بدون هیچگونه مشکلی اجرا شود، از این پس ساختار پروژهای که ساختهایم به صورت زیر خواهد بود:
phpunit
├── composer.json
├── composer.lock
└── vendor
همانطور که میبینیم، فایلی ساخته شده تحت عنوان composer.json
که حاوی محتویات زیر است:
{
"require-dev": {
"phpunit/phpunit": "^8.1"
}
}
میبینیم که فریمورک PHPUnit به عنوان وابستگی این پروژه در نظر گرفته شده است. همچنین با استفاده از دستور vendor/bin/phpunit/.
به صورت زیر، میتوانیم اطلاعاتی در مورد این فریمورک کسب نماییم:
/var/www/phpunit$ ./vendor/bin/phpunit
PHPUnit 8.1.4 by Sebastian Bergmann and contributors.
Usage:
phpunit [options] UnitTest [UnitTest.php]
phpunit [options] <directory>
Code Coverage Options:
--coverage-clover <file> Generate code coverage report in Clover XML format
--coverage-crap4j <file> Generate code coverage report in Crap4J XML format
--coverage-html <dir> Generate code coverage report in HTML format
--coverage-php <file> Export PHP_CodeCoverage object to file
--coverage-text=<file> Generate code coverage report in text format [default:
standard output]
--coverage-xml <dir> Generate code coverage report in PHPUnit XML format
--whitelist <dir> Whitelist <dir> for code coverage analysis
--disable-coverage-ignore Disable annotations for ignoring code coverage
--no-coverage Ignore code coverage configuration
--dump-xdebug-filter <file> Generate script to set Xdebug code coverage filter
Logging Options:
--log-junit <file> Log test execution in JUnit XML format to file
--log-teamcity <file> Log test execution in TeamCity format to file
--testdox-html <file> Write agile documentation in HTML format to file
--testdox-text <file> Write agile documentation in Text format to file
--testdox-xml <file> Write agile documentation in XML format to file
--reverse-list Print defects in reverse order
Test Selection Options:
--filter <pattern> Filter which tests to run
--testsuite <name> Filter which testsuite to run
--group <name> Only runs tests from the specified group(s)
--exclude-group <name> Exclude tests from the specified group(s)
--list-groups List available test groups
--list-suites List available test suites
--list-tests List available tests
--list-tests-xml <file> List available tests in XML format
--test-suffix <suffixes> Only search for test in files with specified suffix(es).
Default: Test.php,.phpt
Test Execution Options:
--dont-report-useless-tests Do not report tests that do not test anything
--strict-coverage Be strict about @covers annotation usage
--strict-global-state Be strict about changes to global state
--disallow-test-output Be strict about output during tests
--disallow-resource-usage Be strict about resource usage during small tests
--enforce-time-limit Enforce time limit based on test size
--default-time-limit=<sec> Timeout in seconds for tests without @small, @medium or
@large
--disallow-todo-tests Disallow @todo-annotated tests
--process-isolation Run each test in a separate PHP process
--globals-backup Backup and restore $GLOBALS for each test
--static-backup Backup and restore static attributes for each test
--colors=<flag> Use colors in output ("never", "auto" or "always")
--columns <n> Number of columns to use for progress output
--columns max Use maximum number of columns for progress output
--stderr Write to STDERR instead of STDOUT
--stop-on-defect Stop execution upon first not-passed test
--stop-on-error Stop execution upon first error
--stop-on-failure Stop execution upon first error or failure
--stop-on-warning Stop execution upon first warning
--stop-on-risky Stop execution upon first risky test
--stop-on-skipped Stop execution upon first skipped test
--stop-on-incomplete Stop execution upon first incomplete test
--fail-on-warning Treat tests with warnings as failures
--fail-on-risky Treat risky tests as failures
-v|--verbose Output more verbose information
--debug Display debugging information
--loader <loader> TestSuiteLoader implementation to use
--repeat <times> Runs the test(s) repeatedly
--teamcity Report test execution progress in TeamCity format
--testdox Report test execution progress in TestDox format
--testdox-group Only include tests from the specified group(s)
--testdox-exclude-group Exclude tests from the specified group(s)
--printer <printer> TestListener implementation to use
--order-by=<order> Run tests in order:
default|reverse|random|defects|no-depends
--random-order-seed=<N> Use a specific random seed <N> for random order
--cache-result Write test results to cache file
--do-not-cache-result Do not write test results to cache file
Configuration Options:
--prepend <file> A PHP script that is included as early as possible
--bootstrap <file> A PHP script that is included before the tests run
-c|--configuration <file> Read configuration from XML file
--no-configuration Ignore default configuration file (phpunit.xml)
--no-logging Ignore logging configuration
--no-extensions Do not load PHPUnit extensions
--include-path <path(s)> Prepend PHP's include_path with given path(s)
-d <key[=value]> Sets a php.ini value
--generate-configuration Generate configuration file with suggested settings
--cache-result-file=<file> Specify result cache path and filename
Miscellaneous Options:
-h|--help Prints this usage information
--version Prints the version and exits
--atleast-version <min> Checks that version is greater than min and exits
--check-version Check whether PHPUnit is the latest version
در ادامه، ابتدا پوشهای تحت عنوان app
میسازیم که قرار است دربرگیرندهٔ کدهای اصلی پروژه باشد سپس پوشهٔ دیگری به نام tests
میسازیم که به منظور نگهداری یونیت تستهای پروژه استفاده خواهد شد به طوری که از این پس خواهیم داشت:
phpunit
├── app
├── composer.json
├── composer.lock
├── tests
└── vendor
حال نیاز به یک فایل پیکربندی برای فریمورک PHPUnit خواهیم داشت که در همین راستا در مسیر روت پروژه، فایلی تحت عنوان phpunit.xml
حاوی محتویات زیر میسازیم:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php"
colors="true"
verbose="true"
stopOnFailure="false">
<testsuites>
<testsuite name="Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
آنچه در ارتباط با کدهای اکسامال فوق حائز اهمیت است اینکه مقداری همچون vendor/autoload.php/.
برای اتریبیوت bootstrap
در نظر گرفتهایم بدان معنا که فایل autoload.php
در پوشهٔ vendor
نقطهٔ شروع برنامه است. اتریبیوت colors
هم حاکی از آن است که خروجی تستها در کامندلاین در قالب رنگهای مختلف به منظور شهودیتر بودن خروجیها نمایش داده شوند و اتریبیوت verbose
نیز اطلاعات جامعی از خروجی تست در اختیارمان خواهد گذاشت. در ارتباط با اتریبیوت stopOnFailure
که مقدار false
را برای آن در نظر گرفتهایم باید گفت که این مقدار باعث میگردد تا اگر چندین تست داشته باشیم و یکی از آنها با شکست مواجه شد، اجرای ادامهٔ تستها متوقف نشده و کار ادامه یابد و در صورتی که مقدار true
برای این اتریبیوت در نظر بگیریم، به محض اینکه یکی از تستها به اصطلاح Fail شد، اجرای سایر تستها متوقف خواهد شد.
در ادامه به تگ <testsuites></testsuites>
میرسیم که داخل آن یک جفت تگ <testsuite></testsuite>
بیشتر در نظر نگرفتهایم به طوری که تگ <directory>./tests/</directory>
حاکی از آن است که این فریمورک جهت تست میباید به پوشهٔ tests
مراجعه نماید.
در این مرحله از کار، مجدد دستور vendor/bin/phpunit/.
را اجرا میکنیم به طوری که به عنوان خروجی خواهیم داشت:
/var/www/phpunit$ ./vendor/bin/phpunit
PHPUnit 8.1.4 by Sebastian Bergmann and contributors.
Runtime: PHP 7.3.4-1+ubuntu18.04.1+deb.sury.org+3
Configuration: /var/www/phpunit/phpunit.xml
Time: 81 ms, Memory: 2.00 MB
No tests executed!
میبینیم با توجه به اینکه تاکنون هیچگونه تستی برای پروژهٔ خود ننوشتهایم، عبارت !No tests executed در معرض دیدمان قرار میگیرد (چنانچه مقدار "colors="false
را در نظر گرفته و مجدد کامند فوق را اجرا کنیم، خواهیم دید که خروجی دیگر به صورت رنگی نخواهد بود.) در واقع، این خروجی حاکی از آن است که از این پس فایل پیکربندی phpunit.xml
در حین اجرا مبنا قرار داده خواهد شد.