rsanheim-micronaut 0.1.3.2
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/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
|