micronaut 0.2.9

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.
Files changed (79) hide show
  1. data/History.txt +15 -0
  2. data/LICENSE +45 -0
  3. data/README.markdown +66 -0
  4. data/RSPEC-LICENSE +23 -0
  5. data/Rakefile +78 -0
  6. data/VERSION.yml +4 -0
  7. data/bin/micronaut +4 -0
  8. data/examples/example_helper.rb +54 -0
  9. data/examples/lib/micronaut/behaviour_example.rb +351 -0
  10. data/examples/lib/micronaut/configuration_example.rb +133 -0
  11. data/examples/lib/micronaut/example_example.rb +67 -0
  12. data/examples/lib/micronaut/expectations/extensions/object_example.rb +146 -0
  13. data/examples/lib/micronaut/expectations/fail_with_example.rb +17 -0
  14. data/examples/lib/micronaut/expectations/wrap_expectation_example.rb +27 -0
  15. data/examples/lib/micronaut/formatters/base_formatter_example.rb +117 -0
  16. data/examples/lib/micronaut/formatters/documentation_formatter_example.rb +5 -0
  17. data/examples/lib/micronaut/formatters/progress_formatter_example.rb +29 -0
  18. data/examples/lib/micronaut/kernel_extensions_example.rb +13 -0
  19. data/examples/lib/micronaut/matchers/be_close_example.rb +52 -0
  20. data/examples/lib/micronaut/matchers/be_example.rb +298 -0
  21. data/examples/lib/micronaut/matchers/change_example.rb +360 -0
  22. data/examples/lib/micronaut/matchers/description_generation_example.rb +175 -0
  23. data/examples/lib/micronaut/matchers/eql_example.rb +35 -0
  24. data/examples/lib/micronaut/matchers/equal_example.rb +35 -0
  25. data/examples/lib/micronaut/matchers/has_example.rb +69 -0
  26. data/examples/lib/micronaut/matchers/have_example.rb +392 -0
  27. data/examples/lib/micronaut/matchers/include_example.rb +103 -0
  28. data/examples/lib/micronaut/matchers/match_example.rb +43 -0
  29. data/examples/lib/micronaut/matchers/matcher_methods_example.rb +78 -0
  30. data/examples/lib/micronaut/matchers/operator_matcher_example.rb +193 -0
  31. data/examples/lib/micronaut/matchers/raise_error_example.rb +348 -0
  32. data/examples/lib/micronaut/matchers/respond_to_example.rb +54 -0
  33. data/examples/lib/micronaut/matchers/satisfy_example.rb +36 -0
  34. data/examples/lib/micronaut/matchers/simple_matcher_example.rb +93 -0
  35. data/examples/lib/micronaut/matchers/throw_symbol_example.rb +125 -0
  36. data/examples/lib/micronaut/mocha_example.rb +29 -0
  37. data/examples/lib/micronaut/runner_example.rb +41 -0
  38. data/examples/lib/micronaut/world_example.rb +98 -0
  39. data/examples/lib/micronaut_example.rb +43 -0
  40. data/examples/resources/example_classes.rb +67 -0
  41. data/lib/micronaut.rb +40 -0
  42. data/lib/micronaut/behaviour.rb +217 -0
  43. data/lib/micronaut/configuration.rb +162 -0
  44. data/lib/micronaut/example.rb +112 -0
  45. data/lib/micronaut/expectations.rb +45 -0
  46. data/lib/micronaut/expectations/extensions/object.rb +92 -0
  47. data/lib/micronaut/expectations/handler.rb +51 -0
  48. data/lib/micronaut/expectations/wrap_expectation.rb +52 -0
  49. data/lib/micronaut/formatters.rb +12 -0
  50. data/lib/micronaut/formatters/base_formatter.rb +127 -0
  51. data/lib/micronaut/formatters/base_text_formatter.rb +139 -0
  52. data/lib/micronaut/formatters/documentation_formatter.rb +78 -0
  53. data/lib/micronaut/formatters/progress_formatter.rb +30 -0
  54. data/lib/micronaut/kernel_extensions.rb +11 -0
  55. data/lib/micronaut/matchers.rb +141 -0
  56. data/lib/micronaut/matchers/be.rb +204 -0
  57. data/lib/micronaut/matchers/be_close.rb +37 -0
  58. data/lib/micronaut/matchers/change.rb +148 -0
  59. data/lib/micronaut/matchers/eql.rb +26 -0
  60. data/lib/micronaut/matchers/equal.rb +26 -0
  61. data/lib/micronaut/matchers/generated_descriptions.rb +36 -0
  62. data/lib/micronaut/matchers/has.rb +19 -0
  63. data/lib/micronaut/matchers/have.rb +153 -0
  64. data/lib/micronaut/matchers/include.rb +80 -0
  65. data/lib/micronaut/matchers/match.rb +22 -0
  66. data/lib/micronaut/matchers/method_missing.rb +9 -0
  67. data/lib/micronaut/matchers/operator_matcher.rb +50 -0
  68. data/lib/micronaut/matchers/raise_error.rb +128 -0
  69. data/lib/micronaut/matchers/respond_to.rb +50 -0
  70. data/lib/micronaut/matchers/satisfy.rb +50 -0
  71. data/lib/micronaut/matchers/simple_matcher.rb +135 -0
  72. data/lib/micronaut/matchers/throw_symbol.rb +108 -0
  73. data/lib/micronaut/mocking/with_absolutely_nothing.rb +11 -0
  74. data/lib/micronaut/mocking/with_mocha.rb +15 -0
  75. data/lib/micronaut/mocking/with_rr.rb +24 -0
  76. data/lib/micronaut/rake_task.rb +84 -0
  77. data/lib/micronaut/runner.rb +60 -0
  78. data/lib/micronaut/world.rb +75 -0
  79. metadata +165 -0
@@ -0,0 +1,80 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ class Include #:nodoc:
5
+
6
+ def initialize(*expecteds)
7
+ @expecteds = expecteds
8
+ end
9
+
10
+ def matches?(actual)
11
+ @actual = actual
12
+ @expecteds.each do |expected|
13
+ if actual.is_a?(Hash)
14
+ if expected.is_a?(Hash)
15
+ expected.each_pair do |k,v|
16
+ return false unless actual[k] == v
17
+ end
18
+ else
19
+ return false unless actual.has_key?(expected)
20
+ end
21
+ else
22
+ return false unless actual.include?(expected)
23
+ end
24
+ end
25
+ true
26
+ end
27
+
28
+ def failure_message
29
+ _message
30
+ end
31
+
32
+ def negative_failure_message
33
+ _message("not ")
34
+ end
35
+
36
+ def description
37
+ "include #{_pretty_print(@expecteds)}"
38
+ end
39
+
40
+ private
41
+ def _message(maybe_not="")
42
+ "expected #{@actual.inspect} #{maybe_not}to include #{_pretty_print(@expecteds)}"
43
+ end
44
+
45
+ def _pretty_print(array)
46
+ result = ""
47
+ array.each_with_index do |item, index|
48
+ if index < (array.length - 2)
49
+ result << "#{item.inspect}, "
50
+ elsif index < (array.length - 1)
51
+ result << "#{item.inspect} and "
52
+ else
53
+ result << "#{item.inspect}"
54
+ end
55
+ end
56
+ result
57
+ end
58
+ end
59
+
60
+ # :call-seq:
61
+ # should include(expected)
62
+ # should_not include(expected)
63
+ #
64
+ # Passes if actual includes expected. This works for
65
+ # collections and Strings. You can also pass in multiple args
66
+ # and it will only pass if all args are found in collection.
67
+ #
68
+ # == Examples
69
+ #
70
+ # [1,2,3].should include(3)
71
+ # [1,2,3].should include(2,3) #would pass
72
+ # [1,2,3].should include(2,3,4) #would fail
73
+ # [1,2,3].should_not include(4)
74
+ # "spread".should include("read")
75
+ # "spread".should_not include("red")
76
+ def include(*expected)
77
+ Matchers::Include.new(*expected)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,22 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ # :call-seq:
5
+ # should match(regexp)
6
+ # should_not match(regexp)
7
+ #
8
+ # Given a Regexp, passes if actual =~ regexp
9
+ #
10
+ # == Examples
11
+ #
12
+ # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
13
+ def match(regexp)
14
+ simple_matcher do |actual, matcher|
15
+ matcher.failure_message = "expected #{actual.inspect} to match #{regexp.inspect}", regexp, actual
16
+ matcher.negative_failure_message = "expected #{actual.inspect} not to match #{regexp.inspect}", regexp, actual
17
+ matcher.description = "match #{regexp.inspect}"
18
+ actual =~ regexp
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module Micronaut
2
+ module Matchers
3
+ def method_missing(sym, *args, &block) # :nodoc:
4
+ return Matchers::Be.new(sym, *args) if sym.to_s =~ /^be_/
5
+ return has(sym, *args) if sym.to_s =~ /^have_/
6
+ super
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ module Micronaut
2
+ module Matchers
3
+ class OperatorMatcher
4
+
5
+ def initialize(actual)
6
+ @actual = actual
7
+ end
8
+
9
+ ['==','===','<','<=','>=','>','=~'].each do |operator|
10
+ define_method operator do |expected|
11
+ ::Micronaut::Matchers.last_matcher = self
12
+ @operator, @expected = operator, expected
13
+ __delegate_operator(@actual, operator, expected)
14
+ end
15
+ end
16
+
17
+ def fail_with_message(message)
18
+ Micronaut::Expectations.fail_with(message, @expected, @actual)
19
+ end
20
+
21
+ def description
22
+ "#{@operator} #{@expected.inspect}"
23
+ end
24
+
25
+ end
26
+
27
+ class PositiveOperatorMatcher < OperatorMatcher #:nodoc:
28
+
29
+ def __delegate_operator(actual, operator, expected)
30
+ return true if actual.__send__(operator, expected)
31
+ if ['==','===', '=~'].include?(operator)
32
+ fail_with_message("expected: #{expected.inspect},\n got: #{actual.inspect} (using #{operator})")
33
+ else
34
+ fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ class NegativeOperatorMatcher < OperatorMatcher #:nodoc:
41
+
42
+ def __delegate_operator(actual, operator, expected)
43
+ return true unless actual.__send__(operator, expected)
44
+ return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,128 @@
1
+ module Micronaut
2
+ module Matchers
3
+ class RaiseError #:nodoc:
4
+ def initialize(expected_error_or_message=Exception, expected_message=nil, &block)
5
+ @block = block
6
+ case expected_error_or_message
7
+ when String, Regexp
8
+ @expected_error, @expected_message = Exception, expected_error_or_message
9
+ else
10
+ @expected_error, @expected_message = expected_error_or_message, expected_message
11
+ end
12
+ end
13
+
14
+ def matches?(given_proc)
15
+ @raised_expected_error = false
16
+ @with_expected_message = false
17
+ @eval_block = false
18
+ @eval_block_passed = false
19
+ begin
20
+ given_proc.call
21
+ rescue @expected_error => @given_error
22
+ @raised_expected_error = true
23
+ @with_expected_message = verify_message
24
+ rescue Exception => @given_error
25
+ # This clause should be empty, but rcov will not report it as covered
26
+ # unless something (anything) is executed within the clause
27
+ rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
28
+ end
29
+
30
+ unless negative_expectation?
31
+ eval_block if @raised_expected_error && @with_expected_message && @block
32
+ end
33
+ ensure
34
+ return (@raised_expected_error && @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
35
+ end
36
+
37
+ def eval_block
38
+ @eval_block = true
39
+ begin
40
+ @block[@given_error]
41
+ @eval_block_passed = true
42
+ rescue Exception => err
43
+ @given_error = err
44
+ end
45
+ end
46
+
47
+ def verify_message
48
+ case @expected_message
49
+ when nil
50
+ true
51
+ when Regexp
52
+ @expected_message =~ @given_error.message
53
+ else
54
+ @expected_message == @given_error.message
55
+ end
56
+ end
57
+
58
+ def failure_message
59
+ @eval_block ? @given_error.message : "expected #{expected_error}#{given_error}"
60
+ end
61
+
62
+ def negative_failure_message
63
+ "expected no #{expected_error}#{given_error}"
64
+ end
65
+
66
+ def description
67
+ "raise #{expected_error}"
68
+ end
69
+
70
+ private
71
+ def expected_error
72
+ case @expected_message
73
+ when nil
74
+ @expected_error
75
+ when Regexp
76
+ "#{@expected_error} with message matching #{@expected_message.inspect}"
77
+ else
78
+ "#{@expected_error} with #{@expected_message.inspect}"
79
+ end
80
+ end
81
+
82
+ def given_error
83
+ @given_error.nil? ? " but nothing was raised" : ", got #{@given_error.inspect}"
84
+ end
85
+
86
+ def negative_expectation?
87
+ # YES - I'm a bad person... help me find a better way - ryand
88
+ caller.first(3).find { |s| s =~ /should_not/ }
89
+ end
90
+ end
91
+
92
+ # :call-seq:
93
+ # should raise_error()
94
+ # should raise_error(NamedError)
95
+ # should raise_error(NamedError, String)
96
+ # should raise_error(NamedError, Regexp)
97
+ # should raise_error() { |error| ... }
98
+ # should raise_error(NamedError) { |error| ... }
99
+ # should raise_error(NamedError, String) { |error| ... }
100
+ # should raise_error(NamedError, Regexp) { |error| ... }
101
+ # should_not raise_error()
102
+ # should_not raise_error(NamedError)
103
+ # should_not raise_error(NamedError, String)
104
+ # should_not raise_error(NamedError, Regexp)
105
+ #
106
+ # With no args, matches if any error is raised.
107
+ # With a named error, matches only if that specific error is raised.
108
+ # With a named error and messsage specified as a String, matches only if both match.
109
+ # With a named error and messsage specified as a Regexp, matches only if both match.
110
+ # Pass an optional block to perform extra verifications on the exception matched
111
+ #
112
+ # == Examples
113
+ #
114
+ # lambda { do_something_risky }.should raise_error
115
+ # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError)
116
+ # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError) { |error| error.data.should == 42 }
117
+ # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, "that was too risky")
118
+ # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, /oo ri/)
119
+ #
120
+ # lambda { do_something_risky }.should_not raise_error
121
+ # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError)
122
+ # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, "that was too risky")
123
+ # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, /oo ri/)
124
+ def raise_error(error=Exception, message=nil, &block)
125
+ Matchers::RaiseError.new(error, message, &block)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,50 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ class RespondTo #:nodoc:
5
+
6
+ def initialize(*names)
7
+ @names = names
8
+ @names_not_responded_to = []
9
+ end
10
+
11
+ def matches?(given)
12
+ @given = given
13
+ @names.each do |name|
14
+ unless given.respond_to?(name)
15
+ @names_not_responded_to << name
16
+ end
17
+ end
18
+ @names_not_responded_to.empty?
19
+ end
20
+
21
+ def failure_message
22
+ "expected #{@given.inspect} to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}"
23
+ end
24
+
25
+ def negative_failure_message
26
+ "expected #{@given.inspect} not to respond to #{@names.collect {|name| name.inspect }.join(', ')}"
27
+ end
28
+
29
+ def description
30
+ # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here
31
+ "respond to #{@names.inspect}"
32
+ end
33
+
34
+ end
35
+
36
+ # :call-seq:
37
+ # should respond_to(*names)
38
+ # should_not respond_to(*names)
39
+ #
40
+ # Matches if the target object responds to all of the names
41
+ # provided. Names can be Strings or Symbols.
42
+ #
43
+ # == Examples
44
+ #
45
+ def respond_to(*names)
46
+ Matchers::RespondTo.new(*names)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ class Satisfy #:nodoc:
5
+
6
+ def initialize(&block)
7
+ @block = block
8
+ end
9
+
10
+ def matches?(given, &block)
11
+ @block = block if block
12
+ @given = given
13
+ @block.call(given)
14
+ end
15
+
16
+ def failure_message
17
+ "expected #{@given} to satisfy block"
18
+ end
19
+
20
+ def negative_failure_message
21
+ "expected #{@given} not to satisfy block"
22
+ end
23
+
24
+ end
25
+
26
+ # :call-seq:
27
+ # should satisfy {}
28
+ # should_not satisfy {}
29
+ #
30
+ # Passes if the submitted block returns true. Yields target to the
31
+ # block.
32
+ #
33
+ # Generally speaking, this should be thought of as a last resort when
34
+ # you can't find any other way to specify the behaviour you wish to
35
+ # specify.
36
+ #
37
+ # If you do find yourself in such a situation, you could always write
38
+ # a custom matcher, which would likely make your specs more expressive.
39
+ #
40
+ # == Examples
41
+ #
42
+ # 5.should satisfy { |n|
43
+ # n > 3
44
+ # }
45
+ def satisfy(&block)
46
+ Matchers::Satisfy.new(&block)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,135 @@
1
+ module Micronaut
2
+ module Matchers
3
+ class SimpleMatcher
4
+
5
+ attr_writer :failure_message, :negative_failure_message, :description
6
+
7
+ def initialize(description, &match_block)
8
+ @description = description
9
+ @match_block = match_block
10
+ end
11
+
12
+ def matches?(given)
13
+ @given = given
14
+ case @match_block.arity
15
+ when 2
16
+ @match_block.call(@given, self)
17
+ else
18
+ @match_block.call(@given)
19
+ end
20
+ end
21
+
22
+ def description
23
+ @description || explanation
24
+ end
25
+
26
+ def failure_message
27
+ @failure_message || (@description.nil? ? explanation : %[expected #{@description.inspect} but got #{@given.inspect}])
28
+ end
29
+
30
+ def negative_failure_message
31
+ @negative_failure_message || (@description.nil? ? explanation : %[expected not to get #{@description.inspect}, but got #{@given.inspect}])
32
+ end
33
+
34
+ def explanation
35
+ "No description provided. See RDoc for simple_matcher()"
36
+ end
37
+
38
+ end
39
+
40
+ # simple_matcher makes it easy for you to create your own custom matchers
41
+ # in just a few lines of code when you don't need all the power of a
42
+ # completely custom matcher object.
43
+ #
44
+ # The <tt>description</tt> argument will appear as part of any failure
45
+ # message, and is also the source for auto-generated descriptions.
46
+ #
47
+ # The <tt>match_block</tt> can have an arity of 1 or 2. The first block
48
+ # argument will be the given value. The second, if the block accepts it
49
+ # will be the matcher itself, giving you access to set custom failure
50
+ # messages in favor of the defaults.
51
+ #
52
+ # The <tt>match_block</tt> should return a boolean: <tt>true</tt>
53
+ # indicates a match, which will pass if you use <tt>should</tt> and fail
54
+ # if you use <tt>should_not</tt>. false (or nil) indicates no match,
55
+ # which will do the reverse: fail if you use <tt>should</tt> and pass if
56
+ # you use <tt>should_not</tt>.
57
+ #
58
+ # An error in the <tt>match_block</tt> will bubble up, resulting in a
59
+ # failure.
60
+ #
61
+ # == Example with default messages
62
+ #
63
+ # def be_even
64
+ # simple_matcher("an even number") { |given| given % 2 == 0 }
65
+ # end
66
+ #
67
+ # describe 2 do
68
+ # it "should be even" do
69
+ # 2.should be_even
70
+ # end
71
+ # end
72
+ #
73
+ # Given an odd number, this example would produce an error message stating:
74
+ # expected "an even number", got 3.
75
+ #
76
+ # Unfortunately, if you're a fan of auto-generated descriptions, this will
77
+ # produce "should an even number." Not the most desirable result. You can
78
+ # control that using custom messages:
79
+ #
80
+ # == Example with custom messages
81
+ #
82
+ # def rhyme_with(expected)
83
+ # simple_matcher("rhyme with #{expected.inspect}") do |given, matcher|
84
+ # matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}"
85
+ # matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}"
86
+ # given.rhymes_with? expected
87
+ # end
88
+ # end
89
+ #
90
+ # # OR
91
+ #
92
+ # def rhyme_with(expected)
93
+ # simple_matcher do |given, matcher|
94
+ # matcher.description = "rhyme with #{expected.inspect}"
95
+ # matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}"
96
+ # matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}"
97
+ # given.rhymes_with? expected
98
+ # end
99
+ # end
100
+ #
101
+ # describe "pecan" do
102
+ # it "should rhyme with 'be gone'" do
103
+ # nut = "pecan"
104
+ # nut.extend Rhymer
105
+ # nut.should rhyme_with("be gone")
106
+ # end
107
+ # end
108
+ #
109
+ # The resulting messages would be:
110
+ # description: rhyme with "be gone"
111
+ # failure_message: expected "pecan" to rhyme with "be gone"
112
+ # negative failure_message: expected "pecan" not to rhyme with "be gone"
113
+ #
114
+ # == Wrapped Expectations
115
+ #
116
+ # Because errors will bubble up, it is possible to wrap other expectations
117
+ # in a SimpleMatcher.
118
+ #
119
+ # def be_even
120
+ # simple_matcher("an even number") { |given| (given % 2).should == 0 }
121
+ # end
122
+ #
123
+ # BE VERY CAREFUL when you do this. Only use wrapped expectations for
124
+ # matchers that will always be used in only the positive
125
+ # (<tt>should</tt>) or negative (<tt>should_not</tt>), but not both.
126
+ # The reason is that is you wrap a <tt>should</tt> and call the wrapper
127
+ # with <tt>should_not</tt>, the correct result (the <tt>should</tt>
128
+ # failing), will fail when you want it to pass.
129
+ #
130
+ def simple_matcher(description=nil, &match_block)
131
+ SimpleMatcher.new(description, &match_block)
132
+ end
133
+
134
+ end
135
+ end