mspec 1.1.1 → 1.2.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/Rakefile +1 -1
- data/lib/mspec/runner/actions/tag.rb +41 -7
- data/lib/mspec/runner/actions/tally.rb +16 -7
- data/lib/mspec/runner/{state.rb → context.rb} +22 -54
- data/lib/mspec/runner/example.rb +37 -0
- data/lib/mspec/runner/exception.rb +39 -0
- data/lib/mspec/runner/formatters/dotted.rb +61 -45
- data/lib/mspec/runner/formatters/html.rb +16 -22
- data/lib/mspec/runner/formatters/specdoc.rb +24 -11
- data/lib/mspec/runner/formatters/spinner.rb +20 -10
- data/lib/mspec/runner/formatters/summary.rb +4 -1
- data/lib/mspec/runner/formatters/unit.rb +5 -9
- data/lib/mspec/runner/formatters/yaml.rb +11 -10
- data/lib/mspec/runner/mspec.rb +15 -16
- data/lib/mspec/version.rb +1 -1
- data/spec/runner/actions/debug_spec.rb +2 -2
- data/spec/runner/actions/gdb_spec.rb +2 -2
- data/spec/runner/actions/tag_spec.rb +76 -22
- data/spec/runner/actions/tally_spec.rb +26 -6
- data/spec/runner/{state_spec.rb → context_spec.rb} +80 -167
- data/spec/runner/example_spec.rb +96 -0
- data/spec/runner/exception_spec.rb +110 -0
- data/spec/runner/formatters/dotted_spec.rb +117 -27
- data/spec/runner/formatters/html_spec.rb +44 -21
- data/spec/runner/formatters/specdoc_spec.rb +52 -12
- data/spec/runner/formatters/spinner_spec.rb +2 -2
- data/spec/runner/formatters/summary_spec.rb +7 -11
- data/spec/runner/formatters/unit_spec.rb +12 -11
- data/spec/runner/formatters/yaml_spec.rb +7 -6
- data/spec/runner/mspec_spec.rb +28 -29
- metadata +7 -3
data/Rakefile
CHANGED
@@ -29,15 +29,35 @@ class TagAction < ActionFilter
|
|
29
29
|
@tag = tag
|
30
30
|
@comment = comment
|
31
31
|
@report = []
|
32
|
+
@exception = false
|
32
33
|
end
|
33
34
|
|
35
|
+
# Returns true if there are no _tag_ or _description_ filters. This
|
36
|
+
# means that a TagAction matches any example by default. Otherwise,
|
37
|
+
# returns true if either the _tag_ or the _description_ filter
|
38
|
+
# matches +string+.
|
34
39
|
def ===(string)
|
35
40
|
return true unless @sfilter or @tfilter
|
36
41
|
@sfilter === string or @tfilter === string
|
37
42
|
end
|
38
43
|
|
44
|
+
# Callback for the MSpec :before event. Resets the +#exception?+
|
45
|
+
# flag to false.
|
46
|
+
def before(state)
|
47
|
+
@exception = false
|
48
|
+
end
|
49
|
+
|
50
|
+
# Callback for the MSpec :exception event. Sets the +#exception?+
|
51
|
+
# flag.
|
52
|
+
def exception(exception)
|
53
|
+
@exception = exception
|
54
|
+
end
|
55
|
+
|
56
|
+
# Callback for the MSpec :after event. Performs the tag action
|
57
|
+
# depending on the type of action and the outcome of evaluating
|
58
|
+
# the example. See +TagAction+ for a description of the actions.
|
39
59
|
def after(state)
|
40
|
-
if self === state.description and outcome?
|
60
|
+
if self === state.description and outcome?
|
41
61
|
tag = SpecTag.new
|
42
62
|
tag.tag = @tag
|
43
63
|
tag.comment = @comment
|
@@ -54,10 +74,19 @@ class TagAction < ActionFilter
|
|
54
74
|
end
|
55
75
|
end
|
56
76
|
|
57
|
-
|
77
|
+
# Returns true if the result of evaluating the example matches
|
78
|
+
# the _outcome_ registered for this tag action. See +TagAction+
|
79
|
+
# for a description of the _outcome_ types.
|
80
|
+
def outcome?
|
58
81
|
@outcome == :all or
|
59
|
-
(@outcome == :pass and not
|
60
|
-
(@outcome == :fail and
|
82
|
+
(@outcome == :pass and not exception?) or
|
83
|
+
(@outcome == :fail and exception?)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns true if an exception was raised while evaluating the
|
87
|
+
# current example.
|
88
|
+
def exception?
|
89
|
+
!!@exception
|
61
90
|
end
|
62
91
|
|
63
92
|
def report
|
@@ -65,6 +94,8 @@ class TagAction < ActionFilter
|
|
65
94
|
end
|
66
95
|
private :report
|
67
96
|
|
97
|
+
# Callback for the MSpec :finish event. Prints the actions
|
98
|
+
# performed while evaluating the examples.
|
68
99
|
def finish
|
69
100
|
case @action
|
70
101
|
when :add
|
@@ -86,12 +117,15 @@ class TagAction < ActionFilter
|
|
86
117
|
|
87
118
|
def register
|
88
119
|
super
|
89
|
-
MSpec.register :
|
90
|
-
MSpec.register :
|
120
|
+
MSpec.register :exception, self
|
121
|
+
MSpec.register :after, self
|
122
|
+
MSpec.register :finish, self
|
91
123
|
end
|
92
124
|
|
93
125
|
def unregister
|
94
126
|
super
|
95
|
-
MSpec.unregister :
|
127
|
+
MSpec.unregister :exception, self
|
128
|
+
MSpec.unregister :after, self
|
129
|
+
MSpec.unregister :finish, self
|
96
130
|
end
|
97
131
|
end
|
@@ -48,14 +48,16 @@ class TallyAction
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def register
|
51
|
-
MSpec.register :load,
|
52
|
-
MSpec.register :
|
51
|
+
MSpec.register :load, self
|
52
|
+
MSpec.register :exception, self
|
53
|
+
MSpec.register :after, self
|
53
54
|
MSpec.register :expectation, self
|
54
55
|
end
|
55
56
|
|
56
57
|
def unregister
|
57
|
-
MSpec.unregister :load,
|
58
|
-
MSpec.unregister :
|
58
|
+
MSpec.unregister :load, self
|
59
|
+
MSpec.unregister :exception, self
|
60
|
+
MSpec.unregister :after, self
|
59
61
|
MSpec.unregister :expectation, self
|
60
62
|
end
|
61
63
|
|
@@ -63,15 +65,22 @@ class TallyAction
|
|
63
65
|
@counter.files!
|
64
66
|
end
|
65
67
|
|
68
|
+
# Callback for the MSpec :expectation event. Increments the
|
69
|
+
# tally of expectations (e.g. #should, #should_receive, etc.).
|
66
70
|
def expectation(state)
|
67
71
|
@counter.expectations!
|
68
72
|
end
|
69
73
|
|
74
|
+
# Callback for the MSpec :exception event. Increments the
|
75
|
+
# tally of errors and failures.
|
76
|
+
def exception(exception)
|
77
|
+
exception.failure? ? @counter.failures! : @counter.errors!
|
78
|
+
end
|
79
|
+
|
80
|
+
# Callback for the MSpec :after event. Increments the tally
|
81
|
+
# of examples.
|
70
82
|
def after(state)
|
71
83
|
@counter.examples!
|
72
|
-
state.exceptions.each do |msg, exc|
|
73
|
-
state.failure?(exc) ? @counter.failures! : @counter.errors!
|
74
|
-
end
|
75
84
|
end
|
76
85
|
|
77
86
|
def format
|
@@ -1,6 +1,18 @@
|
|
1
1
|
require 'mspec/runner/mspec'
|
2
|
-
|
3
|
-
|
2
|
+
require 'mspec/runner/example'
|
3
|
+
|
4
|
+
# Holds the state of the +describe+ block that is being
|
5
|
+
# evaluated. Every example (i.e. +it+ block) is evaluated
|
6
|
+
# in a context, which may include state set up in <tt>before
|
7
|
+
# :each</tt> or <tt>before :all</tt> blocks.
|
8
|
+
#
|
9
|
+
#--
|
10
|
+
# A note on naming: this is named _ContextState_ rather
|
11
|
+
# than _DescribeState_ because +describe+ is the keyword
|
12
|
+
# in the DSL for refering to the context in which an example
|
13
|
+
# is evaluated, just as +it+ refers to the example itself.
|
14
|
+
#++
|
15
|
+
class ContextState
|
4
16
|
def initialize
|
5
17
|
@start = []
|
6
18
|
@before = []
|
@@ -32,7 +44,7 @@ class RunState
|
|
32
44
|
end
|
33
45
|
|
34
46
|
def it(desc, &block)
|
35
|
-
state =
|
47
|
+
state = ExampleState.new @describe, desc
|
36
48
|
@spec << [desc, block, state] unless state.filtered?
|
37
49
|
end
|
38
50
|
|
@@ -42,8 +54,8 @@ class RunState
|
|
42
54
|
end
|
43
55
|
|
44
56
|
def protect(what, blocks, check=true)
|
45
|
-
return if check and MSpec.pretend_mode?
|
46
|
-
Array(blocks).
|
57
|
+
return false if check and MSpec.pretend_mode?
|
58
|
+
Array(blocks).all? { |block| MSpec.protect what, &block }
|
47
59
|
end
|
48
60
|
|
49
61
|
def process
|
@@ -56,10 +68,11 @@ class RunState
|
|
56
68
|
@spec.each do |desc, spec, state|
|
57
69
|
@state = state
|
58
70
|
MSpec.actions :before, state
|
59
|
-
protect
|
60
|
-
|
61
|
-
|
62
|
-
|
71
|
+
if protect("before :each", @before)
|
72
|
+
protect nil, spec
|
73
|
+
protect "after :each", @after
|
74
|
+
protect "Mock.verify_count", lambda { Mock.verify_count }
|
75
|
+
end
|
63
76
|
protect "Mock.cleanup", lambda { Mock.cleanup }
|
64
77
|
MSpec.actions :after, state
|
65
78
|
@state = nil
|
@@ -69,48 +82,3 @@ class RunState
|
|
69
82
|
end
|
70
83
|
end
|
71
84
|
|
72
|
-
class SpecState
|
73
|
-
def initialize(describe, it)
|
74
|
-
@describe = describe
|
75
|
-
@it = it
|
76
|
-
@unfiltered = nil
|
77
|
-
end
|
78
|
-
|
79
|
-
def describe
|
80
|
-
@describe
|
81
|
-
end
|
82
|
-
|
83
|
-
def it
|
84
|
-
@it
|
85
|
-
end
|
86
|
-
|
87
|
-
def description
|
88
|
-
@description ||= "#{@describe} #{@it}"
|
89
|
-
end
|
90
|
-
|
91
|
-
def exceptions
|
92
|
-
@exceptions ||= []
|
93
|
-
end
|
94
|
-
|
95
|
-
def exception?
|
96
|
-
not exceptions.empty?
|
97
|
-
end
|
98
|
-
|
99
|
-
def unfiltered?
|
100
|
-
unless @unfiltered
|
101
|
-
incl = MSpec.retrieve(:include) || []
|
102
|
-
excl = MSpec.retrieve(:exclude) || []
|
103
|
-
@unfiltered = incl.empty? || incl.any? { |f| f === description }
|
104
|
-
@unfiltered &&= excl.empty? || !excl.any? { |f| f === description }
|
105
|
-
end
|
106
|
-
@unfiltered
|
107
|
-
end
|
108
|
-
|
109
|
-
def filtered?
|
110
|
-
not unfiltered?
|
111
|
-
end
|
112
|
-
|
113
|
-
def failure?(exception)
|
114
|
-
exception.is_a?(ExpectationNotMetError)
|
115
|
-
end
|
116
|
-
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'mspec/runner/mspec'
|
2
|
+
|
3
|
+
# Holds some of the state of the example (i.e. +it+ block) that is
|
4
|
+
# being evaluated. See also +ContextState+.
|
5
|
+
class ExampleState
|
6
|
+
def initialize(describe, it)
|
7
|
+
@describe = describe
|
8
|
+
@it = it
|
9
|
+
@unfiltered = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def describe
|
13
|
+
@describe
|
14
|
+
end
|
15
|
+
|
16
|
+
def it
|
17
|
+
@it
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
@description ||= "#{@describe} #{@it}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def unfiltered?
|
25
|
+
unless @unfiltered
|
26
|
+
incl = MSpec.retrieve(:include) || []
|
27
|
+
excl = MSpec.retrieve(:exclude) || []
|
28
|
+
@unfiltered = incl.empty? || incl.any? { |f| f === description }
|
29
|
+
@unfiltered &&= excl.empty? || !excl.any? { |f| f === description }
|
30
|
+
end
|
31
|
+
@unfiltered
|
32
|
+
end
|
33
|
+
|
34
|
+
def filtered?
|
35
|
+
not unfiltered?
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class ExceptionState
|
2
|
+
attr_reader :description, :describe, :it, :exception
|
3
|
+
|
4
|
+
def initialize(state, location, exception)
|
5
|
+
@exception = exception
|
6
|
+
|
7
|
+
@description = location ? "An exception occurred during: #{location}" : ""
|
8
|
+
if state
|
9
|
+
@description << "\n" unless @description.empty?
|
10
|
+
@description << state.description
|
11
|
+
@describe = state.describe
|
12
|
+
@it = state.it
|
13
|
+
else
|
14
|
+
@describe = @it = ""
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def failure?
|
19
|
+
@exception.is_a? ExpectationNotMetError
|
20
|
+
end
|
21
|
+
|
22
|
+
def message
|
23
|
+
if @exception.message.empty?
|
24
|
+
"<No message>"
|
25
|
+
elsif @exception.class == ExpectationNotMetError
|
26
|
+
@exception.message
|
27
|
+
else
|
28
|
+
"#{@exception.class}: #{@exception.message}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def backtrace
|
33
|
+
begin
|
34
|
+
return @exception.awesome_backtrace.show
|
35
|
+
rescue Exception
|
36
|
+
return @exception.backtrace && @exception.backtrace.join("\n")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -3,10 +3,12 @@ require 'mspec/runner/actions/timer'
|
|
3
3
|
require 'mspec/runner/actions/tally'
|
4
4
|
|
5
5
|
class DottedFormatter
|
6
|
-
attr_reader :timer, :tally
|
6
|
+
attr_reader :exceptions, :timer, :tally
|
7
7
|
|
8
8
|
def initialize(out=nil)
|
9
|
-
@
|
9
|
+
@exception = @failure = false
|
10
|
+
@exceptions = []
|
11
|
+
@count = 0
|
10
12
|
if out.nil?
|
11
13
|
@out = $stdout
|
12
14
|
else
|
@@ -14,68 +16,82 @@ class DottedFormatter
|
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
19
|
+
# Creates the +TimerAction+ and +TallyAction+ instances and
|
20
|
+
# registers them. Registers +self+ for the +:exception+,
|
21
|
+
# +:before+, +:after+, and +:finish+ actions.
|
17
22
|
def register
|
18
|
-
@timer = TimerAction.new
|
19
|
-
@
|
20
|
-
@tally = TallyAction.new
|
21
|
-
@tally.register
|
23
|
+
(@timer = TimerAction.new).register
|
24
|
+
(@tally = TallyAction.new).register
|
22
25
|
@counter = @tally.counter
|
23
26
|
|
24
|
-
MSpec.register :
|
25
|
-
MSpec.register :
|
27
|
+
MSpec.register :exception, self
|
28
|
+
MSpec.register :before, self
|
29
|
+
MSpec.register :after, self
|
30
|
+
MSpec.register :finish, self
|
26
31
|
end
|
27
32
|
|
33
|
+
# Returns true if any exception is raised while running
|
34
|
+
# an example. This flag is reset before each example
|
35
|
+
# is evaluated.
|
36
|
+
def exception?
|
37
|
+
@exception
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns true if all exceptions during the evaluation
|
41
|
+
# of an example are failures rather than errors. See
|
42
|
+
# <tt>ExceptionState#failure</tt>. This flag is reset
|
43
|
+
# before each example is evaluated.
|
44
|
+
def failure?
|
45
|
+
@failure
|
46
|
+
end
|
47
|
+
|
48
|
+
# Callback for the MSpec :before event. Resets the
|
49
|
+
# +#exception?+ and +#failure+ flags.
|
50
|
+
def before(state)
|
51
|
+
@failure = @exception = false
|
52
|
+
end
|
53
|
+
|
54
|
+
# Callback for the MSpec :exception event. Stores the
|
55
|
+
# +ExceptionState+ object to generate the list of backtraces
|
56
|
+
# after all the specs are run. Also updates the internal
|
57
|
+
# +#exception?+ and +#failure?+ flags.
|
58
|
+
def exception(exception)
|
59
|
+
@count += 1
|
60
|
+
@failure = @exception ? @failure && exception.failure? : exception.failure?
|
61
|
+
@exception = true
|
62
|
+
@exceptions << exception
|
63
|
+
end
|
64
|
+
|
65
|
+
# Callback for the MSpec :after event. Prints an indicator
|
66
|
+
# for the result of evaluating this example as follows:
|
67
|
+
# . = No failure or error
|
68
|
+
# F = An ExpectationNotMetError was raised
|
69
|
+
# E = Any exception other than ExpectationNotMetError
|
28
70
|
def after(state)
|
29
|
-
unless
|
71
|
+
unless exception?
|
30
72
|
print "."
|
31
73
|
else
|
32
|
-
|
33
|
-
print failure?(state) ? "F" : "E"
|
74
|
+
print failure? ? "F" : "E"
|
34
75
|
end
|
35
76
|
end
|
36
77
|
|
78
|
+
# Callback for the MSpec :finish event. Prints a description
|
79
|
+
# and backtrace for every exception that occurred while
|
80
|
+
# evaluating the examples.
|
37
81
|
def finish
|
38
82
|
print "\n"
|
39
83
|
count = 0
|
40
|
-
@
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
print message(exc)
|
46
|
-
print "\n"
|
47
|
-
print backtrace(exc)
|
48
|
-
print "\n"
|
49
|
-
end
|
84
|
+
@exceptions.each do |exc|
|
85
|
+
outcome = exc.failure? ? "FAILED" : "ERROR"
|
86
|
+
print "\n#{count += 1})\n#{exc.description} #{outcome}\n"
|
87
|
+
print exc.message, "\n"
|
88
|
+
print exc.backtrace, "\n"
|
50
89
|
end
|
51
90
|
print "\n#{@timer.format}\n\n#{@tally.format}\n"
|
52
91
|
end
|
53
92
|
|
93
|
+
# A convenience method to allow printing to different outputs.
|
54
94
|
def print(*args)
|
55
95
|
@out.print(*args)
|
56
96
|
end
|
57
|
-
|
58
|
-
def message(exc)
|
59
|
-
if exc.message.empty?
|
60
|
-
"<No message>"
|
61
|
-
elsif exc.class == ExpectationNotMetError
|
62
|
-
exc.message
|
63
|
-
else
|
64
|
-
"#{exc.class}: #{exc.message}"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def failure?(state)
|
69
|
-
state.exceptions.all? { |msg, exc| state.failure?(exc) }
|
70
|
-
end
|
71
|
-
private :failure?
|
72
|
-
|
73
|
-
def backtrace(exc)
|
74
|
-
begin
|
75
|
-
return exc.awesome_backtrace.show
|
76
|
-
rescue Exception
|
77
|
-
return exc.backtrace && exc.backtrace.join("\n")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
private :backtrace
|
81
97
|
end
|