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,37 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ class BeClose
5
+ def initialize(expected, delta)
6
+ @expected, @delta = expected, delta
7
+ end
8
+
9
+ def matches?(actual)
10
+ @actual = actual
11
+ (@actual - @expected).abs < @delta
12
+ end
13
+
14
+ def failure_message
15
+ "expected #{@expected} +/- (< #{@delta}), got #{@actual}"
16
+ end
17
+
18
+ def description
19
+ "be close to #{@expected} (within +- #{@delta})"
20
+ end
21
+ end
22
+
23
+ # :call-seq:
24
+ # should be_close(expected, delta)
25
+ # should_not be_close(expected, delta)
26
+ #
27
+ # Passes if actual == expected +/- delta
28
+ #
29
+ # == Example
30
+ #
31
+ # result.should be_close(3.0, 0.5)
32
+ def be_close(expected, delta)
33
+ BeClose.new(expected, delta)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,148 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ #Based on patch from Wilson Bilkovich
5
+ class Change #:nodoc:
6
+ def initialize(receiver=nil, message=nil, &block)
7
+ @message = message || "result"
8
+ @value_proc = block || lambda {
9
+ receiver.__send__(message)
10
+ }
11
+ end
12
+
13
+ def matches?(event_proc)
14
+ raise_block_syntax_error if block_given?
15
+
16
+ @before = evaluate_value_proc
17
+ event_proc.call
18
+ @after = evaluate_value_proc
19
+
20
+ return false if @from unless @from == @before
21
+ return false if @to unless @to == @after
22
+ return (@before + @amount == @after) if @amount
23
+ return ((@after - @before) >= @minimum) if @minimum
24
+ return ((@after - @before) <= @maximum) if @maximum
25
+ @before != @after
26
+ end
27
+
28
+ def raise_block_syntax_error
29
+ raise MatcherError.new(<<-MESSAGE
30
+ block passed to should or should_not change must use {} instead of do/end
31
+ MESSAGE
32
+ )
33
+ end
34
+
35
+ def evaluate_value_proc
36
+ @value_proc.call
37
+ end
38
+
39
+ def failure_message
40
+ if @to
41
+ "#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}"
42
+ elsif @from
43
+ "#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}"
44
+ elsif @amount
45
+ "#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}"
46
+ elsif @minimum
47
+ "#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
48
+ elsif @maximum
49
+ "#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
50
+ else
51
+ "#{@message} should have changed, but is still #{@before.inspect}"
52
+ end
53
+ end
54
+
55
+ def actual_delta
56
+ @after - @before
57
+ end
58
+
59
+ def negative_failure_message
60
+ "#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}"
61
+ end
62
+
63
+ def by(amount)
64
+ @amount = amount
65
+ self
66
+ end
67
+
68
+ def by_at_least(minimum)
69
+ @minimum = minimum
70
+ self
71
+ end
72
+
73
+ def by_at_most(maximum)
74
+ @maximum = maximum
75
+ self
76
+ end
77
+
78
+ def to(to)
79
+ @to = to
80
+ self
81
+ end
82
+
83
+ def from (from)
84
+ @from = from
85
+ self
86
+ end
87
+ end
88
+
89
+ # :call-seq:
90
+ # should change(receiver, message, &block)
91
+ # should change(receiver, message, &block).by(value)
92
+ # should change(receiver, message, &block).from(old).to(new)
93
+ # should_not change(receiver, message, &block)
94
+ #
95
+ # Allows you to specify that a Proc will cause some value to change.
96
+ #
97
+ # == Examples
98
+ #
99
+ # lambda {
100
+ # team.add_player(player)
101
+ # }.should change(roster, :count)
102
+ #
103
+ # lambda {
104
+ # team.add_player(player)
105
+ # }.should change(roster, :count).by(1)
106
+ #
107
+ # lambda {
108
+ # team.add_player(player)
109
+ # }.should change(roster, :count).by_at_least(1)
110
+ #
111
+ # lambda {
112
+ # team.add_player(player)
113
+ # }.should change(roster, :count).by_at_most(1)
114
+ #
115
+ # string = "string"
116
+ # lambda {
117
+ # string.reverse!
118
+ # }.should change { string }.from("string").to("gnirts")
119
+ #
120
+ # lambda {
121
+ # person.happy_birthday
122
+ # }.should change(person, :birthday).from(32).to(33)
123
+ #
124
+ # lambda {
125
+ # employee.develop_great_new_social_networking_app
126
+ # }.should change(employee, :title).from("Mail Clerk").to("CEO")
127
+ #
128
+ # Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after
129
+ # it evaluates the c object (generated by the lambdas in the examples
130
+ # above).
131
+ #
132
+ # Then compares the values before and after the <tt>receiver.message</tt>
133
+ # and evaluates the difference compared to the expected difference.
134
+ #
135
+ # == WARNING
136
+ # <tt>should_not change</tt> only supports the form with no
137
+ # subsequent calls to <tt>by</tt>, <tt>by_at_least</tt>,
138
+ # <tt>by_at_most</tt>, <tt>to</tt> or <tt>from</tt>.
139
+ #
140
+ # blocks passed to <tt>should</tt> <tt>change</tt> and <tt>should_not</tt>
141
+ # <tt>change</tt> must use the <tt>{}</tt> form (<tt>do/end</tt> is not
142
+ # supported).
143
+ #
144
+ def change(receiver=nil, message=nil, &block)
145
+ Matchers::Change.new(receiver, message, &block)
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,26 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ # :call-seq:
5
+ # should eql(expected)
6
+ # should_not eql(expected)
7
+ #
8
+ # Passes if actual and expected are of equal value, but not necessarily the same object.
9
+ #
10
+ # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
11
+ #
12
+ # == Examples
13
+ #
14
+ # 5.should eql(5)
15
+ # 5.should_not eql(3)
16
+ def eql(expected)
17
+ simple_matcher do |actual, matcher|
18
+ matcher.failure_message = "expected #{expected.inspect}, got #{actual.inspect} (using .eql?)", expected, actual
19
+ matcher.negative_failure_message = "expected #{actual.inspect} not to equal #{expected.inspect} (using .eql?)", expected, actual
20
+ matcher.description = "eql #{expected.inspect}"
21
+ actual.eql?(expected)
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ # :call-seq:
5
+ # should equal(expected)
6
+ # should_not equal(expected)
7
+ #
8
+ # Passes if given and expected are the same object (object identity).
9
+ #
10
+ # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
11
+ #
12
+ # == Examples
13
+ #
14
+ # 5.should equal(5) #Fixnums are equal
15
+ # "5".should_not equal("5") #Strings that look the same are not the same object
16
+ def equal(expected)
17
+ simple_matcher do |actual, matcher|
18
+ matcher.failure_message = "expected #{expected.inspect}, got #{actual.inspect} (using .equal?)", expected, actual
19
+ matcher.negative_failure_message = "expected #{actual.inspect} not to equal #{expected.inspect} (using .equal?)", expected, actual
20
+ matcher.description = "equal #{expected.inspect}"
21
+ actual.equal?(expected)
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module Micronaut
2
+ module Matchers
3
+ class << self
4
+ attr_accessor :last_matcher, :last_should
5
+
6
+ def clear_generated_description
7
+ self.last_matcher = nil
8
+ self.last_should = nil
9
+ end
10
+
11
+ def generated_description
12
+ return nil if last_should.nil?
13
+ "#{last_should} #{last_description}"
14
+ end
15
+
16
+ private
17
+
18
+ def last_description
19
+ last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
20
+ When you call a matcher in an example without a String, like this:
21
+
22
+ specify { object.should matcher }
23
+
24
+ or this:
25
+
26
+ it { should matcher }
27
+
28
+ the runner expects the matcher to have a #describe method. You should either
29
+ add a String to the example this matcher is being used in, or give it a
30
+ description method. Then you won't have to suffer this lengthy warning again.
31
+ MESSAGE
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,19 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ def has(sym, *args) # :nodoc:
5
+ simple_matcher do |actual, matcher|
6
+ matcher.failure_message = "expected ##{predicate(sym)}(#{args[0].inspect}) to return true, got false"
7
+ matcher.negative_failure_message = "expected ##{predicate(sym)}(#{args[0].inspect}) to return false, got true"
8
+ matcher.description = "have key #{args[0].inspect}"
9
+ actual.__send__(predicate(sym), *args)
10
+ end
11
+ end
12
+
13
+ private
14
+ def predicate(sym)
15
+ "#{sym.to_s.sub("have_","has_")}?".to_sym
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,153 @@
1
+ module Micronaut
2
+ module Matchers
3
+
4
+ class Have #:nodoc:
5
+
6
+ def initialize(expected, relativity=:exactly)
7
+ @expected = (expected == :no ? 0 : expected)
8
+ @relativity = relativity
9
+ end
10
+
11
+ def relativities
12
+ @relativities ||= {
13
+ :exactly => "",
14
+ :at_least => "at least ",
15
+ :at_most => "at most "
16
+ }
17
+ end
18
+
19
+ def matches?(collection_owner)
20
+ if collection_owner.respond_to?(@collection_name)
21
+ collection = collection_owner.__send__(@collection_name, *@args, &@block)
22
+ elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name))
23
+ collection = collection_owner.__send__(@plural_collection_name, *@args, &@block)
24
+ elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size))
25
+ collection = collection_owner
26
+ else
27
+ collection_owner.__send__(@collection_name, *@args, &@block)
28
+ end
29
+ @given = collection.size if collection.respond_to?(:size)
30
+ @given = collection.length if collection.respond_to?(:length)
31
+ raise not_a_collection if @given.nil?
32
+ return @given >= @expected if @relativity == :at_least
33
+ return @given <= @expected if @relativity == :at_most
34
+ @given == @expected
35
+ end
36
+
37
+ def not_a_collection
38
+ "expected #{@collection_name} to be a collection but it does not respond to #length or #size"
39
+ end
40
+
41
+ def failure_message
42
+ "expected #{relative_expectation} #{@collection_name}, got #{@given}"
43
+ end
44
+
45
+ def negative_failure_message
46
+ if @relativity == :exactly
47
+ return "expected target not to have #{@expected} #{@collection_name}, got #{@given}"
48
+ elsif @relativity == :at_most
49
+ return <<-EOF
50
+ Isn't life confusing enough?
51
+ Instead of having to figure out the meaning of this:
52
+ should_not have_at_most(#{@expected}).#{@collection_name}
53
+ We recommend that you use this instead:
54
+ should have_at_least(#{@expected + 1}).#{@collection_name}
55
+ EOF
56
+ elsif @relativity == :at_least
57
+ return <<-EOF
58
+ Isn't life confusing enough?
59
+ Instead of having to figure out the meaning of this:
60
+ should_not have_at_least(#{@expected}).#{@collection_name}
61
+ We recommend that you use this instead:
62
+ should have_at_most(#{@expected - 1}).#{@collection_name}
63
+ EOF
64
+ end
65
+ end
66
+
67
+ def description
68
+ "have #{relative_expectation} #{@collection_name}"
69
+ end
70
+
71
+ def respond_to?(sym)
72
+ @expected.respond_to?(sym) || super
73
+ end
74
+
75
+ private
76
+
77
+ def method_missing(sym, *args, &block)
78
+ @collection_name = sym
79
+ if inflector = (defined?(ActiveSupport::Inflector) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil))
80
+ @plural_collection_name = inflector.pluralize(sym.to_s)
81
+ end
82
+ @args = args
83
+ @block = block
84
+ self
85
+ end
86
+
87
+ def relative_expectation
88
+ "#{relativities[@relativity]}#{@expected}"
89
+ end
90
+ end
91
+
92
+ # :call-seq:
93
+ # should have(number).named_collection__or__sugar
94
+ # should_not have(number).named_collection__or__sugar
95
+ #
96
+ # Passes if receiver is a collection with the submitted
97
+ # number of items OR if the receiver OWNS a collection
98
+ # with the submitted number of items.
99
+ #
100
+ # If the receiver OWNS the collection, you must use the name
101
+ # of the collection. So if a <tt>Team</tt> instance has a
102
+ # collection named <tt>#players</tt>, you must use that name
103
+ # to set the expectation.
104
+ #
105
+ # If the receiver IS the collection, you can use any name
106
+ # you like for <tt>named_collection</tt>. We'd recommend using
107
+ # either "elements", "members", or "items" as these are all
108
+ # standard ways of describing the things IN a collection.
109
+ #
110
+ # This also works for Strings, letting you set an expectation
111
+ # about its length
112
+ #
113
+ # == Examples
114
+ #
115
+ # # Passes if team.players.size == 11
116
+ # team.should have(11).players
117
+ #
118
+ # # Passes if [1,2,3].length == 3
119
+ # [1,2,3].should have(3).items #"items" is pure sugar
120
+ #
121
+ # # Passes if "this string".length == 11
122
+ # "this string".should have(11).characters #"characters" is pure sugar
123
+ def have(n)
124
+ Matchers::Have.new(n)
125
+ end
126
+ alias :have_exactly :have
127
+
128
+ # :call-seq:
129
+ # should have_at_least(number).items
130
+ #
131
+ # Exactly like have() with >=.
132
+ #
133
+ # == Warning
134
+ #
135
+ # +should_not+ +have_at_least+ is not supported
136
+ def have_at_least(n)
137
+ Matchers::Have.new(n, :at_least)
138
+ end
139
+
140
+ # :call-seq:
141
+ # should have_at_most(number).items
142
+ #
143
+ # Exactly like have() with <=.
144
+ #
145
+ # == Warning
146
+ #
147
+ # +should_not+ +have_at_most+ is not supported
148
+ def have_at_most(n)
149
+ Matchers::Have.new(n, :at_most)
150
+ end
151
+
152
+ end
153
+ end