rsanheim-micronaut 0.1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +45 -0
- data/README +17 -0
- data/RSPEC-LICENSE +23 -0
- data/Rakefile +83 -0
- data/bin/micronaut +4 -0
- data/examples/example_helper.rb +36 -0
- data/examples/lib/micronaut/behaviour_example.rb +188 -0
- data/examples/lib/micronaut/configuration_example.rb +70 -0
- data/examples/lib/micronaut/example_example.rb +46 -0
- data/examples/lib/micronaut/expectations/extensions/object_example.rb +72 -0
- data/examples/lib/micronaut/expectations/fail_with_example.rb +17 -0
- data/examples/lib/micronaut/expectations/wrap_expectation_example.rb +31 -0
- data/examples/lib/micronaut/formatters/base_formatter_example.rb +107 -0
- data/examples/lib/micronaut/formatters/documentation_formatter_example.rb +5 -0
- data/examples/lib/micronaut/formatters/progress_formatter_example.rb +74 -0
- data/examples/lib/micronaut/kernel_extensions_example.rb +13 -0
- data/examples/lib/micronaut/matchers/be_close_example.rb +52 -0
- data/examples/lib/micronaut/matchers/be_example.rb +298 -0
- data/examples/lib/micronaut/matchers/change_example.rb +360 -0
- data/examples/lib/micronaut/matchers/description_generation_example.rb +175 -0
- data/examples/lib/micronaut/matchers/eql_example.rb +35 -0
- data/examples/lib/micronaut/matchers/equal_example.rb +35 -0
- data/examples/lib/micronaut/matchers/handler_example.rb +153 -0
- data/examples/lib/micronaut/matchers/has_example.rb +71 -0
- data/examples/lib/micronaut/matchers/have_example.rb +575 -0
- data/examples/lib/micronaut/matchers/include_example.rb +103 -0
- data/examples/lib/micronaut/matchers/match_example.rb +43 -0
- data/examples/lib/micronaut/matchers/matcher_methods_example.rb +66 -0
- data/examples/lib/micronaut/matchers/operator_matcher_example.rb +189 -0
- data/examples/lib/micronaut/matchers/raise_error_example.rb +346 -0
- data/examples/lib/micronaut/matchers/respond_to_example.rb +54 -0
- data/examples/lib/micronaut/matchers/satisfy_example.rb +36 -0
- data/examples/lib/micronaut/matchers/simple_matcher_example.rb +93 -0
- data/examples/lib/micronaut/matchers/throw_symbol_example.rb +96 -0
- data/examples/lib/micronaut/runner_example.rb +5 -0
- data/examples/lib/micronaut/runner_options_example.rb +5 -0
- data/examples/lib/micronaut/world_example.rb +102 -0
- data/examples/lib/micronaut_example.rb +23 -0
- data/examples/resources/example_classes.rb +67 -0
- data/lib/autotest/discover.rb +3 -0
- data/lib/autotest/micronaut.rb +47 -0
- data/lib/micronaut/behaviour.rb +211 -0
- data/lib/micronaut/configuration.rb +133 -0
- data/lib/micronaut/example.rb +28 -0
- data/lib/micronaut/expectations/extensions/object.rb +62 -0
- data/lib/micronaut/expectations/extensions/string_and_symbol.rb +19 -0
- data/lib/micronaut/expectations/handler.rb +52 -0
- data/lib/micronaut/expectations/wrap_expectation.rb +57 -0
- data/lib/micronaut/expectations.rb +46 -0
- data/lib/micronaut/formatters/base_formatter.rb +82 -0
- data/lib/micronaut/formatters/base_text_formatter.rb +148 -0
- data/lib/micronaut/formatters/documentation_formatter.rb +62 -0
- data/lib/micronaut/formatters/progress_formatter.rb +36 -0
- data/lib/micronaut/formatters.rb +12 -0
- data/lib/micronaut/kernel_extensions.rb +11 -0
- data/lib/micronaut/matchers/be.rb +204 -0
- data/lib/micronaut/matchers/be_close.rb +22 -0
- data/lib/micronaut/matchers/change.rb +148 -0
- data/lib/micronaut/matchers/eql.rb +26 -0
- data/lib/micronaut/matchers/equal.rb +26 -0
- data/lib/micronaut/matchers/generated_descriptions.rb +36 -0
- data/lib/micronaut/matchers/has.rb +19 -0
- data/lib/micronaut/matchers/have.rb +153 -0
- data/lib/micronaut/matchers/include.rb +80 -0
- data/lib/micronaut/matchers/match.rb +22 -0
- data/lib/micronaut/matchers/method_missing.rb +9 -0
- data/lib/micronaut/matchers/operator_matcher.rb +50 -0
- data/lib/micronaut/matchers/raise_error.rb +128 -0
- data/lib/micronaut/matchers/respond_to.rb +50 -0
- data/lib/micronaut/matchers/satisfy.rb +50 -0
- data/lib/micronaut/matchers/simple_matcher.rb +135 -0
- data/lib/micronaut/matchers/throw_symbol.rb +108 -0
- data/lib/micronaut/matchers.rb +148 -0
- data/lib/micronaut/mocking/with_absolutely_nothing.rb +11 -0
- data/lib/micronaut/mocking/with_mocha.rb +13 -0
- data/lib/micronaut/mocking/with_rr.rb +24 -0
- data/lib/micronaut/mocking.rb +7 -0
- data/lib/micronaut/runner.rb +57 -0
- data/lib/micronaut/runner_options.rb +33 -0
- data/lib/micronaut/world.rb +75 -0
- data/lib/micronaut.rb +37 -0
- metadata +149 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
module Micronaut
|
2
|
+
|
3
|
+
class Configuration
|
4
|
+
# Destired mocking framework - expects the symbol name of the framework
|
5
|
+
# Currently supported: :mocha, :rr, or nothing (the default if this is not set at all)
|
6
|
+
attr_reader :mock_framework
|
7
|
+
|
8
|
+
# Array of regular expressions to scrub from backtrace
|
9
|
+
attr_reader :backtrace_clean_patterns
|
10
|
+
|
11
|
+
# An array of arrays to store before and after blocks
|
12
|
+
attr_reader :before_and_afters
|
13
|
+
|
14
|
+
# Filters allow you to exclude or include certain examples from running based on options you pass in
|
15
|
+
attr_reader :filters
|
16
|
+
|
17
|
+
# When this is true, if you have filters enabled and no examples match, all examples are added and run - defaults to true
|
18
|
+
attr_accessor :run_all_when_everything_filtered
|
19
|
+
|
20
|
+
# Enable profiling of the top 10 slowest examples - defaults to false
|
21
|
+
attr_accessor :profile_examples
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@backtrace_clean_patterns = [/\/lib\/ruby\//, /bin\/rcov:/, /vendor\/rails/]
|
25
|
+
@profile_examples = false
|
26
|
+
@run_all_when_everything_filtered = true
|
27
|
+
@filters = []
|
28
|
+
@before_and_afters = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def cleaned_from_backtrace?(line)
|
32
|
+
return true if line.starts_with?(::Micronaut::InstallDirectory)
|
33
|
+
|
34
|
+
@backtrace_clean_patterns.any? do |pattern|
|
35
|
+
line =~ pattern
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def mock_with(make_a_mockery_with=nil)
|
40
|
+
@mock_framework = case make_a_mockery_with
|
41
|
+
when :mocha
|
42
|
+
require 'micronaut/mocking/with_mocha'
|
43
|
+
Micronaut::Mocking::WithMocha
|
44
|
+
when :rr
|
45
|
+
require 'micronaut/mocking/with_rr'
|
46
|
+
Micronaut::Mocking::WithRR
|
47
|
+
else
|
48
|
+
Micronaut::Mocking::WithAbsolutelyNothing
|
49
|
+
end
|
50
|
+
|
51
|
+
Micronaut::Behaviour.send(:include, @mock_framework)
|
52
|
+
end
|
53
|
+
|
54
|
+
def autorun!
|
55
|
+
Micronaut::Runner.autorun unless Micronaut::Runner.installed_at_exit?
|
56
|
+
end
|
57
|
+
|
58
|
+
def options=(new_options)
|
59
|
+
raise ArguementError unless new_options.is_a?(Micronaut::RunnerOptions)
|
60
|
+
@options = new_options
|
61
|
+
end
|
62
|
+
|
63
|
+
def options
|
64
|
+
# Do we need this?
|
65
|
+
@options ||= Micronaut::RunnerOptions.new(:color => true, :formatter => :documentation)
|
66
|
+
end
|
67
|
+
|
68
|
+
def extra_modules
|
69
|
+
@extra_modules ||= []
|
70
|
+
end
|
71
|
+
|
72
|
+
def include(module_to_include, options={})
|
73
|
+
extra_modules << [:include, module_to_include, options]
|
74
|
+
end
|
75
|
+
|
76
|
+
def extend(module_to_extend, options={})
|
77
|
+
extra_modules << [:extend, module_to_extend, options]
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_modules(group)
|
81
|
+
extra_modules.select do |include_or_extend, mod, options|
|
82
|
+
options.all? do |key, value|
|
83
|
+
case value
|
84
|
+
when Hash
|
85
|
+
value.all? { |k, v| group.metadata[key][k] == v }
|
86
|
+
when Regexp
|
87
|
+
group.metadata[key] =~ value
|
88
|
+
when Proc
|
89
|
+
value.call(group.metadata[key]) rescue false
|
90
|
+
else
|
91
|
+
group.metadata[key] == value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def add_filter(options={})
|
98
|
+
filters << options
|
99
|
+
end
|
100
|
+
|
101
|
+
def run_all_when_everything_filtered?
|
102
|
+
@run_all_when_everything_filtered
|
103
|
+
end
|
104
|
+
|
105
|
+
def before(type=:each, options={}, &block)
|
106
|
+
before_and_afters << [:before, :each, options, block]
|
107
|
+
end
|
108
|
+
|
109
|
+
def after(type=:each, options={}, &block)
|
110
|
+
before_and_afters << [:after, :each, options, block]
|
111
|
+
end
|
112
|
+
|
113
|
+
def find_before_or_after(desired_type, desired_each_or_all, group)
|
114
|
+
before_and_afters.select do |type, each_or_all, options, block|
|
115
|
+
type == desired_type && each_or_all == desired_each_or_all &&
|
116
|
+
options.all? do |key, value|
|
117
|
+
case value
|
118
|
+
when Hash
|
119
|
+
value.all? { |k, v| group.metadata[key][k] == v }
|
120
|
+
when Regexp
|
121
|
+
group.metadata[key] =~ value
|
122
|
+
when Proc
|
123
|
+
value.call(group.metadata[key]) rescue false
|
124
|
+
else
|
125
|
+
group.metadata[key] == value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end.map { |type, each_or_all, options, block| block }
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Micronaut
|
2
|
+
|
3
|
+
class Example
|
4
|
+
|
5
|
+
attr_reader :behaviour, :description, :options, :example_block
|
6
|
+
|
7
|
+
def initialize(behaviour, desc, options, example_block=nil)
|
8
|
+
@behaviour, @description, @options, @example_block = behaviour, desc, options, example_block
|
9
|
+
end
|
10
|
+
|
11
|
+
def metadata
|
12
|
+
@metadata ||= behaviour.metadata.dup
|
13
|
+
@metadata[:description] = description
|
14
|
+
@metadata[:options].update(options)
|
15
|
+
@metadata
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
"#{behaviour.name} - #{description}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
inspect
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Expectations
|
3
|
+
# rspec adds #should and #should_not to every Object (and, implicitly, every Class).
|
4
|
+
module ObjectExpectations
|
5
|
+
# :call-seq:
|
6
|
+
# should(matcher)
|
7
|
+
# should == expected
|
8
|
+
# should === expected
|
9
|
+
# should =~ expected
|
10
|
+
#
|
11
|
+
# receiver.should(matcher)
|
12
|
+
# => Passes if matcher.matches?(receiver)
|
13
|
+
#
|
14
|
+
# receiver.should == expected #any value
|
15
|
+
# => Passes if (receiver == expected)
|
16
|
+
#
|
17
|
+
# receiver.should === expected #any value
|
18
|
+
# => Passes if (receiver === expected)
|
19
|
+
#
|
20
|
+
# receiver.should =~ regexp
|
21
|
+
# => Passes if (receiver =~ regexp)
|
22
|
+
#
|
23
|
+
# See Micronaut::Matchers for more information about matchers
|
24
|
+
#
|
25
|
+
# == Warning
|
26
|
+
#
|
27
|
+
# NOTE that this does NOT support receiver.should != expected.
|
28
|
+
# Instead, use receiver.should_not == expected
|
29
|
+
def should(matcher=nil, &block)
|
30
|
+
ExpectationMatcherHandler.handle_matcher(self, matcher, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# :call-seq:
|
34
|
+
# should_not(matcher)
|
35
|
+
# should_not == expected
|
36
|
+
# should_not === expected
|
37
|
+
# should_not =~ expected
|
38
|
+
#
|
39
|
+
# receiver.should_not(matcher)
|
40
|
+
# => Passes unless matcher.matches?(receiver)
|
41
|
+
#
|
42
|
+
# receiver.should_not == expected
|
43
|
+
# => Passes unless (receiver == expected)
|
44
|
+
#
|
45
|
+
# receiver.should_not === expected
|
46
|
+
# => Passes unless (receiver === expected)
|
47
|
+
#
|
48
|
+
# receiver.should_not =~ regexp
|
49
|
+
# => Passes unless (receiver =~ regexp)
|
50
|
+
#
|
51
|
+
# See Micronaut::Matchers for more information about matchers
|
52
|
+
def should_not(matcher=nil, &block)
|
53
|
+
NegativeExpectationMatcherHandler.handle_matcher(self, matcher, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Object
|
61
|
+
include Micronaut::Expectations::ObjectExpectations
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Expectations
|
3
|
+
module StringHelpers
|
4
|
+
|
5
|
+
def starts_with?(prefix)
|
6
|
+
to_s[0..(prefix.to_s.length - 1)] == prefix.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class String
|
14
|
+
include Micronaut::Expectations::StringHelpers
|
15
|
+
end
|
16
|
+
|
17
|
+
class Symbol
|
18
|
+
include Micronaut::Expectations::StringHelpers
|
19
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Expectations
|
3
|
+
class InvalidMatcherError < ArgumentError; end
|
4
|
+
|
5
|
+
class ExpectationMatcherHandler
|
6
|
+
|
7
|
+
def self.handle_matcher(actual, matcher, &block)
|
8
|
+
::Micronaut::Matchers.last_should = "should"
|
9
|
+
return Micronaut::Matchers::PositiveOperatorMatcher.new(actual) if matcher.nil?
|
10
|
+
|
11
|
+
unless matcher.respond_to?(:matches?)
|
12
|
+
raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
|
13
|
+
end
|
14
|
+
|
15
|
+
match = matcher.matches?(actual, &block)
|
16
|
+
::Micronaut::Matchers.last_matcher = matcher
|
17
|
+
Micronaut::Expectations.fail_with(matcher.failure_message) unless match
|
18
|
+
match
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class NegativeExpectationMatcherHandler
|
24
|
+
|
25
|
+
def self.handle_matcher(actual, matcher, &block)
|
26
|
+
::Micronaut::Matchers.last_should = "should not"
|
27
|
+
return Micronaut::Matchers::NegativeOperatorMatcher.new(actual) if matcher.nil?
|
28
|
+
|
29
|
+
unless matcher.respond_to?(:matches?)
|
30
|
+
raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
|
31
|
+
end
|
32
|
+
|
33
|
+
unless matcher.respond_to?(:negative_failure_message)
|
34
|
+
Micronaut::Expectations.fail_with(
|
35
|
+
<<-EOF
|
36
|
+
Matcher does not support should_not.
|
37
|
+
See Micronaut::Matchers for more information
|
38
|
+
about matchers.
|
39
|
+
EOF
|
40
|
+
)
|
41
|
+
end
|
42
|
+
match = matcher.matches?(actual, &block)
|
43
|
+
::Micronaut::Matchers.last_matcher = matcher
|
44
|
+
Micronaut::Expectations.fail_with(matcher.negative_failure_message) if match
|
45
|
+
match
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Matchers
|
3
|
+
|
4
|
+
# wraps an expectation in a block that will return true if the
|
5
|
+
# expectation passes and false if it fails (without bubbling up
|
6
|
+
# the failure).
|
7
|
+
#
|
8
|
+
# This is intended to be used in the context of a simple matcher,
|
9
|
+
# and is especially useful for wrapping multiple expectations or
|
10
|
+
# one or more assertions from test/unit extensions when running
|
11
|
+
# with test/unit.
|
12
|
+
#
|
13
|
+
# == Examples
|
14
|
+
#
|
15
|
+
# def eat_cheese(cheese)
|
16
|
+
# simple_matcher do |mouse, matcher|
|
17
|
+
# matcher.negative_failure_message = "expected #{mouse} not to eat cheese"
|
18
|
+
# wrap_expectation do |matcher|
|
19
|
+
# assert_eats_cheese(mouse)
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# describe Mouse do
|
25
|
+
# it "eats cheese" do
|
26
|
+
# Mouse.new.should eat_cheese
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# You might be wondering "why would I do this if I could just say"
|
31
|
+
# assert_eats_cheese?", a fair question, indeed. You might prefer
|
32
|
+
# to replace the word assert with something more aligned with the
|
33
|
+
# rest of your code examples. You are using rspec, after all.
|
34
|
+
#
|
35
|
+
# The other benefit you get is that you can use the negative version
|
36
|
+
# of the matcher:
|
37
|
+
#
|
38
|
+
# describe Cat do
|
39
|
+
# it "does not eat cheese" do
|
40
|
+
# Cat.new.should_not eat_cheese
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# So in the event there is no assert_does_not_eat_cheese available,
|
45
|
+
# you're all set!
|
46
|
+
def wrap_expectation(matcher, &block)
|
47
|
+
begin
|
48
|
+
block.call(matcher)
|
49
|
+
return true
|
50
|
+
rescue Exception => e
|
51
|
+
matcher.failure_message = e.message
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'micronaut/matchers'
|
2
|
+
require 'micronaut/expectations/extensions/object'
|
3
|
+
require 'micronaut/expectations/extensions/string_and_symbol'
|
4
|
+
require 'micronaut/expectations/handler'
|
5
|
+
require 'micronaut/expectations/wrap_expectation'
|
6
|
+
|
7
|
+
module Micronaut
|
8
|
+
|
9
|
+
# Micronaut::Expectations lets you set expectations on your objects.
|
10
|
+
#
|
11
|
+
# result.should == 37
|
12
|
+
# team.should have(11).players_on_the_field
|
13
|
+
#
|
14
|
+
# == How Expectations work.
|
15
|
+
#
|
16
|
+
# Micronaut::Expectations adds two methods to Object:
|
17
|
+
#
|
18
|
+
# should(matcher=nil)
|
19
|
+
# should_not(matcher=nil)
|
20
|
+
#
|
21
|
+
# Both methods take an optional Expression Matcher (See Micronaut::Matchers).
|
22
|
+
#
|
23
|
+
# When +should+ receives an Expression Matcher, it calls <tt>matches?(self)</tt>. If
|
24
|
+
# it returns +true+, the spec passes and execution continues. If it returns
|
25
|
+
# +false+, then the spec fails with the message returned by <tt>matcher.failure_message</tt>.
|
26
|
+
#
|
27
|
+
# Similarly, when +should_not+ receives a matcher, it calls <tt>matches?(self)</tt>. If
|
28
|
+
# it returns +false+, the spec passes and execution continues. If it returns
|
29
|
+
# +true+, then the spec fails with the message returned by <tt>matcher.negative_failure_message</tt>.
|
30
|
+
#
|
31
|
+
# Micronaut ships with a standard set of useful matchers, and writing your own
|
32
|
+
# matchers is quite simple. See Micronaut::Matchers for details.
|
33
|
+
module Expectations
|
34
|
+
|
35
|
+
class ExpectationNotMetError < ::StandardError; end
|
36
|
+
|
37
|
+
def self.fail_with(message, expected=nil, target=nil) # :nodoc:
|
38
|
+
if Array === message && message.length == 3
|
39
|
+
message, expected, target = message[0], message[1], message[2]
|
40
|
+
end
|
41
|
+
Kernel::raise(Micronaut::Expectations::ExpectationNotMetError.new(message))
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Formatters
|
3
|
+
# Baseclass for formatters that implements all required methods as no-ops.
|
4
|
+
class BaseFormatter
|
5
|
+
attr_accessor :behaviour, :options, :output, :total_example_failed, :total_example_pending
|
6
|
+
|
7
|
+
def initialize(options, output_to)
|
8
|
+
@options, @output = options, output_to
|
9
|
+
@total_example_failed, @total_example_pending = 0, 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def profile_examples?
|
13
|
+
Micronaut.configuration.profile_examples
|
14
|
+
end
|
15
|
+
|
16
|
+
# This method is invoked before any examples are run, right after
|
17
|
+
# they have all been collected. This can be useful for special
|
18
|
+
# formatters that need to provide progress on feedback (graphical ones)
|
19
|
+
#
|
20
|
+
# This method will only be invoked once, and the next one to be invoked
|
21
|
+
# is #add_behaviour
|
22
|
+
def start(example_count)
|
23
|
+
end
|
24
|
+
|
25
|
+
# This method is invoked at the beginning of the execution of each behaviour.
|
26
|
+
# +behaviour+ is the behaviour.
|
27
|
+
#
|
28
|
+
# The next method to be invoked after this is #example_failed or #example_finished
|
29
|
+
def add_behaviour(behaviour)
|
30
|
+
@behaviour = behaviour
|
31
|
+
end
|
32
|
+
|
33
|
+
# This method is invoked when an +example+ starts.
|
34
|
+
def example_started(example)
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
# This method is invoked when an +example+ passes.
|
39
|
+
def example_passed(example)
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method is invoked when an +example+ fails, i.e. an exception occurred
|
43
|
+
# inside it (such as a failed should or other exception). +counter+ is the
|
44
|
+
# sequence number of the failure (starting at 1) and +failure+ is the associated
|
45
|
+
# exception.
|
46
|
+
def example_failed(example, exception)
|
47
|
+
@total_example_failed += 1
|
48
|
+
end
|
49
|
+
|
50
|
+
# This method is invoked when an example is not yet implemented (i.e. has not
|
51
|
+
# been provided a block), or when an ExamplePendingError is raised.
|
52
|
+
# +message+ is the message from the ExamplePendingError, if it exists, or the
|
53
|
+
# default value of "Not Yet Implemented"
|
54
|
+
# +pending_caller+ is the file and line number of the spec which
|
55
|
+
# has called the pending method
|
56
|
+
def example_pending(example, message)
|
57
|
+
end
|
58
|
+
|
59
|
+
# This method is invoked after all of the examples have executed. The next method
|
60
|
+
# to be invoked after this one is #dump_failure (once for each failed example),
|
61
|
+
def start_dump
|
62
|
+
end
|
63
|
+
|
64
|
+
# Dumps detailed information about each example failure.
|
65
|
+
def dump_failures
|
66
|
+
end
|
67
|
+
|
68
|
+
# This method is invoked after the dumping of examples and failures.
|
69
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
70
|
+
end
|
71
|
+
|
72
|
+
# This gets invoked after the summary if option is set to do so.
|
73
|
+
def dump_pending
|
74
|
+
end
|
75
|
+
|
76
|
+
# This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
|
77
|
+
def close
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Micronaut
|
2
|
+
|
3
|
+
module Formatters
|
4
|
+
|
5
|
+
class BaseTextFormatter < BaseFormatter
|
6
|
+
attr_reader :pending_examples, :failed_examples
|
7
|
+
|
8
|
+
def initialize(options, output_to)
|
9
|
+
super
|
10
|
+
@pending_examples = []
|
11
|
+
@failed_examples = []
|
12
|
+
@example_profiling_info = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def example_passed(example)
|
16
|
+
super
|
17
|
+
# Why && @start_time
|
18
|
+
if profile_examples? && @start_time
|
19
|
+
@example_profiling_info << [example, Time.now - @start_time]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def example_started(example)
|
24
|
+
@start_time = Time.now
|
25
|
+
end
|
26
|
+
|
27
|
+
def example_pending(example, message)
|
28
|
+
@pending_examples << [example, message]
|
29
|
+
end
|
30
|
+
|
31
|
+
def example_failed(example, exception)
|
32
|
+
super
|
33
|
+
@failed_examples << [example, exception]
|
34
|
+
end
|
35
|
+
|
36
|
+
def dump_failures
|
37
|
+
@output.puts
|
38
|
+
@failed_examples.each_with_index do |examples_with_exception, index|
|
39
|
+
example, exception = examples_with_exception.first, examples_with_exception.last
|
40
|
+
@output.puts "#{index.next}) #{example}"
|
41
|
+
@output.puts colorise(exception.message, exception)
|
42
|
+
@output.puts format_backtrace(exception.backtrace)
|
43
|
+
@output.puts
|
44
|
+
@output.flush
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def colorise(s, failure)
|
49
|
+
if failure.is_a?(Micronaut::Expectations::ExpectationNotMetError)
|
50
|
+
red(s)
|
51
|
+
else
|
52
|
+
magenta(s)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
57
|
+
@output.puts "\nFinished in #{duration} seconds\n"
|
58
|
+
|
59
|
+
summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
|
60
|
+
summary << ", #{pending_count} pending" if pending_count > 0
|
61
|
+
|
62
|
+
if failure_count == 0
|
63
|
+
if pending_count > 0
|
64
|
+
@output.puts yellow(summary)
|
65
|
+
else
|
66
|
+
@output.puts green(summary)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
@output.puts red(summary)
|
70
|
+
end
|
71
|
+
|
72
|
+
if profile_examples?
|
73
|
+
sorted_examples = @example_profiling_info.sort_by { |desc, time| time }
|
74
|
+
@output.puts "\nTop 10 slowest examples:\n"
|
75
|
+
sorted_examples.last(10).reverse.each do |desc, time|
|
76
|
+
@output.puts " (#{sprintf("%.7f", time)} seconds) #{desc}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
@output.flush
|
81
|
+
end
|
82
|
+
|
83
|
+
def dump_pending
|
84
|
+
unless @pending_examples.empty?
|
85
|
+
@output.puts
|
86
|
+
@output.puts "Pending:"
|
87
|
+
@pending_examples.each do |pending_example, message|
|
88
|
+
@output.puts "\n #{pending_example.behaviour}\n - #{pending_example.description}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
@output.flush
|
92
|
+
end
|
93
|
+
|
94
|
+
def close
|
95
|
+
if IO === @output && @output != $stdout
|
96
|
+
@output.close
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def format_backtrace(backtrace)
|
101
|
+
return "" if backtrace.nil?
|
102
|
+
cleansed = backtrace.map { |line| backtrace_line(line) }.compact.join("\n")
|
103
|
+
cleansed.empty? ? backtrace : cleansed
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
def enable_color_in_output?
|
109
|
+
@options.enable_color_in_output?
|
110
|
+
end
|
111
|
+
|
112
|
+
def backtrace_line(line)
|
113
|
+
return nil if Micronaut.configuration.cleaned_from_backtrace?(line)
|
114
|
+
line.sub!(/\A([^:]+:\d+)$/, '\\1')
|
115
|
+
return nil if line == '-e:1'
|
116
|
+
line
|
117
|
+
end
|
118
|
+
|
119
|
+
def color(text, color_code)
|
120
|
+
return text unless enable_color_in_output?
|
121
|
+
"#{color_code}#{text}\e[0m"
|
122
|
+
end
|
123
|
+
|
124
|
+
def green(text)
|
125
|
+
color(text, "\e[32m")
|
126
|
+
end
|
127
|
+
|
128
|
+
def red(text)
|
129
|
+
color(text, "\e[31m")
|
130
|
+
end
|
131
|
+
|
132
|
+
def magenta(text)
|
133
|
+
color(text, "\e[35m")
|
134
|
+
end
|
135
|
+
|
136
|
+
def yellow(text)
|
137
|
+
color(text, "\e[33m")
|
138
|
+
end
|
139
|
+
|
140
|
+
def blue(text)
|
141
|
+
color(text, "\e[34m")
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Formatters
|
3
|
+
|
4
|
+
class DocumentationFormatter < BaseTextFormatter
|
5
|
+
|
6
|
+
attr_reader :previous_nested_behaviours
|
7
|
+
|
8
|
+
def initialize(options, output_to)
|
9
|
+
super
|
10
|
+
@previous_nested_behaviours = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_behaviour(behaviour)
|
14
|
+
super
|
15
|
+
|
16
|
+
described_behaviour_chain.each_with_index do |nested_behaviour, i|
|
17
|
+
unless nested_behaviour == previous_nested_behaviours[i]
|
18
|
+
desc_or_name = (i == 0) ? nested_behaviour.name : nested_behaviour.description
|
19
|
+
output.puts "#{' ' * i}#{desc_or_name}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
@previous_nested_behaviours = described_behaviour_chain
|
24
|
+
end
|
25
|
+
|
26
|
+
def example_failed(example, exception)
|
27
|
+
super
|
28
|
+
expectation_not_met = exception.is_a?(Micronaut::Expectations::ExpectationNotMetError)
|
29
|
+
|
30
|
+
message = if expectation_not_met
|
31
|
+
"#{current_indentation}#{example.description} (FAILED)"
|
32
|
+
else
|
33
|
+
"#{current_indentation}#{example.description} (ERROR)"
|
34
|
+
end
|
35
|
+
|
36
|
+
@output.puts(expectation_not_met ? red(message) : magenta(message))
|
37
|
+
@output.flush
|
38
|
+
end
|
39
|
+
|
40
|
+
def example_passed(example)
|
41
|
+
output.puts green("#{current_indentation}#{example.description}")
|
42
|
+
output.flush
|
43
|
+
end
|
44
|
+
|
45
|
+
def example_pending(example, message)
|
46
|
+
super
|
47
|
+
output.puts yellow("#{current_indentation}#{example.description} (PENDING: #{message})")
|
48
|
+
output.flush
|
49
|
+
end
|
50
|
+
|
51
|
+
def current_indentation
|
52
|
+
' ' * previous_nested_behaviours.length
|
53
|
+
end
|
54
|
+
|
55
|
+
def described_behaviour_chain
|
56
|
+
behaviour.ancestors
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|