Recently I've started to write tests in my Laravel applications. Tests are useful because they allow you to make sure important parts of your application are working, things like registration or subscriptions. Things that could be easily missed and could cause uproar if they broke.
When I started building ReadCast, about a month ago I created it as a prototype and missed out on writing tests. Now that the application is stable and has a few users, I think it's about time to write some tests.
In a standard Laravel install, PHPUnit is already installed for you and so are a few example tests.
In this tutorial I'm going to go through:
- Setting up your tests
- Creating database seeds
- Writing tests
Setting up your tests
In Laravel, your tests belong inside the `tests` directory. In there you have two directories. One for your feature tests and one for your unit tests. I should probably know the difference between this but I don't, so go elsewhere if you want to know the meaning.
Most applications will talk to a database when doing anything. When testing, there are two types of databases that people will likely use. They will either use a SQLite database or a MySQL database.
If you don't know, a SQLite database is pretty much a lightweight SQL database that's stored in a single file.
I tend to create a separate MySQL database for running my tests. Why? Because last time I tried to use SQLite I managed to break some dependency that every programming language needed which meant I had to rebuild my Mac, not a fun time. However, feel free to use whatever you like best.
If you like using MySQL like me, this is how I tend to configure it.
First, I create my testing database, usually called something like `app_testing`.
The next thing I do is go to my `database.php` configuration file and setup a new `testing` database connection. It looks like this:
The values rely on some environment variables so you'll need to add these env variables to your `.env` and `.env.example` files.
Now there's one more thing you need to do before being fully setup. You'll need to specific the type of database you wish to use when testing. We can do this in PHPUnit's configuration file, `phpunit.xml`.
In the bottom `<php>` part, make it look like below, where we add the `DB_CONNECTION` rule and specify the `testing` database connection we just created.
That should be us done with the setup.
Setting up factories
Factories allow you to you to generate database records. Laravel comes with a package called Faker which makes it easy to create factories with fake information. Things like names, emails, passwords, that sort of thing.
You can find your factories in the `database/factories` directory. If you need to create your own factory, you can do so with a simple artisan command: `php artisan make:factory ArticleFactory`
Laravel comes with a User Factory, so we'll just use that one. The user factory looks like this:
The information in the sample user factory is fine for me but you might want to change it, depending on what fields you have in models.
Laravel gives you a pretty basic test which visits a page and the test passes if the status of the page request is 200 (that means its OK).
Now that we know what tests look like, let's delete the example test and create our own. To create our example test, run this command:
```php artisan make:test LoginTest```
In the test I'm going to write, I'm going to create a user, login to my application, submit my email and password then the test will pass if we get status code 200.
Just a heads up, when writing test, make sure to start the method with `test` so PHPUnit knows which methods are actually tests.
In our test, we need to specify that we want to use the `RefreshDatabase` trait. This will allow us to have a clean database for every test meaning results won't be messed up with those from other tests, You can add trait like this:
Now let's write the test. The first thing I said we would do in the test would be to create the user we want to login. We can use Factories to do this. In the code sample below, we're creating a user and storing it's information in the `user` variable.
```$user = factory(\App\User::class)->create();```
Now we have created the user, we need to send a POST request to my login endpoint with my email and password.
The below code will find the input with the name of `email` and will fill it with the email of the user we created and will find the input with the name `password` and will fill it with the password of the user (by default, Laravel's user factory password is 'secret'). It will then find the button with the text that says 'Login' which submits the form. Then it checks to make sure we're redirected successfully to the `/articles` url.
You should now have something that looks a little like this:
If you've done everything correctly, you should be able to run your tests and see them all pass.
And that's it, we've got Laravel setup and we've written tests to make sure logins to our application are working.