テストは安心を増やすのではなく、ルールを固定するためにある

John Smith

Hatched by John Smith

Jun 08, 2026

1 min read

63%

0

ルーティングが増えるほど、何を信じればいいのか分からなくなる

Webアプリを作っていると、いつの間にか不安が増えていきます。ページは増え、画面遷移は複雑になり、API呼び出しは散らばり、しかも見た目はちゃんと動いているように見える。けれど本当に怖いのは、画面ではなく「このファイルは何の役割を持つのか」「このURLはどこに向かうのか」「この処理は壊れていないと言い切れるのか」が曖昧になることです。

ここで面白いのは、設計の曖昧さテストの曖昧さは、まったく別の問題ではないということです。App Routerが「app直下のpage.tsxだけがルーティング対象」と絞り込むのは、単に便利だからではありません。世界の見え方を狭くして、意味を固定するためです。テストも同じです。Supertestのような仕組みでHTTPの入口から振る舞いを確かめるのは、細部をいじるためではなく、「このアプリはこの入口ではこう振る舞う」という約束を固定するためです。

つまり、ルーティング設計とテスト設計は別々の技術ではなく、複雑さに対して境界を引くための二つの方法なのです。


すべてをルーティングしない勇気が、テスト可能性を生む

昔のページベースの発想では、pages直下に置いたファイルがそのままルートになりました。これは直感的です。ファイルを増やせばURLが増える。分かりやすい。けれど、分かりやすさには副作用があります。ファイルが増えるほど、どこまでが公開される意図なのか、どこからが内部実装なのかが曖昧になります。

App Routerが示しているのは、単なる新しい書き方ではありません。「ルーティングされるもの」と「ただそこに置かれているもの」を切り分けるという思想です。app直下のpage.tsxだけが入口になるなら、それ以外のファイルは、少なくともURLという意味では沈黙しています。沈黙しているからこそ、意図を持って公開する対象が明確になる。

この考え方はテストにそのままつながります。テストもまた、すべてを対象にしないから強いのです。内部の実装の細部を逐一追いかけるテストは、壊れやすい。少しリファクタリングしただけで落ちるからです。逆に、HTTPの入口から見るテストは、内部のファイル構造ではなく、外に見えている約束を確認します。これはまさに、App Routerがファイル構造の中に作る境界と同じ発想です。

強いシステムとは、すべてを見通せるシステムではない。何を公開し、何を隠すかが明確なシステムだ。

この視点に立つと、ルーティングとテストは「機能」ではなく「境界の設計」になります。どのファイルがURLになるのか。どのリクエストがどの応答につながるのか。どこまでを安定した契約として扱うのか。こうした問いに答えることが、開発を速くする前提条件なのです。


テストは正しさを証明するものではなく、壊れ方を限定するもの

多くの人はテストを「バグを見つける仕組み」だと考えます。もちろんそれは正しい。ただし、もっと本質的には、テストは壊れ方を限定する装置です。アプリが大きくなるほど、完全な正しさを一気に証明するのは不可能になります。だからこそ、「最低でもここは壊れない」という線を引く必要がある。

SupertestのようなHTTPテストが有効なのは、まさにそこです。例えば、POST /users に対して正しいJSONを送れば201が返る、空のメールアドレスなら400が返る、認証が必要なら401が返る。これらは単なる確認ではありません。外部から見たシステムの人格を定義する行為です。

ここで大事なのは、テストが内部の仕組みを説明する必要はないということです。たとえば、内部でどの関数が呼ばれたかを逐一検査するよりも、入力に対してどんな応答が返るかを確かめるほうが、システムの本質に近い場合が多い。なぜなら、ユーザーも他のサービスも、内部実装ではなくHTTPという境界越しにアプリを理解するからです。

この発想は、App Routerの構造ともきれいに噛み合います。ルーティング対象をpage.tsxに限定することで、アプリは「入口」を明確にする。同じように、Supertestで入口からテストすることで、アプリの「契約」を明確にする。どちらも、複雑さを消しているのではありません。複雑さを境界の内側に閉じ込めているのです。

たとえるなら、建物の設計に近いです。部屋の家具の配置は自由でも、玄関、廊下、非常口は曖昧であってはいけない。テストは家具の置き方を固定するためではなく、玄関が玄関として機能し続けることを保証するためにある。だから、良いテストは細かすぎないし、粗すぎもしない。境界線のちょうど外側に立っている必要があります。


フレームワークが与えるのは自由ではなく、意味の集中である

フレームワークを使うと自由になる、とよく言われます。でも実際には、優れたフレームワークが与えるのは自由ではなく、意味の集中です。何でもできる状態は一見自由ですが、実際には判断が増えすぎて遅くなります。どのファイルがルートになるのか分からない、どこまでが公開APIなのか曖昧、どのテストが壊れてはいけない契約を示しているのか不明。これでは自由ではなく、迷路です。

App Routerのような構造は、その迷路に明確な地図を与えます。page.tsxという名前に役割を限定し、それ以外を明示的に内部へ押し込める。すると、アプリの理解はファイル一覧を眺める行為ではなく、どこが入口かを認識する行為に変わります。

テストも同じです。テストが増えるほど開発が遅くなると感じる人がいますが、多くの場合、それはテストが多いのではなく、テストが境界を誤っているのです。内部の配列の並びや、一時的な実装詳細まで固定してしまうと、変更のたびに足を引っ張る。けれど、HTTPの入口で期待を定義していれば、実装の自由度は保たれたまま、重要な契約だけが固定されます。

この関係を一言で言うなら、フレームワークは抽象化ではなく、責任の配置替えです。ルーティングはページの責任を明確にし、テストは振る舞いの責任を明確にする。責任が明確になるほど、チームは速くなります。なぜなら、迷いが減るからです。


良い開発は「どこまでを見るか」を決める作業である

ここまでをまとめると、開発の難しさは、機能を作ることそのものよりも、観測範囲を適切に決めることにあります。すべてを見る必要はない。むしろ、見るべきものを絞るほど、システムは理解しやすく、変更しやすくなる。

この観点で見ると、App Routerは「見える範囲」を整理する仕組みであり、Supertestは「確かめる範囲」を整理する仕組みです。前者はURLに意味を集中させる。後者はHTTP応答に意味を集中させる。両者が重なると、アプリは次のような形で安定します。

  1. 公開されるものが明確になる。
  2. テストすべき契約が明確になる。
  3. 内部実装を変えても外形が崩れにくくなる。
  4. チーム全体が同じ地図を共有できる。

これは開発速度の話でもありますが、それ以上に認知負荷の削減の話です。人は複雑なシステムを完全には理解できません。だからこそ、システム側が理解の単位を小さくしてくれる必要がある。ファイルの置き場所に役割を持たせること、HTTPの入口で振る舞いを検査することは、そのための具体的な手段です。

設計とは、未来の自分たちが迷わないように、意味の境界を先に引いておくことだ。

この言葉を実務に落とすなら、テストを書く前にまず「何を契約として守りたいか」を決めるべきです。逆に、ルーティングを切るときにも「これは外に出る名前か、それとも内部の構成か」を意識するべきです。両者を切り離して考えるのではなく、同じ境界設計の問題として扱うと、コードベースの見え方が変わります。


Key Takeaways

  • ルーティングは構造の問題ではなく、意味の問題です。何をURLとして公開するかを明確にすると、アプリの責任範囲が見えやすくなります。
  • テストは内部実装を縛るためではなく、外部から見た約束を固定するために書くと強くなります。HTTPの入口から確かめると、リファクタリングに耐えやすくなります。
  • 境界を狭めることは、自由を減らすことではありません。むしろ、内部の自由度を増やし、変更可能性を高めます。
  • ファイルの配置とテストの粒度は連動させるべきです。公開するものだけをルーティングし、その公開部分だけを重点的に検証すると、設計が安定します。
  • 開発の本質は、何を見るかを決めることです。すべてを見ようとするより、壊れてはいけない境界だけを見張るほうが、長期的には速くなります。

まとめ: アプリを守るのはコードではなく、境界の明確さである

多くの開発者は、コードを書けば問題が解決すると考えます。けれど、実際にシステムを支えているのは、コードそのものよりも、どこまでが外に見えるかどこを契約として扱うかという境界の設計です。App Routerがルーティングの対象を絞るのも、SupertestがHTTPの入口からふるまいを確認するのも、その境界を守るためです。

だから、良いアプリとは、機能がたくさんあるアプリではありません。意味が整理されているアプリです。何が公開され、何が内部に留まり、何が壊れてはいけないのかが分かる。そういうアプリは、見た目以上に強い。なぜなら、変更されても自分を見失わないからです。

次にテストを書いたり、ルーティングを切ったりするときは、こう問い直してみてください。これは単なる実装か、それとも将来の変更を支える境界か。もし後者なら、その一行はコードではなく、システムの約束そのものです。

Sources

← Back to Library

Hatch New Ideas with Glasp AI 🐣

Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)

Start Hatching 🐣