回線の犯人さがし
ボタン1つで下り・上り・待機中の反応・通信中の反応を測り、その数字から「遅さの原因が家の中にあるのか外にあるのか」を日本語で判定する。速度の数字を出して終わりにしない。各指標にはA+〜Fの目安と「その速さで何ができるか」が付き、測るたび履歴が貯まって3回めからは夜だけ遅いのか・いつも遅いのかまで分かれる
所要時間1時間25分
制作メモ
- AIに任せた
- 着手前の実現可能性の確認(speed.cloudflare.com が Access-Control-Allow-Origin: * と timing-allow-origin: * を返すことを実際に叩いて確認。後者が無いとブラウザから正確な時間が取れない)/ブラウザでは原理的にできないことの切り分け(Wi-Fiの電波強度・チャンネルはOS APIのみ、IPv4/IPv6の指定はHappy Eyeballsで不可、定期自動測定はタブを閉じると止まる)を要件から先に外す判断/測定エンジンの自作(@cloudflare/speedtest は結果をCloudflareへ送信する仕様で「どこにも送信しない」という画面の記述と食い違うため不採用にした)/診断ロジック8分岐の設計と、実回線なしで全分岐を固定入力で検証するユニットテスト46本/スタブだけで作り切らず、最後に本物のエンドポイントへ実際に繋いで通すところまでやったこと(そこで初めて見つかった不具合が1件ある)/指標の目安(A+〜F)のしきい値を、感覚ではなく実際の用途が要求する値から引いたこと(Netflixの推奨速度・Zoomの送信量・ITU-T G.114・ゲームのping・通話が崩れる30ms)。遅延は往復時間で測っているのに対しG.114は片道の規定なので、片道150ms=往復300msへ換算して使っている
- 自分でやった
- 題材の指定(自宅回線の診断経験をアプリにする)と、アプリ名・通信量の初期値の決定/作る前に「今使っているルーターと買い替え候補どちらが良いか」という実際の困りごとを持ち込んだこと/公開後に「指標があるならどこかに書いておいてほしい。A〜Fのクラスとクラスごとの目安があるとよい」と発案(Day010・014・015と同じ流れ)
- 失敗と修正
- 上りが62Mbpsしか出ず、狙って作った「下りだけ遅い回線」の判定が出なかった。原因は本体のバグで、転送しながら往復時間も測る組み立てのまま「往復時間の測定が終わるまで待ってから」経過時間を取っていた=遅延の測定にかかった時間が帯域の分母に混ざっていた → 転送が終わった時点で経過時間を取り、往復時間の結果はそのあとで受け取るように直した。転送が終わったら往復時間の測定も止める。1本200msの測定を6本仕込むと25Mbpsが13Mbpsまで落ちることを固定入力で再現する回帰テストを足した
画面にはグレードBと出ているのに、保存された履歴のグレードが空(—)のままだった。採点を表示のときだけ行い、保存には採点前の値を渡していた。スタブのテストは全部通っていて気付けず、本物の回線で1回動かして初めて分かった → 採点まで済ませた1件を先に作り、保存・表示・診断のすべてがそれを使うようにした。画面のグレードと保存されたグレードが一致することを見るE2Eを足した
E2Eで、接続がIPv6かどうかの表示だけが落ちた。スタブがヘッダを返しているのにブラウザから読めなかった → 別オリジンのJSがレスポンスヘッダを読むには Access-Control-Expose-Headers での公開が要る。本物はこれを返しているので、スタブ側を本物の応答に合わせた。スタブが現実より甘いと、本番だけ動かない作りを通してしまう
ローカルでE2E228本が全部通ったのにCIで1本だけ落ちた。「下りだけが遅い」判定のE2Eが、実際に測った速さで分岐する作りになっていて、上りが下りの3倍を超える必要があった。ローカルでは余裕1.2倍程度で通っていたが、CIの機械では上りが伸びずに条件を満たさなかった → 節約モードで運ぶ量を1/10にし、下りを遅らせる時間を1.2秒から3秒に増やして、条件の余裕を18.8倍に広げた(下り2.6Mbpsに対し上りは7.8Mbps出れば足りるところ146.8Mbps)。実測値で分岐するE2Eは機械の速さで結果が変わるので、余裕を数値で確かめてから置くようにした














