サーバーサイドの実装

サーバーサイドを実装していきます。
開発言語は PHP、 フレームワークは Laravel を使用します。
可能な限り最新安定版の利用を推奨します。
観光地紹介サービスを作るに記載した Docker ファイルを使って環境構築している場合は、あまり気にする必要はありません。

テストを書く

簡易的な TDD (テスト駆動開発)を実践してもらいます。
まず、以下の動画を視聴してください。
TDD の概要が非常にわかりやすく解説されています。
50分でわかるテスト駆動開発

テスティングフレームワークは、 PHPUnit を使用します。
Laravel はデフォルトでインストールされるようになっているので、すぐに使い始めることができます。
書き方については、日本語化されたPHPUnit マニュアルを参照してください。

ひとまず PHPUnit が動くかどうかの確認をしてみましょう。
コンソールにて、以下を実行します。

$ ./vendor/bin/phpunit --testdox
# docker-compose で動かす場合
$ docker-compose exec php ./vendor/bin/phpunit --testdox

以下のような出力がされれば、正しく動いています。

docker-compose exec php ./vendor/bin/phpunit --testdox
PHPUnit 7.5.9 by Sebastian Bergmann and contributors.

Unit\Example
 ✔ Basic test

Feature\Example
 ✔ Basic test

Time: 1 seconds, Memory: 24.00 MB

OK (2 tests, 2 assertions)

毎回コマンドを打つのは面倒なので、以下を参考に PhpStorm で PHPUnit を実行できるように設定しましょう(記事中では Docker for Mac となっていますが、 Windows でもほぼ同等の作業で設定可能)。
PhpStorm + Docker for Mac(docker-compose)での PHPUnit と Remote Debug の設定 - Shin x Blog

観光地一覧表示(全件)のテストを書く

環境が整ったら、観光地一覧表示のテストを書いてみましょう。
※ テストコードの詳細は書きません。

まず、テストクラスを作成します。

$ php artisan make:test TouristSpotsListTest

すると、tests/Feature/TouristSpotsListTest.php というファイルが作成されます。
このファイルにテストを書いていきます。

次に、どういう結果がこちらの想定している状態なのかをメソッドで定義します。

/**
 * @test
 */
public function 観光地情報を全件取得できる()
{
    // TODO 取得処理
    $response = $this->json('GET', route('spots-list'));
    $response->assertStatus(200);
}

上記では、観光地一覧を表示する URL に GET リクエストを飛ばし、そのレスポンスが 200(リクエスト成功) であるかをテストしています。
もちろん仮実装です。

テストコードは基本的に実行時、何をテストしているのかをひと目でわかるよう、文章になるように書きます。
その際は、常体(言い切り)で記述するといいでしょう。
もちろん英語で書いても問題ないです。
開発チームのメイン言語に合わせてルール化していきましょう。

次に @test の記述。
これは、 PHPUnit に「以下のメソッドはテストメソッドです」という宣言だと思って差し支えありません。
この記述が無くても、メソッド名を「test」で始めることでテストメソッドと認識させることができます。
どちらを使うかは、好みでいいと思いますが、その場合は、プロジェクトで統一するよう心がけてください。

ひとまず実行してみましょう。

$ ./vendor/bin/phpunit --testdox tests/Feature/TouristSpotsListTest.php
PHPUnit 7.5.9 by Sebastian Bergmann and contributors.

 Feature\TouristSpotsList
 ✘ 観光地情報を全件取得できる
   │
   │ InvalidArgumentException: Route [spots-list] not defined.
   │
   │ /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php:388
   │ /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:782
   │ /var/www/html/tests/Feature/TouristSpotsList.php:183
   │

Time: 2.53 seconds, Memory: 24.00 MB

Summary of non-successful tests:

 Feature\TouristSpotsList
 ✘ 観光地情報を全件取得できる
   │
   │ InvalidArgumentException: Route [spots-list] not defined.
   │
   │ /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php:388
   │ /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:782
   │ /var/www/html/tests/Feature/TouristSpotsList.php:183
   │

ERRORS!
Tests: 1, Assertions: 1, Errors: 1.

まだ何も実装していないので、エラーになってしまいました。
このテストを正しく実行させるために、機能を実装してみましょう。
テストが成功したら、テストコードを実際の仕様に近づけます。
上記の場合はレスポンスデータ数が DB に保存されているデータ数と同一か否かを比較するようなテストを書けばいいかと思います。
書けたら再度テストします。
恐らくテストは失敗します。
失敗したら、テストが成功するような実装にします。

これを繰り返してプログラムを作成していきます。
すると結果として、「少なくとも仕様の通りに動くと保証されたプログラム」が完成します。
テストがなければ、どんなに完璧に作ったとしても、「たぶん仕様通りに動くプログラム」にしかなりません。
仕事の成果物として、不確かなモノを提出するべきではありません。
必ずテストを書くように心がけましょう

機能を実装する

テストを書くで出てきた「観光地一覧表示」機能の詳細を記述します。

  1. 観光地テーブルのデータを全件取得すること
  2. レスポンスは JSON を返すこと
  3. Eloquent モデルを利用すること
  4. API として扱うこと

以上の4点が守られているものとします。
初めて目にする単語が複数あると思いますが、自身で調べて実装してみてください。
その他機能についても、基本的に 2 以降を守って実装していってください。
view を表示する場合などは例外です。

results matching ""

    No results matching ""