Laravel makes TDD a lot more fun, it is such a joy to work with . The essence of the tests in this series is to ensure that your app model relationship is not missing a bolt. The code snippets will be available for easy reach at this Github project link.
To make this post more organized it will be split into three (3) parts.
- Part 1: Intro and Schema Tests ⏯
- Part 2: Testing Basic Model Relationships
- Part 3: Testing Polymorphic Relationships
Writing tests make your code rock solid, predictable and highly maintainable. I have written some terrible apps in the past and it can be unnerving when broken codes scream in — y o u r — face. Those years I had no clue about unit tests — fix one bug and another one surfaces, more annoying is that you don’t know when another will pop up. Errors are bound to occur if relevant models are missing or wrongly connected.
Unit Tests are written for small pieces of a code base such as methods or attributes in a class. It usually deals with testing fine details at low level only. In our case we will be testing some methods on Laravel model classes, that is, model connections and relationships between different parts of an app.
Feature Tests is more encompassing as it sums up different part of a code and tests how well they inter-operate eg functional tests and integration tests on components, modules etc. We are not going into functional test in this post.
NB: it is assumed that you have a working knowledge of Laravel, therefore nitty gritty of installation, eloquent model setup and relationship are not discussed. However, test relevant topics will be discussed in depth.
laravel new modelRelTestsvia installer
composer create-project --prefer-dist laravel/laravel modelRelTestsvia create-project
We are going to make use of an sqlite database and use it in memory for faster test runs. Go to phpunit.xml at the root directory of your application and add:
... <server name=" **DB\_CONNECTION**" value=" **sqlite**"/> <server name=" **DB\_DATABASE**" value=" **:memory:**"/>
If we run
vendor/bin/phpunit at this point we get 2 tests for the dummy tests added by Laravel, one test each in the Unit and Feature test directories. Seeing the green is refreshing. You should delete the two files in preparation for our real tests.
By default, every new Laravel installation comes with a User model class (along with migration, controller etc) but not a test. We should create our own test file with the command:
php artisan make:test **UserTest --unit**
This creates a test file named UserTest.php within the tests/Unit directory in the root folder. The
--unit flag implies that we are creating a unit test and should add the generated file to the unit test directory. Without the
--unit flag we have a feature test and it gets added to tests/Feature directory.
Before visiting model relationship tests, my very first unit test in every Laravel model is the schema test. We can use this test to ensure that relevant table columns are not missing and also have the correct and expected names. All we need to do is this:
Take note of :
WithFakertraits. These two traits are important in most tests since you will most likely need a database of data to test your models and the faker library to populate a database with data to be tested upon.
If you want to be explicit about your schema checks you may check each individual field with:
...Schema:: **hasColumn** ('model', **'column'** ), 1);instead of
...Schema:: **hasColumns** ('model', **['column\_1', 'column\_2']**), 1);which checks all columns existence at once.
**hasColumns()** though, odd part is that you get a general error report and so don’t know the actual column affected unless you check thoroughly.
vendor/bin/phpunit and see the result below 👇
This test failed, why? We have not set up or created our database yet. Set up your database configurations within the
.env file according to your machine. See the snippet below:
DB\_DATABASE=homestead DB\_USERNAME=homestead DB\_PASSWORD=secret
Then, create your database within your xampp, wamp or homestead and run:
$ php artisan migrate
Illuminate\Database\QueryException : SQLSTATE: If you encounter the
Illuminate\Database\QueryException : SQLSTATE error while running the migration like in image below
Go to App/Providers/AppServiceProvider.php and make the following updates. Within the boot method add
Schema::defaultStringLength(191); and add a the namespace like so
use Illuminate\Support\Facades\Schema;. See below 👇
vendor/bin/phpunit again and you should get a success result as below:
Play around a little more by adding a new column into the test, do not add to the schema migration file initially, run the test to see results, failed? Make it pass. This particular test may look boring but from the ground up you can be sure your schema integrity is accounted for.
Now that you are beginning to write tests there will be a lot of tests to run. It would make much sense to have shortcut form of some lengthy commands, the cli commands you use often. This will surely improve your productivity. Bash alias es to the rescue, it is a method of supplementing or overriding Bash commands with new ones eg allow users to customize their experience in a POSIX terminal.
alias name="command to shorten"— creates a new alias ‘name’ NB: there are no spaces around the
alias— displays all your set aliases directly in the CLI.
- On a Windows PC, you may access and manage a list of your set aliases in the .bash_profile file at
C:\Users\yourUsername\.bash\_profile. Here you can add, update or remove the entries.
I use the commands below most times in my tests:
vendor/bin/phpunitthis runs all tests within the tests directory.
vendor/bin/phpunit --filterthis selectively runs test within all files and test methods whose name has the string (pattern).
vendor/bin/phpunit --testsuite Unitthis runs all tests within the Test\Units directory only.
vendor/bin/phpunit --testsuite Featurethis runs all tests within the
There are more others but these ones comes handy for me all the time.
I become paranoid if I write an app without some tests these days. I learnt the hard way and has since inculcate the habit of writing comprehensive tests for my apps — the predictability, ease of maintenance and confidence that accompanies a well tested codebase is indescribable. Kindly check the remaining two parts (see links below 👇) for they are the biggest deal.
- ⏯Part 1: Intro and Schema Tests
- 👉Part 2: Testing Basic Model Relationships
- 👉Part 3: Testing Polymorphic Relationships
Your comments are highly appreciated.