|

Getting Started With Testing In Laravel

testing-with-laravel

Testing is not something I’ve personally ever put a lot of time in to. If the code I was writing did what I wanted it to do, that was good enough for me. If formal testing is not part of your background, the benefits of testing are not all that obvious. In fact, being new to testing myself, some of the benefits are not obvious to me. Mostly, I’d like to take a dive into testing with Laravel because it is a new challenge and something fun to tinker with and learn. As we go, let’s see if we can uncover some of the benefits and advantages to test driven development. At the end of this tutorial, we will try to answer the question: Why should I write tests?


Introduction to Testing in Laravel

When I’m starting something new, I like to go as basic as is humanly possible. By default, we learn that Laravel has built in support for PHPUnit, one of the most common testing frameworks for PHP. An xml file for testing is also configured for us. For the purposes of this tutorial, it is located in a folder named lpg. This folder is short for Laravel Play Ground, and it resides on Laravel Homestead. Let’s look at this file.

So far this file does not mean a lot to us, but we’ll see if we can learn about it as we move forward. We can make some generalized assumptions though such as there is a /tests directory and an /app directory to be aware of, as well as an autoload file for the bootstrap. Let’s get to that first magical test by typing phpunit at the command line like so.

your-first-laravel-test

Wow this looks pretty cool! Let’s see what we did here. First we had to ssh into the homestead box, as we need to run tests on the virtual machine, not the host computer. Then, we change into the directory which holds our application. In our case we had to cd Code, then cd lpg. Finally, we are ready to run our very first Test! At the command line from the root of our project we run phpunit. The output as we can see is OK with a green background. We can also see there was 1 test and 2 assertions. So what does this actually mean?

It turns out, there is an ExampleTest.php that already lives in the tests directory of our project. This is the file which ran when we just typed phpunit at the command line. So what does this file contain? Let’s have a look.

Pretty cool! Just by looking at the code we can infer that by visiting the root of our project, we will see the text of Laravel. If we manually visit the page in our browser, this is in fact what we see.
visiting-the-root-of-our-laravel-app

Micro Summary: This first example was simply inspecting the default test that ships with Laravel. In it we see how to make use of the visit() and see() methods. We also ran the phpunit command at the command line to test things out.


So just what is a test?

Most tests do 3 simple things

  • 1. Arrange or initialize some data.
  • 2. Run a function to act on this data.
  • 3. Verify or assert that the output matches what we expected.

Let’s try to create a function and test it. We will simply add a public function to the Home Controller in Laravel.

Before we even try to use this function, we will create a test for it. We can use artisan to do this for us. We’ll create a test class to test the HomeController class. We do so by typing php artisan make:test HomeControllerTest. This creates a new test class for us, and it looks like this.

So now we have two files for testing in our tests directory, both the ExampleTest.php and HomeControllerTest.php. We’ll need to update our new test class to test the function in our controller. Let’s update the HomeControllerTest.php file to actually test our add function in the HomeController.

What we are doing here is to create the test. We name it test_add() since that is what we are trying to confirm. First off, we set up some data. This is the first number and second number to add. Then, we make a call to our function, passing in two number arguments. We know that 1 + 1 should be 2. Now let’s tell our test case that this is what is supposed to happen. Notice we make use of the PHP Unit method assertEquals(). This function simply verifies or asserts if argument 1 and argument 2 are equal. So since we know that 1 + 1 should equal 2, we assign this as the first parameter to assertEquals(). We pass the $sum that our add() function returns as argument 2. Let’s test it by running phpunit.

test-add-passing
Cool! Our test is passing. Let’s make a change and see what happens.

Now notice that we pass 2 and 3 as the arguments to our add() function. In our assertEquals() function, we are leaving 2 as the first argument. What this is saying is that 2 + 5 should equal 2, and we know that is not true, so our test should fail. Let’s see if it does.
test-add-failing
This is what a failing PHP Unit test looks like. In our case, it tells us exactly what went wrong. Failed asserting that 5 matches expected 2. Let’s make our test pass again. We will simply change our expected result from 2 to 5 like so.

test-add-passing-again

It looks like we are back to passing, which is great.


Application Testing in Laravel

At this point, we know just a little bit about testing with PHP Unit and Laravel. Let’s now tackle an introduction to application level testing in Laravel. We actually already touched on it just a bit. When we ran the ExampleTest that comes with Laravel, we tested the ability to visit a route, and display some text. What is interesting is that this type of testing is a higher level zoomed out so to speak type of test. Laravel provides these nice methods we can use which wrap up more complex assertions in PHP Unit. Therefore, we can do some pretty good testing with just minimal syntax. Now, let’s customize this basic example to start getting used to writing basic tests. We will take the approach of writing our tests first, running them to witness the failures, then fix things one at a time to make them pass.

1. Write out the sudo code

  • 1. Visit /pageone
  • 2. Click on the “Page Two” link
  • 3. See Page Two
  • 4. Assert that the current url is /pagetwo

2. Write the test

At this point, running phpunit produces complete failure.
404-test-fail
3. Make them pass

With our test in place, we start by running phpunit. We find the following error.

There was 1 failure:

1) ExampleTest::testBasicExample
A request to [http://localhost/pageone] failed. Received status code [404].

We got a 404 error, how do we fix that? Well, we need a route to pageone so let’s set that up.

Let us run phpunit again. Now we get this error.

There was 1 failure:

1) ExampleTest::testBasicExample
A request to [http://localhost/pageone] failed. Received status code [500].

Hmmm… Typically a 500 error code is a server failure. Well, we know that we need a view for page one so let’s create one, and include a link in it.

pageone.blade.php

Running phpunit again now gives us this error.

There was 1 failure:

1) ExampleTest::testBasicExample
A request to [http://localhost/pagetwo] failed. Received status code [404].

This makes sense, as we don’t have a route for pagetwo, let’s create it.

Running phpunit again, and we get another error. It looks like we blew up the server again.

There was 1 failure:

1) ExampleTest::testBasicExample
A request to [http://localhost/pagetwo] failed. Received status code [500].

Oh right, we need to add a view for pagetwo. Create pagetwo.blade.php and run phpunit again.

There was 1 error:

1) ExampleTest::testBasicExample
InvalidArgumentException: The current node list is empty.

Hmmm, maybe this is because we did not add the text on page two yet. Add the text, “This is page two” to this view, then run phpunit again.

vagrant@homestead:~/Code/lpg$ phpunit
PHPUnit 5.5.2 by Sebastian Bergmann and contributors.

. 1 / 1 (100%)

Time: 319 ms, Memory: 10.00MB

OK (1 test, 5 assertions)
vagrant@homestead:~/Code/lpg$

Nice! It is now fully working!

Even though our test only used four methods, there is a lot of horsepower there. Looking at the source code that makes this possible shows us how it works.

visit()

click()

see()

seePageIs()


Learn More About Testing In Laravel!


Getting Started With Testing In Laravel Summary

This was a really basic introduction to getting started with testing in Laravel. What did we learn and what is the benefit of testing? Well, it is so easy to not test. We go about hacking together a project very quickly, and we manually test each thing as we go. We add a feature, then run it in the browser. Did it work? No? Ok fix all the things, then check the result in the browser again. Did it work? Yes? Great, move on to the next thing. This works, but the problem is what comes in the future. What if you want or need to refactor features in your project? You likely fear this like the plague if you have no tests to give you confidence things will continue to work. And this is the number one key benefit of testing: Confidence. Confidence in the fact that you can at any time run all the tests you have built up over time on a particular project and see that things are working as they should. Think of how many times you manually tested every single thing on the last project you built. If you wanted to refactor anything now, in the future, you now are worried about if anything will break. In theory, you would have to manually test every scenario in the browser, for all features of the application. Not only would that be time consuming and painful, it might not even be possible to accurately remember how you even verified how things worked in the first place. This is the benefit of tests. You create them as you go, and then in the future, you have them to fall back on for your own sanity and confidence in your code. I think this really hits home at the question of “Why should I write tests?” in my application. Confidence and an Investment in the future of your application.