In order to unit test in Symfony, we need to install symfony's test-pack first:
$ composer require --dev symfony/test-pack
Check if install succeed by running PHPUnit:
$ php bin/phpunit
If you are running your project in a docker container, make sure you run this command in your container.
$ docker exec -it [enter_container_name] php bin/phpunit
If everything went well, you should receive the message "No tests executed!"
Write your first test
Create your first test "FirstTest.php" and place it in the directory "tests" of the root of your project:
<?php
namespace Api\Tests;
use PHPUnit\Framework\TestCase;
class FirstTest extends TestCase
{
public function testEquals() {
$actual = 1;
$expected = 1;
$this->assertEquals($expected, $actual);
}
}
As you can see this class extends from TestCase, which is needed to initiate a PHPUnit test. In this test we test if the $actual and $expected are equals.
Now try and run this test to see what happens:
$ php bin/phpunit
The result should be something like "OK (1 test, 1 assertion)"
Congrats! You just wrote your very first PHPUnit test.
What to test?
This is great, but how can I apply this to my code? Great question, lets check this out.
Firstly, we'll create a controller so we can test the outcome of our method:
<?php
namespace Api\Controller;
class Calculator
{
public function add ($a, $b) {
return $a + $b;
}
}
The naming convention for a test exists of "Controller + Test" used in CamelCase. So ours will be CalculatorTest. The method itself exist of "test + Method". Like so:
<?php
namespace Api\Tests;
use Api\Controller\Calculator;
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdd() {
$calculator = new Calculator();
$actual = $calculator->add(1,2);
$expected = 3;
$this->assertEquals($expected, $actual);
}
}
As you can see, we've initiated a Calculator object and added the numbers 1 and 2 as $actual result. My $expected result is an outcome of 3. If we run this test $ php bin/phpunit
we'll see our test runs successfully "OK (1 test, 1 assertion)".
Why to test
Now lets say after a couple of months your colleague gets the question to change your method because of whatever reason. He or she changed it to always add +10:
<?php
namespace Api\Controller;
class Calculator
{
public function add ($a) {
return $a + 10;
}
}
If we run our test again now $ php bin/phpunit
, we'll get exactly what we want. An error:
"FAILURES! Tests: 1, Assertions: 1, Failures: 1.".
So our colleague knows he changed something what shouldn't be changed or he needs to refactor our test and probably more code elsewhere.
Bonus
If you write tests before you write the actual code itself, this would be a great practice for Test Driven Development (TDD). A great way to think before coding and ensure the quality of your code.
Couple of asserts I like to use are:
- $this->assertEquals($expected, $actual);
- $this->assertTrue($argument);
- $this->assertInstanceOf(Object::class, $object);
- $this->assertSame($expected, $actual);
- $this->assertFalse($argument);
Hope this helps!
Top comments (2)
sooo basically test, unittests are for some features that are discussed to work in a way that remains fixed throughout the app. And they make it so you knowif chnages ruin these preset things.
Am i in the ball paark or not?
i;m asking because i;ve been wanting to do this but i didn;t know how its done and i don;t have people that do TDD sadly
I use it to make sure I don’t break something when I’m fixing a bug or adding features. TDD is just a different approach, it makes you think first about the minimal requirements of the feature and program after. In my experience a lot of people talk about it but don’t really use it. So I will try by myself and share my thoughts