Better Integration Testing in Laravel 5.1: Powerful Integration Tests in A Few Lines

(This is part of a series of posts on New Features in Laravel 5.1.)

  1. Broadcasting events with & in Laravel 5.1
  2. Injecting an object (from the IOC) using Laravel Blade Service Injection
  3. Passing parameters to Middleware in Laravel 5.1
  4. Creating Artisan commands with the new, simpler syntax in Laravel 5.1
  5. Advanced input & output with Artisan commands, tables, & progress bars in Laravel 5.1
  6. Better Integration Testing in Laravel 5.1: Powerful Integration Tests in A Few Lines
  7. Better Integration Testing in Laravel 5.1: Model Factories
  8. Better Integration Testing in Laravel 5.1: DatabaseMigrations, DatabaseTransactions, and WithoutMiddleware
  9. Improvements to Elixir in Laravel 5.1 (coming soon)
  10. Excluding Routes from the CSRF Middleware in Laravel 5.1
  11. Login Throttling in Laravel 5.1
  12. ACL (Access Control List) Authorization in Laravel 5.1

Whether or not you've written integration tests in Laravel before, you'll be pleased to hear that integration testing is more powerful, easier to use, and easier to learn in Laravel 5.1.

Note: If you do a lot of testing, it's likely you already have Faker and Mockery installed on every site you run, but you just got saved a step: they're now installed by default.

Integration Tests? #

For a quick refresher, integration tests are those which test your entire system as an integrated application, as compared against unit tests, which test each system of your application separately.

Usually integration tests pass in input to your application (often just an instruction like "visit this page") and check the output (often "I should see this text somewhere on the page"), with no concern of how that input was converted to that output. Integration tests see the actual processes running your application as a black box. Don't know, don't care.

Integrated package integrated #

Jeffrey Way's fantastic Integrated package has given integration tests in Laravel superpowers for a while now, and it's now a part of the Laravel core.

This means that any tests extending TestCase provide a simple, fluent interface for you to operate what amounts to almost a fake web browser that can check your output. If you've ever written Selenium-based tests, think that but simpler and easier to set up.

I'll show a few examples here, but note that the full documentation is available at the docs.

Simple tests with visit() and see() #

Check this out:

class HomePageTest extends TestCase
    public function test_home_page_says_wowee()

In two lines of code, we just tested that a user who visits the home page of the application sees the phrase "Wowee" somewhere on the site. Two lines of code. If you have any imagination, you can see how far we can take this, with almost no work, to ensure that the front end of our application functions properly, not just its guts.

Check the page with seePageIs() #

    public function test_forwarder_forwards_the_page()
    public function test_cta_link_functions()
            ->click('Try it now!')
            ->see('Sign up for trial')

Fill out forms with type(), select(), check(), attach(), and press() #

There are many more interactions you can script with the new functionality.

For example, you can fill out a form and submit it:

    public function test_it_can_subscribe_to_newsletter()
            ->type('', '#newsletter-email')
            ->press('Sign Up')
            ->see('Thanks for signing up!')

Note that press() can either be passed the value of the button (press("Sign Up")) or the name (press("sign-up-button"))

You can also fill out other fields:

    public function test_signups_can_complete()
            ->type('Matt Stauffer', 'name')
            ->select('Florida', 'state')
            ->attach('../uploads/test.jpg', 'profilePicture')
            ->press('Sign Up')

Submit a form all at once with submitForm() #

    public function test_login_form()
            ->submitForm('Log In', ['email' => '', 'password' => 'secret'])

Verify a record exists in the database with seeInDatabase() #

    public function test_saves_newsletter_signups()
            ->press('Sign up')
            ->seeInDatabase('signups', ['email' => '']);

Super power auto-testing #

Cool trick: you can tell Elixir to run your tests every time you modify a file by adding the following code to your gulp file: mix.phpUnit(). Now, just run gulp tdd from the command line and it will re-run PHPUnit every time you change any of your files and notify you of the results.

Thanks to Jeffrey Way for pointing this out—I had no idea it existed and now I'm in love with it.

Conclude #

As you can see, bringing in Integrated has laid the foundation for simple and powerful integration tests with almost no work. I have to make this clear: I've written integration tests before and it's never been this easy to get started.

We're not done yet—check back later this week to learn more about all the amazing things you can do with integration testing in Laravel 5.1.

Comments? I'm @stauffermatt on Twitter

Tags: laravel | laravel 5.1 | testing | integration testing

Matt Stauffer headshot

Hi, I'm Matt Stauffer.

I'm partner & technical director at Tighten Co.

You can find me on Twitter at @stauffermatt

Like what you're reading?

I wrote an entire 450+ page book for O'Reilly: Laravel: Up and Running.

You can order the eBook or print book today.