mspec 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mspec/commands/mkspec.rb +16 -22
- data/lib/mspec/commands/mspec-ci.rb +41 -50
- data/lib/mspec/commands/mspec-run.rb +46 -53
- data/lib/mspec/commands/mspec-tag.rb +81 -50
- data/lib/mspec/commands/mspec.rb +35 -26
- data/lib/mspec/guards.rb +1 -0
- data/lib/mspec/guards/guard.rb +2 -15
- data/lib/mspec/helpers.rb +1 -0
- data/lib/mspec/helpers/ruby_exe.rb +101 -0
- data/lib/mspec/ruby_name.rb +8 -0
- data/lib/mspec/runner/actions.rb +1 -0
- data/lib/mspec/runner/actions/filter.rb +1 -1
- data/lib/mspec/runner/actions/taglist.rb +56 -0
- data/lib/mspec/runner/filters/tag.rb +1 -1
- data/lib/mspec/runner/mspec.rb +3 -1
- data/lib/mspec/utils/options.rb +258 -195
- data/lib/mspec/utils/script.rb +11 -1
- data/lib/mspec/version.rb +1 -1
- data/spec/commands/mkspec_spec.rb +19 -18
- data/spec/commands/mspec_ci_spec.rb +13 -40
- data/spec/commands/mspec_run_spec.rb +14 -14
- data/spec/commands/mspec_spec.rb +41 -7
- data/spec/commands/mspec_tag_spec.rb +248 -15
- data/spec/helpers/ruby_exe_spec.rb +115 -0
- data/spec/runner/actions/filter_spec.rb +4 -4
- data/spec/runner/actions/tag_spec.rb +1 -5
- data/spec/runner/actions/taglist_spec.rb +152 -0
- data/spec/runner/filters/tag_spec.rb +1 -1
- data/spec/runner/mspec_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/utils/options_spec.rb +562 -283
- data/spec/utils/script_spec.rb +32 -0
- metadata +6 -1
data/lib/mspec/commands/mspec.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
MSPEC_HOME = File.expand_path(File.dirname(__FILE__) + '/../../..')
|
4
4
|
|
5
|
-
require '
|
5
|
+
require 'mspec/version'
|
6
6
|
require 'mspec/utils/options'
|
7
7
|
require 'mspec/utils/script'
|
8
8
|
require 'mspec/helpers/tmp'
|
@@ -20,24 +20,19 @@ class MSpecMain < MSpecScript
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def options(argv=ARGV)
|
23
|
-
if ["ci", "run", "tag"].include?
|
24
|
-
config[:command] = argv.shift
|
25
|
-
config[:options] << "-h" if argv.delete("-h") || argv.delete("--help")
|
26
|
-
config[:options] << "-v" if argv.delete("-v") || argv.delete("--version")
|
27
|
-
end
|
23
|
+
config[:command] = argv.shift if ["ci", "run", "tag"].include?(argv[0])
|
28
24
|
|
29
|
-
options = MSpecOptions.new
|
25
|
+
options = MSpecOptions.new "mspec [COMMAND] [options] (FILE|DIRECTORY|GLOB)+", 30, config
|
30
26
|
|
31
|
-
options.
|
32
|
-
options.
|
33
|
-
options.
|
34
|
-
options.separator " with different implementations like ruby, jruby, rbx, etc.\n"
|
27
|
+
options.doc " The mspec command sets up and invokes the sub-commands"
|
28
|
+
options.doc " (see below) to enable, for instance, running the specs"
|
29
|
+
options.doc " with different implementations like ruby, jruby, rbx, etc.\n"
|
35
30
|
|
36
|
-
options.
|
31
|
+
options.configure do |f|
|
37
32
|
config[:options] << '-B' << f
|
38
33
|
end
|
39
34
|
|
40
|
-
options.
|
35
|
+
options.targets
|
41
36
|
|
42
37
|
options.on("-D", "--gdb", "Run under gdb") do
|
43
38
|
config[:flags] << '--gdb'
|
@@ -53,21 +48,32 @@ class MSpecMain < MSpecScript
|
|
53
48
|
config[:multi] = true
|
54
49
|
config[:options] << "-fy"
|
55
50
|
end
|
56
|
-
options.
|
57
|
-
|
58
|
-
|
59
|
-
|
51
|
+
options.version MSpec::VERSION do
|
52
|
+
if config[:command]
|
53
|
+
config[:options] << "-v"
|
54
|
+
else
|
55
|
+
puts options
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
end
|
59
|
+
options.help do
|
60
|
+
if config[:command]
|
61
|
+
config[:options] << "-h"
|
62
|
+
else
|
63
|
+
puts options
|
64
|
+
exit 1
|
65
|
+
end
|
60
66
|
end
|
61
67
|
|
62
68
|
# The rest of the help output
|
63
|
-
options.
|
64
|
-
options.
|
65
|
-
options.
|
66
|
-
options.
|
67
|
-
options.
|
68
|
-
|
69
|
-
config[:options]
|
70
|
-
options.parse
|
69
|
+
options.doc "\n where COMMAND is one of:\n"
|
70
|
+
options.doc " run - Run the specified specs (default)"
|
71
|
+
options.doc " ci - Run the known good specs"
|
72
|
+
options.doc " tag - Add or remove tags\n"
|
73
|
+
options.doc " mspec COMMAND -h for more options\n"
|
74
|
+
|
75
|
+
options.on_extra { |o| config[:options] << o }
|
76
|
+
config[:options].concat options.parse(argv)
|
71
77
|
end
|
72
78
|
|
73
79
|
def register; end
|
@@ -126,11 +132,14 @@ class MSpecMain < MSpecScript
|
|
126
132
|
|
127
133
|
def run
|
128
134
|
ENV['MSPEC_RUNNER'] = '1'
|
135
|
+
ENV['RUBY_EXE'] = config[:target]
|
136
|
+
ENV['RUBY_FLAGS'] = config[:flags].join " "
|
129
137
|
|
130
|
-
argv = [
|
138
|
+
argv = []
|
131
139
|
argv.concat config[:flags]
|
132
140
|
argv.concat config[:includes]
|
133
141
|
argv.concat config[:requires]
|
142
|
+
argv << "-v"
|
134
143
|
argv << "#{MSPEC_HOME}/bin/mspec-#{ config[:command] || "run" }"
|
135
144
|
argv.concat config[:options]
|
136
145
|
|
data/lib/mspec/guards.rb
CHANGED
data/lib/mspec/guards/guard.rb
CHANGED
@@ -1,21 +1,6 @@
|
|
1
1
|
require 'mspec/runner/mspec'
|
2
2
|
require 'mspec/runner/actions/tally'
|
3
3
|
|
4
|
-
unless defined?(RUBY_NAME) and RUBY_NAME
|
5
|
-
if defined?(RUBY_ENGINE) and RUBY_ENGINE
|
6
|
-
RUBY_NAME = RUBY_ENGINE
|
7
|
-
if defined?(ARG0)
|
8
|
-
RUBY_CLI = /rubinius|rbx/.match(ARG0) ? "shotgun/rubinius" : ARG0
|
9
|
-
else
|
10
|
-
RUBY_CLI = RUBY_NAME
|
11
|
-
end
|
12
|
-
else
|
13
|
-
require 'rbconfig'
|
14
|
-
RUBY_NAME = Config::CONFIG["RUBY_INSTALL_NAME"] || Config::CONFIG["ruby_install_name"]
|
15
|
-
RUBY_CLI = RUBY_NAME
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
4
|
class SpecGuard
|
20
5
|
def self.register
|
21
6
|
unless @registered
|
@@ -81,6 +66,8 @@ class SpecGuard
|
|
81
66
|
RUBY_NAME =~ /^ruby(1.9)?/ and RUBY_VERSION =~ /^1.9/
|
82
67
|
when :jruby
|
83
68
|
RUBY_NAME =~ /^jruby/
|
69
|
+
when :ironruby, :ir
|
70
|
+
RUBY_NAME =~ /^ironruby/
|
84
71
|
else
|
85
72
|
false
|
86
73
|
end
|
data/lib/mspec/helpers.rb
CHANGED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'mspec/ruby_name'
|
2
|
+
|
3
|
+
# The ruby_exe helper provides a wrapper for invoking the
|
4
|
+
# same Ruby interpreter as the one running the specs and
|
5
|
+
# getting the output from running the code. If +code+ is a
|
6
|
+
# file that exists, it will be run. Otherwise, +code+ should
|
7
|
+
# be Ruby code that will be run with the -e command line
|
8
|
+
# option. For example:
|
9
|
+
#
|
10
|
+
# ruby_exe('path/to/some/file.rb')
|
11
|
+
#
|
12
|
+
# will be executed as
|
13
|
+
#
|
14
|
+
# `#{RUBY_EXE} #{'path/to/some/file.rb'}`
|
15
|
+
#
|
16
|
+
# while
|
17
|
+
#
|
18
|
+
# ruby_exe('puts "hello, world."')
|
19
|
+
#
|
20
|
+
# will be executed as
|
21
|
+
#
|
22
|
+
# `#{RUBY_EXE} -e #{'puts "hello, world."'}`
|
23
|
+
#
|
24
|
+
# The RUBY_EXE constant can be set explicitly since the value
|
25
|
+
# is used each time ruby_exe is invoked. The mspec runner script
|
26
|
+
# will set ENV['RUBY_EXE'] to the name of the executable used
|
27
|
+
# to invoke the mspec-run script. The value of RUBY_EXE will be
|
28
|
+
# constructed as follows:
|
29
|
+
#
|
30
|
+
# 1. the value of ENV['RUBY_EXE']
|
31
|
+
# 2. an explicit value based on RUBY_NAME
|
32
|
+
# 3. cwd/(RUBY_NAME + $(EXEEXT) || $(exeext) || '')
|
33
|
+
# 4. $(bindir)/$(RUBY_INSTALL_NAME)
|
34
|
+
#
|
35
|
+
# The value will only be used if the file exists and is executable.
|
36
|
+
#
|
37
|
+
# These 4 ways correspond to the following scenarios:
|
38
|
+
#
|
39
|
+
# 1. Using the MSpec runner scripts, the name of the
|
40
|
+
# executable is explicitly passed by ENV['RUBY_EXE']
|
41
|
+
# so there is no ambiguity.
|
42
|
+
#
|
43
|
+
# Otherwise, if using RSpec (or something else)
|
44
|
+
#
|
45
|
+
# 2. Running the specs while developing an alternative
|
46
|
+
# Ruby implementation. This explicitly names the
|
47
|
+
# executable in the development directory based on
|
48
|
+
# the value of RUBY_NAME, which is probably initialized
|
49
|
+
# from the value of RUBY_ENGINE.
|
50
|
+
# 3. Running the specs within the source directory for
|
51
|
+
# some implementation. (E.g. a local build directory.)
|
52
|
+
# 4. Running the specs against some installed Ruby
|
53
|
+
# implementation.
|
54
|
+
|
55
|
+
class Object
|
56
|
+
def ruby_exe_options(option)
|
57
|
+
case option
|
58
|
+
when :env
|
59
|
+
ENV['RUBY_EXE']
|
60
|
+
when :engine
|
61
|
+
case RUBY_NAME
|
62
|
+
when 'rbx'
|
63
|
+
"bin/rbx"
|
64
|
+
when 'jruby'
|
65
|
+
"bin/jruby"
|
66
|
+
when 'ironruby'
|
67
|
+
"ir"
|
68
|
+
end
|
69
|
+
when :name
|
70
|
+
bin = RUBY_NAME + (Config::CONFIG['EXEEXT'] || Config::CONFIG['exeext'] || '')
|
71
|
+
File.join(".", bin)
|
72
|
+
when :install_name
|
73
|
+
bin = Config::CONFIG["RUBY_INSTALL_NAME"] || Config::CONFIG["ruby_install_name"]
|
74
|
+
bin << (Config::CONFIG['EXEEXT'] || Config::CONFIG['exeext'] || '')
|
75
|
+
File.join(Config::CONFIG['bindir'], bin)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def resolve_ruby_exe
|
80
|
+
[:env, :engine, :name, :install_name].each do |option|
|
81
|
+
exe = ruby_exe_options option
|
82
|
+
return exe if exe and File.exists?(exe) and File.executable?(exe)
|
83
|
+
end
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def ruby_exe(code)
|
88
|
+
if File.exists?(code) and File.executable?(code)
|
89
|
+
`#{RUBY_EXE} #{ENV['RUBY_FLAGS']} #{code}`
|
90
|
+
else
|
91
|
+
`#{RUBY_EXE} #{ENV['RUBY_FLAGS']} -e #{code.inspect}`
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE
|
96
|
+
require 'rbconfig'
|
97
|
+
|
98
|
+
RUBY_EXE = resolve_ruby_exe or
|
99
|
+
raise Exception, "Unable to find a suitable ruby executable."
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
unless Object.const_defined?(:RUBY_NAME) and RUBY_NAME
|
2
|
+
if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE
|
3
|
+
RUBY_NAME = RUBY_ENGINE
|
4
|
+
else
|
5
|
+
require 'rbconfig'
|
6
|
+
RUBY_NAME = Config::CONFIG["RUBY_INSTALL_NAME"] || Config::CONFIG["ruby_install_name"]
|
7
|
+
end
|
8
|
+
end
|
data/lib/mspec/runner/actions.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'mspec/runner/actions/filter'
|
2
|
+
|
3
|
+
# TagListAction - prints out the descriptions for any specs
|
4
|
+
# tagged with +tags+. If +tags+ is an empty list, prints out
|
5
|
+
# descriptions for any specs that are tagged.
|
6
|
+
class TagListAction
|
7
|
+
def initialize(tags=nil)
|
8
|
+
@tags = tags.nil? || tags.empty? ? nil : Array(tags)
|
9
|
+
@filter = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns true. This enables us to match any tag when loading
|
13
|
+
# tags from the file.
|
14
|
+
def include?(arg)
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns true if any tagged descriptions matches +string+.
|
19
|
+
def ===(string)
|
20
|
+
@filter === string
|
21
|
+
end
|
22
|
+
|
23
|
+
# Prints a banner about matching tagged specs.
|
24
|
+
def start
|
25
|
+
if @tags
|
26
|
+
print "\nListing specs tagged with #{@tags.map { |t| "'#{t}'" }.join(", ") }\n\n"
|
27
|
+
else
|
28
|
+
print "\nListing all tagged specs\n\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Creates a MatchFilter for specific tags or for all tags.
|
33
|
+
def load
|
34
|
+
@filter = nil
|
35
|
+
desc = MSpec.read_tags(@tags || self).map { |t| t.description }
|
36
|
+
@filter = MatchFilter.new(nil, *desc) unless desc.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Prints the spec description if it matches the filter.
|
40
|
+
def after(state)
|
41
|
+
return unless self === state.description
|
42
|
+
print state.description, "\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
def register
|
46
|
+
MSpec.register :start, self
|
47
|
+
MSpec.register :load, self
|
48
|
+
MSpec.register :after, self
|
49
|
+
end
|
50
|
+
|
51
|
+
def unregister
|
52
|
+
MSpec.unregister :start, self
|
53
|
+
MSpec.unregister :load, self
|
54
|
+
MSpec.unregister :after, self
|
55
|
+
end
|
56
|
+
end
|
data/lib/mspec/runner/mspec.rb
CHANGED
@@ -237,7 +237,9 @@ module MSpec
|
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
240
|
-
|
240
|
+
# Returns a list of tags matching any tag string in +keys+ based
|
241
|
+
# on the return value of <tt>keys.include?("tag_name")</tt>
|
242
|
+
def self.read_tags(keys)
|
241
243
|
tags = []
|
242
244
|
file = tags_file
|
243
245
|
if File.exist? file
|
data/lib/mspec/utils/options.rb
CHANGED
@@ -1,215 +1,341 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
1
|
+
require 'mspec/version'
|
2
|
+
|
3
|
+
class MSpecOption
|
4
|
+
attr_reader :short, :long, :arg, :description, :block
|
5
|
+
|
6
|
+
def initialize(short, long, arg, description, block)
|
7
|
+
@short = short
|
8
|
+
@long = long
|
9
|
+
@arg = arg
|
10
|
+
@description = description
|
11
|
+
@block = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def arg?
|
15
|
+
@arg != nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def match?(opt)
|
19
|
+
opt == @short or opt == @long
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# MSpecOptions provides a parser for command line options. It also
|
24
|
+
# provides a composable set of options from which the runner scripts
|
25
|
+
# can select for their particular functionality.
|
26
|
+
class MSpecOptions
|
27
|
+
# Raised if incorrect or incomplete formats are passed to #on.
|
28
|
+
class OptionError < Exception; end
|
29
|
+
|
30
|
+
# Raised if an unrecognized option is encountered.
|
31
|
+
class ParseError < Exception; end
|
32
|
+
|
33
|
+
attr_accessor :config, :banner, :width, :options
|
34
|
+
|
35
|
+
def initialize(banner="", width=30, config=nil)
|
36
|
+
@banner = banner
|
37
|
+
@config = config
|
38
|
+
@width = width
|
39
|
+
@options = []
|
40
|
+
@doc = []
|
41
|
+
@extra = []
|
42
|
+
@on_extra = lambda { |x|
|
43
|
+
raise ParseError, "Unrecognized option: #{x}" if x[0] == ?-
|
44
|
+
@extra << x
|
45
|
+
}
|
46
|
+
|
47
|
+
yield self if block_given?
|
48
|
+
end
|
49
|
+
|
50
|
+
# Registers an option. Acceptable formats for arguments are:
|
51
|
+
#
|
52
|
+
# on "-a", "description"
|
53
|
+
# on "-a", "--abdc", "description"
|
54
|
+
# on "-a", "ARG", "description"
|
55
|
+
# on "--abdc", "ARG", "description"
|
56
|
+
# on "-a", "--abdc", "ARG", "description"
|
57
|
+
#
|
58
|
+
# If an block is passed, it will be invoked when the option is
|
59
|
+
# matched. Not passing a block is permitted, but nonsensical.
|
60
|
+
def on(*args, &block)
|
61
|
+
raise OptionError, "option and description are required" if args.size < 2
|
62
|
+
|
63
|
+
description = args.pop
|
64
|
+
short, long, argument = nil
|
65
|
+
args.each do |arg|
|
66
|
+
if arg[0] == ?-
|
67
|
+
if arg[1] == ?-
|
68
|
+
long = arg
|
69
|
+
else
|
70
|
+
short = arg
|
71
|
+
end
|
23
72
|
else
|
24
|
-
|
73
|
+
argument = arg
|
25
74
|
end
|
26
75
|
end
|
76
|
+
|
77
|
+
add short, long, argument, description, block
|
27
78
|
end
|
28
79
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
80
|
+
# Adds documentation text for an option and adds an +MSpecOption+
|
81
|
+
# instance to the list of registered options.
|
82
|
+
def add(short, long, arg, description, block)
|
83
|
+
s = short ? short.dup : " "
|
84
|
+
s << (short ? ", " : " ") if long
|
85
|
+
doc " #{s}#{long} #{arg}".ljust(@width-1) + " #{description}"
|
86
|
+
@options << MSpecOption.new(short, long, arg, description, block)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Searches all registered options to find a match for +opt+. Returns
|
90
|
+
# +nil+ if no registered options match.
|
91
|
+
def match?(opt)
|
92
|
+
@options.find { |o| o.match? opt }
|
93
|
+
end
|
94
|
+
|
95
|
+
# Processes an option. Calles the #on_extra block (or default) for
|
96
|
+
# unrecognized options. For registered options, possibly fetches an
|
97
|
+
# argument and invokes the option's block if it is not nil.
|
98
|
+
def process(argv, entry, opt, arg)
|
99
|
+
unless option = match?(opt)
|
100
|
+
@on_extra[entry]
|
101
|
+
else
|
102
|
+
if option.arg?
|
103
|
+
arg = argv.shift if arg.nil?
|
104
|
+
raise ParseError, "No argument provided for #{opt}" unless arg
|
34
105
|
end
|
35
|
-
|
106
|
+
option.block[arg] if option.block
|
36
107
|
end
|
108
|
+
option
|
109
|
+
end
|
37
110
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
111
|
+
# Splits a string at +n+ characters into the +opt+ and the +rest+.
|
112
|
+
# The +arg+ is set to +nil+ if +rest+ is an empty string.
|
113
|
+
def split(str, n)
|
114
|
+
opt = str[0, n]
|
115
|
+
rest = str[n, str.size]
|
116
|
+
arg = rest == "" ? nil : rest
|
117
|
+
return opt, arg, rest
|
118
|
+
end
|
119
|
+
|
120
|
+
# Parses an array of command line entries, calling blocks for
|
121
|
+
# registered options.
|
122
|
+
def parse(argv=ARGV)
|
123
|
+
argv = Array(argv).dup
|
124
|
+
|
125
|
+
while entry = argv.shift
|
126
|
+
# collect everything that is not an option
|
127
|
+
if entry[0] != ?- or entry.size < 2
|
128
|
+
@on_extra[entry]
|
129
|
+
next
|
130
|
+
end
|
131
|
+
|
132
|
+
# this is a long option
|
133
|
+
if entry[1] == ?-
|
134
|
+
opt, arg = entry.split "="
|
135
|
+
process argv, entry, opt, arg
|
136
|
+
next
|
137
|
+
end
|
138
|
+
|
139
|
+
# disambiguate short option group from short option with argument
|
140
|
+
opt, arg, rest = split entry, 2
|
141
|
+
|
142
|
+
# process first option
|
143
|
+
option = process argv, entry, opt, arg
|
144
|
+
next unless option and not option.arg?
|
145
|
+
|
146
|
+
# process the rest of the options
|
147
|
+
while rest.size > 0
|
148
|
+
opt, arg, rest = split rest, 1
|
149
|
+
opt = "-" + opt
|
150
|
+
option = process argv, opt, opt, arg
|
151
|
+
break if option.arg?
|
49
152
|
end
|
50
153
|
end
|
51
|
-
|
52
|
-
|
154
|
+
|
155
|
+
@extra
|
156
|
+
rescue ParseError => e
|
157
|
+
puts self
|
158
|
+
puts e
|
159
|
+
exit 1
|
53
160
|
end
|
54
|
-
end
|
55
161
|
|
56
|
-
|
162
|
+
# Adds a string of documentation text inline in the text generated
|
163
|
+
# from the options. See #on and #add.
|
164
|
+
def doc(str)
|
165
|
+
@doc << str
|
166
|
+
end
|
57
167
|
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
168
|
+
# Convenience method for providing -v, --version options.
|
169
|
+
def version(version, &block)
|
170
|
+
show = block || lambda { puts "#{File.basename $0} #{version}"; exit }
|
171
|
+
on "-v", "--version", "Show version", &show
|
172
|
+
end
|
62
173
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
174
|
+
# Convenience method for providing -h, --help options.
|
175
|
+
def help(&block)
|
176
|
+
help = block || lambda { puts self; exit 1 }
|
177
|
+
on "-h", "--help", "Show this message", &help
|
178
|
+
end
|
68
179
|
|
69
|
-
|
180
|
+
# Stores a block that will be called with unrecognized options
|
181
|
+
def on_extra(&block)
|
182
|
+
@on_extra = block
|
70
183
|
end
|
71
184
|
|
72
|
-
|
73
|
-
|
185
|
+
# Returns a string representation of the options and doc strings.
|
186
|
+
def to_s
|
187
|
+
@banner + "\n\n" + @doc.join("\n") + "\n"
|
188
|
+
end
|
189
|
+
|
190
|
+
# The methods below provide groups of options that
|
191
|
+
# are composed by the particular runners to provide
|
192
|
+
# their functionality
|
193
|
+
|
194
|
+
def configure(&block)
|
195
|
+
on("-B", "--config", "FILE",
|
74
196
|
"Load FILE containing configuration options", &block)
|
75
197
|
end
|
76
198
|
|
77
|
-
def
|
78
|
-
on("-n", "--name RUBY_NAME",
|
199
|
+
def name
|
200
|
+
on("-n", "--name", "RUBY_NAME",
|
79
201
|
"Set the value of RUBY_NAME (used to determine the implementation)") do |n|
|
80
202
|
Object.const_set :RUBY_NAME, n
|
81
203
|
end
|
82
204
|
end
|
83
205
|
|
84
|
-
def
|
85
|
-
on("-t", "--target TARGET",
|
206
|
+
def targets
|
207
|
+
on("-t", "--target", "TARGET",
|
86
208
|
"Implementation to run the specs, where:") do |t|
|
87
209
|
case t
|
88
210
|
when 'r', 'ruby'
|
89
|
-
|
90
|
-
@config[:flags] << '-v'
|
211
|
+
config[:target] = 'ruby'
|
91
212
|
when 'r19', 'ruby19'
|
92
|
-
|
213
|
+
config[:target] = 'ruby19'
|
93
214
|
when 'x', 'rubinius'
|
94
|
-
|
215
|
+
config[:target] = './bin/rbx'
|
95
216
|
when 'X', 'rbx'
|
96
|
-
|
217
|
+
config[:target] = 'rbx'
|
97
218
|
when 'j', 'jruby'
|
98
|
-
|
219
|
+
config[:target] = 'jruby'
|
220
|
+
when 'i','ironruby'
|
221
|
+
config[:target] = 'ir'
|
99
222
|
else
|
100
|
-
|
223
|
+
config[:target] = t
|
101
224
|
end
|
102
225
|
end
|
103
226
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
227
|
+
doc ""
|
228
|
+
doc " r or ruby invokes ruby in PATH"
|
229
|
+
doc " r19 or ruby19 invokes ruby19 in PATH"
|
230
|
+
doc " x or rubinius invokes ./bin/rbx"
|
231
|
+
doc " X or rbx invokes rbx in PATH"
|
232
|
+
doc " j or jruby invokes jruby in PATH"
|
233
|
+
doc " i or ironruby invokes ir in PATH\n"
|
110
234
|
|
111
|
-
on("-T", "--target-opt OPT",
|
235
|
+
on("-T", "--target-opt", "OPT",
|
112
236
|
"Pass OPT as a flag to the target implementation") do |t|
|
113
|
-
|
237
|
+
config[:flags] << t
|
114
238
|
end
|
115
|
-
on("-I", "--include DIR",
|
239
|
+
on("-I", "--include", "DIR",
|
116
240
|
"Pass DIR through as the -I option to the target") do |d|
|
117
|
-
|
241
|
+
config[:includes] << "-I#{d}"
|
118
242
|
end
|
119
|
-
on("-r", "--require LIBRARY",
|
243
|
+
on("-r", "--require", "LIBRARY",
|
120
244
|
"Pass LIBRARY through as the -r option to the target") do |f|
|
121
|
-
|
245
|
+
config[:requires] << "-r#{f}"
|
122
246
|
end
|
123
247
|
end
|
124
248
|
|
125
|
-
def
|
126
|
-
on("-f", "--format FORMAT",
|
249
|
+
def formatters
|
250
|
+
on("-f", "--format", "FORMAT",
|
127
251
|
"Formatter for reporting, where FORMAT is one of:") do |o|
|
128
252
|
case o
|
129
253
|
when 's', 'spec', 'specdoc'
|
130
|
-
|
254
|
+
config[:formatter] = SpecdocFormatter
|
131
255
|
when 'h', 'html'
|
132
|
-
|
256
|
+
config[:formatter] = HtmlFormatter
|
133
257
|
when 'd', 'dot', 'dotted'
|
134
|
-
|
258
|
+
config[:formatter] = DottedFormatter
|
135
259
|
when 'u', 'unit', 'unitdiff'
|
136
|
-
|
260
|
+
config[:formatter] = UnitdiffFormatter
|
137
261
|
when 'm', 'summary'
|
138
|
-
|
262
|
+
config[:formatter] = SummaryFormatter
|
139
263
|
when 'a', '*', 'spin'
|
140
|
-
|
264
|
+
config[:formatter] = SpinnerFormatter
|
141
265
|
when 'y', 'yaml'
|
142
|
-
|
266
|
+
config[:formatter] = YamlFormatter
|
143
267
|
else
|
144
268
|
puts "Unknown format: #{o}"
|
145
269
|
puts @parser
|
146
270
|
exit
|
147
271
|
end
|
148
272
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
273
|
+
|
274
|
+
doc ""
|
275
|
+
doc " s, spec, specdoc SpecdocFormatter"
|
276
|
+
doc " h, html, HtmlFormatter"
|
277
|
+
doc " d, dot, dotted DottedFormatter"
|
278
|
+
doc " u, unit, unitdiff UnitdiffFormatter"
|
279
|
+
doc " m, summary SummaryFormatter"
|
280
|
+
doc " a, *, spin SpinnerFormatter"
|
281
|
+
doc " y, yaml YamlFormatter\n"
|
282
|
+
|
283
|
+
on("-o", "--output", "FILE",
|
158
284
|
"Write formatter output to FILE") do |f|
|
159
|
-
|
285
|
+
config[:output] = f
|
160
286
|
end
|
161
287
|
end
|
162
288
|
|
163
|
-
def
|
164
|
-
on("-e", "--example STR",
|
289
|
+
def filters
|
290
|
+
on("-e", "--example", "STR",
|
165
291
|
"Run examples with descriptions matching STR") do |o|
|
166
|
-
|
292
|
+
config[:includes] << o
|
167
293
|
end
|
168
|
-
on("-E", "--exclude STR",
|
294
|
+
on("-E", "--exclude", "STR",
|
169
295
|
"Exclude examples with descriptions matching STR") do |o|
|
170
|
-
|
296
|
+
config[:excludes] << o
|
171
297
|
end
|
172
|
-
on("-p", "--pattern PATTERN",
|
298
|
+
on("-p", "--pattern", "PATTERN",
|
173
299
|
"Run examples with descriptions matching PATTERN") do |o|
|
174
|
-
|
300
|
+
config[:patterns] << Regexp.new(o)
|
175
301
|
end
|
176
|
-
on("-P", "--excl-pattern PATTERN",
|
302
|
+
on("-P", "--excl-pattern", "PATTERN",
|
177
303
|
"Exclude examples with descriptions matching PATTERN") do |o|
|
178
|
-
|
304
|
+
config[:xpatterns] << Regexp.new(o)
|
179
305
|
end
|
180
|
-
on("-g", "--tag TAG",
|
306
|
+
on("-g", "--tag", "TAG",
|
181
307
|
"Run examples with descriptions matching ones tagged with TAG") do |o|
|
182
|
-
|
308
|
+
config[:tags] << o
|
183
309
|
end
|
184
|
-
on("-G", "--excl-tag TAG",
|
310
|
+
on("-G", "--excl-tag", "TAG",
|
185
311
|
"Exclude examples with descriptions matching ones tagged with TAG") do |o|
|
186
|
-
|
312
|
+
config[:xtags] << o
|
187
313
|
end
|
188
|
-
on("-w", "--profile FILE",
|
314
|
+
on("-w", "--profile", "FILE",
|
189
315
|
"Run examples for methods listed in the profile FILE") do |f|
|
190
|
-
|
316
|
+
config[:profiles] << f
|
191
317
|
end
|
192
|
-
on("-W", "--excl-profile FILE",
|
318
|
+
on("-W", "--excl-profile", "FILE",
|
193
319
|
"Exclude examples for methods listed in the profile FILE") do |f|
|
194
|
-
|
320
|
+
config[:xprofiles] << f
|
195
321
|
end
|
196
322
|
end
|
197
323
|
|
198
|
-
def
|
324
|
+
def pretend
|
199
325
|
on("-Z", "--dry-run",
|
200
326
|
"Invoke formatters and other actions, but don't execute the specs") do
|
201
327
|
MSpec.register_mode :pretend
|
202
328
|
end
|
203
329
|
end
|
204
330
|
|
205
|
-
def
|
331
|
+
def randomize
|
206
332
|
on("-H", "--random",
|
207
333
|
"Randomize the list of spec files") do
|
208
334
|
MSpec.randomize
|
209
335
|
end
|
210
336
|
end
|
211
337
|
|
212
|
-
def
|
338
|
+
def verbose
|
213
339
|
on("-V", "--verbose", "Output the name of each file processed") do
|
214
340
|
obj = Object.new
|
215
341
|
def obj.start
|
@@ -223,7 +349,7 @@ class MSpecOptions
|
|
223
349
|
MSpec.register :load, obj
|
224
350
|
end
|
225
351
|
|
226
|
-
on("-m", "--marker MARKER",
|
352
|
+
on("-m", "--marker", "MARKER",
|
227
353
|
"Output MARKER for each file processed") do |o|
|
228
354
|
obj = Object.new
|
229
355
|
obj.instance_variable_set :@marker, o
|
@@ -234,104 +360,41 @@ class MSpecOptions
|
|
234
360
|
end
|
235
361
|
end
|
236
362
|
|
237
|
-
def
|
363
|
+
def interrupt
|
238
364
|
on("--int-spec", "Control-C interupts the current spec only") do
|
239
|
-
|
365
|
+
config[:abort] = false
|
240
366
|
end
|
241
367
|
end
|
242
368
|
|
243
|
-
def
|
369
|
+
def verify
|
244
370
|
on("-Y", "--verify",
|
245
371
|
"Verify that guarded specs pass and fail as expected") do
|
246
|
-
MSpec.
|
372
|
+
MSpec.register_mode :verify
|
247
373
|
end
|
248
374
|
on("-O", "--report", "Report guarded specs") do
|
249
|
-
MSpec.
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def add_tagging
|
254
|
-
on("-N", "--add TAG", String,
|
255
|
-
"Add TAG with format 'tag' or 'tag(comment)' (see -Q, -F, -L)") do |o|
|
256
|
-
@config[:tagger] = :add
|
257
|
-
@config[:tag] = "#{o}:"
|
258
|
-
end
|
259
|
-
on("-R", "--del TAG", String,
|
260
|
-
"Delete TAG (see -Q, -F, -L)") do |o|
|
261
|
-
@config[:tagger] = :del
|
262
|
-
@config[:tag] = "#{o}:"
|
263
|
-
@config[:outcome] = :pass
|
264
|
-
end
|
265
|
-
on("-Q", "--pass", "Apply action to specs that pass (default for --del)") do
|
266
|
-
@config[:outcome] = :pass
|
267
|
-
end
|
268
|
-
on("-F", "--fail", "Apply action to specs that fail (default for --add)") do
|
269
|
-
@config[:outcome] = :fail
|
270
|
-
end
|
271
|
-
on("-L", "--all", "Apply action to all specs") do
|
272
|
-
@config[:outcome] = :all
|
375
|
+
MSpec.register_mode :report
|
273
376
|
end
|
274
377
|
end
|
275
378
|
|
276
|
-
def
|
277
|
-
on("-K", "--action-tag TAG",
|
379
|
+
def action_filters
|
380
|
+
on("-K", "--action-tag", "TAG",
|
278
381
|
"Spec descriptions marked with TAG will trigger the specified action") do |o|
|
279
|
-
|
382
|
+
config[:atags] << o
|
280
383
|
end
|
281
|
-
on("-S", "--action-string STR",
|
384
|
+
on("-S", "--action-string", "STR",
|
282
385
|
"Spec descriptions matching STR will trigger the specified action") do |o|
|
283
|
-
|
386
|
+
config[:astrings] << o
|
284
387
|
end
|
285
388
|
end
|
286
389
|
|
287
|
-
def
|
390
|
+
def actions
|
288
391
|
on("--spec-debug",
|
289
392
|
"Invoke the debugger when a spec description matches (see -K, -S)") do
|
290
|
-
|
393
|
+
config[:debugger] = true
|
291
394
|
end
|
292
395
|
on("--spec-gdb",
|
293
396
|
"Invoke Gdb when a spec description matches (see -K, -S)") do
|
294
|
-
|
397
|
+
config[:gdb] = true
|
295
398
|
end
|
296
399
|
end
|
297
|
-
|
298
|
-
def add_version
|
299
|
-
on("-v", "--version", "Show version") do
|
300
|
-
puts "#{File.basename $0} #{MSpec::VERSION}"
|
301
|
-
exit
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
def add_help
|
306
|
-
on("-h", "--help", "Show this message") do
|
307
|
-
puts @parser
|
308
|
-
exit
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
def on(*args, &block)
|
313
|
-
@parser.on(*args, &block)
|
314
|
-
end
|
315
|
-
|
316
|
-
def separator(str)
|
317
|
-
@parser.separator str
|
318
|
-
end
|
319
|
-
|
320
|
-
def parse(argv=ARGV)
|
321
|
-
result = @parser.parse argv
|
322
|
-
|
323
|
-
if (@config[:debugger] || @config[:gdb]) &&
|
324
|
-
@config[:atags].empty? && @config[:astrings].empty?
|
325
|
-
puts "Missing --action-tag or --action-string."
|
326
|
-
puts @parser
|
327
|
-
exit 1
|
328
|
-
end
|
329
|
-
|
330
|
-
result
|
331
|
-
rescue OptionParser::ParseError => e
|
332
|
-
puts @parser
|
333
|
-
puts
|
334
|
-
puts e
|
335
|
-
exit 1
|
336
|
-
end
|
337
400
|
end
|