Laravel migration testing

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'.