PHPでテストを書く(PHPUnit)
自動テストの重要性
コードを書き換えた後、再テストには大きな労力がかかる。 => 自動テストという仕組みが役に立つ。
参考書籍に則り、PHPUnitという自動テストツールを使用する。
他にも様々なツールがあるみたい。
PHPUnitのインストール
PHPUnitのインストール
composer require --dev phpunit/phpunit
テストの書き方
- PHPUnitに用意されてる TestCaseを継承したクラスを作成する必要がある。
- クラス名、ファイル名は
Test
で終わる必要がある。 - テストの成功か、失敗かはメソッド内に書かれたassertOOメソッドが真を返すかどうかで決まる。
実行
ファイル名: MyTest.php
<?php require_once dirname(__FILE__) . '/vendor/autoload.php'; use PHPUnit\Framework\TestCase; class MyTest extends TestCase { // テスト処理 public function test1() { $array = [1, 5, 10]; // 配列($array)の要素数が3つであることをテストする。 $this->assertCount(3, $array); } public function test2() { $num1 = 1; $num2 = 1; // 2つの値が型も含めて等しいことをテストする。 $this->assertSame($num1, $num2); } public function test3() { $text = "hello"; // 値が空であることをテストする。 $this->assertEmpty($text); } }
実行
./vendor/phpunit/phpunit/phpunit MyTest.php
実行結果
PHPUnit 9.5.0 by Sebastian Bergmann and contributors. ..F 3 / 3 (100%) Time: 00:00.008, Memory: 4.00 MB There was 1 failure: 1) MyTest::test3 Failed asserting that a string is empty. /Users/kona/PHPUnitApp/MyTest.php:31 FAILURES! Tests: 3, Assertions: 3, Failures: 1.
↑の実行結果は2つが成功し、1つが失敗している。
2行目が結果を示している。
- 「.」が成功
- 「F」が失敗
- 「E」がエラー
- 「R」がリスク
- 「S」がスキップ
- 「I」が不完全
おまけ(エイリアスの作成)
エイリアスを作成して楽しよう
alias phpunit="./vendor/phpunit/phpunit/phpunit"
以降、
phpunit MyTest.php
で実行可能。
参考情報
PHP本格入門[下] ~オブジェクト指向設計、セキュリティ、現場で使える実践ノウハウまで
- 作者:大家 正登
- 発売日: 2020/08/03
- メディア: 単行本(ソフトカバー)
簡単なRESTful APIサーバーを作ってみる
RESTful APIって?
標準的なWebAPIの設計方式。
リソースに対するURLを1つだけ用意し、HTTPメソッドの切り替えで操作を表す。
例
- 読書リストのうち、ID「0001」の本を取得する
- (URL)https://xxxxx/readinglist/0001
- (HTTPメソッド) GET
- 読書リストのうち、ID「1000」の本を削除する
- (URL)https://xxxxx/readinglist/1000
- (HTTPメソッド) DELETE
RESTful APIはステートレスであるべき
ステートレス = WebAPIサーバはセッション変数を持つべきではない。
サーバ間で共有ができなくなる。などの問題があるから。
スケーラビリティの問題。(今後サーバを増やしたいときとか)
PHPでRESTfulAPIサーバ、クライアントの作成
環境
macOS BigSur 11.0.1
PHP 7.3.22
MAMP 5.7
サーバサイドのPHPファイルを作成
<?php declare(strict_types=1); // GET function getMessage() { $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $_GET['userName'] . 'の好きな食べ物は、' . $_GET['food'] . 'です。', ]; return $res; } //POST function postMessage() { $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $_POST['userName'] . 'の好きな食べ物を、' . $_POST['food'] . 'に登録しました。', ]; return $res; } // PUT function putMessage() { parse_str(file_get_contents('php://input'), $putRequest); $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $putRequest['userName'] . 'の好きな食べ物を、 ' . $putRequest['food'] . 'に変更しました。', ]; return $res; } // DELETE function deleteMessage() { parse_str(file_get_contents('php://input'), $deleteRequest); $res = [ 'status' => 'success', 'message' => 'ユーザ: ' . $deleteRequest['userName'] . 'の好きな食べ物、' . $deleteRequest['food'] . 'を削除しました。', ]; return $res; } switch (strtolower($_SERVER['REQUEST_METHOD'])) { case 'get': echo json_encode(getMessage()); break; case 'post': echo json_encode(postMessage()); break; case 'put': echo json_encode(putMessage()); break; case 'delete': echo json_encode(deleteMessage()); break; }
クライアントサイドのPHPファイルを作成
cUEL関数を使用。
curl_init()
でURLを指定。cURLハンドルを取得。curl_setopt()
でオプションの指定。curl_exec()
でハンドルを渡し、リクエストを送信。レスポンスを取得。curl_close()
でハンドルを閉じる。
GET
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶', ]; $url = "http://localhost:8888/server.php?" . http_build_query($params); $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答:\n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物は、抹茶です。 )
http_build_query()
で連想配列をパラメータ文字列へ。
$params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶', ];
↓
userId=1001&userName=kona&food=抹茶(Unicodeに変換される)
POST
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶', ]; $opt = [ CURLOPT_URL => 'http://localhost:8888/server.php', CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $params, CURLOPT_RETURNTRANSFER => true, ]; $handle = curl_init(); curl_setopt_array($handle, $opt); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答:\n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物を、抹茶に登録しました。 )
curl_setopt_array()
で配列で指定した設定を適応できる。
PUT
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶アイス', ]; $opt = [ CURLOPT_URL => 'http://localhost:8888/server.php', CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_POSTFIELDS => http_build_query($params), CURLOPT_RETURNTRANSFER => true, ]; $handle = curl_init(); curl_setopt_array($handle, $opt); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答:\n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物を、 抹茶アイスに変更しました。 )
DELETE
<?php declare(strict_types=1); $params = [ 'userId' => 1001, 'userName' => "kona", 'food' => '抹茶アイス', ]; $opt = [ CURLOPT_URL => 'http://localhost:8888/server.php', CURLOPT_CUSTOMREQUEST => 'DELETE', CURLOPT_POSTFIELDS => http_build_query($params), CURLOPT_RETURNTRANSFER => true, ]; $handle = curl_init(); curl_setopt_array($handle, $opt); $apiResponse = json_decode(curl_exec($handle), true); curl_close($handle); echo "サーバからの応答: \n"; print_r($apiResponse);
実行結果
サーバからの応答: Array ( [status] => success [message] => ユーザ: konaの好きな食べ物、抹茶アイスを削除しました。 )
参考書籍
PHP本格入門[下] ~オブジェクト指向設計、セキュリティ、現場で使える実践ノウハウまで
- 作者:大家 正登
- 発売日: 2020/08/03
- メディア: 単行本(ソフトカバー)