はじめに
コマンドライン引数を用いる処理のテストに際して、
引数を好きなように指定して処理を実行する方法を備忘録として残しておきます。
※ 実行環境: 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つまとめました。
いずれの方法でも後に実行されるテストへの影響を考慮して、
指定したコマンドライン引数を元に戻すための処理を書いておく必要があります。
もし何かより良い方法をご存知の方がいましたら教えていただけると嬉しいです。