mspec 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README +101 -0
- data/Rakefile +44 -0
- data/bin/mkspec +7 -0
- data/bin/mspec +7 -0
- data/bin/mspec-ci +8 -0
- data/bin/mspec-run +8 -0
- data/bin/mspec-tag +8 -0
- data/lib/mspec.rb +6 -0
- data/lib/mspec/commands/mkspec.rb +147 -0
- data/lib/mspec/commands/mspec-ci.rb +71 -0
- data/lib/mspec/commands/mspec-run.rb +80 -0
- data/lib/mspec/commands/mspec-tag.rb +87 -0
- data/lib/mspec/commands/mspec.rb +143 -0
- data/lib/mspec/expectations.rb +2 -0
- data/lib/mspec/expectations/expectations.rb +12 -0
- data/lib/mspec/expectations/should.rb +23 -0
- data/lib/mspec/guards.rb +13 -0
- data/lib/mspec/guards/bug.rb +27 -0
- data/lib/mspec/guards/compliance.rb +18 -0
- data/lib/mspec/guards/conflict.rb +16 -0
- data/lib/mspec/guards/endian.rb +40 -0
- data/lib/mspec/guards/extensions.rb +12 -0
- data/lib/mspec/guards/guard.rb +120 -0
- data/lib/mspec/guards/noncompliance.rb +12 -0
- data/lib/mspec/guards/platform.rb +38 -0
- data/lib/mspec/guards/quarantine.rb +15 -0
- data/lib/mspec/guards/runner.rb +30 -0
- data/lib/mspec/guards/superuser.rb +15 -0
- data/lib/mspec/guards/support.rb +12 -0
- data/lib/mspec/guards/version.rb +40 -0
- data/lib/mspec/helpers.rb +6 -0
- data/lib/mspec/helpers/bignum.rb +5 -0
- data/lib/mspec/helpers/const_lookup.rb +5 -0
- data/lib/mspec/helpers/flunk.rb +5 -0
- data/lib/mspec/helpers/io.rb +13 -0
- data/lib/mspec/helpers/scratch.rb +17 -0
- data/lib/mspec/helpers/tmp.rb +32 -0
- data/lib/mspec/matchers.rb +16 -0
- data/lib/mspec/matchers/base.rb +95 -0
- data/lib/mspec/matchers/be_ancestor_of.rb +24 -0
- data/lib/mspec/matchers/be_close.rb +27 -0
- data/lib/mspec/matchers/be_empty.rb +20 -0
- data/lib/mspec/matchers/be_false.rb +20 -0
- data/lib/mspec/matchers/be_kind_of.rb +24 -0
- data/lib/mspec/matchers/be_nil.rb +20 -0
- data/lib/mspec/matchers/be_true.rb +20 -0
- data/lib/mspec/matchers/complain.rb +56 -0
- data/lib/mspec/matchers/eql.rb +26 -0
- data/lib/mspec/matchers/equal.rb +26 -0
- data/lib/mspec/matchers/equal_utf16.rb +34 -0
- data/lib/mspec/matchers/include.rb +32 -0
- data/lib/mspec/matchers/output.rb +67 -0
- data/lib/mspec/matchers/output_to_fd.rb +71 -0
- data/lib/mspec/matchers/raise_error.rb +48 -0
- data/lib/mspec/mocks.rb +3 -0
- data/lib/mspec/mocks/mock.rb +123 -0
- data/lib/mspec/mocks/object.rb +28 -0
- data/lib/mspec/mocks/proxy.rb +112 -0
- data/lib/mspec/runner.rb +13 -0
- data/lib/mspec/runner/actions.rb +6 -0
- data/lib/mspec/runner/actions/debug.rb +17 -0
- data/lib/mspec/runner/actions/filter.rb +40 -0
- data/lib/mspec/runner/actions/gdb.rb +17 -0
- data/lib/mspec/runner/actions/tag.rb +97 -0
- data/lib/mspec/runner/actions/tally.rb +80 -0
- data/lib/mspec/runner/actions/timer.rb +22 -0
- data/lib/mspec/runner/filters.rb +4 -0
- data/lib/mspec/runner/filters/match.rb +22 -0
- data/lib/mspec/runner/filters/profile.rb +54 -0
- data/lib/mspec/runner/filters/regexp.rb +7 -0
- data/lib/mspec/runner/filters/tag.rb +29 -0
- data/lib/mspec/runner/formatters.rb +7 -0
- data/lib/mspec/runner/formatters/dotted.rb +81 -0
- data/lib/mspec/runner/formatters/html.rb +87 -0
- data/lib/mspec/runner/formatters/specdoc.rb +27 -0
- data/lib/mspec/runner/formatters/spinner.rb +89 -0
- data/lib/mspec/runner/formatters/summary.rb +8 -0
- data/lib/mspec/runner/formatters/unit.rb +25 -0
- data/lib/mspec/runner/formatters/yaml.rb +43 -0
- data/lib/mspec/runner/mspec.rb +232 -0
- data/lib/mspec/runner/object.rb +20 -0
- data/lib/mspec/runner/shared.rb +12 -0
- data/lib/mspec/runner/state.rb +116 -0
- data/lib/mspec/runner/tag.rb +20 -0
- data/lib/mspec/utils/name_map.rb +130 -0
- data/lib/mspec/utils/options.rb +344 -0
- data/lib/mspec/utils/script.rb +77 -0
- data/lib/mspec/version.rb +3 -0
- data/spec/commands/mkspec_spec.rb +321 -0
- data/spec/commands/mspec_ci_spec.rb +139 -0
- data/spec/commands/mspec_run_spec.rb +146 -0
- data/spec/commands/mspec_spec.rb +359 -0
- data/spec/commands/mspec_tag_spec.rb +131 -0
- data/spec/expectations/expectations_spec.rb +16 -0
- data/spec/expectations/should_spec.rb +99 -0
- data/spec/guards/bug_spec.rb +137 -0
- data/spec/guards/compliance_spec.rb +70 -0
- data/spec/guards/conflict_spec.rb +20 -0
- data/spec/guards/endian_spec.rb +42 -0
- data/spec/guards/extensions_spec.rb +36 -0
- data/spec/guards/guard_spec.rb +355 -0
- data/spec/guards/noncompliance_spec.rb +36 -0
- data/spec/guards/platform_spec.rb +84 -0
- data/spec/guards/quarantine_spec.rb +19 -0
- data/spec/guards/runner_spec.rb +75 -0
- data/spec/guards/superuser_spec.rb +22 -0
- data/spec/guards/support_spec.rb +22 -0
- data/spec/guards/version_spec.rb +133 -0
- data/spec/helpers/bignum_spec.rb +11 -0
- data/spec/helpers/const_lookup_spec.rb +19 -0
- data/spec/helpers/flunk_spec.rb +15 -0
- data/spec/helpers/io_spec.rb +34 -0
- data/spec/helpers/scratch_spec.rb +22 -0
- data/spec/helpers/tmp_spec.rb +72 -0
- data/spec/matchers/base_spec.rb +180 -0
- data/spec/matchers/be_ancestor_of_spec.rb +28 -0
- data/spec/matchers/be_close_spec.rb +46 -0
- data/spec/matchers/be_empty_spec.rb +26 -0
- data/spec/matchers/be_false_spec.rb +28 -0
- data/spec/matchers/be_kind_of_spec.rb +29 -0
- data/spec/matchers/be_nil_spec.rb +27 -0
- data/spec/matchers/be_true_spec.rb +28 -0
- data/spec/matchers/complain_spec.rb +52 -0
- data/spec/matchers/eql_spec.rb +33 -0
- data/spec/matchers/equal_spec.rb +33 -0
- data/spec/matchers/equal_utf16_spec.rb +47 -0
- data/spec/matchers/include_spec.rb +37 -0
- data/spec/matchers/output_spec.rb +74 -0
- data/spec/matchers/output_to_fd_spec.rb +33 -0
- data/spec/matchers/raise_error_spec.rb +56 -0
- data/spec/mocks/mock_spec.rb +272 -0
- data/spec/mocks/proxy_spec.rb +259 -0
- data/spec/runner/actions/debug_spec.rb +61 -0
- data/spec/runner/actions/filter_spec.rb +84 -0
- data/spec/runner/actions/gdb_spec.rb +61 -0
- data/spec/runner/actions/tag_spec.rb +253 -0
- data/spec/runner/actions/tally_spec.rb +107 -0
- data/spec/runner/actions/timer_spec.rb +42 -0
- data/spec/runner/filters/a.yaml +4 -0
- data/spec/runner/filters/b.yaml +11 -0
- data/spec/runner/filters/match_spec.rb +44 -0
- data/spec/runner/filters/profile_spec.rb +117 -0
- data/spec/runner/filters/regexp_spec.rb +13 -0
- data/spec/runner/filters/tag_spec.rb +77 -0
- data/spec/runner/formatters/dotted_spec.rb +184 -0
- data/spec/runner/formatters/html_spec.rb +191 -0
- data/spec/runner/formatters/specdoc_spec.rb +57 -0
- data/spec/runner/formatters/spinner_spec.rb +78 -0
- data/spec/runner/formatters/summary_spec.rb +29 -0
- data/spec/runner/formatters/unit_spec.rb +71 -0
- data/spec/runner/formatters/yaml_spec.rb +123 -0
- data/spec/runner/mspec_spec.rb +393 -0
- data/spec/runner/shared_spec.rb +41 -0
- data/spec/runner/state_spec.rb +535 -0
- data/spec/runner/tag_spec.rb +93 -0
- data/spec/runner/tags.txt +3 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/utils/name_map_spec.rb +178 -0
- data/spec/utils/options_spec.rb +862 -0
- data/spec/utils/script_spec.rb +240 -0
- metadata +217 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
class RaiseErrorMatcher
|
2
|
+
def initialize(exception, message, &block)
|
3
|
+
@exception = exception
|
4
|
+
@message = message
|
5
|
+
@block = block
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(proc)
|
9
|
+
proc.call
|
10
|
+
return false
|
11
|
+
rescue Exception => @actual
|
12
|
+
return false unless @exception === @actual
|
13
|
+
if @message then
|
14
|
+
case @message
|
15
|
+
when String then
|
16
|
+
return false if @message != @actual.message
|
17
|
+
when Regexp then
|
18
|
+
return false if @message !~ @actual.message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
@block[@actual] if @block
|
23
|
+
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message
|
28
|
+
message = ["Expected #{@exception}#{%[ (#{@message})] if @message}"]
|
29
|
+
|
30
|
+
if @actual then
|
31
|
+
message << "but got #{@actual.class}#{%[ (#{@actual.message})] if @actual.message}"
|
32
|
+
else
|
33
|
+
message << "but no exception was raised"
|
34
|
+
end
|
35
|
+
|
36
|
+
message
|
37
|
+
end
|
38
|
+
|
39
|
+
def negative_failure_message
|
40
|
+
["Expected to not get #{@exception}#{%[ (#{@message})] if @message}", ""]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Object
|
45
|
+
def raise_error(exception=Exception, message=nil, &block)
|
46
|
+
RaiseErrorMatcher.new(exception, message, &block)
|
47
|
+
end
|
48
|
+
end
|
data/lib/mspec/mocks.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'mspec/expectations/expectations'
|
2
|
+
|
3
|
+
module Mock
|
4
|
+
def self.reset
|
5
|
+
@expects = nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.expects
|
9
|
+
@expects ||= Hash.new { |h,k| h[k] = [] }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.replaced_name(sym)
|
13
|
+
:"__ms_#{sym}__"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.install_method(obj, sym, type = :mock)
|
17
|
+
meta = class << obj; self; end
|
18
|
+
|
19
|
+
if (sym.to_sym == :respond_to? or obj.respond_to?(sym)) and !meta.instance_methods.include?(replaced_name(sym).to_s)
|
20
|
+
meta.__send__ :alias_method, replaced_name(sym), sym.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
meta.class_eval <<-END
|
24
|
+
def #{sym}(*args, &block)
|
25
|
+
Mock.verify_call self, :#{sym}, *args, &block
|
26
|
+
end
|
27
|
+
END
|
28
|
+
|
29
|
+
MSpec.actions :expectation, MSpec.current.state
|
30
|
+
|
31
|
+
proxy = MockProxy.new
|
32
|
+
|
33
|
+
if type == :stub
|
34
|
+
expects[[obj, sym]] << proxy
|
35
|
+
proxy.at_least(0)
|
36
|
+
else
|
37
|
+
expects[[obj, sym]].unshift proxy
|
38
|
+
proxy.exactly(1)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.verify_count
|
43
|
+
expects.each do |key, proxies|
|
44
|
+
obj, sym = key.first, key.last
|
45
|
+
|
46
|
+
proxies.each do |proxy|
|
47
|
+
qualifier, count = proxy.count
|
48
|
+
pass = case qualifier
|
49
|
+
when :at_least
|
50
|
+
proxy.calls >= count
|
51
|
+
when :at_most
|
52
|
+
proxy.calls <= count
|
53
|
+
when :exactly
|
54
|
+
proxy.calls == count
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
unless pass
|
59
|
+
Expectation.fail_with("Mock #{obj.inspect}\nexpected to receive #{sym} #{qualifier.to_s.sub('_', ' ')} #{count} times",
|
60
|
+
"but received it #{proxy.calls} times")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.verify_call(obj, sym, *args, &block)
|
67
|
+
compare = *args
|
68
|
+
|
69
|
+
expects[[obj, sym]].each do |proxy|
|
70
|
+
pass = case proxy.arguments
|
71
|
+
when :any_args
|
72
|
+
true
|
73
|
+
when :no_args
|
74
|
+
compare.nil?
|
75
|
+
else
|
76
|
+
proxy.arguments == compare
|
77
|
+
end
|
78
|
+
|
79
|
+
if proxy.yielding?
|
80
|
+
if block
|
81
|
+
proxy.yielding.each do |args_to_yield|
|
82
|
+
if block.arity == -1 || block.arity == args_to_yield.size
|
83
|
+
block.call(*args_to_yield)
|
84
|
+
else
|
85
|
+
Expectation.fail_with("Mock #{obj.inspect} asked to yield |#{proxy.yielding.join(', ')}| on #{sym}\n",
|
86
|
+
"but a block with arity #{block.arity} was passed")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
else
|
90
|
+
Expectation.fail_with("Mock #{obj.inspect} asked to yield |[#{proxy.yielding.join('], [')}]| on #{sym}\n",
|
91
|
+
"but no block was passed")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if pass
|
96
|
+
proxy.called
|
97
|
+
return proxy.returning
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
if sym.to_sym == :respond_to?
|
102
|
+
return obj.__send__(replaced_name(sym), compare)
|
103
|
+
else
|
104
|
+
Expectation.fail_with("Mock #{obj.inspect}: method #{sym}\n",
|
105
|
+
"called with unexpected arguments (#{Array(compare).join(' ')})")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.cleanup
|
110
|
+
expects.keys.each do |obj, sym|
|
111
|
+
meta = class << obj; self; end
|
112
|
+
|
113
|
+
replaced = replaced_name(sym)
|
114
|
+
if meta.instance_methods.include?(replaced.to_s)
|
115
|
+
meta.__send__ :alias_method, sym.to_sym, replaced
|
116
|
+
meta.__send__ :remove_method, replaced
|
117
|
+
else
|
118
|
+
meta.__send__ :remove_method, sym.to_sym
|
119
|
+
end
|
120
|
+
end
|
121
|
+
reset
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'mspec/mocks/proxy'
|
2
|
+
|
3
|
+
class MockObject
|
4
|
+
def initialize(name)
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Object
|
10
|
+
def stub!(sym)
|
11
|
+
Mock.install_method self, sym, :stub
|
12
|
+
end
|
13
|
+
|
14
|
+
def should_receive(sym)
|
15
|
+
Mock.install_method self, sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def should_not_receive(sym)
|
19
|
+
proxy = Mock.install_method self, sym
|
20
|
+
proxy.exactly(0).times
|
21
|
+
# return nil so that further chained calls will raise
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def mock(name)
|
26
|
+
MockObject.new(name)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
class MockProxy
|
2
|
+
def initialize
|
3
|
+
@multiple_returns = nil
|
4
|
+
@returning = nil
|
5
|
+
@yielding = []
|
6
|
+
@arguments = :any_args
|
7
|
+
end
|
8
|
+
|
9
|
+
def count
|
10
|
+
@count ||= [:exactly, 0]
|
11
|
+
end
|
12
|
+
|
13
|
+
def arguments
|
14
|
+
@arguments
|
15
|
+
end
|
16
|
+
|
17
|
+
def returning
|
18
|
+
if @multiple_returns
|
19
|
+
if @returning.size == 1
|
20
|
+
@multiple_returns = false
|
21
|
+
return @returning = @returning.shift
|
22
|
+
end
|
23
|
+
return @returning.shift
|
24
|
+
end
|
25
|
+
@returning
|
26
|
+
end
|
27
|
+
|
28
|
+
def times
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def calls
|
33
|
+
@calls ||= 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def called
|
37
|
+
@calls = calls + 1
|
38
|
+
end
|
39
|
+
|
40
|
+
def exactly(n)
|
41
|
+
@count = [:exactly, n_times(n)]
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def at_least(n)
|
46
|
+
@count = [:at_least, n_times(n)]
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def at_most(n)
|
51
|
+
@count = [:at_most, n_times(n)]
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def once
|
56
|
+
exactly 1
|
57
|
+
end
|
58
|
+
|
59
|
+
def twice
|
60
|
+
exactly 2
|
61
|
+
end
|
62
|
+
|
63
|
+
def any_number_of_times
|
64
|
+
at_least 0
|
65
|
+
end
|
66
|
+
|
67
|
+
def with(*args)
|
68
|
+
raise ArgumentError, "you must specify the expected arguments" if args.empty?
|
69
|
+
@arguments = *args
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def and_return(*args)
|
74
|
+
case args.size
|
75
|
+
when 0
|
76
|
+
@returning = nil
|
77
|
+
when 1
|
78
|
+
@returning = args[0]
|
79
|
+
else
|
80
|
+
@multiple_returns = true
|
81
|
+
@returning = args
|
82
|
+
count[1] = args.size if count[1] < args.size
|
83
|
+
end
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def and_yield(*args)
|
88
|
+
@yielding << args
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
def yielding
|
93
|
+
@yielding
|
94
|
+
end
|
95
|
+
|
96
|
+
def yielding?
|
97
|
+
!@yielding.empty?
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def n_times(n)
|
103
|
+
case n
|
104
|
+
when :once
|
105
|
+
1
|
106
|
+
when :twice
|
107
|
+
2
|
108
|
+
else
|
109
|
+
Integer n
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/mspec/runner.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'mspec/mocks'
|
2
|
+
require 'mspec/runner/mspec'
|
3
|
+
require 'mspec/runner/object'
|
4
|
+
require 'mspec/runner/formatters'
|
5
|
+
require 'mspec/runner/actions'
|
6
|
+
require 'mspec/runner/filters'
|
7
|
+
require 'mspec/runner/shared'
|
8
|
+
require 'mspec/runner/tag'
|
9
|
+
|
10
|
+
def $stderr.write(str)
|
11
|
+
# The 'useless use of' warnings are a crime against OO.
|
12
|
+
str =~ /useless use of/ ? nil : super
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'mspec/runner/actions/filter'
|
2
|
+
|
3
|
+
class DebugAction < ActionFilter
|
4
|
+
def before(state)
|
5
|
+
Kernel.debugger if self === state.description
|
6
|
+
end
|
7
|
+
|
8
|
+
def register
|
9
|
+
super
|
10
|
+
MSpec.register :before, self
|
11
|
+
end
|
12
|
+
|
13
|
+
def unregister
|
14
|
+
super
|
15
|
+
MSpec.unregister :before, self
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'mspec/runner/filters/match'
|
2
|
+
|
3
|
+
# ActionFilter is a base class for actions that are triggered by
|
4
|
+
# specs that match the filter. The filter may be specified by
|
5
|
+
# strings that match spec descriptions or by tags for strings
|
6
|
+
# that match spec descriptions.
|
7
|
+
#
|
8
|
+
# Unlike TagFilter and RegexpFilter, ActionFilter instances do
|
9
|
+
# not affect the specs that are run. The filter is only used to
|
10
|
+
# trigger the action.
|
11
|
+
|
12
|
+
class ActionFilter
|
13
|
+
def initialize(tags=nil, descs=nil)
|
14
|
+
@tags = Array(tags)
|
15
|
+
descs = Array(descs)
|
16
|
+
@sfilter = MatchFilter.new(nil, *descs) unless descs.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def ===(string)
|
20
|
+
@sfilter === string or @tfilter === string
|
21
|
+
end
|
22
|
+
|
23
|
+
def load
|
24
|
+
@tfilter = nil
|
25
|
+
return if @tags.empty?
|
26
|
+
|
27
|
+
desc = MSpec.read_tags(*@tags).map { |t| t.description }
|
28
|
+
return if desc.empty?
|
29
|
+
|
30
|
+
@tfilter = MatchFilter.new(nil, *desc)
|
31
|
+
end
|
32
|
+
|
33
|
+
def register
|
34
|
+
MSpec.register :load, self
|
35
|
+
end
|
36
|
+
|
37
|
+
def unregister
|
38
|
+
MSpec.unregister :load, self
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'mspec/runner/actions/filter'
|
2
|
+
|
3
|
+
class GdbAction < ActionFilter
|
4
|
+
def before(state)
|
5
|
+
Kernel.yield_gdb(true) if self === state.description
|
6
|
+
end
|
7
|
+
|
8
|
+
def register
|
9
|
+
super
|
10
|
+
MSpec.register :before, self
|
11
|
+
end
|
12
|
+
|
13
|
+
def unregister
|
14
|
+
super
|
15
|
+
MSpec.unregister :before, self
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'mspec/runner/actions/filter'
|
2
|
+
|
3
|
+
# TagAction - Write tagged spec description string to a
|
4
|
+
# tag file associated with each spec file.
|
5
|
+
#
|
6
|
+
# The action is triggered by specs whose descriptions
|
7
|
+
# match the filter created with 'tags' and/or 'desc'
|
8
|
+
#
|
9
|
+
# The action fires in the :after event, after the spec
|
10
|
+
# had been run. The action fires if the outcome of
|
11
|
+
# running the spec matches 'outcome'.
|
12
|
+
#
|
13
|
+
# The arguments are:
|
14
|
+
#
|
15
|
+
# action: :add, :del
|
16
|
+
# outcome: :pass, :fail, :all
|
17
|
+
# tag: the tag to create/delete
|
18
|
+
# comment: the comment to create
|
19
|
+
# tags: zero or more tags to get matching
|
20
|
+
# spec description strings from
|
21
|
+
# desc: zero or more strings to match the
|
22
|
+
# spec description strings
|
23
|
+
|
24
|
+
class TagAction < ActionFilter
|
25
|
+
def initialize(action, outcome, tag, comment, tags=nil, descs=nil)
|
26
|
+
super tags, descs
|
27
|
+
@action = action
|
28
|
+
@outcome = outcome
|
29
|
+
@tag = tag
|
30
|
+
@comment = comment
|
31
|
+
@report = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def ===(string)
|
35
|
+
return true unless @sfilter or @tfilter
|
36
|
+
@sfilter === string or @tfilter === string
|
37
|
+
end
|
38
|
+
|
39
|
+
def after(state)
|
40
|
+
if self === state.description and outcome? state
|
41
|
+
tag = SpecTag.new
|
42
|
+
tag.tag = @tag
|
43
|
+
tag.comment = @comment
|
44
|
+
tag.description = state.description
|
45
|
+
|
46
|
+
case @action
|
47
|
+
when :add
|
48
|
+
changed = MSpec.write_tag tag
|
49
|
+
when :del
|
50
|
+
changed = MSpec.delete_tag tag
|
51
|
+
end
|
52
|
+
|
53
|
+
@report << state.description if changed
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def outcome?(state)
|
58
|
+
@outcome == :all or
|
59
|
+
(@outcome == :pass and not state.exception?) or
|
60
|
+
(@outcome == :fail and state.exception?)
|
61
|
+
end
|
62
|
+
|
63
|
+
def report
|
64
|
+
@report.join("\n") + "\n"
|
65
|
+
end
|
66
|
+
private :report
|
67
|
+
|
68
|
+
def finish
|
69
|
+
case @action
|
70
|
+
when :add
|
71
|
+
if @report.empty?
|
72
|
+
print "\nTagAction: no specs were tagged with '#{@tag}'\n"
|
73
|
+
else
|
74
|
+
print "\nTagAction: specs tagged with '#{@tag}':\n\n"
|
75
|
+
print report
|
76
|
+
end
|
77
|
+
when :del
|
78
|
+
if @report.empty?
|
79
|
+
print "\nTagAction: no tags '#{@tag}' were deleted\n"
|
80
|
+
else
|
81
|
+
print "\nTagAction: tag '#{@tag}' deleted for specs:\n\n"
|
82
|
+
print report
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def register
|
88
|
+
super
|
89
|
+
MSpec.register :after, self
|
90
|
+
MSpec.register :finish, self
|
91
|
+
end
|
92
|
+
|
93
|
+
def unregister
|
94
|
+
super
|
95
|
+
MSpec.unregister :after, self
|
96
|
+
end
|
97
|
+
end
|