When writing feature tests there’s often a lot of boilerplate code that you might have to add to your tests. The default testing framework with Laravel is PHPUnit, a reliable if not somewhat difficult testing tool at time. It’s heavily based on JUnit, a testing cool for Java libraries. Normally if we want to add something to our tests setup we have to implement a Setup method which can be a bit tedious if we’d using the same one over lots of tests. Of course, we could also just add things to the setup method of our TestCase class but then that’s going to run for every test and sometimes we just need for particular tests. Luckily Laravel already has a mechanism baked into its own TestCase that we can modify to switch on and off with our traits.
An Example Trait
So first we need a trait. For the example I’m going to use something simple that pretty much everyone will have to do if making a feature tests, generate users for authentication.
So often a bit of code for a test this might look like this:
$user = factory(User::class)->create();
$this->actingAs($user)
->get('/home')
->assertOk();
This can be a bit redundant as our tests get more complicated and we’re left creating a user for authentication for each test. Instead we’re going to put this into a trait that will create the user for each test at set up.
What this will mean is we no longer have to generate our User model or even specify the user when we want to authenticate the request to the API, simply bringing in the trait will give us a user property in our test case.
We still have to change our TestCase to make this happen though. We’ll do this by adding a setUpTraits method to the TestCase class found in tests/TestCase.php which is made with every fresh Laravel application.
The setUpTraits method is actually a part of the parent TestCast. This is how Laravel normally knows how to do things like refresh databases etc. It works by checking what traits are applied to a test. In this case the parent class method is doing this for us and just returns those traits to us as an array. We can then check if there is a key for the Trait we’re using. If there is we want it to set up the user using the setUpUser method found in our Authentication trait.
Now when we produce a test we only need use the trait Authentication and it’ll create a user. For example we can create the test below to open the home page for a user and then see if our user’s name is printed on the page.
It’s a small change but it’s one I think that really lightens the load when you’re making lots of Feature tests for your application. Just being able to do this opens up a lot of possibilities as well so your can keep your testing code in serviceable state.
If need to, you can always evolve this system also. In the following code I’ve made changes to the trait so you can customise the factory used on a per test case basis simply by checking for the existence of additional methods on the test case.
Now all you would need to do is add a getUserFactoryAttributes method to a TestCase like so:
public function getUserFactoryAttributes()
{
return [
'email' => 'testaccount@mydomain.com',
];
}
And there we have it, test setups we can swap out via Traits with mechanisms for customisation per test case. If you want to check out the code for this you can find it on Github.
I’m Peter Fox, a software developer in the UK who works with Laravel among other things. If you want to know more about me you can at https://www.peterfox.me and feel free to follow me @SlyFireFox on twitter for more Laravel tips and tutorials.
Top comments (0)