ユニットテストの信頼性を担保するために大切にしている3つの思想(Rails × RSpec)-フルスタックエンジニアS-

社員ブログ 2025.06.02

こんにちは。 フルスタックエンジニア兼 情報システム部長、執行役員のSです。

普段からRSpecでテストを書いていますが、単に「通るテスト」ではなく、 プロダクトの信頼性を支えるテストとは何か?を考えながら書くようにしています。

今回は、Railsの基本的なMVC構造を前提として、 ユニットテストの信頼性を担保するために自分が大切にしている3つの思想を紹介します。

1. 「テストの対象範囲は最小に」
ControllerのテストではControllerの責務のみ、ModelのテストではModelのロジックのみ。 テストではつい全体の流れを確認したくなりますが、 ユニットテストは流れを保証するものではなく、責務を保証するものです。 例えば UsersController#create のテストでは、「適切なパラメータを与えたとき、期待通りのリクエストが送られ、保存されるか」だけを見ます。 Modelのバリデーションが正しく働いているかはModelのテストに任せます。

「コントローラーは『つなぎ役』モデルは『ルール』それぞれの役割をテストする」

ということですね。

2. 「分岐があるなら、その全てをテストする」
Modelに条件分岐がある場合、そこは重点的に網羅します。 バリデーションやスコープ、コールバックなど、Railsは”魔法”が多いぶん、意図しない挙動が起きやすい。 ユニットテストの役割は「意図を明示すること」でもあるので、 ・条件Aのときにどうなるか ・条件Bのときに何が発生しないか こうした 「設計者の意図がにじみ出るテスト」 を意識しています。

「コードにコメントを書く代わりに、テストで意図を語る」

ことができると尚良いですね。

3. 「壊れたとき、原因が一瞬でわかる構造に」
最終的に目指しているのは、 テストが壊れたときに”どこが悪いのか”をすぐ特定できる構造です。 責務が曖昧なテストは、壊れたときに迷路になります。 たとえばControllerのテストでModelの分岐ロジックが原因で落ちたとき、 それがControllerの問題なのかModelの問題なのか判断に時間がかかる。
そうならないよう、責務を明確に切り分けたテスト構成を意識しています。 この積み重ねが、チーム開発において「安心してリファクタリングできる環境」を生みます。

テストは「結果を見るもの」ではなく「設計の健全性を見るもの」です。

おわりに
今回は基本的な構造を前提として記載しましたがServiceクラス等を用いた場合も同様です。 Railsのユニットテストは「書いたかどうか」ではなく「どういう考えで、どこまでを担保するのか」が全てです。

全部を一つのテストで見ようとせず、 小さく分けて、役割ごとに守っていく。 これを意識するだけで、テストの信頼性は格段に上がります。 そして、信頼できるテストがあるプロダクトは、開発スピードも安心感も段違いです。

こんにちは。 フルスタックエンジニア兼 情報システム部長、執行役員のSです。

普段からRSpecでテストを書いていますが、単に「通るテスト」ではなく、 プロダクトの信頼性を支えるテストとは何か?を考えながら書くようにしています。

今回は、Railsの基本的なMVC構造を前提として、 ユニットテストの信頼性を担保するために自分が大切にしている3つの思想を紹介します。

1. 「テストの対象範囲は最小に」
ControllerのテストではControllerの責務のみ、ModelのテストではModelのロジックのみ。 テストではつい全体の流れを確認したくなりますが、 ユニットテストは流れを保証するものではなく、責務を保証するものです。 例えば UsersController#create のテストでは、「適切なパラメータを与えたとき、期待通りのリクエストが送られ、保存されるか」だけを見ます。 Modelのバリデーションが正しく働いているかはModelのテストに任せます。

「コントローラーは『つなぎ役』モデルは『ルール』それぞれの役割をテストする」

ということですね。

2. 「分岐があるなら、その全てをテストする」
Modelに条件分岐がある場合、そこは重点的に網羅します。 バリデーションやスコープ、コールバックなど、Railsは”魔法”が多いぶん、意図しない挙動が起きやすい。 ユニットテストの役割は「意図を明示すること」でもあるので、 ・条件Aのときにどうなるか ・条件Bのときに何が発生しないか こうした 「設計者の意図がにじみ出るテスト」 を意識しています。

「コードにコメントを書く代わりに、テストで意図を語る」

ことができると尚良いですね。

3. 「壊れたとき、原因が一瞬でわかる構造に」
最終的に目指しているのは、 テストが壊れたときに”どこが悪いのか”をすぐ特定できる構造です。 責務が曖昧なテストは、壊れたときに迷路になります。 たとえばControllerのテストでModelの分岐ロジックが原因で落ちたとき、 それがControllerの問題なのかModelの問題なのか判断に時間がかかる。
そうならないよう、責務を明確に切り分けたテスト構成を意識しています。 この積み重ねが、チーム開発において「安心してリファクタリングできる環境」を生みます。

テストは「結果を見るもの」ではなく「設計の健全性を見るもの」です。

おわりに
今回は基本的な構造を前提として記載しましたがServiceクラス等を用いた場合も同様です。 Railsのユニットテストは「書いたかどうか」ではなく「どういう考えで、どこまでを担保するのか」が全てです。

全部を一つのテストで見ようとせず、 小さく分けて、役割ごとに守っていく。 これを意識するだけで、テストの信頼性は格段に上がります。 そして、信頼できるテストがあるプロダクトは、開発スピードも安心感も段違いです。