I have a command-line application which uses thor to handle the parsing of options. I want to unit test the command-line functionality against the code with test-unit and/or minitest.
I can't seem to figure out how to make sure the ARGV array (which normally would hold the options from the command line) holds my test options so they can be tested against the code.
The specific application code:
# myapp/commands/build.rb
require 'thor'
module Myapp
module Commands
# Define build commands for MyApp command line
class Build < Thor::Group
include Thor::Actions
build = ARGV.shift
build = aliases[build] || build
# Define arguments and options
argument :type
class_option :test_framework, :default => :test_unit
# Define source root of application
def self.source_root
File.dirname(__FILE__)
end
case build
# 'build html' generates a html
when 'html'
# The resulting html
puts "<p>HTML</p>"
end
end
end
end
The executable
# bin/myapp
The Test File
# tests/test_build_html.rb
require 'test/unit'
require 'myapp/commands/build'
class TestBuildHtml < Test::Unit::TestCase
include Myapp::Commands
# HERE'S WHAT I'D LIKE TO DO
def test_html_is_built
# THIS SHOULD SIMULATE 'myapp build html' FROM THE COMMAND-LINE
result = MyApp::Commands::Build.run(ARGV << 'html')
assert_equal result, "<p>HTML</p>"
end
end
I have been able to pass an array into ARGV in the test class, but once I call Myapp/Commands/Build the ARGV appears to be empty. I need to make sure the ARGV array is holding 'build' and 'html' in order for the Build command to work and this to pass.
We can run all of our tests at once by using the bin/rails test command. Or we can run a single test file by passing the bin/rails test command the filename containing the test cases.
test-unit (Test::Unit) is unit testing framework for Ruby, based on xUnit principles. These were originally designed by Kent Beck, creator of extreme programming software development methodology, for Smalltalk's SUnit. It allows writing tests, checking results and automated testing in Ruby.
The easiest way to set ARGV and avoid warning is to do:
ARGV.replace your_argv
Found in http://apidock.com/ruby/Test/Unit/setup_argv/class
A better pattern would be to abstract out the direct usage of ARGV
for testing. Given your current design, you could make a module called something like CommandLineArguments
and provide access that way:
module CommandLineArguments
def argv; ARGV; end
end
In your main code:
class Build < Thor::Group
include CommandLineArguments
include Thor::Actions
args = argv
build = args.shift
Finally, in your test, you can modify the module or your test class:
def setup
@myargs = nil
end
class MyApp::Commands::Build
def argv; @myargs || ARGV; end
end
def test_html_is_built
@myargs = %w(html)
result = MyApp::Commands::Build.run
end
If this seems rather complex, it is. You might be better served by extracting the majority of your code into actual classes and then use them in your Thor-powered executable (rather than having all that code in the executable).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With