Permalink
Browse files

Improve CLI and configuration handling.

  • Loading branch information...
1 parent 7236a55 commit 59d2c62c8d4a587ef876870b6d81f83edf6403cb @trans trans committed Mar 21, 2012
Showing with 157 additions and 66 deletions.
  1. +4 −2 Testfile
  2. +1 −1 bin/ruby-test
  3. +1 −1 bin/rubytest
  4. +74 −31 lib/rubytest/cli.rb
  5. +77 −31 lib/rubytest/config.rb
View
@@ -4,8 +4,10 @@ end
Test.run(:cov) do |run|
run.files << 'test/*_case.rb'
- SimpleCov.start do |cov|
- cov.coverage_dir = 'log/coverage'
+
+ require 'simplecov'
+ SimpleCov.start do
+ coverage_dir 'log/coverage'
end
end
View
@@ -1,4 +1,4 @@
#!/usr/bin/env ruby
require 'rubytest'
-Test::Runner.cli(*ARGV)
+Test::CLI.run(*ARGV)
View
@@ -1,4 +1,4 @@
#!/usr/bin/env ruby
require 'rubytest'
-Test::Runner.cli(*ARGV)
+Test::CLI.run(*ARGV)
View
@@ -1,16 +1,51 @@
module Test
- # Command line interface.
- class Runner
+ # Command line interface to test runner.
+ #
+ class CLI
- # Test runner command line interface.
#
- def self.cli(*argv)
- runner = Runner.new
+ # Convenience method for invoking the CLI.
+ #
+ def self.run(*argv)
+ new.run(*argv)
+ end
+
+ #
+ # Initialize CLI instance.
+ #
+ def initialize
+ require 'optparse'
Test::Config.load
- cli_options(runner, argv)
+ @profile = 'default'
+ @config = Test.config
+ @runner = Runner.new
+ end
+
+ #
+ # @return [Runner]
+ #
+ attr :runner
+
+ #
+ # @return [Hash]
+ #
+ attr :config
+
+ #
+ attr_accessor :profile
+
+ #
+ # Run tests.
+ #
+ def run(*argv)
+ options.parse!(argv)
+
+ run_profile
+
+ runner.files.replace(argv) unless argv.empty?
Test::Config.load_path_setup #unless runner.autopath == false
@@ -23,34 +58,44 @@ def self.cli(*argv)
end
end
- # TODO: replace dynamic preset options with `-p` option
-
#
- def self.cli_options(runner, argv)
- require 'optparse'
+ # Run the common profile if defined and then the specific
+ # profile.
+ #
+ def run_profile
+ raise "no such profile -- #{profile}" unless config[profile] or profile == 'default'
- config = Test.config.dup
- config_loaded = false
+ common = config['common']
+ common.call(runner) if common
- common = config.delete('common')
- default = config.delete('default')
+ profig = config[profile]
+ profig.call(runner) if profig
+ end
- common.call(runner) if common
+ #
+ # Setup OptionsParser instance.
+ #
+ def options
+ this = self
OptionParser.new do |opt|
opt.banner = "Usage: #{$0} [options] [files ...]"
- unless config.empty?
- opt.separator "PRESET OPTIONS:"
- config.each do |name, block|
- opt.on("--#{name}") do
- block.call(runner)
- end
+ opt.separator "PRESET OPTIONS:"
+
+ opt.on '-p', '--profile NAME', "use configuration profile" do |name|
+ this.profile = name.to_s
+ end
+
+ config_names = config.keys - ['common', 'default']
+
+ unless config_names.empty?
+ config_names.each do |name|
+ opt.separator((" " * 40) + "* #{name}")
end
end
opt.separator "CONFIG OPTIONS:"
-
opt.on '-f', '--format NAME', 'report format' do |name|
runner.format = name
end
@@ -85,22 +130,20 @@ def self.cli_options(runner, argv)
#opt.on('--log DIRECTORY', 'log directory'){ |dir|
# options[:log] = dir
#}
- opt.on_tail("--[no-]ansi" , 'turn on/off ANSI colors'){ |v| $ansi = v }
- opt.on_tail("--debug" , 'turn on debugging mode'){ $DEBUG = true }
- #opt.on_tail("--about" , 'display information about lemon'){
+ opt.on("--[no-]ansi" , 'turn on/off ANSI colors'){ |v| $ansi = v }
+ opt.on("--debug" , 'turn on debugging mode'){ $DEBUG = true }
+
+ opt.separator "COMMAND OPTIONS:"
+ #opt.on("--about" , 'display information about rubytest'){
# puts "Ruby Test v#{VERSION}"
# puts "#{COPYRIGHT}"
# exit
#}
- opt.on_tail('-h', '--help', 'display this help message'){
+ opt.on('-h', '--help', 'display this help message'){
puts opt
exit
}
- end.parse!(argv)
-
- default.call(runner) if default && !config_loaded
-
- runner.files.replace(argv) unless argv.empty?
+ end
end
end
View
@@ -1,58 +1,104 @@
module Test
#
- def self.run(name=:default, &block)
+ def self.run(name=nil, &block)
+ name = name ? name : 'default'
+
@config ||= {}
@config[name.to_s] = block
end
+ #
def self.config
@config ||= {}
end
- # TODO: Add optional support for Confection.
-
+ # Handle test run configruation.
+ #
+ # @todo Why not use the instace level for `Test.config` ?
#
class Config
- # Test configuration file.
+ # Tradional test configuration file glob. This glob
+ # looks for a `Testfile` or a `.test` file.
+ # Either can have an optional `.rb` extension.
+ GLOB_RC = '{testfile.rb,testfile,.test.rb,.test}'
+
+ # If a root level test file can't be found, then use this
+ # glob to search the task directory for `*.rubytest` files.
+ GLOB_TASK = 'task/*.rubytest'
+
+ # Glob used to find project root directory.
+ GLOB_ROOT = '{.ruby,.git,.hg,_darcs,lib/}'
+
#
- # @example
- # .test
- # .test.rb
- # task/test.rb
- # Testfile
+ # Load configuration. This will first look for a root level `Testfile.rb`
+ # or `.test.rb` file. Failing that it will look for `task/*.rubytest` files.
+ # An example entry into any of these look like:
#
- # @todo Too many options for ruby-test configuration file.
- GLOB_RC = '{,.,task/}test{,file}{.rb,}'
-
+ # Test.run :name do |run|
+ # run.files << 'test/case_*.rb'
+ # end
#
- GLOB_ROOT = '{.ruby,.git,.hg}'
-
+ # Use `:default` for name for non-specific profile and `:common` for code that
+ # should apply to all configurations.
+ #
+ # Failing any traditional configuration files, the Confection system will
+ # be used. An example entry in a projects `Confile` is:
+ #
+ # config :test, :name do |run|
+ # run.files << 'test/case_*.rb'
+ # end
+ #
+ # You can leave the `:name` parameter out for `:default`.
#
def self.load
- super(rc_file) if rc_file
- #Ruth.module_eval(File.read(rc_file)) if rc_file
+ if rc_files.empty?
+ if confection_file
+ require 'confection'
+ confection('test', '*').each do |c|
+ name = c.profile ? c.profile : :default
+ Test.run(name, &c)
+ end
+ end
+ else
+ rc_files.each do |file|
+ super(file)
+ end
+ end
+ end
+
+ #
+ def self.confection_file
+ @confection_file ||= (
+ Dir.glob(File.join(root, '{,.}confile{,.rb}'), File::FNM_CASEFOLD).first
+ )
end
# Find rc file.
- def self.rc_file
- @rc_file ||= (
- glob = GLOB_RC
- stop = root
- default = nil
- dir = Dir.pwd
- file = nil
- loop do
- files = Dir.glob(File.join(dir, glob), File::FNM_CASEFOLD)
- file = files.find{ |f| File.file?(f) }
- break file if file
- break if dir == stop
- dir = File.dirname(dir)
- break if dir == '/'
+ def self.rc_files
+ @rc_files ||= (
+ if file = Dir.glob(File.join(root, GLOB_RC), File::FNM_CASEFOLD).first
+ [file]
+ else
+ Dir.glob(File.join(root, GLOB_TASK))
end
- file ? file : default
)
+
+ # glob = GLOB_RC
+ # stop = root
+ # default = nil
+ # dir = Dir.pwd
+ # file = nil
+ # loop do
+ # files = Dir.glob(File.join(dir, glob), File::FNM_CASEFOLD)
+ # file = files.find{ |f| File.file?(f) }
+ # break file if file
+ # break if dir == stop
+ # dir = File.dirname(dir)
+ # break if dir == '/'
+ # end
+ # file ? file : default
end
# Find and cache project root directory.

0 comments on commit 59d2c62

Please sign in to comment.