Nov 8, 2017 4 min read
Laravel Feature Tests Using Regex Patterns
I recently created a Laravel app that implemented swappable repositories to create random numbers.
Jon Berbaum
President
I recently created a Laravel app that implemented swappable repositories to create random numbers. One of the repositories would be injected into a controller. The app is actually a tutorial/demo to show off Laravel’s Automatic Injection and random number generators seemed like an interesting way to demonstrate how to inject one particular implementation out of several. I decided to create one implementation using the standard random number generator, another using the Mersenne Twister generator, and a third using a cryptographically secure generator.

I often use TDD in my process so the first test I wrote was to test for the generation of a random number. My test would drive my implementation. I created a Feature test using http-test and quickly realized that the available assertions did not contain any regex style assertions. All I wanted to do was assert that the returned content include a random number between 0 and 100. A simple pattern match on a regex of 1 to 3 digits would do nicely. But how to do this?
Laravel’s http-test capabilities are intended to make testing APIs, URLs and fixed content simple. Unfortunately, a regex pattern matching assertion is not included. To solve this shortcoming, I needed to get the actual rendered content and use PHPUnit assertions. This turned out to be quite easy since http-test tests are a superset of PHPUnit and all PHPUnit assertions are already available. This approach can be used to leverage any PHPUnit style assertion or even create a custom assertion when needed.
This example assumes a controller and route that will generate a string that includes a random number.
<?php
// app/Http/Controllers/RandomController.phpnamespace App\Http\Controllers;use Illuminate\Http\Request;class RandomController extends Controller
{
public function index()
{
return sprintf("Hello and the winning number is %d!", rand(0,100));
}
}
We need a route to invoke the controller.
<?php
// routes/web.phpRoute::get('/random', 'RandomController@index');
And finally the test.
<?php
// tests/Feature/CanMatchRegexTest.phpnamespace Tests\Feature;use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;class CanMatchRegexTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
//$this->assertTrue(true);
$response = $this->get('/random'); $response->assertStatus(200);
$response->assertSeeText('Hello'); // expect content: 'Hello and the winning number is <number>!' where number is >= 0 and <= 100
// get the actual page content
$content = $response->getContent();
// assert a regex
$this->assertRegExp('/^Hello .* winning number is \d+!$/', $content);
}
}
The rendered page is available in $response->getContent(). This can be matched using PHPUnit’s assertRegExp() assertion. You can obviously use any PHPUnit assertion or even create a more complex assertion when required.
Here’s a similar example with subtle differences. The rendered page shows a number between 0 and 100. I wanted a single assertion that verified the number to be in that range.
<?php
// tests/Feature/CanViewRandomNumberTest.phpnamespace Tests\Feature;use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;class CanViewRandomNumberTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$response = $this->get('/random'); $response->assertStatus(200); // laravel http-tests available-assertions don't include
// numeric tests - let's roll our own
// first grab the page content
$content = $response->getContent(); // create a PHPUnit assertion on both >= and <=
$this->assertThat(
$content,
$this->logicalAnd(
$this->greaterThanOrEqual(0),
$this->lessThanOrEqual(100)
)
);
}
}
Sometimes a simple assertSeeText() is sufficient, but sometimes you need more flexibility. Even though Laravel is missing http-test regex assertions out-of-the-box, they are really easy to add when needed.
Testing may seem difficult, confusing, and time consuming, but I find that testing speeds up my process in the long run. And I have much more confidence in my work when I have tests to prove that it works as intended. Finally, I get the benefit of a nice regression suite that grows with the code.

Happy testing with regex patterns!
Download the code here.