PHPUnitではじめるLaravelテスト自動化 - 実践的アサーション集

# はじめに
実務でLaravelを使用して開発することが多いですが、自動テストフレームワーク(PHPUnit)の勉強を始めました。その備忘録をの残しておきます。間違っているところなどありましたら、易しく教示していただけると大変ありがたいです。

# PHPUnit基本コマンド
PHPUnitを使うときによく使用するコマンド一覧になります。

| コマンド　| 説明 | 
| ---- | ---- | 
| `php artisan test` | 	Laravel の全テストを実行 | 
| `php artisan test --filter=TestClassName` | 	特定のテストクラスだけ実行 | 
| `vendor/bin/phpunit` | PHPUnit を直接実行 | 
| `vendor/bin/phpunit tests/Feature/ExampleTest.php` | 	定のファイルだけ実行 | 
| `vendor/bin/phpunit --testdox` | テスト結果を人間が読みやすい形式で出力 | 

# PHPUnit の主要なアサーション
### 1. assertTrue($value)
→　「$value」 が 「true」 であることを確認
```php
$this->assertTrue(true); // 成功
$this->assertTrue(1 === 1); // 成功
$this->assertTrue(false); // 失敗
```

### 2. assertTrue($value)
→　「$value」 が 「false」 であることを確認
```php
$this->assertFalse(false); // 成功
$this->assertFalse(1 === 2); // 成功
$this->assertFalse(true); // 失敗
```

### 3. assertEquals($expected, $actual)
→　「$value」 が 「$actual」 であることを確認
```php
$this->assertEquals(5, 2+3); // ✅ 成功
$this->assertEquals('hello', 'hello'); // ✅ 成功
$this->assertEquals(3, 5); // ❌ 失敗
```

### 4. assertNotEquals($expected, $actual)
→　「$expected」と「$actual」 が異なる
```php
$this->assertNotEquals(4, 2+3); // 成功
$this->assertNotEquals('hello', 'world'); // 成功
$this->assertNotEquals(5, 5); //  失敗
```

### 5. assertSame($expected, $actual)
→　型も含めて 「$expected」と 「$actual」 が等しい
```php
$this->assertSame(5, 5); // 成功（型も一致）
$this->assertSame('hello', 'hello'); // 成功
$this->assertSame(5, '5'); // 失敗（型が違う）
```

### 6. assertNotSame($expected, $actual)
→　型も含めて「$expected 」と「$actual」が異なる
```php
$this->assertNotSame('5', 5); // 成功（型が違う）
$this->assertNotSame(10, 10.0); // 成功（int と float）
$this->assertNotSame(5, 5); // 失敗
```

### 7. assertNull($value)
→　「$value」 が 「null」 であることを確認
```php
$this->assertNull(null); // 成功
$this->assertNull(''); // 失敗（空文字）
$this->assertNull(0); // 失敗（数値0）
```

### 8. assertNotNull($value)
→　「$value」 が 「null」 でないことを確認
```php
$this->assertNotNull(5); // 成功
$this->assertNotNull('hello'); // 成功
$this->assertNotNull(null); // 失敗
```

### 9. assertGreaterThan($expected, $actual)
→　「$actual」 が 「$expected」 より大きい
```php
$this->assertGreaterThan(3, 5); //　成功
$this->assertGreaterThan(0, 1); // 成功
$this->assertGreaterThan(5, 3); // 失敗
```

### 10. assertLessThan($expected, $actual)
→　「$actual」 が 「$expected」 より小さい
```php
$this->assertLessThan(5, 3); // 成功
$this->assertLessThan(10, 2); // 成功
$this->assertLessThan(3, 5); // 失敗
```

### 11. assertContains($needle, $haystack)
→　配列や文字列に 「$needle」 が含まれる
```php
$this->assertContains(3, [1, 2, 3, 4]); // 成功
$this->assertContains('hello', 'hello world'); // 成功
$this->assertContains(5, [1, 2, 3, 4]); // 失敗
```

### 12. assertNotContains($needle, $haystack)
→　配列や文字列に 「$needle」 が含まれない
```php
$this->assertNotContains(5, [1, 2, 3, 4]); // 成功
$this->assertNotContains('bye', 'hello world'); // 成功
$this->assertNotContains(3, [1, 2, 3, 4]); //　失敗
```

### 13. assertCount($expectedCount, $array)
→　「$array」 の要素数が 「$expectedCount」 と一致
```php
$this->assertCount(3, [1, 2, 3]); // 成功
$this->assertCount(2, ['a', 'b']); //  成功
$this->assertCount(4, [1, 2, 3]); // 失敗
```
### 14. assertEmpty($value)
→　「$value」 が空であることを確認
```php
$this->assertEmpty([]); //　成功
$this->assertEmpty(''); // 成功
$this->assertEmpty([1]); // 失敗
```

### 15. assertNotEmpty($value)
→　「$value」 が空であることを確認
```php
$this->assertEmpty([]); //　成功
$this->assertEmpty(''); // 成功
$this->assertEmpty([1]); // 失敗
```

# Laravel ならではのアサーション
### 1. assertDatabaseHas()
→　指定のデータがデータベースに存在する
```php
$this->assertDatabaseHas('employees', [
    'email' => 'john@example.com'
]);
```

(例)従業員 (employees テーブル) に 新しいレコードを追加し、それが DB に存在するか確認

```php
/** @test */
    public function it_checks_if_an_employee_exists_in_database()
    {
        // データを作成
        Employee::create([
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'position' => 'Developer'
        ]);

        // データがDBにあるかチェック
        $this->assertDatabaseHas('employees', [
            'email' => 'john@example.com'
        ]);
    }
```
### 2. assertDatabaseMissing()
→　指定のデータがデータベースに存在しない
```php
$this->assertDatabaseMissing('employees', [
    'email' => 'nonexistent@example.com'
]);
```

(例) データベースに特定のデータが存在しないことを確認
```php
/** @test */
public function it_checks_if_an_employee_is_deleted()
{
    // データ作成
    $employee = Employee::create([
        'name' => 'Jane Doe',
        'email' => 'jane@example.com',
        'position' => 'Manager'
    ]);

    // データを削除
    $employee->delete();

    // データがDBに存在しないことを確認
    $this->assertDatabaseMissing('employees', [
        'email' => 'jane@example.com'
    ]);
}

```

### 3. postJson()
→　APIリクエストを送信し、ステータスを確認

```php
$response = $this->postJson('/api/employees', [
    'name' => 'John Doe',
    'email' => 'john@example.com'
]);

$response->assertStatus(201);
```
(例) 新しい従業員を API 経由で登録し、201 Created のレスポンスを返すか確認
```php
/** @test */
public function it_creates_an_employee_via_api()
{
    // APIリクエスト送信
    $response = $this->postJson('/api/employees', [
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'position' => 'Developer'
    ]);

    // ステータスコードが201（Created）であることを確認
    $response->assertStatus(201);

    // レスポンスJSONが期待通りか確認
    $response->assertJson([
        'message' => 'Employee created successfully',
        'employee' => [
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'position' => 'Developer'
        ]
    ]);

    // データベースに正しく登録されているか確認
    $this->assertDatabaseHas('employees', [
        'email' => 'john@example.com'
    ]);
}

```

### 4. post()
→　リダイレクトを確認
```php
$response = $this->post('/employees', [
    'name' => 'John Doe',
    'email' => 'john@example.com'
]);

$response->assertRedirect('/employees');
```

(例)新しい従業員を登録した後、/employees にリダイレクトされることを確認
```php
/** @test */
public function it_redirects_after_employee_creation()
{
    // フォームリクエスト送信
    $response = $this->post('/employees', [
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'position' => 'Developer'
    ]);

    // `/employees` にリダイレクトされることを確認
    $response->assertRedirect('/employees');
}

```

### 5. actingAs()
→　認証ユーザーとしてリクエストを送る
```php
$user = User::factory()->create();
$this->actingAs($user)->get('/dashboard')->assertOk();
```

(例)証済みのユーザーで ダッシュボード (/dashboard) にアクセスできることを確認。
```php
use App\Models\User;

/** @test */
public function authenticated_user_can_access_dashboard()
{
    // テスト用のユーザーを作成
    $user = User::factory()->create();

    // 認証済みユーザーとしてアクセス
    $this->actingAs($user)->get('/dashboard')->assertOk();
}
```

# おわりに
PHPUnitを使用してテストコードの作成を始めましたが、覚えることが多くてとても大変です。引き続き勉強をしていこうと思います。最後までご覧いただきありがとうございました