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,112 @@
1
+ module Micronaut
2
+
3
+ class Example
4
+
5
+ attr_reader :behaviour, :description, :metadata, :example_block
6
+
7
+ def initialize(behaviour, desc, options, example_block=nil)
8
+ @behaviour, @description, @options, @example_block = behaviour, desc, options, example_block
9
+ @metadata = @behaviour.metadata.dup
10
+ @metadata[:description] = description
11
+ @metadata[:execution_result] = {}
12
+ @metadata[:caller] = options.delete(:caller)
13
+ if @metadata[:caller]
14
+ @metadata[:file_path] = @metadata[:caller].split(":")[0].strip
15
+ @metadata[:line_number] = @metadata[:caller].split(":")[1].to_i
16
+ end
17
+ @metadata.update(options)
18
+ end
19
+
20
+ def record_results(results={})
21
+ @metadata[:execution_result].update(results)
22
+ end
23
+
24
+ def execution_result
25
+ @metadata[:execution_result]
26
+ end
27
+
28
+ def file_path
29
+ @metadata[:file_path] || behaviour.file_path
30
+ end
31
+
32
+ def run_started
33
+ record_results :started_at => Time.now
34
+ end
35
+
36
+ def run_passed
37
+ run_finished 'passed'
38
+ end
39
+
40
+ def run_pending(message='Not yet implemented')
41
+ run_finished 'pending', :pending_message => message
42
+ end
43
+
44
+ def run_failed(exception)
45
+ run_finished 'failed', :exception_encountered => exception
46
+ end
47
+
48
+ def run_finished(status, results={})
49
+ record_results results.update(:status => status)
50
+ finish_time = Time.now
51
+ record_results :finished_at => finish_time, :run_time => (finish_time - execution_result[:started_at])
52
+ Micronaut.configuration.formatter.example_finished(self)
53
+ end
54
+
55
+ def run_before_each
56
+ @behaviour_instance._setup_mocks if @behaviour_instance.respond_to?(:_setup_mocks)
57
+ @behaviour.eval_before_eachs(@behaviour_instance)
58
+ end
59
+
60
+ def run_after_each
61
+ @behaviour.eval_after_eachs(@behaviour_instance)
62
+ @behaviour_instance._verify_mocks if @behaviour_instance.respond_to?(:_verify_mocks)
63
+ ensure
64
+ @behaviour_instance._teardown_mocks if @behaviour_instance.respond_to?(:_teardown_mocks)
65
+ end
66
+
67
+ def run(behaviour_instance)
68
+ @behaviour_instance = behaviour_instance
69
+ @behaviour_instance.running_example = self
70
+
71
+ run_started
72
+
73
+ all_systems_nominal = true
74
+ exception_encountered = nil
75
+
76
+ begin
77
+ run_before_each
78
+ @behaviour_instance.instance_eval(&example_block) if example_block
79
+ rescue Exception => e
80
+ exception_encountered = e
81
+ all_systems_nominal = false
82
+ end
83
+
84
+ begin
85
+ run_after_each
86
+ rescue Exception => e
87
+ exception_encountered ||= e
88
+ all_systems_nominal = false
89
+ ensure
90
+ @behaviour_instance.running_example = nil
91
+ end
92
+
93
+ if exception_encountered
94
+ run_failed(exception_encountered)
95
+ else
96
+ example_block ? run_passed : run_pending
97
+ end
98
+
99
+ all_systems_nominal
100
+ end
101
+
102
+ def inspect
103
+ "#{@metadata[:behaviour][:name]} - #{@metadata[:description]}"
104
+ end
105
+
106
+ def to_s
107
+ inspect
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,45 @@
1
+ require 'micronaut/matchers'
2
+ require 'micronaut/expectations/extensions/object'
3
+ require 'micronaut/expectations/handler'
4
+ require 'micronaut/expectations/wrap_expectation'
5
+
6
+ module Micronaut
7
+
8
+ # Micronaut::Expectations lets you set expectations on your objects.
9
+ #
10
+ # result.should == 37
11
+ # team.should have(11).players_on_the_field
12
+ #
13
+ # == How Expectations work.
14
+ #
15
+ # Micronaut::Expectations adds two methods to Object:
16
+ #
17
+ # should(matcher=nil)
18
+ # should_not(matcher=nil)
19
+ #
20
+ # Both methods take an optional Expression Matcher (See Micronaut::Matchers).
21
+ #
22
+ # When +should+ receives an Expression Matcher, it calls <tt>matches?(self)</tt>. If
23
+ # it returns +true+, the spec passes and execution continues. If it returns
24
+ # +false+, then the spec fails with the message returned by <tt>matcher.failure_message</tt>.
25
+ #
26
+ # Similarly, when +should_not+ receives a matcher, it calls <tt>matches?(self)</tt>. If
27
+ # it returns +false+, the spec passes and execution continues. If it returns
28
+ # +true+, then the spec fails with the message returned by <tt>matcher.negative_failure_message</tt>.
29
+ #
30
+ # Micronaut ships with a standard set of useful matchers, and writing your own
31
+ # matchers is quite simple. See Micronaut::Matchers for details.
32
+ module Expectations
33
+
34
+ class ExpectationNotMetError < ::StandardError; end
35
+
36
+ def self.fail_with(message, expected=nil, target=nil) # :nodoc:
37
+ if Array === message && message.length == 3
38
+ message, expected, target = message[0], message[1], message[2]
39
+ end
40
+ Kernel::raise(Micronaut::Expectations::ExpectationNotMetError.new(message))
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,92 @@
1
+ module Micronaut
2
+ module Expectations
3
+ class InvalidMatcherError < ArgumentError; end
4
+
5
+ module ObjectExpectations
6
+ # :call-seq:
7
+ # should(matcher)
8
+ # should == expected
9
+ # should === expected
10
+ # should =~ expected
11
+ #
12
+ # receiver.should(matcher)
13
+ # => Passes if matcher.matches?(receiver)
14
+ #
15
+ # receiver.should == expected #any value
16
+ # => Passes if (receiver == expected)
17
+ #
18
+ # receiver.should === expected #any value
19
+ # => Passes if (receiver === expected)
20
+ #
21
+ # receiver.should =~ regexp
22
+ # => Passes if (receiver =~ regexp)
23
+ #
24
+ # See Micronaut::Matchers for more information about matchers
25
+ #
26
+ # == Warning
27
+ # NOTE that this does NOT support receiver.should != expected.
28
+ # Instead, use receiver.should_not == expected
29
+ def should(matcher=nil, &block)
30
+ ::Micronaut::Matchers.last_should = "should"
31
+ return ::Micronaut::Matchers::PositiveOperatorMatcher.new(self) if matcher.nil?
32
+
33
+ unless matcher.respond_to?(:matches?)
34
+ raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
35
+ end
36
+
37
+ match_found = matcher.matches?(self, &block)
38
+ ::Micronaut::Matchers.last_matcher = matcher
39
+
40
+ ::Micronaut::Expectations.fail_with(matcher.failure_message) unless match_found
41
+ match_found
42
+ end
43
+
44
+ # :call-seq:
45
+ # should_not(matcher)
46
+ # should_not == expected
47
+ # should_not === expected
48
+ # should_not =~ expected
49
+ #
50
+ # receiver.should_not(matcher)
51
+ # => Passes unless matcher.matches?(receiver)
52
+ #
53
+ # receiver.should_not == expected
54
+ # => Passes unless (receiver == expected)
55
+ #
56
+ # receiver.should_not === expected
57
+ # => Passes unless (receiver === expected)
58
+ #
59
+ # receiver.should_not =~ regexp
60
+ # => Passes unless (receiver =~ regexp)
61
+ #
62
+ # See Micronaut::Matchers for more information about matchers
63
+ def should_not(matcher=nil, &block)
64
+ ::Micronaut::Matchers.last_should = "should not"
65
+ return ::Micronaut::Matchers::NegativeOperatorMatcher.new(self) if matcher.nil?
66
+
67
+ unless matcher.respond_to?(:matches?)
68
+ raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
69
+ end
70
+
71
+ unless matcher.respond_to?(:negative_failure_message)
72
+ ::Micronaut::Expectations.fail_with(
73
+ <<-EOF
74
+ Matcher does not support should_not.
75
+ See Micronaut::Matchers for more information about matchers.
76
+ EOF
77
+ )
78
+ end
79
+ match_found = matcher.matches?(self, &block)
80
+ ::Micronaut::Matchers.last_matcher = matcher
81
+
82
+ ::Micronaut::Expectations.fail_with(matcher.negative_failure_message) if match_found
83
+ match_found
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+
90
+ class Object
91
+ include Micronaut::Expectations::ObjectExpectations
92
+ end
@@ -0,0 +1,51 @@
1
+ module Micronaut
2
+ module Expectations
3
+
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
@@ -0,0 +1,52 @@
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
+ # The other benefit you get is that you can use the negative version
31
+ # of the matcher:
32
+ #
33
+ # describe Cat do
34
+ # it "does not eat cheese" do
35
+ # Cat.new.should_not eat_cheese
36
+ # end
37
+ # end
38
+ #
39
+ # So in the event there is no assert_does_not_eat_cheese available,
40
+ # you're all set!
41
+ def wrap_expectation(matcher, &block)
42
+ begin
43
+ block.call(matcher)
44
+ return true
45
+ rescue Exception => e
46
+ matcher.failure_message = e.message
47
+ return false
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,12 @@
1
+ require 'micronaut/formatters/base_formatter'
2
+ require 'micronaut/formatters/base_text_formatter'
3
+ require 'micronaut/formatters/documentation_formatter'
4
+ require 'micronaut/formatters/progress_formatter'
5
+
6
+ module Micronaut
7
+
8
+ module Formatters
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,127 @@
1
+ module Micronaut
2
+ module Formatters
3
+
4
+ class BaseFormatter
5
+ attr_accessor :behaviour
6
+ attr_reader :example_count, :duration, :examples
7
+
8
+ def initialize
9
+ @example_count = 0
10
+ @examples = []
11
+ @behaviour = nil
12
+ end
13
+
14
+ def configuration
15
+ Micronaut.configuration
16
+ end
17
+
18
+ def output
19
+ Micronaut.configuration.output
20
+ end
21
+
22
+ def trace(&blk)
23
+ Micronaut.configuration.trace(trace_override_flag, &blk)
24
+ end
25
+
26
+ # Allow setting trace at the behaviour level as well globally
27
+ def trace_override_flag
28
+ behaviour && behaviour.metadata[:trace]
29
+ end
30
+
31
+ def profile_examples?
32
+ Micronaut.configuration.profile_examples
33
+ end
34
+
35
+ def color_enabled?
36
+ configuration.color_enabled?
37
+ end
38
+
39
+ def pending_examples
40
+ @pending_examples ||= ::Micronaut.world.find(examples, :execution_result => { :status => 'pending' })
41
+ end
42
+
43
+ def failed_examples
44
+ @failed_examples ||= ::Micronaut.world.find(examples, :execution_result => { :status => 'failed' })
45
+ end
46
+
47
+ # This method is invoked before any examples are run, right after
48
+ # they have all been collected. This can be useful for special
49
+ # formatters that need to provide progress on feedback (graphical ones)
50
+ #
51
+ # This method will only be invoked once, and the next one to be invoked
52
+ # is #add_behaviour
53
+ def start(example_count)
54
+ @example_count = example_count
55
+ end
56
+
57
+ def example_finished(example)
58
+ examples << example
59
+ end
60
+
61
+ # This method is invoked at the beginning of the execution of each behaviour.
62
+ # +behaviour+ is the behaviour.
63
+ #
64
+ # The next method to be invoked after this is #example_failed or #example_finished
65
+ def add_behaviour(behaviour)
66
+ @behaviour = behaviour
67
+ end
68
+
69
+ # This method is invoked after all of the examples have executed. The next method
70
+ # to be invoked after this one is #dump_failure (once for each failed example),
71
+ def start_dump(duration)
72
+ @duration = duration
73
+ end
74
+
75
+ # Dumps detailed information about each example failure.
76
+ def dump_failures
77
+ end
78
+
79
+ # This method is invoked after the dumping of examples and failures.
80
+ def dump_summary
81
+ end
82
+
83
+ # This gets invoked after the summary if option is set to do so.
84
+ def dump_pending
85
+ end
86
+
87
+ # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
88
+ def close
89
+ end
90
+
91
+ def format_backtrace(backtrace, example)
92
+ return "" unless backtrace
93
+ return backtrace if example.metadata[:full_backtrace] == true
94
+
95
+ cleansed = backtrace.select { |line| backtrace_line(line) }
96
+ # Kick the describe stack info off the list, just keep the line the problem happened on from that file
97
+ # cleansed = [cleansed.detect { |line| line.split(':').first == example.metadata[:caller].split(':').first }] if cleansed.size > 1
98
+ cleansed.empty? ? backtrace : cleansed
99
+ end
100
+
101
+ protected
102
+
103
+ def backtrace_line(line)
104
+ return nil if configuration.cleaned_from_backtrace?(line)
105
+ line.sub!(/\A([^:]+:\d+)$/, '\\1')
106
+ return nil if line == '-e:1'
107
+ line
108
+ end
109
+
110
+ def read_failed_line(exception, example)
111
+ original_file = example.file_path.to_s.downcase
112
+ matching_line = exception.backtrace.detect { |line| line.split(':').first.downcase == original_file.downcase }
113
+
114
+ return "Unable to find matching line from backtrace" if matching_line.nil?
115
+
116
+ file_path, line_number = matching_line.split(':')
117
+ if File.exist?(file_path)
118
+ open(file_path, 'r') { |f| f.readlines[line_number.to_i - 1] }
119
+ else
120
+ "Unable to find #{file_path} to read failed line"
121
+ end
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+ end