Laravel migration testing
Testing a Laravel migration, which columns exist on our database?
Our objective in this article is to specifically test a small subset of our application. Migrations. And I know some people would argue that testing a migration is not a feature to test because, Features are what a user can do in our application a behavior. A user, however, has no means to interact with a migration directly. Nevertheless, you will occasionally pursue 100% coverage for a reason or another.
This is exactly what we are going to be doing today, testing a migration
Laravel setup
We simply start a new Laravel application from scratch.
Laravel migration
php artisan make:migration create_blogs_table
Lets assume we create a blogs migration, and add columns
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->string('slug')->unique();
$table->text('post');
$table->boolean('published');
$table->timestamps();
Testing a migration
We create a feature test
php artisan make:test BlogsTest
We can write logic related blogs, here, like blogs relationships or migrations..etc
Lets try a first way that will. accomplish what we want but still not the way we want it
/** @test */
public function blog_table_has_proper_columns(): void
{
$this->assertTrue(
Schema::hasColumns('blogs', [
'user_id', 'title', 'slug', 'post', 'published
'])
);
If we on puropse change a name column, or add one that dont exist we get the error
Failed asserting that false is true.
This wont help figure out which column name isnt working properly.
Ultimate solution
We first find out. what. are the columns and then we assert the table columns contains what we expect.
public function blog_table_has_proper_columns(): void
{
$actualColumns = Schema::getColumnListing('blogs');
// we assert contains for each column we expect
$this->assertContains('title', $actualColumns);
$this->assertContains('published', $actualColumns);
$this->assertContains('user_id', $actualColumns);
$this->assertContains('slug', $actualColumns);
$this->assertContains('post', $actualColumns);
}
In case we try to assert against a non existing column, our test error would be.
Failed asserting that an array contains 'not-a-column'.