
どーも!
たかぽんです!
Symfonyで簡単なテストを実装して試してみようと思います!
やってみること
さて、ではこれから何をしてみるかというと...
前回下記の記事でMySQLの設定を行い、"http://127.0.0.1:8001/lucky/number"へアクセスをするとDBの内容が返ってくるControllerを作成しました。
実際の表示は以下のような感じです。
1 2 | User: User1 Comment: Message from User1 |
また、コードは以下のような形です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?php namespace App\Controller; use App\Entity\User; use App\Entity\Comment; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class LuckyController { #[Route('/lucky/number')] public function number(EntityManagerInterface $entityManager): Response { $userId = 1; // テスト用に決め打ちで仮置き // userIdの情報をそれぞれ取得 $user = $entityManager->getRepository(User::class)->find($userId); $comments = $entityManager->getRepository(Comment::class)->findByUserId($user->getId()); // コメントは表示できる形に整形 $commentStrings = array_map(function($comment) { return $comment->getMessage(); }, $comments); $commentsOutput = implode('<br>', $commentStrings); return new Response( '<html> <body> User: '.$user->getName() . '<br>Comment: '. $commentsOutput.' </body> </html>' ); } } |
全然適当な内容ではありますが、今回はこれをテストして行ってみようと思います!
テストの準備を整える
ではいつも通りsymfonyの公式ページをチラッと眺めます。
基本的には下記のSymfonyのテストの資料を眺めながら軽く確認していきます。
では、まずはtestようにphpunitなどをインストールするため、"symfony/test-pack"コンポーネントをインストールします。
1 | composer require --dev symfony/test-pack |
インストールは上記コマンドでサクッとできるはずです!
実行は下記コマンドでできるので、インストールができたら試してみてください。
1 | php bin/phpunit |
(初回はテスト内容がないので、特に何もせずに終わるとおもいます)
ここまで確認ができたら、今度は".env.test"ファイルを開きます。
この.env.testファイルが".env"の中からテスト向けに上書きしたい内容を上書きするためのファイルのようです。
In the test environment, these env files are read (if vars are duplicated in them, files lower in the list override previous items):
- .env : containing env vars with application defaults;
- .env.test : overriding/setting specific test values or vars;
- .env.test.local : overriding settings specific for this machine.
上記にある通り、テスト用の環境変数は、".env.test.local > .env.test > .env"の順で優先順位が付けられているため、.env.test.localに設定した値が最も最優先で読み込まれるようです。
使い分けとして、
.envはアプリケーションのデフォルトで使用する環境変数
.env.testは全体に共通するテスト用の環境変数
.env.test.localはテストを実行するマシンに依存する環境変数
といった具合のようですね。
今回は".env.test"を追記します。
1 | DATABASE_URL="mysql://newuser:password@127.0.0.1:3306/symfony?serverVersion=8.0.33&charset=utf8mb4" |
上記を入れることで、"symfony_test"データベースに接続されるようになります。
前回の記事を読んだ方ならわかるかと思いますが、筆者の環境だと、"symfony_test"というデータベースを作成しました。
しかし、Symfonyのテストで使用されるデータベースは、envで指定した値の末尾に"_test"が付与されるようです。
そのため、DB接続情報を"symfony_test"と設定すると、"symfony_test_test"というDBにアクセスしようとして、エラーになりました。
本来はこちらにあるように、データベース名があった場合、その末尾に"_test"を付けた形でテスト用テーブルを作ることを推奨しています。
そのため、フレームワーク側で、DBアクセスの時も"_test"をつけた形で接続しようとするのだと思います。
筆者はたまたまですが、"symfony_test"で作っていたので、テスト用テーブルは作らず、そのまま"symfony"で.env.testを設定して、"symfony_test"データベースで試します...w
envを設定できたら準備はOKです!
テストを書いて実行する!
それではテストを書いていきます!
本来はDBに値を追加して、その値でコントローラーの返り値を検証すべきなんだろうな...と思いますが、割愛させてください...w
すでに入っているデータを取得する想定で下記のようにしてみました。
ファイルパスは”my_project/tests/Controller/LuckyControllerTest.php"にしてみました。
(テストのファイルの構造は一考の余地があるかもしれません)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php namespace App\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class LuckyControllerTest extends WebTestCase { public function testLuckyController(): void { $client = static::createClient(); $response = $client->request('GET', '/lucky/number'); $this->assertResponseIsSuccessful(); $this->assertSelectorTextContains('body', 'User1'); $this->assertSelectorTextContains('body', 'Message from User1'); } } |
$clientを作成することで、ブラウザのような挙動を確認できます。
なので、$clientで"/lucky/number/"に対してGET requestを送信し、返り値を確認します。
$this->assertResponseIsSuccessful();でResponseが成功だったかどうか?
$this->assertSelectorTextContainsで第一引数のタグの中に第二引数の文字列が含まれるかどうか?といったことが検証できるようです。
今回はテストを最低限動かしてみたいだけなので上記のような形で実行してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | taka@Taka my_project % php bin/phpunit tests/Controller/LuckyControllerTest.php PHPUnit 9.6.10 by Sebastian Bergmann and contributors. Testing App\Tests\Controller\LuckyControllerTest . 1 / 1 (100%) Time: 00:00.275, Memory: 30.00 MB OK (1 test, 3 assertions) Remaining indirect deprecation notices (1) 1x: The "Monolog\Logger" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Bridge\Monolog\Logger". 1x in LuckyControllerTest::testLuckyController from App\Tests\Controller |
実行すると、ちゃんと3つのassertionsが問題なく、3つのassertionを含む一つのテストが成功していることがわかります。
ここら辺はPHP Unitなので、Laravelの時とほぼ一緒な印象でした!
ちなみに、下記のように全件実行・フォルダ下のみ実行・特定ファイルのテストのみ実行といったコマンドの差分があったりするようです。
1 2 3 | taka@Taka my_project % php bin/phpunit taka@Taka my_project % php bin/phpunit tests/Controller taka@Taka my_project % php bin/phpunit tests/Controller/LuckyControllerTest.php |
まとめ
Symfonyでテストを実行してみました!
PHPUnitを使っていることもあり、大体laravelと変わらず実行できそうな気がします。
今回はテストした内容があまりよろしくなかったのですが、テストの実装感は掴めたかな?と思います。
さらにどこかのタイミングで深掘りしてMockとか...複雑なテストなんかも試してみたいですね!
それでわ!