【Laravel】PHPUnitテスト用にSQLiteをDBに設定した際に気を付けるべきマイグレーションの記述と解決方法

# つらい思いをした

テストコードが破城しているプロジェクトのシステム(Laravel5.6)に対して、とりあえず正常にテストが走るようにリファクタしようと思い、
まずはテストのDBをSQLiteに設定して個々のテストコードを直そうと思った矢先、マイグレーションの書き方が不味かったらしく、
**SQLiteの仕様でこけました**。
のでとりあえずマイグレーションの記述をSQLiteでも対応できるように直しました。

# SQLiteは1回の変更で`dropColumn`や`renameColumn`を複数回呼び出すことはできない

どうやら**SQLiteは1回の変更で`dropColumn`や`renameColumn`を複数回呼び出すことはできない**らしい

ので以下のようにマイグレーションを記述していると、**MySQLでは正常に処理されるがSQLiteではエラーが発生する**。

```php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class DeleteNameAndKanaOnUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->dropColumn('name');
            $table->dropColumn('kana');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->string('name');
            $table->string('kana');
        });
    }
}
```

以下エラー内容

```
BadMethodCallException: SQLite doesn't support multiple calls to dropColumn / renameColumn in a single modification.
```

なので複数の処理は以下のように修正する必要があります。


```php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class DeleteNameAndKanaOnUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->dropColumn('name');
        });
        Schema::table('user', function (Blueprint $table) {
            $table->dropColumn('kana');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->string('name');
        });
        Schema::table('user', function (Blueprint $table) {
            $table->string('kana');
        });
    }
}
```

# テーブル作成時は`NOT NULL制約`を指定できるが、列追加する際は`NOT NULL制約`をつけることができない

**テーブルを作成するときは`NOT NULL制約`をつけることはできるみたいですが、後で列を追加するときに`NOT NULL制約`をつけることはできない**みたいです。

なので以下のように書いている場合、エラーが発生します。

```php
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->string('hoge');
        });
        Schema::table('user', function (Blueprint $table) {
            $table->string('huga');
        });
    }
```

以下エラー内容

```
PDOException: SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL
```

もし`NOT NULL制約`でない場合は以下のようにデフォルトでNULLを入れてやれば大丈夫のようです

```php
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->string('hoge')->nullable();
        });
        Schema::table('user', function (Blueprint $table) {
            $table->string('huga')->nullable();
        });
    }
```

もし`NOT NULL制約`があるカラムの場合は以下のように**一旦NULLを許可して、後でNOT NULL制約にする必要がある**みたいです
（もっと他にやり方がありそうな気もしますが・・・）

```php
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->string('tell')->nullable();
        });
        Schema::table('user', function (Blueprint $table) {
            $table->string('tell')->nullable(false)->change();
        });
    }
```

# おわり
- そもそもテストDBにSQLiteを設定するのがいいのかわからない・・・

# 参考URL

- [php - PHPUnit doesn't seem to be running Laravel Migration - Stack Overflow](https://stackoverflow.com/questions/43234735/phpunit-doesnt-seem-to-be-running-laravel-migration)
- [[migrations] SQLite General error: 1 Cannot add a NOT NULL column with default value NULL](https://laracasts.com/discuss/channels/general-discussion/migrations-sqlite-general-error-1-cannot-add-a-not-null-column-with-default-value-null)