📃

サンプルコードで学ぶ!RSpecでCSV機能をテストする方法

2024/12/02に公開

こんにちは!
ラブグラフエンジニアのひろです。
今回は、CSVデータを使った機能を RSpec でどのようにテストするかについて解説します。

この記事では、以下の3つのテスト方法を具体例と共に紹介します:

  1. CSVファイルを読み込む方法
  2. ヒアドキュメントでデータを直接利用する方法
  3. テンポラリファイル( Tempfile )を使う方法

CSV機能をテストする3つの手法

1. CSVファイルを読み込む方法

概要

テスト用のCSVファイルを spec/fixtures ディレクトリなどに保存しておき、それを読み込んでテストする方法です。
実際の運用に近い形で検証できるため、複雑な構造や大規模データのテストに向いています。

サンプルコード

require "rails_helper"

RSpec.describe BatchOrderCreationFromCsvJob, type: :job do
  describe "#perform" do
    it "CSVファイルを読み込んで注文データを作成する" do
      # 保存済みのCSVファイルパスを指定
      csv_file_path = Rails.root.join("spec/fixtures/orders.csv")

      # ジョブを実行
      expect {
        BatchOrderCreationFromCsvJob.perform_now(csv_file_path)
      }.to change(Order, :count).by(2)

      order1 = Order.find_by(product_name: "Pen")
      order2 = Order.find_by(product_name: "Notebook")

      expect(order1.quantity).to eq(10)
      expect(order2.quantity).to eq(5)
    end
  end
end

準備するCSVファイル

以下の内容を spec/fixtures/orders.csv に保存しておきます:

product_name,quantity
Pen,10
Notebook,5

メリット

  • 実運用に近い形でテスト可能。
  • 大規模データや複雑なCSV構造に対応しやすい。

デメリット

  • 外部ファイルの管理が必要になる。
  • ファイルが変更された場合、テストの再現性に影響を与える。

2. ヒアドキュメントでデータを直接利用する方法

概要

テストコード内にCSVデータを直接埋め込み、ファイルに保存せずにそのまま処理する方法です。
データがシンプルな場合や、小規模なロジックを検証したい場合に適しています。

サンプルコード

require "rails_helper"

RSpec.describe BatchOrderCreationFromCsvJob, type: :job do
  describe "#perform" do
    subject { described_class.new.perform(csv_content) }

    let(:csv_content) do
      <<~CSV
        product_name,quantity
        Pen,10
        Notebook,5
      CSV
    end

    it "CSVデータを直接利用して注文データを作成する" do
      # ジョブを実行
      subject

      # 作成されたOrderの検証
      expect(Order.count).to eq(2)
      expect(Order.find_by(product_name: "Pen").quantity).to eq(10)
      expect(Order.find_by(product_name: "Notebook").quantity).to eq(5)
    end
  end
end

メリット

  • ファイル操作を省略でき、テストコードが簡潔。
  • テスト内で完結するため、外部ファイル管理が不要。

デメリット

  • CSVデータの中身を丸ごと受け取って処理するようなものしかテストできない。
  • データが複雑になる場合や大量データには不向き。
  • 実際のファイル入出力処理は検証できない。

3. テンポラリファイル( Tempfile )を使う方法

概要

一時的なファイルを生成し、そのファイルにデータを書き込んで利用するテスト。
ファイルの入出力処理を伴う場合や、テスト終了後にファイルを自動で削除したい場合に適しています。

サンプルコード

require "rails_helper"

RSpec.describe BatchOrderCreationFromCsvJob, type: :job do
  describe "#perform" do
    it "テンポラリファイルを利用して注文データを作成する" do
      Tempfile.open(["orders", ".csv"]) do |tempfile|
        tempfile.write("product_name,quantity\nPen,10\nNotebook,5\n")
        tempfile.rewind

        expect {
          BatchOrderCreationFromCsvJob.perform_now(tempfile.path)
        }.to change(Order, :count).by(2)

        order1 = Order.find_by(product_name: "Pen")
        order2 = Order.find_by(product_name: "Notebook")

        expect(order1.quantity).to eq(10)
        expect(order2.quantity).to eq(5)
      end
    end
  end
end

メリット

  • ファイル入出力処理の動作を検証可能。
  • テスト終了後にファイルが自動的に削除されるため、管理が簡単。

デメリット

  • データが複雑になる場合や大量データには不向き。

各手法の使い分けガイド

紹介した3つの手法を使い分ける際の簡単なガイドです。

方法 適しているケース 注意点
CSVファイル 実運用に近い環境でテストしたい場合 外部ファイルの管理が必要
ヒアドキュメント 小規模データやシンプルなロジックのテストに最適 ファイル入出力処理は検証できない
テンポラリファイル ファイル入出力の動作をテストしたい場合 データ量が多い場合はセットアップが少し手間

まとめ

この記事では、CSV機能をテストする3つの手法を紹介しました。

  1. CSVファイルを読み込む方法
  2. ヒアドキュメントでデータを直接利用する方法
  3. テンポラリファイルを使う方法

CSVファイルを用意する場合は、変更時にCSVファイルとテストファイルそれぞれの変更が必要になり、ヒアドキュメントやテンポラリファイルの場合は、ある程度の大きさのものを用意しようとすると、大変かつテストファイルが大きくなってしまう問題がありそうです。

どの方法もメリットデメリットが存在するので、要件や状況に応じて最適な方法を選択してみてください。

ラブグラフのエンジニアブログ

Discussion