私は小さな Ruby プログラムを作成していますが、複数のユーザー コマンド ライン入力をシミュレートする RSpec 仕様を記述する方法がわかりません (機能自体は機能します)。この StackOverflow の回答は、おそらく私がいる場所に最も近い場所をカバーしていると思いますが、それは私が必要としているものではありません。コマンド ライン インターフェースにThorを使用していますが、これは Thor の問題ではないと思います。
このプログラムは、ファイルまたはコマンド ラインからコマンドを読み込むことができます。テストを正常に記述して、それらを読み込んで実行することができました。ここにいくつかのコードがあります:
cli.rb
class CLI < Thor
# ...
method_option :filename, aliases: ['-f'],
desc: "name of the file containing instructions",
banner: 'FILE'
desc "execute commands", "takes actions as per commands"
def execute
thing = Thing.new
instruction_set do |instructions|
instructions.each do |instruction|
command, args = parse_instruction(instruction) # private helper method
if valid_command?(command, args) # private helper method
response = thing.send(command, *args)
puts format(response) if response
end
end
end
end
# ...
no_tasks do
def instruction_set
if options[:filename]
yield File.readlines(options[:filename]).map { |a| a.chomp }
else
puts usage
print "> "
while line = gets
break if line =~ /EXIT/i
yield [line]
print "> "
end
end
end
# ..
end
次のコードを使用して、ファイルに含まれるコマンドを実行するテストに成功しました。
仕様/cli_spec.rb
describe CLI do
let(:cli) { CLI.new }
subject { cli }
describe "executing instructions from a file" do
let(:default_file) { "instructions.txt" }
let(:output) { capture(:stdout) { cli.execute } }
context "containing valid test data" do
valid_test_data.each do |data|
expected_output = data[:output]
it "should parse the file contents and output a result" do
cli.stub(:options) { { filename: default_file } } # Thor options hash
File.stub(:readlines).with(default_file) do
StringIO.new(data[:input]).map { |a| a.strip.chomp }
end
output.should == expected_output
end
end
end
end
# ...
end
上記はvalid_test_data
次の形式です。
サポート/utilities.rb
def valid_test_data
[
{
input: "C1 ARGS\r
C2\r
C3\r
C4",
output: "OUTPUT\n"
}
# ...
]
end
私が今やりたいことはまったく同じことですが、「ファイル」から各コマンドを読み取って実行する代わりに、ユーザーがstdin
. 以下のコードは完全に間違っていますが、私が行きたい方向性を伝えることができれば幸いです.
仕様/cli_spec.rb
# ...
# !!This code is wrong and doesn't work and needs rewriting!!
describe "executing instructions from the command line" do
let(:output) { capture(:stdout) { cli.execute } }
context "with valid commands" do
valid_test_data.each do |data|
let(:expected_output) { data[:output] }
let(:commands) { StringIO.new(data[:input]).map { |a| a.strip } }
it "should process the commands and output the results" do
commands.each do |command|
cli.stub!(:gets) { command }
if command == :report
STDOUT.should_receive(:puts).with(expected_output)
else
STDOUT.should_receive(:puts).with("> ")
end
end
output.should include(expected_output)
end
end
end
end
私はcli.stub(:puts)
さまざまな場所で使用しようとしましたが、一般的にこのコードを何度も再配置しましたが、データを標準入力に入れるためのスタブを取得できないようです。コマンドのファイルで行うのと同じ方法で、コマンドラインから期待される一連の入力を解析できるかどうか、またはこの問題を解決するためにどのコード構造を使用する必要があるかはわかりません。コマンドライン アプリの仕様を決めた人が参加できれば、それは素晴らしいことです。ありがとう。