micronaut 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
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