includeマッチャーで配列やハッシュの中身を検証しよう
学習の目標
本章では、以下の内容を学習します。
- includeマッチャーの基本的な使い方を理解する
- 配列の要素検証における実践的な適用方法を習得する
- 複数要素の同時検証など、includeマッチャーの高度な使用方法を学ぶ
- ハッシュのキーと値の検証方法を理解する
- valuesメソッドを組み合わせた実践的なテスト手法を習得する
はじめに
前回はbeマッチャーを使って、オブジェクトの状態を検証する方法を学びました。今回は、配列やハッシュの中身を検証するincludeマッチャーについて説明していきます。
includeマッチャーは、配列やハッシュの内容を検証するためのマッチャーです。このマッチャーを使うことで、特定の要素が含まれているかどうかを簡単に確認することができます。また、このマッチャーの特徴的な点は、単一の要素だけでなく、複数の要素が同時に含まれているかどうかも確認できることです。これにより、柔軟なテストを書くことができるため、RSpecでよく使われるマッチャーの一つとなっています。
それでは、実際のコードを通してincludeマッチャーの使い方を学んでいきましょう。
配列の要素を検証する
最初に、買い物リストを管理する簡単なクラスを作成します。shopping_list.rbというファイルを作成し、以下のコードを記述してください。
class ShoppingList  def initialize    @items = []  end
  def add_item(item)    @items << item  end
  def items    @items  endendこのShoppingListクラスでは、買い物リストを管理するために@itemsという配列を使用しています。配列は複数のデータを順番に並べて保存できるデータ構造で、Rubyのプログラミングでは非常によく使用されます。
initializeメソッドでは最初は空の配列を作成し、add_itemメソッドで新しい商品を追加できるようにしています。Rubyでは<<という演算子を使って、配列に新しい要素を追加することができます。
では、このクラスに対するテストを書いていきましょう。spec/shopping_list_spec.rbというファイルを作成し、以下のコードを記述してください。
require_relative '../shopping_list'
RSpec.describe ShoppingList do  describe '#items' do    it '買い物リストにりんごが含まれている' do      shopping_list = ShoppingList.new      shopping_list.add_item('りんご')      shopping_list.add_item('バナナ')      shopping_list.add_item('オレンジ')
      expect(shopping_list.items).to include('りんご')    end  endendこのテストコードでは、includeマッチャーを使って買い物リストの中身を検証しています。expect(shopping_list.items).to include('りんご')という部分は、「買い物リストの中にりんごが含まれていることを期待する」という意味になります。
ファイルを保存したら、ターミナルで以下のコマンドを実行してテストを走らせてみましょう。
bundle exec rspec spec/shopping_list_spec.rbテストが成功すると、以下のような結果が表示されるはずです。
ShoppingList  #items    買い物リストにりんごが含まれている
Finished in 0.00231 seconds (files took 0.15594 seconds to load)1 example, 0 failuresテストが成功したことが確認できました。では次に、includeマッチャーの真価が発揮される、複数の要素を同時に検証するテストを書いてみましょう。spec/shopping_list_spec.rbに以下のテストケースを追加します。
require_relative '../shopping_list'
RSpec.describe ShoppingList do  describe '#items' do    it '買い物リストにりんごが含まれている' do      shopping_list = ShoppingList.new      shopping_list.add_item('りんご')      shopping_list.add_item('バナナ')      shopping_list.add_item('オレンジ')
      expect(shopping_list.items).to include('りんご')    end
    it '買い物リストに必要な果物がすべて含まれている' do      shopping_list = ShoppingList.new      shopping_list.add_item('りんご')      shopping_list.add_item('バナナ')      shopping_list.add_item('オレンジ')
      expect(shopping_list.items).to include('りんご', 'バナナ', 'オレンジ')    end  endendこのテストの特徴的な点は、一度に複数の要素を検証できることです。include('りんご', 'バナナ', 'オレンジ')というように、カンマ区切りで複数の要素を指定することで、それらがすべて含まれているかを一度に確認できます。
再度テストを実行して、追加したテストケースも成功することを確認しましょう。
bundle exec rspec spec/shopping_list_spec.rbハッシュの検証に挑戦する
次は、includeマッチャーの活用範囲をさらに広げて、ハッシュの検証方法を学んでいきましょう。まずは、ユーザー情報を管理する簡単なクラスを作成します。user.rbというファイルを作成し、以下のコードを記述してください。
class User  def initialize(name:, age:, email:)    @data = {      name: name,      age: age,      email: email    }  end
  def data    @data  endendこのUserクラスでは、ユーザーの情報をハッシュという形で管理しています。ハッシュは、データに名前(キー)をつけて管理できる便利なデータ構造です。たとえば、name: nameという部分は、nameというキーに対して、引数で渡された名前の値を保存しています。このような構造により、データベースのレコードのように、関連する情報をまとめて扱うことができます。
それでは、このクラスに対するテストを書いてみましょう。spec/user_spec.rbというファイルを作成し、以下のコードを記述してください。
require_relative '../user'
RSpec.describe User do  describe '#data' do    it 'ユーザー情報に必要な属性が含まれている' do      user = User.new(        name: '山田太郎',        age: 25,        email: 'yamada@example.com'      )
      expect(user.data).to include(:name, :age, :email)    end  endendこのテストの特徴的な点は、ハッシュに対してincludeマッチャーを使用する際、デフォルトではキーの存在を確認することです。つまり、include(:name, :age, :email)は、これらのキーがハッシュに存在することを検証しています。
ファイルを保存したら、テストを実行してみましょう。
bundle exec rspec spec/user_spec.rbでは、ハッシュの値についても検証してみましょう。Rubyのハッシュにはvaluesというメソッドがあり、これを使うことで値だけを取り出して検証することができます。spec/user_spec.rbに以下のテストケースを追加します。
require_relative '../user'
RSpec.describe User do  describe '#data' do    it 'ユーザー情報に必要な属性が含まれている' do      user = User.new(        name: '山田太郎',        age: 25,        email: 'yamada@example.com'      )
      expect(user.data).to include(:name, :age, :email)    end
    it 'ユーザー情報に必要な値が含まれている' do      user = User.new(        name: '山田太郎',        age: 25,        email: 'yamada@example.com'      )
      expect(user.data.values).to include('山田太郎', 25, 'yamada@example.com')    end  endenduser.data.valuesは、ハッシュの値だけを配列として取得します。そして、その配列に対してincludeマッチャーを使用することで、特定の値が含まれているかどうかを検証しています。
再度テストを実行して、追加したテストケースも成功することを確認しましょう。
bundle exec rspec spec/user_spec.rb特定のキーと値のペアを検証する
ハッシュの特定のキーに対して、特定の値が設定されているかどうかを検証したい場合もあります。例えば、ユーザーの名前が「山田太郎」であることを確認したい場合などです。
このような場合は、ハッシュのキーと値のペアを指定して検証することができます。spec/user_spec.rbに以下のテストケースを追加してみましょう。
require_relative '../user'
RSpec.describe User do  describe '#data' do    # 既存のテストケースはそのままで...
    it 'ユーザーの名前が正しく設定されている' do      user = User.new(        name: '山田太郎',        age: 25,        email: 'yamada@example.com'      )
      expect(user.data).to include(name: '山田太郎')    end  endendこのテストでは、include(name: '山田太郎')という形で、nameキーの値が「山田太郎」であることを検証しています。複数のキーと値のペアを同時に検証することも可能です。
expect(user.data).to include(name: '山田太郎', age: 25)このように、includeマッチャーはハッシュの検証においても非常に柔軟に使用することができます。
実践的な例: 商品リストの管理
最後に、これまで学んだincludeマッチャーの知識を活かして、より実践的な例を見ていきましょう。ここでは、ECサイトの商品リストを管理するクラスを例に、様々な検証方法を試してみます。
まず、product_catalog.rbというファイルを作成し、以下のコードを記述してください。
class ProductCatalog  def initialize    @products = []  end
  def add_product(id:, name:, price:, category:)    @products << {      id: id,      name: name,      price: price,      category: category    }  end
  def products    @products  end
  def product_names    @products.map { |product| product[:name] }  end
  def categories    @products.map { |product| product[:category] }.uniq  endendこのクラスでは、商品情報をハッシュの配列として管理しています。また、商品名だけを取得するproduct_namesメソッドや、カテゴリーの一覧を取得するcategoriesメソッドも用意しています。
では、このクラスに対するテストを書いていきましょう。spec/product_catalog_spec.rbというファイルを作成し、以下のコードを記述してください。
require_relative '../product_catalog'
RSpec.describe ProductCatalog do  let(:catalog) do    catalog = ProductCatalog.new    catalog.add_product(      id: 1,      name: 'コーヒーメーカー',      price: 5000,      category: '家電'    )    catalog.add_product(      id: 2,      name: '電気ケトル',      price: 3000,      category: '家電'    )    catalog.add_product(      id: 3,      name: 'トースター',      price: 4000,      category: '家電'    )    catalog  end
  describe '#product_names' do    it '商品名の一覧に特定の商品が含まれている' do      expect(catalog.product_names).to include('コーヒーメーカー', '電気ケトル')    end  end
  describe '#categories' do    it 'カテゴリー一覧に「家電」が含まれている' do      expect(catalog.categories).to include('家電')    end  end
  describe '#products' do    it '商品リストに特定の商品情報が含まれている' do      expect(catalog.products).to include(        id: 1,        name: 'コーヒーメーカー',        price: 5000,        category: '家電'      )    end  endendこのテストでは、letを使ってテストデータを共通化しています。これにより、各テストケースで同じデータを使用することができ、コードの重複を避けることができます。
また、様々な形でのincludeマッチャーの使用方法を示しています。商品名の配列に特定の名前が含まれているかの検証、カテゴリー一覧に特定のカテゴリーが含まれているかの検証、そして商品リスト(ハッシュの配列)に特定のハッシュが含まれているかの検証など、実践的な使用例を見ることができます。
ファイルを保存したら、テストを実行してみましょう。
bundle exec rspec spec/product_catalog_spec.rbまとめ
本章では、includeマッチャーについて学びました。このマッチャーは配列やハッシュの内容を検証する際に非常に便利で、以下のような特徴があります。
- 配列の要素が含まれているかを直感的に検証できます
- 複数の要素を一度に確認できるため、テストをより簡潔に書くことができます
- ハッシュのキーや値の存在確認にも使用でき、柔軟な検証が可能です
- 実際のアプリケーション開発でも頻繁に使用されるマッチャーです
includeマッチャーをマスターすることで、配列やハッシュを扱うテストを効率的に書くことができるようになります。次回は、さらに別のマッチャーについて学んでいきましょう。
Basicプランでより詳しく学習
この先のコンテンツを読むにはBasicプラン以上が必要です。より詳細な解説、実践的なサンプルコード、演習問題にアクセスして学習を深めましょう。