mspec 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|