🛠️

Laravel テスト作成時に役立つかも知れないDBダンプするスニペット

2022/10/31に公開

前書き

例によって大したものでは無いのですが、テスト作成時に役立つ事もあるかも知れないスニペット(メソッド)を作ってみましたので、良ければ使ってみて下さい。

本文

Laravel で PHPUnit を使った Feature テストを作成する際、テストメソッド内で必要なデータ(モデル)を作成すると思います。1~2テーブル位ならいいのですが、3~4以上のテーブルが絡んできて、各モデルがリレーションで繋がっていたりすると、テスト用のデータがちゃんと作れているか、心配になる時もあります。そんな時、とっさに、

dump(User::get()->toArray());

などと書いたりして確認できる訳ですが、やはり複数のテーブルがあると地味に手間ですね。
そこで、

$this->dumpdb();

とする事で、全テーブルの中でデータの入っているテーブルのデータを dump() するというスニペットを作りました。

使用例と出力結果の例は、下記みたいな感じです。

使用例
class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    function 何かのテスト()
    {
        Post::factory()->create();

        $this->dumpdb();
    }
}
出力結果の例
"■■■■■■■■■■■■■■■■■■■ users 1件 ■■■■■■■■■■■■■■■■■■■"
array:1 [
  0 => {#1018
    +"id": 1
    +"name": "Michel Quitzon"
    +"email": "earnest.okuneva@example.org"
    +"email_verified_at": "2022-10-31 06:19:10"
    +"password": "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi"
    +"remember_token": "ZOGp6KyO1v"
  }
]
"■■■■■■■■■■■■■■■■■■■ posts 1件 ■■■■■■■■■■■■■■■■■■■"
array:1 [
  0 => {#1238
    +"id": 1
    +"user_id": 1
    +"title": "Queen in."
    +"body": "King was."
    +"img": null
  }
]

   PASS  Tests\Feature\ExampleTest
  ✓ 何かのテスト

  Tests:  1 passed
  Time:   0.10s

dumpdb のコード

tests/TestCase.php に以下を追記します。

TestCase.php
<?php

namespace Tests;

use Illuminate\Foundation\Console\CliDumper;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    /**
     * dumpdb
     */
    protected function dumpdb(): void
    {
        if (class_exists(CliDumper::class)) {
            // ファイル名や行数の出力を消す
            CliDumper::resolveDumpSourceUsing(fn () => null);
        }

        foreach (Schema::getAllTables() as $table) {
            if (isset($table->name)) {
                $name = $table->name;
            } else {
                $table = (array) $table;
                $name = reset($table);
            }

            if (in_array($name, ['migrations'], true)) {
                continue;
            }

            $collection = DB::table($name)->get();

            if ($collection->isEmpty()) {
                continue;
            }

            $data = $collection->map(function ($item) {
                unset($item->created_at, $item->updated_at);

                return $item;
            })->toArray();

            dump(sprintf('■■■■■■■■■■■■■■■■■■■ %s %s件 ■■■■■■■■■■■■■■■■■■■', $name, $collection->count()));
            dump($data);
        }

        $this->assertTrue(true);
    }
}

動作確認状況

MySQL であれば、Laravel 6 でも大丈夫。(Laravel6.10 で動作確認)
SQLite であれば、Laravel 9.9 以上が必要。
PostgreSQL 13.5 & Laravel 9.35 で大丈夫でした。

以下、補足です。

  1. Laravel Ver.9.32 から dump() などにファイル名や行数が表示されるようになっていますが、その機能は無効化しています。
  2. migrations テーブルは対象外にしています。
  3. created_atupdated_at の項目はカットしています。
  4. 最後に、$this->assertTrue(true); を実行して、不要な表示を抑えています。

以上です。

雑感

これで、少しテストも楽になるでしょうか🍷

もし良ければ、下記の記事もご覧下さい。
https://zenn.dev/nshiro/articles/8ee5e2480b2ed3

間違い等見つけましたらコメント下さい🙇‍♂️

Discussion