LoginSignup
13
3

More than 1 year has passed since last update.

【Ruby/minitest】テスト実行時にコマンドライン引数を置き換える

Posted at

はじめに

コマンドライン引数を用いる処理のテストに際して、
引数を好きなように指定して処理を実行する方法を備忘録として残しておきます。

※ 実行環境: ruby 3.1.2p20
※ この記事では以下のfoo.rbをテスト対象とします

foo.rb
class Foo
  def initialize; end

  def call
    ARGV[0].to_i * 2
  end
end

Array#replaceを使う

ARGVの中身をArray#replaceで置き換えてテストしたい処理を実行します。
テスト実行後に引数なしの状態に戻しておくことで、
後に実行される他のテストに置換の影響が及ぶのを防ぎます。

foo_test.rb
require 'minitest/autorun'

class FooTest < Minitest::Test
  def test_specify_argv
    ARGV.replace([9])
    assert_equal(18, Foo.new.call)
  end

  def test_no_argv
    assert_equal(0, Foo.new.call)
  end

  def teardown
    # 他のテストへの影響を考慮しでARGVを引数なしの状態に戻す
    ARGV.replace([])
  end
end

Module#const_setを使う

Module#const_setにより定数ARGVを定義し直す方法です。
これだけだと定数の重複によってARGVの値を設定できないため、
Module#remove_constにより一度定数ARGVを除きます。
なおObject#sendを用いるのは、Module#remove_constがprivateメソッドであるためです。

foo_test.rb
require 'minitest/autorun'

class FooTest < Minitest::Test
  def test_specify_argv
    Object.send(:remove_const, :ARGV)
    Object.const_set(:ARGV, [9])
    assert_equal(18, Foo.new.call)
  end

  def test_no_argv
    assert_equal(0, Foo.new.call)
  end

  def teardown
    # 他のテストへの影響を考慮しでARGVを引数なしの状態に戻す
    Object.send(:remove_const, :ARGV)
    Object.const_set(:ARGV, [])
  end
end

おわりに

以上テスト実行する際にコマンドライン引数を置き換える方法を2つまとめました。

いずれの方法でも後に実行されるテストへの影響を考慮して、
指定したコマンドライン引数を元に戻すための処理を書いておく必要があります。
もし何かより良い方法をご存知の方がいましたら教えていただけると嬉しいです。

13
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3