This article will introduce how to write a unit test. IDE is using Visual Studio Code.
VSCode
First, Open VS Code and install plugins:
- PHPUnit Snippets
- PHPUnit Test Explorer
- PHP IntelliSense
- PHP Namespace Resolver
- PHP Debug
Prepare your unit test
First, init composer project
composer init
Input your package name, description, and stability, type, license
Package name (<vendor>/<name>) [adam/adam]: adam/adam
Description []: phpunit test
Author [adam <adam@xxx.xxx>, n to skip]:
Minimum Stability []: stable
Package Type (e.g. library, project, metapackage, composer-plugin) []: project
License []: proprietary
Define your dependencies.
Would you like to define your dependencies (require) interactively [yes]? no
Would you like to define your dev dependencies (require-dev) interactively [yes]? yes
Search for a package: phpunit
Warning from https://repo.packagist.org: You are using an outdated version of Composer. Composer 2 is now available and you should upgrade. See https://getcomposer.org/2
Found 15 packages matching phpunit
[0] phpunit/phpunit
[1] phpunit/php-timer
[2] phpunit/php-text-template
[3] phpunit/php-file-iterator
[4] phpunit/php-code-coverage
[5] phpunit/phpunit-mock-objects Abandoned. Use instead.
[6] symfony/phpunit-bridge
[7] phpunit/php-token-stream Abandoned. Use instead.
[8] jean85/pretty-package-versions
[9] brianium/paratest
[10] phpunit/php-invoker
[11] phpunit/phpunit-selenium
[12] johnkary/phpunit-speedtrap
[13] codedungeon/phpunit-result-printer
[14] spatie/phpunit-watcher
Enter package # to add, or the complete package name if it is not listed: 0
Enter package # to add, or the complete package name if it is not listed: 0
Enter the version constraint to require (or leave blank to use the latest version):
Using version ^9.5 for phpunit/phpunit
Search for a package:
{
"name": "adam/adam",
"description": "phpunit test",
"type": "project",
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"license": "proprietary",
"authors": [
{
"name": "adam",
"email": "adam@xxx.xxx"
}
],
"minimum-stability": "stable",
"require": {}
}
Test phpunit work
./vendor/bin/phpunit
Init your phpunit configuration:
./vendor/bin/phpunit --generate-configuration
There will three questions and auto-generate:
(Fellowing will using default value)
Bootstrap script (relative to the path shown above; default: vendor/autoload.php):
Tests directory (relative to path shown above; default: tests):
Source directory (relative to path shown above; default: src):
Cache directory (relative to path shown above; default: .phpunit.cache):
Generated phpunit.xml in /php_test.
Make sure to exclude the .phpunit.cache directory from version control.
First unit test
Create tests
and src
folder, and create a HelloworldTest.php file for unittest demo.
mkdir src tests
code tests/HelloworldTest.php
PHPUnit Snippets plugin will auto generate a quickly notify:
Open HelloworldTest.php, you can type pu:
will show lists:
pu:TestCase : will generate a default class
<?php
use PHPUnit\Framework\TestCase;
/**
* HelloworldTest
* @group group
*/
class HelloworldTest extends TestCase
{
/** @test */
public function test_function()
{
// Test
}
}
When using pu:testFunction
will auto-generate test function
<?php
/** @test */
public function test_function()
{
// Test
}
Here, using assert:same
keyword auto-generate an assert code, and try to prepare our expected and actual value and run our first test:
<?php
/** @test */
public function test_function()
{
// Expected
$expected = 'hello';
// Actual
$results = 'hello';
$actual = $results;
// Assert
$this->assertSame($expected, $actual)
}
Run following command or using PHPUnit Test Explorer
run first unittest:
./vendor/bin/phpunit
Will output unittest results:
PHPUnit 9.5.5 by Sebastian Bergmann and contributors.
Runtime: PHP 7.3.11
Configuration: /php_test/phpunit.xml
R 1 / 1 (100%)
Time: 00:00.009, Memory: 6.00 MB
There was 1 risky test:
1) helloTest::test_function
This test does not have a @covers annotation but is expected to have one
OK, but incomplete, skipped, or risky tests!
Tests: 1, Assertions: 1, Risky: 1.
Test a Class
That try to create a Hello.php in src, and setting a namespace App
.
<?php
namespace App;
class Hello
{
public function say()
{
return "helloworld";
}
}
Setting composer autoload using psr-4 loading rule:
Here we also setting tests namespace:
{
"name": "adam/adam",
"description": "phpunit test",
"type": "project",
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"license": "proprietary",
"authors": [
{
"name": "adam",
"email": "adam@xxx.xxx"
}
],
"minimum-stability": "stable",
"require": {},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}
In test file, we can just add fellowing new Class, and using PHP Namespace Resolver
auto-import class:
<?php
namespace Tests;
use App\Hello;
use PHPUnit\Framework\TestCase;
/**
*helloTest
* @group group
*/
class helloTest extends TestCase
{
/** @test */
public function test_function()
{
// expected
$expected = 'hello';
// actual
$results = new Hello();
$actual = $results;
// assert
$this->assertSame($expected, $actual);
}
}
In this case, we make assert false, and will show the fellowing result:
PHPUnit 9.5.5 by Sebastian Bergmann and contributors.
Runtime: PHP 7.3.11
Configuration: /php_test/phpunit.xml
F 1 / 1 (100%)
Time: 00:00.015, Memory: 6.00 MB
There was 1 failure:
1) Tests\helloTest::test_function
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'hello'
+'helloworld'
/php_test/tests/HelloTest.php:25
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
It says failed asserting that two strings are identical.
We can reset our expected to helloworld, and get the assert true.
<?php
namespace Tests;
use App\Hello;
use PHPUnit\Framework\TestCase;
/**
*helloTest
* @group group
*/
class helloTest extends TestCase
{
/** @test */
public function test_function()
{
// expected
$expected = 'helloworld';
// actual
$results = new Hello();
$actual = $results->say();
// assert
$this->assertSame($expected, $actual);
}
}