MySQLでユーザー作成権限付与＆PHPUnitテスト

# この記事の目的
- laravelでテスト用にMySQLのDBを作成した際にDB権限付与でエラーが出たためその解消
- 単純にMySQLでユーザー作成から権限付与までについてまとめ

# 概要
①MySQLでユーザー作成から権限付与
②テストコード実行時にだけ接続するテーブルを用意して設定する方法をまとめる


## ①MySQLでユーザー作成から権限付与
#### まずはMySQLにログインする
```
mysql -uroot -p
```
#### ユーザー作成
```
CREATE USER 'ユーザー名'@'localhost' IDENTIFIED BY 'パスワード';

例）ユーザー名：test_user、パスワード：password123
CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'password123';
```

#### 権限付与DBの作成
作成済みであれば飛ばす
```
create database DB名;

例）DB名：laravel_testing
create database laravel_testing;
```

#### 権限付与
```
GRANT ALL ON DB名.* to 'ユーザー名'@'localhost';

例）ユーザー名：test_user、DB名：laravel_testing
GRANT ALL ON laravel_testing.* to 'test_user'@'localhost';
```

#### 付与した権限の確認
```
show grants for 'ユーザー名'@'localhost';

例）ユーザー名：test_user
show grants for 'test_user'@'localhost';
```
```
+------------------------------------------------------------------------+
| Grants for test_user@localhost                                         |
+------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `test_user`@`localhost`                          |
| GRANT ALL PRIVILEGES ON `laravel_testing`.* TO `test_user`@`localhost` |
+------------------------------------------------------------------------+
```

## ②テストコード実行時にだけ接続するテーブルを用意して設定する方法
#### テスト用.envの作成
下記コマンドで既に存在する.env.exampleをコピーして.env.testingを作成する。
作成したlaravelのプロジェクト階層にて実行（.envファイルがある階層）
```
cp .env.example .env.testing
```
#### テスト用.env.testingのAPP_KEYを発行
下記コマンドを実行して.env.testing用のAPP_KEYを発行する。
```
php artisan key:generate --env=testing
```
#### DB_DATABASEの値をlaravel_testingに変更する。
```.env.testing
APP_ENV=testing

DB_DATABASE=laravel_testing
```
#### テスト時に使うDBの設定

- laravelのアプリケーションディレクトリ内にあるphpunit.xmlを開く。
- コメントアウトされている`<!-- <env name="DB_DATABASE" value=":memory:"/> -->`を修正して下記のように記載する。（こちらでテスト時に使用するDB名を設定している。）

```phpunit.xml
<env name="DB_DATABASE" value="laravel_testing"/>
```

#### テストコードを記載するファイルの作成
デフォルトで`tests/Feature/ExampleTest.php`というテストファイルがありますが、下記のコマンドでテストようのファイルを作成します。
```
php artisan make:test ファイル名

例）ファイル名：TaskTest
php artisan make:test TaskTest
```
`tests/Feature/`配下に`TaskTest.php`ファイルが作成されます。

#### テストコード編集
デフォルトで作成されるテスト処理自体は変えず実行していきます。
##### テストコード作成ルール
- パブリックメソッドであること
- メソッド名の接頭辞に “test” をつけるか、メソッドのコメントに @test アノテーションをつけること
因みにコメントアウトに`@test`というコメントをつけることで、テストとして認識されメソッド名は何をつけても問題なくなります。
下記に上記のルールに則りメソッド名を変更したものを載せています。

```tests/Feature/TaskTest.php
<?php
namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class TaskTest extends TestCase
{
    /**
     * @test
     */
    public function 一覧取得()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}
```
#### テストコード実行
下記コマンドで上で載せているテストを実行します。
```
./vendor/bin/phpunit　ファイルのパス

例）ファイルパス：tests/Feature/TaskTest.php
vendor/bin/phpunit tests/Feature/TaskTest.php
```
今はステータスコード200を返すだけなのでOKと返ってきます。
![test１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/279fa187-4a61-7ea4-9da0-66235ba486f5.png)

#### テストコード編集
デフォルトの処理でテストができることを確認できたので、
DB処理のテストについて行っていきます。
```tests/Feature/TaskTest.php
<?php
namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
//モデルをインポート
use App\Models\Task;

class TaskTest extends TestCase
{
    use RefreshDatabase;
    /**
     * @test
     */
    public function 一覧取得()
    {
        //DBにテスト用にデータ10件を追加
        $tasks = Task::factory()->count(10)->create();
        // 取得するデータはJSONなのでgetJsonを使用
        $response = $this->getJson('api/tasks');
        // 取得データの確認
        // dd($response->json());

        //登録と取得のデータ数が同じであるかの確認
        $response
            ->assertOk()
            ->assertJsonCount($tasks->count());
    }
}
```

#### テストコード実行
下記コマンドで上で載せているテストを実行します。
```
vendor/bin/phpunit tests/Feature/TaskTest.php
```
OKと返っていればテストが無事完了しています。
![test2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/4bc5d43a-1030-c56d-9330-008d16269d5a.png)
因みに`dd($response->json());`のコメントアウトを外すと取得データの確認ができます。
![test3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/7a1af454-fa51-d173-f52f-d5f55d95ae47.png)

## 番外
テスト実行の際にテストの中のある特定の関数のみ実行したいときは、
下記のように`--filter`オプションで関数名を指定することで指定の関数のみテスト実行できます。
```
vendor/bin/phpunit tests/Feature/TaskTest.php --filter "関数名"

例）関数名：一覧取得
vendor/bin/phpunit tests/Feature/TaskTest.php --filter "一覧取得"

```