PHP Test Driven Development Part 3: Unit Testing Continued

Sameer Nyaupane
Sep 12, 2018 · 5 min read

Now continuing from Part 2, let’s revisit the test we were looking at:

Please check out Part 2, if you have not read it yet: https://hackernoon.com/php-test-driven-development-part-2-unit-testing-c327ba3fbf14

If you would also like to check out the accompanying YouTube video, here’s the link:

We learned that asserts are statements that we use to verify or check if our output is what we need.

Here, we are checking if “true” is true. Which is obvious duh, right? This test is really of no use to us. It does not test any of our code. It is just an example assert statement given to us by the Laravel framework.

Now, let’s make a practical use of assertTrue statement. Just for an example, let’s make a simple Class called Calculate.php under /app, one step inside of the root laravel folder “laravel5” that we made on the previous episode. So the path is “/app/Calculate.php”. This is a simple demonstration class that just calculates the area of a square.

Now, you can get rid of the ExampleTest file as we don’t need it. We will make a new test file to test the Calculate class.

Make a new file called “CalculateTest.php” under /tests/Unit folder with the code as follows:

Okay let’s go through this one by one. On line 4, we declare that we are going to use the App\Calculate class, using the “use” statement.

Line 7 we have the class name declared as “CalculateTest” which is the standard format we will use for our tests. {Name of Class}Test

On line 9, we use a template method called “setUp” that is provided by PHPUnit. This method is called each time any tests are run in this class. This makes it effective to use as a common method that can share setup codes for this class. There is another template method we use called “tearDown” and it is used to cleanup after a test is run. We do not need it here yet, but we will need it once we use mocks. You can read more about them here: https://phpunit.readthedocs.io/en/7.3/fixtures.html

On line 11, we can see that we’ve initiated the class that we are about to test.

On line 14, we follow the standard naming that we discussed on the previous episode:

test_nameOfTheMethodYouAreTesting_WhenCalledWithSomeInput_ShouldReceiveSomeExpectedOutput

areaOfSquare is our target method that we want to test. “WhenCalledWithLength2” represents we are calling the method with length as 2 supplied. “Return4” is what we expect to receive from the target method.

On line 16, we assign 2 as our length of square.

On line 17, we call the “areaOfSquare” method with the assigned length.

Line 20 is where we assert that the given response is an integer.

Finally on line 21 we assert if the given response equals to 4, which is the required area of the square.

Now, let’s go back to our console and run “phpunit”.

1 test ran and 2 assertions (“assertTrue” and “assertEquals”) passed within it.

Congratulations, you’ve written your first unit test. :)

Let’s say we want to test the same method more to ensure that it really does what it says. We may write another test duplicating the code but changing the input value and expected value. Below I added another test:

Now you should have 2 tests and 4 assertions passed.

Adding more tests for the same method makes the tests more reliable and takes care of edge cases. But of course, the tests have to be meaningful and test the right things.

Could we add more tests to this method? What if somebody called the method without providing any length? What if the length is negative, what will the output be? What if we supply a string instead of number to the method? We can ask ourselves these questions and write tests that matter for us.

Ok so let’s look at the case where it is called without any data.

On line 34 we declare our intention with “WhenCalledWithoutLength” and the expected result which is “ThrowAnException”.

Line number 36 uses the expectException assertion expecting ‘ArugmentCountError’ exception.

Line 37 does the same for the exception message.

We finally call the method without passing any length on line 39. This should give us the exception. When the exception is thrown, it will count as “passed test” as the test has completed our objective.

To run only this test we can use the --filter option this way:

phpunit --filter test_areaOfSquare_WhenCalledWithoutLength_ThrowAnException

When we run the above command, we get the following result:

Congratulations, your test passed. :)

Similarly, you can write tests for the case where the number supplied is negative or when something else is supplied instead of a number. And it is up to you to react to those things in the code or to let it throw an exception if that is what you intended it to happen.

So go ahead, start writing extra tests for the method. And also you can start writing tests for other functions that calculate area of circle, rectangle etc.

If you face any issues or have questions, please feel free to write in the comments below.

Please don’t forget to share and give claps if you found it helpful.

On the next part we will be learning about mocking. This is another crucial area that we will need in our arsenal for unit testing.

Link to part 4: https://medium.com/@sameernyaupane/php-test-driven-development-part-4-enter-the-mock-106b4fdedd00

Check out my other series at:

Sameer Nyaupane

Written by

(Software Developer | Technical Writer | Speaker) sameernyaupane.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade