rspec 0.9.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +24 -0
- data/EXAMPLES.rd +6 -2
- data/README +9 -9
- data/Rakefile +32 -29
- data/examples/not_yet_implemented_spec.rb +12 -0
- data/examples/shared_behaviours_example.rb +8 -0
- data/examples/stack_spec.rb +1 -0
- data/lib/spec/dsl/behaviour.rb +21 -6
- data/lib/spec/dsl/behaviour_callbacks.rb +44 -26
- data/lib/spec/dsl/behaviour_eval.rb +21 -12
- data/lib/spec/dsl/behaviour_factory.rb +23 -13
- data/lib/spec/dsl/configuration.rb +85 -5
- data/lib/spec/dsl/description.rb +14 -6
- data/lib/spec/dsl/example.rb +2 -2
- data/lib/spec/matchers.rb +5 -5
- data/lib/spec/matchers/be.rb +16 -0
- data/lib/spec/matchers/operator_matcher.rb +21 -1
- data/lib/spec/matchers/raise_error.rb +1 -1
- data/lib/spec/rake/verify_rcov.rb +5 -1
- data/lib/spec/runner.rb +7 -27
- data/lib/spec/runner/behaviour_runner.rb +1 -1
- data/lib/spec/runner/extensions/kernel.rb +20 -0
- data/lib/spec/runner/formatter/base_formatter.rb +6 -1
- data/lib/spec/runner/formatter/base_text_formatter.rb +10 -2
- data/lib/spec/runner/formatter/failing_behaviours_formatter.rb +1 -1
- data/lib/spec/runner/formatter/failing_examples_formatter.rb +1 -1
- data/lib/spec/runner/formatter/html_formatter.rb +63 -31
- data/lib/spec/runner/formatter/progress_bar_formatter.rb +5 -0
- data/lib/spec/runner/formatter/rdoc_formatter.rb +4 -0
- data/lib/spec/runner/formatter/specdoc_formatter.rb +6 -1
- data/lib/spec/runner/option_parser.rb +1 -1
- data/lib/spec/runner/reporter.rb +13 -4
- data/lib/spec/runner/spec_parser.rb +1 -1
- data/lib/spec/version.rb +5 -5
- data/spec/spec/dsl/behaviour_spec.rb +88 -24
- data/spec/spec/dsl/configuration_spec.rb +8 -1
- data/spec/spec/dsl/example_class_spec.rb +1 -1
- data/spec/spec/dsl/example_instance_spec.rb +5 -5
- data/spec/spec/dsl/shared_behaviour_spec.rb +24 -2
- data/spec/spec/matchers/be_spec.rb +20 -2
- data/spec/spec/matchers/operator_matcher_spec.rb +158 -0
- data/spec/spec/runner/command_line_spec.rb +5 -4
- data/spec/spec/runner/drb_command_line_spec.rb +15 -8
- data/spec/spec/runner/formatter/html_formatter_spec.rb +22 -5
- data/spec/spec/runner/formatter/progress_bar_formatter_dry_run_spec.rb +1 -1
- data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +7 -2
- data/spec/spec/runner/formatter/rdoc_formatter_dry_run_spec.rb +1 -1
- data/spec/spec/runner/formatter/rdoc_formatter_spec.rb +6 -1
- data/spec/spec/runner/formatter/specdoc_formatter_dry_run_spec.rb +1 -1
- data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +15 -5
- data/spec/spec/runner/option_parser_spec.rb +5 -0
- data/spec/spec/runner/reporter_spec.rb +23 -5
- data/spec/spec/runner/spec_matcher_spec.rb +1 -1
- data/spec/spec/runner/spec_parser_spec.rb +1 -1
- data/spec/spec_helper.rb +38 -2
- metadata +41 -42
- data/spec/spec/matchers/should_===_spec.rb +0 -38
- data/spec/spec/matchers/should_==_spec.rb +0 -37
- data/spec/spec/matchers/should_=~_spec.rb +0 -36
@@ -6,27 +6,37 @@ module Spec
|
|
6
6
|
|
7
7
|
BEHAVIOUR_CLASSES = {:default => Spec::DSL::Behaviour}
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
# Registers a behaviour class +klass+ with the symbol
|
10
|
+
# +behaviour_type+. For example:
|
11
|
+
#
|
12
|
+
# Spec::DSL::BehaviourFactory.add_behaviour_class(:farm, Spec::Farm::DSL::FarmBehaviour)
|
13
|
+
#
|
14
|
+
# This will cause Kernel#describe from a file living in
|
15
|
+
# <tt>spec/farm</tt> to create behaviour instances of type
|
16
|
+
# Spec::Farm::DSL::FarmBehaviour.
|
17
|
+
def add_behaviour_class(behaviour_type, klass)
|
18
|
+
BEHAVIOUR_CLASSES[behaviour_type] = klass
|
11
19
|
end
|
12
20
|
|
13
|
-
def remove_behaviour_class(
|
14
|
-
BEHAVIOUR_CLASSES.delete(
|
21
|
+
def remove_behaviour_class(behaviour_type)
|
22
|
+
BEHAVIOUR_CLASSES.delete(behaviour_type)
|
15
23
|
end
|
16
24
|
|
17
25
|
def create(*args, &block)
|
18
|
-
return BEHAVIOUR_CLASSES[behaviour_type(*args)].new(*args, &block)
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def behaviour_type(*args)
|
24
26
|
opts = Hash === args.last ? args.last : {}
|
25
|
-
|
27
|
+
if opts[:shared]
|
28
|
+
behaviour_type = :default
|
29
|
+
elsif opts[:behaviour_type]
|
30
|
+
behaviour_type = opts[:behaviour_type]
|
31
|
+
elsif opts[:spec_path] =~ /spec\/(#{BEHAVIOUR_CLASSES.keys.join('|')})/
|
32
|
+
behaviour_type = $1.to_sym
|
33
|
+
else
|
34
|
+
behaviour_type = :default
|
35
|
+
end
|
36
|
+
return BEHAVIOUR_CLASSES[behaviour_type].new(*args, &block)
|
26
37
|
end
|
27
|
-
|
38
|
+
|
28
39
|
end
|
29
|
-
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
@@ -2,6 +2,27 @@ module Spec
|
|
2
2
|
module DSL
|
3
3
|
class Configuration
|
4
4
|
|
5
|
+
# Chooses what mock framework to use. Example:
|
6
|
+
#
|
7
|
+
# Spec::Runner.configure do |config|
|
8
|
+
# config.mock_with :rspec # or :mocha, or :flexmock
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# To use any other mock framework, you'll have to provide
|
12
|
+
# your own adapter. This is simply a module that responds to
|
13
|
+
# setup_mocks_for_rspec, verify_mocks_for_rspec and teardown_mocks_for_rspec.
|
14
|
+
# These are your hooks into the lifecycle of a given example. RSpec will
|
15
|
+
# call setup_mocks_for_rspec before running anything else in each Example.
|
16
|
+
# After executing the #after methods, RSpec will then call verify_mocks_for_rspec
|
17
|
+
# and teardown_mocks_for_rspec (this is guaranteed to run even if there are
|
18
|
+
# failures in verify_mocks_for_rspec).
|
19
|
+
#
|
20
|
+
# Once you've defined this module, you can pass that to mock_with:
|
21
|
+
#
|
22
|
+
# Spec::Runner.configure do |config|
|
23
|
+
# config.mock_with MyMockFrameworkAdapter
|
24
|
+
# end
|
25
|
+
#
|
5
26
|
def mock_with(mock_framework)
|
6
27
|
@mock_framework = case mock_framework
|
7
28
|
when Symbol
|
@@ -11,23 +32,82 @@ module Spec
|
|
11
32
|
end
|
12
33
|
end
|
13
34
|
|
14
|
-
def mock_framework
|
35
|
+
def mock_framework # :nodoc:
|
15
36
|
@mock_framework ||= mock_framework_path("rspec")
|
16
37
|
end
|
17
38
|
|
18
|
-
|
19
|
-
|
20
|
-
|
39
|
+
# Declares modules to be included in all behaviours (<tt>describe</tt> blocks).
|
40
|
+
#
|
41
|
+
# config.include(My::Bottle, My::Cup)
|
42
|
+
#
|
43
|
+
# If you want to restrict the inclusion to a subset of all the behaviours then
|
44
|
+
# specify this in a Hash as the last argument:
|
45
|
+
#
|
46
|
+
# config.include(My::Pony, My::Horse, :behaviour_type => :farm)
|
47
|
+
#
|
48
|
+
# Only behaviours that have that type will get the modules included:
|
49
|
+
#
|
50
|
+
# describe "Downtown", :behaviour_type => :city do
|
51
|
+
# # Will *not* get My::Pony and My::Horse included
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# describe "Old Mac Donald", :behaviour_type => :farm do
|
55
|
+
# # *Will* get My::Pony and My::Horse included
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
def include(*args)
|
59
|
+
included_modules.push(*args)
|
21
60
|
end
|
22
61
|
|
23
|
-
def included_modules
|
62
|
+
def included_modules # :nodoc:
|
24
63
|
@included_modules ||= []
|
25
64
|
end
|
26
65
|
|
66
|
+
# Defines global predicate matchers. Example:
|
67
|
+
#
|
68
|
+
# config.predicate_matchers[:swim] = :can_swim?
|
69
|
+
#
|
70
|
+
# This makes it possible to say:
|
71
|
+
#
|
72
|
+
# person.should swim # passes if person.should_swim? returns true
|
73
|
+
#
|
27
74
|
def predicate_matchers
|
28
75
|
@predicate_matchers ||= {}
|
29
76
|
end
|
30
77
|
|
78
|
+
# Prepends a global <tt>before</tt> block to all behaviours.
|
79
|
+
# See #append_before for filtering semantics.
|
80
|
+
def prepend_before(*args, &proc)
|
81
|
+
Behaviour.prepend_before(*args, &proc)
|
82
|
+
end
|
83
|
+
# Appends a global <tt>before</tt> block to all behaviours.
|
84
|
+
#
|
85
|
+
# If you want to restrict the block to a subset of all the behaviours then
|
86
|
+
# specify this in a Hash as the last argument:
|
87
|
+
#
|
88
|
+
# config.prepend_before(:all, :behaviour_type => :farm)
|
89
|
+
#
|
90
|
+
# or
|
91
|
+
#
|
92
|
+
# config.prepend_before(:behaviour_type => :farm)
|
93
|
+
#
|
94
|
+
def append_before(*args, &proc)
|
95
|
+
Behaviour.append_before(*args, &proc)
|
96
|
+
end
|
97
|
+
alias_method :before, :append_before
|
98
|
+
|
99
|
+
# Prepends a global <tt>after</tt> block to all behaviours.
|
100
|
+
# See #append_before for filtering semantics.
|
101
|
+
def prepend_after(*args, &proc)
|
102
|
+
Behaviour.prepend_after(*args, &proc)
|
103
|
+
end
|
104
|
+
alias_method :after, :prepend_after
|
105
|
+
# Appends a global <tt>after</tt> block to all behaviours.
|
106
|
+
# See #append_before for filtering semantics.
|
107
|
+
def append_after(*args, &proc)
|
108
|
+
Behaviour.append_after(*args, &proc)
|
109
|
+
end
|
110
|
+
|
31
111
|
private
|
32
112
|
|
33
113
|
def mock_framework_path(framework_name)
|
data/lib/spec/dsl/description.rb
CHANGED
@@ -1,17 +1,25 @@
|
|
1
1
|
module Spec
|
2
2
|
module DSL
|
3
3
|
class Description
|
4
|
+
module ClassMethods
|
5
|
+
def generate_description(*args)
|
6
|
+
description = args.shift.to_s
|
7
|
+
unless args.empty?
|
8
|
+
suffix = args.shift.to_s
|
9
|
+
description << " " unless suffix =~ /^\s|\.|#/
|
10
|
+
description << suffix
|
11
|
+
end
|
12
|
+
description
|
13
|
+
end
|
14
|
+
end
|
15
|
+
extend ClassMethods
|
16
|
+
|
4
17
|
attr_reader :description, :described_type
|
5
18
|
|
6
19
|
def initialize(*args)
|
7
20
|
args, @options = args_and_options(*args)
|
8
21
|
@described_type = args.first unless args.first.is_a?(String)
|
9
|
-
@description =
|
10
|
-
unless args.empty?
|
11
|
-
suffix = args.shift.to_s
|
12
|
-
@description << " " unless suffix =~ /^\s|\.|#/
|
13
|
-
@description << suffix
|
14
|
-
end
|
22
|
+
@description = self.class.generate_description(*args)
|
15
23
|
end
|
16
24
|
|
17
25
|
def [](key)
|
data/lib/spec/dsl/example.rb
CHANGED
@@ -26,7 +26,7 @@ module Spec
|
|
26
26
|
end
|
27
27
|
|
28
28
|
ExampleShouldRaiseHandler.new(@from, @options).handle(errors)
|
29
|
-
reporter.example_finished(description, errors.first, location) if reporter
|
29
|
+
reporter.example_finished(description, errors.first, location, @example_block.nil?) if reporter
|
30
30
|
end
|
31
31
|
|
32
32
|
def matches?(matcher, specified_examples)
|
@@ -70,7 +70,7 @@ module Spec
|
|
70
70
|
|
71
71
|
def run_example(execution_context, errors)
|
72
72
|
begin
|
73
|
-
execution_context.instance_eval(&@example_block)
|
73
|
+
execution_context.instance_eval(&@example_block) if @example_block
|
74
74
|
return true
|
75
75
|
rescue Exception => e
|
76
76
|
@failed = true
|
data/lib/spec/matchers.rb
CHANGED
@@ -86,15 +86,15 @@ module Spec
|
|
86
86
|
# def initialize(expected)
|
87
87
|
# @expected = expected
|
88
88
|
# end
|
89
|
-
# def matches?(
|
90
|
-
# @
|
91
|
-
#
|
89
|
+
# def matches?(target)
|
90
|
+
# @target = target
|
91
|
+
# @target.current_zone.eql?(Zone.new(@expected))
|
92
92
|
# end
|
93
93
|
# def failure_message
|
94
|
-
# "expected #{@
|
94
|
+
# "expected #{@target.inspect} to be in Zone #{@expected}"
|
95
95
|
# end
|
96
96
|
# def negative_failure_message
|
97
|
-
# "expected #{@
|
97
|
+
# "expected #{@target.inspect} not to be in Zone #{@expected}"
|
98
98
|
# end
|
99
99
|
# end
|
100
100
|
#
|
data/lib/spec/matchers/be.rb
CHANGED
@@ -57,8 +57,24 @@ module Spec
|
|
57
57
|
return @actual <= @expected if @less_than_or_equal
|
58
58
|
return @actual >= @expected if @greater_than_or_equal
|
59
59
|
return @actual > @expected if @greater_than
|
60
|
+
return @actual == @expected if @double_equal
|
61
|
+
return @actual === @expected if @triple_equal
|
60
62
|
return @actual.equal?(@expected)
|
61
63
|
end
|
64
|
+
|
65
|
+
def ==(expected)
|
66
|
+
@double_equal = true
|
67
|
+
@comparison = "== "
|
68
|
+
@expected = expected
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def ===(expected)
|
73
|
+
@triple_equal = true
|
74
|
+
@comparison = "=== "
|
75
|
+
@expected = expected
|
76
|
+
self
|
77
|
+
end
|
62
78
|
|
63
79
|
def <(expected)
|
64
80
|
@less_than = true
|
@@ -21,6 +21,26 @@ module Spec
|
|
21
21
|
__delegate_method_missing_to_target("=~", expected)
|
22
22
|
end
|
23
23
|
|
24
|
+
def >(expected)
|
25
|
+
@expected = expected
|
26
|
+
__delegate_method_missing_to_target(">", expected)
|
27
|
+
end
|
28
|
+
|
29
|
+
def >=(expected)
|
30
|
+
@expected = expected
|
31
|
+
__delegate_method_missing_to_target(">=", expected)
|
32
|
+
end
|
33
|
+
|
34
|
+
def <(expected)
|
35
|
+
@expected = expected
|
36
|
+
__delegate_method_missing_to_target("<", expected)
|
37
|
+
end
|
38
|
+
|
39
|
+
def <=(expected)
|
40
|
+
@expected = expected
|
41
|
+
__delegate_method_missing_to_target("<=", expected)
|
42
|
+
end
|
43
|
+
|
24
44
|
def fail_with_message(message)
|
25
45
|
Spec::Expectations.fail_with(message, @expected, @target)
|
26
46
|
end
|
@@ -33,7 +53,7 @@ module Spec
|
|
33
53
|
::Spec::Matchers.generated_description = "should #{operator} #{expected.inspect}"
|
34
54
|
return if @target.send(operator, expected)
|
35
55
|
return fail_with_message("expected #{expected.inspect}, got #{@target.inspect} (using #{operator})") if ['==','==='].include?(operator)
|
36
|
-
return fail_with_message("expected
|
56
|
+
return fail_with_message("expected #{operator} #{expected.inspect}, got #{@target.inspect}")
|
37
57
|
end
|
38
58
|
|
39
59
|
end
|
@@ -19,10 +19,14 @@ module RCov
|
|
19
19
|
# exception.
|
20
20
|
attr_accessor :threshold
|
21
21
|
|
22
|
+
# Require the threshold value be met exactly. This is the default.
|
23
|
+
attr_accessor :require_exact_threshold
|
24
|
+
|
22
25
|
def initialize(name=:verify_rcov)
|
23
26
|
@name = name
|
24
27
|
@index_html = 'coverage/index.html'
|
25
28
|
@verbose = true
|
29
|
+
@require_exact_threshold = true
|
26
30
|
yield self if block_given?
|
27
31
|
raise "Threshold must be set" if @threshold.nil?
|
28
32
|
define
|
@@ -41,7 +45,7 @@ module RCov
|
|
41
45
|
end
|
42
46
|
puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose
|
43
47
|
raise "Coverage must be at least #{threshold}% but was #{total_coverage}%" if total_coverage < threshold
|
44
|
-
raise "Coverage has increased above the threshold of #{threshold}% to #{total_coverage}%. You should update your threshold value." if total_coverage > threshold
|
48
|
+
raise "Coverage has increased above the threshold of #{threshold}% to #{total_coverage}%. You should update your threshold value." if (total_coverage > threshold) and require_exact_threshold
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
data/lib/spec/runner.rb
CHANGED
@@ -147,38 +147,18 @@ module Spec
|
|
147
147
|
end
|
148
148
|
|
149
149
|
# Use this to configure various configurable aspects of
|
150
|
-
# RSpec
|
151
|
-
# RSpec, mocha and flexmock, you can do this:
|
150
|
+
# RSpec:
|
152
151
|
#
|
153
|
-
# Spec::Runner.configure do |
|
154
|
-
#
|
152
|
+
# Spec::Runner.configure do |configuration|
|
153
|
+
# # Configure RSpec here
|
155
154
|
# end
|
156
155
|
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
# These are your hooks into the lifecycle of a given example. RSpec will
|
161
|
-
# call setup_mocks_for_rspec before running anything else in each Example.
|
162
|
-
# After executing the #after methods, RSpec will then call verify_mocks_for_rspec
|
163
|
-
# and teardown_mocks_for_rspec (this is guaranteed to run even if there are
|
164
|
-
# failures in verify_mocks_for_rspec).
|
156
|
+
# The yielded <tt>configuration</tt> object is a
|
157
|
+
# Spec::DSL::Configuration instance. See its RDoc
|
158
|
+
# for details about what you can do with it.
|
165
159
|
#
|
166
|
-
# Once you've defined this module, you can pass that to mock_with:
|
167
|
-
#
|
168
|
-
# Spec::Runner.configure do |config|
|
169
|
-
# config.mock_with MyMockFrameworkAdapter
|
170
|
-
# end
|
171
|
-
#
|
172
|
-
# You can also configure the following items:
|
173
|
-
#
|
174
|
-
# # include SomeModule in every Behaviour
|
175
|
-
# config.include SomeModule
|
176
|
-
#
|
177
|
-
# # generate a do_something predicate_matcher for every Behaviour
|
178
|
-
# # - See Spec::DSL::Behaviour#predicate_matchers
|
179
|
-
# config.predicate_matchers[:does_something?] = :do_something
|
180
160
|
def configure
|
181
|
-
yield configuration
|
161
|
+
yield configuration if @configuration.nil?
|
182
162
|
end
|
183
163
|
end
|
184
164
|
end
|
@@ -1,6 +1,26 @@
|
|
1
1
|
module Kernel
|
2
|
+
# Creates and registers an instance of a Spec::DSL::Behaviour (or a subclass).
|
3
|
+
# The instantiated behaviour class depends on the directory of the file
|
4
|
+
# calling this method. For example, Spec::Rails will use different
|
5
|
+
# classes for specs living in <tt>spec/models</tt>, <tt>spec/helpers</tt>,
|
6
|
+
# <tt>spec/views</tt> and <tt>spec/controllers</tt>.
|
7
|
+
#
|
8
|
+
# It is also possible to override autodiscovery of the behaviour class
|
9
|
+
# with an options Hash as the last argument:
|
10
|
+
#
|
11
|
+
# describe "name", :behaviour_type => :something_special do ...
|
12
|
+
#
|
13
|
+
# The reason for using different behaviour classes is to have
|
14
|
+
# different matcher methods available from within the <tt>describe</tt>
|
15
|
+
# block.
|
16
|
+
#
|
17
|
+
# See Spec::DSL::BehaviourFactory#add_behaviour_class for details about
|
18
|
+
# how to register special Spec::DSL::Behaviour implementations.
|
19
|
+
#
|
2
20
|
def describe(*args, &block)
|
3
21
|
raise ArgumentError if args.empty?
|
22
|
+
args << {} unless Hash === args.last
|
23
|
+
args.last[:spec_path] = caller(0)[1]
|
4
24
|
register_behaviour(Spec::DSL::BehaviourFactory.create(*args, &block))
|
5
25
|
end
|
6
26
|
alias :context :describe
|
@@ -40,6 +40,11 @@ module Spec
|
|
40
40
|
# (starting at 1) and +failure+ is the associated Failure object.
|
41
41
|
def example_failed(name, counter, failure)
|
42
42
|
end
|
43
|
+
|
44
|
+
# This method is invoked when an example is not yet implemented (i.e. has not been provided a block).
|
45
|
+
# +name+ is the name of the example.
|
46
|
+
def example_not_implemented(name)
|
47
|
+
end
|
43
48
|
|
44
49
|
# This method is invoked after all of the examples have executed. The next method
|
45
50
|
# to be invoked after this one is #dump_failure (once for each failed example),
|
@@ -54,7 +59,7 @@ module Spec
|
|
54
59
|
end
|
55
60
|
|
56
61
|
# This method is invoked at the very end.
|
57
|
-
def dump_summary(duration, example_count, failure_count)
|
62
|
+
def dump_summary(duration, example_count, failure_count, not_implemented_count)
|
58
63
|
end
|
59
64
|
|
60
65
|
end
|
@@ -46,14 +46,21 @@ module Spec
|
|
46
46
|
@output.flush
|
47
47
|
end
|
48
48
|
|
49
|
-
def dump_summary(duration, example_count, failure_count)
|
49
|
+
def dump_summary(duration, example_count, failure_count, not_implemented_count)
|
50
50
|
return if @dry_run
|
51
51
|
@output.puts
|
52
52
|
@output.puts "Finished in #{duration} seconds"
|
53
53
|
@output.puts
|
54
|
+
|
54
55
|
summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
|
56
|
+
summary << ", #{not_implemented_count} not implemented" if not_implemented_count > 0
|
57
|
+
|
55
58
|
if failure_count == 0
|
56
|
-
|
59
|
+
if not_implemented_count > 0
|
60
|
+
@output.puts yellow(summary)
|
61
|
+
else
|
62
|
+
@output.puts green(summary)
|
63
|
+
end
|
57
64
|
else
|
58
65
|
@output.puts red(summary)
|
59
66
|
end
|
@@ -87,6 +94,7 @@ module Spec
|
|
87
94
|
def red(text); colour(text, "\e[31m"); end
|
88
95
|
def green(text); colour(text, "\e[32m"); end
|
89
96
|
def magenta(text); colour(text, "\e[35m"); end
|
97
|
+
def yellow(text); colour(text, "\e[33m"); end
|
90
98
|
|
91
99
|
end
|
92
100
|
end
|