クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

HTTP API のテスト

このレッスンのあとで: 正しいリクエスト、間違ったリクエスト、再試行で API をテストし、各確認が何を示すかを言える。

60分のレッスンコマンド16件PostgreSQL と PostgREST のラボ:ブラウザーで学ぶデータベースと REST API

Web API のテストの仕方

API のテストは、リクエストを送って、答えを確かめます。API の裏のコードは見ません。呼ぶ側が聞くことだけを聞き、答えを、API が約束したことと比べます。

確認を手で数個書き、失敗するものを1つ見て、リクエストを2回送ったときに何が起きるかを試します。

このレッスンのゴール

メモ

正しいリクエスト、間違ったリクエスト、再試行で API をテストし、各確認が何を示すかを言える。

重要な言葉

ことばいみ
テストケース1つのリクエストと、返ってくると期待する答え
期待するステータスAPI が返すはずのステータスコード
テストデータテストのためだけに作り、探して消せる行
再試行最初の答えが届かなかったので、同じリクエストをまた送ること
冪等2回送っても、1回送ったあとと変わらないこと

学生が入力するセルは、このプレビューでは空白です。

確認はリクエストと期待する番号

curl を打って数字を目で読むやり方は、数が増えると続きません。確認を一度だけ書きます。名前、期待するステータス、リクエストです。

まず psql にパスワードを渡し、books 表を作ります。そのあと、check という小さな関数を端末に定義します。リクエストを送り、PASS か FAIL を言う関数です。

psql にパスワードを渡す

コマンド
export PGPASSWORD=shop

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

books 表を作る

コマンド
psql -h db -U shop -c "drop table if exists books; create table books (id serial primary key, title text not null, year int not null, available boolean not null default true); insert into books (title, year, available) values ('海の地図', 1998, true), ('ヨーロッパの川', 2004, false), ('夜行列車', 2011, true); notify pgrst, 'reload schema'"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

check 関数を定義する

コマンド
check() { want=$1; name=$2; shift 2; got=$(curl -s -o /dev/null -w '%{http_code}' "$@"); if [ "$got" = "$want" ]; then echo "PASS $name"; else echo "FAIL $name, wanted $want and got $got"; fi; }

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

正しいリクエストを確かめる

コマンド
check 200 "本の一覧" "http://api:3000/books"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

失敗するはずのものを確かめる

コマンド
check 200 "わざと間違い" "http://api:3000/nothing"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

断られるものをテストする

2つ目の確認は、関数が FAIL と言えると示すために、わざと間違えました。いつも PASS と出る確認は、ない方が悪いくらいです。

よいテスト一式は、正しいリクエストと同じだけ、間違ったリクエストに時間を使います。どれも正しいコードの 4xx で返り、データを変えてはいけません。

タイトルのない本を確かめる

コマンド
check 400 "タイトルなし" -X POST -H "Content-Type: application/json" -d '{"year":2019}' "http://api:3000/books"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

JSON でない本文を確かめる

コマンド
check 400 "壊れた JSON" -X POST -H "Content-Type: application/json" -d 'this is not json' "http://api:3000/books"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

テスト用の本の追加を確かめる

コマンド
check 201 "本を追加" -X POST -H "Content-Type: application/json" -d '{"id":900,"title":"テスト本","year":2020}' "http://api:3000/books"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

同じ id をもう一度確かめる

コマンド
check 409 "同じ id の再送" -X POST -H "Content-Type: application/json" -d '{"id":900,"title":"テスト本","year":2020}' "http://api:3000/books"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ステータスだけでなく本文も確かめる

コマンド
curl -s "http://api:3000/books?id=eq.900" | grep -q '"title":"テスト本"' && echo "PASS 本文にタイトルがある" || echo "FAIL 本文にタイトルがある"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

2回送られたリクエストをテストする

ネットワークは答えを失うので、クライアントは同じリクエストをまた送ります。2回送っても、1回送ったあとと同じデータなら、そのリクエストは冪等です。

行を数えて確かめます。まず値を設定する変更、次に、毎回新しい本を作るはずの、id なしの POST です。

同じ変更を2回送る

コマンド
for i in 1 2; do curl -s -o /dev/null -w "%{http_code}\n" -X PATCH -H "Content-Type: application/json" -d '{"available":false}' "http://api:3000/books?id=eq.1"; done

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

同じ新しい本を2回送る

コマンド
for i in 1 2; do curl -s -o /dev/null -X POST -H "Content-Type: application/json" -d '{"title":"二重登録","year":2020}' "http://api:3000/books"; done

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

「二重登録」の本を数える

コマンド
psql -h db -U shop -At -c "select count(*) from books where title = '二重登録'"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

作成を再試行しても安全にする

「二重登録」が2冊あるのは、再試行が重複を作った、ということです。呼ぶ側が id を決めれば、作成を安全にできます。同じ id に、「もうあれば更新する」というヘッダーを付けて送ります。

1回目は201、2回目は200です。どちらも行は1つのままです。

安全な作成を2回送る

コマンド
for i in 1 2; do curl -s -o /dev/null -w "%{http_code}\n" -X POST -H "Content-Type: application/json" -H "Prefer: resolution=merge-duplicates" -d '{"id":902,"title":"一度だけ","year":2020}' "http://api:3000/books"; done

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

その id の行を数える

コマンド
psql -h db -U shop -At -c "select count(*) from books where id = 902"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

例: 再試行しても安全なもの

2回送るリクエスト2回目のあとの行再試行しても安全か
1冊を available false にする PATCH1回目のあとと同じ安全。値を設定するから
id なしの本の POST1回目のあとより1行多い安全でない。重複ができる
id と merge-duplicates を付けた POST1回目のあとと同じ安全。id が行を決める
本900の DELETE1回目で消え、そのまま消えている安全。ただしラボは両方で204を返す

学生が入力するセルは、このプレビューでは空白です。

テスト用の行を消す

コマンド
psql -h db -U shop -c "delete from books where id >= 900 or title = '二重登録'"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

正しいリクエストだけをテストして、失敗を一度も見ない人がいます。断られるものをテストしましょう。自分のテスト行も片付けます。片付けないと、2回目の実行が、1回目の残したデータに出会い、API と関係のない理由で失敗します。

このラボとソースについて: PostgreSQL と PostgREST のラボ:ブラウザーで学ぶデータベースと REST API

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。