bundle exec ruby で cannot load such file -- test/unit (LoadError) になる問題


この記事について

sidekiqの調査中にはまった。sidekiq自体は関係無いがrubyの基本的な知識が少ないため、「test/unit 自体はrubyに同梱されてるんじゃないの?」とか想像しつつ何時間も費やしたのでメモで残す。

結論

現象

$ bundle exec ruby test/test_example.rb

結果

test/test_example.rb:1:in `require': cannot load such file -- test/unit (LoadError)
    from test/test_example.rb:1:in `<main>'

対象のrubyソース

test/test_example.rb
require 'test/unit'
require_relative '../lib/example/example'

class TestExample < Test::Unit::TestCase
  def test_greeting
    example = Example.new
    assert_equal 'Hello World', example.say
  end
end

Gemfile

# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}"}

gem 'sidekiq', '5.1.1'

原因

bundle exec ruby 経由でrubyを実行すると、基本的には bundle install でインストールされたgemのみが参照可能になる。そのため、require "test/unit" に必要な test-unit がインストールされていない状態では参照不可能で cannot load such file になる。

ハマった理由

  • もともと RubyMine でプロジェクト構成を作る練習をしてたので切り分けに時間 かかった
  • rbenv 使ってたり bundler 使ってたり、 bundle install --path vendor/bundle でインストールしてたのでどこが原因か不明だった
  • そもそも知識不足

対応方法

Gemfile に gem 'test-unit' を書く

# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}"}

gem 'sidekiq', '5.1.1'
# bundler 経由で実行するので test-unit も必要
# https://github.com/rspec/rspec-rails/issues/1273
gem 'test-unit'