【CakePHP5】PHPUnitでテストをしてみる

# はじめに

こんにちは、エンジニアのkeitaMaxです。

今回は、以前作成したCakePHPの環境をつかってテストコードを書いていきます。

https://qiita.com/keitaMax/items/6152aa9fff66bee4e887

# インストール
>CakePHP には PHPUnit をベースとした高度なインテグレーションが組み込まれており、PHPUnit 本体が持つ機能に加えて、CakePHPでテストをスマートに管理するための便利な拡張機能を備えています。
(引用：https://book.cakephp.org/5/ja/development/testing.html)

CakePHPはインストールしなくてもすでに組み込まれているので、インストールは必要ないです。

# テストを作成

コントローラとモデルを作成するコマンドを打った時に一緒にテストを書くファイルお作成されます。

コントローラとモデルを作成については以前記事書いているので以下を参照してください。

https://qiita.com/keitaMax/items/b260eb3899de1115ffd0

以下のようにファイルが作成されます。


```php:tests/TestCase/Controller/ArticlesControllerTest.php
<?php
declare(strict_types=1);

namespace App\Test\TestCase\Controller;

use App\Controller\ArticlesController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;

/**
 * App\Controller\ArticlesController Test Case
 *
 * @uses \App\Controller\ArticlesController
 */
class ArticlesControllerTest extends TestCase
{
    use IntegrationTestTrait;

    /**
     * Fixtures
     *
     * @var list<string>
     */
    protected array $fixtures = [
        'app.Articles',
    ];

    /**
     * Test index method
     *
     * @return void
     * @uses \App\Controller\ArticlesController::index()
     */
    public function testIndex(): void
    {
        $this->markTestIncomplete('Not implemented yet.');
    }
    
    /**
     * Test add method
     *
     * @return void
     * @uses \App\Controller\ArticlesController::add()
     */
    public function testAdd(): void
    {
        $this->markTestIncomplete('Not implemented yet.');
    }

    /**
     * Test edit method
     *
     * @return void
     * @uses \App\Controller\ArticlesController::edit()
     */
    public function testEdit(): void
    {
        $this->markTestIncomplete('Not implemented yet.');
    }

    /**
     * Test delete method
     *
     * @return void
     * @uses \App\Controller\ArticlesController::delete()
     */
    public function testDelete(): void
    {
        $this->markTestIncomplete('Not implemented yet.');
    }
}

```

# テストコードを書く

`testIndex`にテストコードを書いていこうと思います。

テストコードのAssertionsについては以前記事でまとめていたので、そちらを参考にしてください。

https://qiita.com/keitaMax/items/f3dc680edcf35e13e92f

今回はとても簡単に、文字列が合っているかというテストを以下のように書きました。

```php:tests/TestCase/Controller/ArticlesControllerTest.php
    public function testIndex(): void
    {
        $this->assertSame("test","test");
    }
```

# 実行

以下のコマンドでまとめてテストコードを実行することができます。

```
vendor/bin/phpunit
```

実際に実行すると以下のようになります。

```
root@04a17a8a001b:/app# vendor/bin/phpunit
PHPUnit 10.5.20 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.8
Configuration: /app/phpunit.xml.dist

....IIII......I                                                   15 / 15 (100%)

Time: 00:00.124, Memory: 22.00 MB

OK, but there were issues!
Tests: 15, Assertions: 23, Incomplete: 5.
root@04a17a8a001b:/app# 
```

もし今書いたテストファイルだけ実行することもできます。

今回作成した`tests/TestCase/Controller/ArticlesControllerTest.php`だけをしたい場合は以下のようなコマンドになります。

```
vendor/bin/phpunit tests/TestCase/Controller/ArticlesControllerTest.php 
```
実行結果は以下のようになります。

```
root@04a17a8a001b:/app# vendor/bin/phpunit tests/TestCase/Controller/ArticlesControllerTest.php 
PHPUnit 10.5.20 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.8
Configuration: /app/phpunit.xml.dist

.IIII                                                               5 / 5 (100%)

Time: 00:00.037, Memory: 14.00 MB

OK, but there were issues!
Tests: 5, Assertions: 1, Incomplete: 4.
root@04a17a8a001b:/app# 
```

また、特定のファイルの１つの関数だけ実行することもできます。

tests/TestCase/Controller/ArticlesControllerTest.php`の`testIndex`だけをしたい場合は以下のようなコマンドになります。

```
vendor/bin/phpunit tests/TestCase/Controller/ArticlesControllerTest.php --filter testIndex
```

実行結果は以下のようになります。

```
root@04a17a8a001b:/app# vendor/bin/phpunit tests/TestCase/Controller/ArticlesControllerTest.php --filter testIndex
PHPUnit 10.5.20 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.8
Configuration: /app/phpunit.xml.dist

.                                                                   1 / 1 (100%)

Time: 00:00.019, Memory: 14.00 MB

OK (1 test, 1 assertion)
root@04a17a8a001b:/app# 
```

# 失敗させてみる

正しくテストできているか確認するために、今度は失敗させてみます。

`testIndex`を以下のように修正します。

```php:tests/TestCase/Controller/ArticlesControllerTest.php
    public function testIndex(): void
    {
        $this->assertSame("test","error");
    }
```
この状態で以下コマンドを打ちます。


```
vendor/bin/phpunit tests/TestCase/Controller/ArticlesControllerTest.php --filter testIndex
```

実行結果は以下のようにエラーになりました。

```
root@04a17a8a001b:/app# vendor/bin/phpunit tests/TestCase/Controller/ArticlesControllerTest.php --filter testIndex
PHPUnit 10.5.20 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.8
Configuration: /app/phpunit.xml.dist

F                                                                   1 / 1 (100%)

Time: 00:00.026, Memory: 14.00 MB

There was 1 failure:

1) App\Test\TestCase\Controller\ArticlesControllerTest::testIndex
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'test'
+'error'

/app/tests/TestCase/Controller/ArticlesControllerTest.php:36

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
root@04a17a8a001b:/app# 
```

これで正しくテストができていることが確認できました。

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://book.cakephp.org/5/ja/development/testing.html

https://qiita.com/keitaMax/items/6152aa9fff66bee4e887

https://qiita.com/keitaMax/items/b260eb3899de1115ffd0

https://qiita.com/keitaMax/items/f3dc680edcf35e13e92f