【Ruby】RSpecの基本:テストの書き方入門

Ruby

こんにちは、かつコーチです。

「テストを書いたほうがいいのは分かるけど、何から始めればいいか分からない」と感じたことはありませんか。

Rubyの世界で最もよく使われるテストツールがRSpecです。

この記事では、RSpecのインストールから、describeitexpectという基本構文、実際にテストを実行するところまでを、順を追って解説します。

読み終える頃には、簡単なクラスに対して自分でテストを書けるようになります。

基本の書き方:RSpecの導入から実行まで

手順1:RSpecをインストールする

RSpecはgem(Rubyのライブラリパッケージ)として提供されています。

プロジェクトのディレクトリで、以下のコマンドを実行してインストールします。

bundle init

Gemfileが生成されるので、rspecを追記します。

# Gemfile
source "https://rubygems.org"

gem "rspec"

追記したら、bundle installでインストールします。

bundle install

続けて、RSpecの初期設定ファイルを生成します。

bundle exec rspec --init

このコマンドを実行すると、.rspecファイルとspec/spec_helper.rbが作成されます。

specディレクトリの中に、これからテストコードを書いていきます。

手順2:テスト対象のクラスを用意する

まずは、テストの対象となるシンプルなクラスを用意します。

lib/calculator.rbとして保存します。

# lib/calculator.rb
class Calculator
  def add(a, b)
    a + b
  end

  def divide(a, b)
    raise ArgumentError, "0で割ることはできません" if b == 0

    a / b
  end
end

足し算を行うaddメソッドと、0除算を防ぐバリデーション付きのdivideメソッドを用意しました。

手順3:describe・it・expectで最初のテストを書く

テストコードはspec/calculator_spec.rbのように、_spec.rbという名前で保存するのが慣例です。

# spec/calculator_spec.rb
require "calculator"

RSpec.describe Calculator do
  describe "#add" do
    it "2つの数値を足した結果を返す" do
      calculator = Calculator.new
      expect(calculator.add(1, 2)).to eq(3)
    end
  end

  describe "#divide" do
    it "2つの数値を割った結果を返す" do
      calculator = Calculator.new
      expect(calculator.divide(6, 2)).to eq(3)
    end

    it "0で割るとArgumentErrorになる" do
      calculator = Calculator.new
      expect { calculator.divide(1, 0) }.to raise_error(ArgumentError)
    end
  end
end

それぞれのキーワードの役割は以下の通りです。

  • describeテスト対象をグループ化する。「何についてのテストか」を表す
  • it:具体的なテストケースを1つ書く。「〇〇のとき××になる」という仕様を文章で書くのがポイント
  • expect実際の値を渡して、期待する結果と一致するかを検証する

expect(実際の値).to eq(期待する値)という形が、RSpecの最も基本的な書き方です。

エラーが発生することを検証したい場合は、expect { ブロック }.to raise_error(エラークラス)のように、波括弧のブロック形式で書く点に注意してください。

手順4:rspecコマンドでテストを実行する

テストを実行するには、bundle exec rspecコマンドを使います。

bundle exec rspec

すべてのテストが通ると、以下のような結果が表示されます。

Calculator
  #add
    2つの数値を足した結果を返す
  #divide
    2つの数値を割った結果を返す
    0で割るとArgumentErrorになる

Finished in 0.01234 seconds (files took 0.1 seconds to load)
3 examples, 0 failures

3 examples, 0 failuresという表示から、3つのテストケースがすべて成功したことが分かります。

よくあるつまずきポイント・エラー対処

require忘れによるNameError

❌ Before:requireを書き忘れてクラスが見つからない

わたしが初めてRSpecを使ったとき、spec_helper.rbだけを読み込ませれば、対象のクラスも自動で読み込まれると勘違いしていました。

# spec/calculator_spec.rb(requireなし)
RSpec.describe Calculator do
  it "2つの数値を足した結果を返す" do
    calculator = Calculator.new
    expect(calculator.add(1, 2)).to eq(3)
  end
end

これを実行すると、以下のエラーになりました。

NameError:
  uninitialized constant Calculator

「クラスは確かに定義したはずなのに、なぜ見つからないんだろう」と原因に気づくまで時間がかかりました。

✅ After:require “calculator”でテスト対象を読み込む

原因は、テスト対象のファイルをrequireしていなかったことでした。

# spec/calculator_spec.rb
require "calculator"

RSpec.describe Calculator do
  it "2つの数値を足した結果を返す" do
    calculator = Calculator.new
    expect(calculator.add(1, 2)).to eq(3)
  end
end

さらに、libディレクトリを読み込みパスに追加する必要がある場合は、.rspecファイルに以下を追記しておくと安定します。

# .rspec
--require spec_helper
-I lib

-I libを指定することで、require "calculator"だけでlib/calculator.rbを見つけられるようになります。

NameError: uninitialized constantが出たときは、まず「対象のファイルをrequireしているか」「読み込みパスが通っているか」の2点を疑うとよいでしょう。

まとめ

この記事のポイント

  • RSpecはGemfilegem "rspec"を追記し、bundle installでインストールする
  • bundle exec rspec --initで、.rspecspec_helper.rbが生成される
  • describeはテスト対象のグループ化、itは個別のテストケース、expectは検証を担当する
  • expect(値).to eq(期待値)が最も基本的な検証の書き方
  • NameError: uninitialized constantが出たら、require忘れと読み込みパスをまず疑う

次に読むべき記事

RSpecの基本を押さえたら、次はRubyの標準テストライブラリであるMinitestとの違いを比較した記事に進むと、テストツール選びの判断軸が身につきます。

タグ: Ruby, 中級者向け, テスト

タイトルとURLをコピーしました