はじめに
現在個人プロダクト開発を行っており、そのテストを実施するにあたり、自分用にその必要性などを整理してみました。Ruby on Railsを使ったアプリケーションのテスト向けです。
なぜ必要か
バグを早期に見つける
開発を進めると、コードがどんどん蓄積され、場合によってはバグに依存したコードが出てきます。これらのバグをあとから修正しようとすると、そこに依存する大量のコードを修正しなければならず、コストがかかってしまいます。
そのため、バグを初期段階でみつけることは、コスト削減となり大きな利益になって返ってきます。また、バグの発見と修正は、それが作られた時間に近ければ近いほど簡単です。
仕様書となる
テストは唯一信頼できる設計の仕様書となります。
私はよく「このコードってどう動いてたっけ?」と忘れてしまうことがあるため、将来の自分が記憶を失ったつもりで、テストを実装しておくよう心がけたいと思います。
設計の欠陥を明らかにする
一つのテストを実装するに苦痛が伴うのであれば、そのコードは改善の余地があると疑いの目が必要です。例えば、コンテキストを要求しすぎている、他のオブジェクトとの依存関係を持ち過ぎている、等々の原因が考えられます。
こういった実装は、他のオブジェクトから見ても再利用が難しいので設計の欠陥があると慎重になる必要があるそうです。設計に疑いの目をむけるきっかけを提供するのもテストが必要の理由です。
実装例
describe / context / it の説明を明確に書く
describe にはテスト対象の「クラス」や「メソッド」などを書きます。
context にはテストしようとしている状況「ログイン中のユーザーの場合」などを書きます。
it は期待する結果を書きます。このとき「正しいこと」などのような表現を避けます。「正しいとはどういう状況か」を書きます。
describe / context / it の説明を読むことでテストの概要がわかるのが理想的です。
なんのテストをしているかわかりやすく説明しましょう。
AAA( Arrange-Act-Assert)
テストコードを Arrange(準備)、Act(実行)、Assert(確認)の3つのフェーズに分けて記述する、テストコードを読みやすくするためのパターンのひとつです。それぞれのフェーズで記述する内容は次のようになります。
Arrange
テストを実施するために必要となる前提条件や必要なデータを準備する。
テスト環境の初期化や依存関係(テストダブルも含む)の構築。
テスト対象のメソッドに渡すパラメータ。
Act
テスト対象の振る舞いを実行する。
テスト対象のメソッドの実行など。
Assert
期待された結果であるかを確認する。
実装
上記2点を考慮した以下のテストコードの例を示します。今回は、Calculator クラスを作成し、その #add メソッドが正しく動作するかをテストします。以下の記事を参考にしました。
class Calculator
def add(a, b)
a + b
end
end
テストコード例
require 'rails_helper'
RSpec.describe Calculator, type: :model do
describe '#add' do
let(:calculator) { Calculator.new } # Arrange: テストに使うオブジェクトを準備
context '2つの正の数を足す場合' do
it '正しい合計を返す' do
# Act: メソッドを呼び出す
result = calculator.add(3, 5)
# Assert: 結果を検証
expect(result).to eq(8)
end
end
end
end
テストコマンド実行
rspec spec/models/calculator_spec.rb
モデルとコントロラー
これは、自分用のメモですが、テストを行う際には、モデルとコントローラーが果たす役割を理解することが大切です。それぞれの役割、テスト対象を簡単にまとめました。特に、自分はコントローラの実装が多くなってしまうため、以下の役割を意識した実装を心がる必要があります。
項目 | モデル | コントローラー |
---|---|---|
役割 | データの管理、バリデーション、ビジネスロジック | リクエストの処理、レスポンスの作成 |
テスト対象 | バリデーション、メソッド、データ操作 | HTTPステータスコード、レスポンス、ビューの呼び出し |
依存範囲 | データベースや関連モデル | モデル、ビュー、リクエスト |
例 | ユーザー名のバリデーションやフルネーム計算 | ユーザー一覧の取得や表示、APIレスポンス生成 |
テストの目的 | データやロジックが正しいかを確認する | リクエスト処理が正しく行われるかを確認する |
さいごに
テストの記述、実行はコストがかかるため、テストファーストのプログラミングは面倒だと思っておりました。しかし、テストのコストがかかることの解決は上手くなるのみです。テストを書くスキルを磨くことで、全体を俯瞰したときにその価値が見えてきます。
まだまだ、個人開発の先は長いですが、費用対効果の高いテストを実装するよう心がけたいです!