spicycode-micronaut 0.0.3 → 0.0.4
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 +25 -0
- data/README +1 -1
- data/Rakefile +1 -1
- data/examples/example_helper.rb +1 -1
- data/examples/lib/micronaut/example_runner_example.rb +1 -1
- data/examples/lib/micronaut/formatters/base_formatter_example.rb +107 -0
- data/examples/lib/micronaut/formatters/progress_formatter_example.rb +98 -0
- data/examples/lib/micronaut/matchers/have_example.rb +8 -8
- data/examples/lib/micronaut/matchers/match_example.rb +1 -3
- data/examples/lib/micronaut_example.rb +0 -2
- data/lib/micronaut.rb +3 -3
- data/lib/micronaut/behaviour_group.rb +13 -9
- data/lib/micronaut/behaviour_group_class_methods.rb +3 -3
- data/lib/micronaut/expectations.rb +1 -1
- data/lib/micronaut/formatters.rb +11 -0
- data/lib/micronaut/formatters/base_formatter.rb +76 -0
- data/lib/micronaut/formatters/base_text_formatter.rb +119 -0
- data/lib/micronaut/formatters/progress_formatter.rb +35 -0
- data/lib/micronaut/matchers.rb +1 -1
- data/lib/micronaut/runner.rb +62 -0
- data/lib/micronaut/runner_options.rb +26 -0
- metadata +12 -3
- data/lib/micronaut/example_runner.rb +0 -106
data/LICENSE
CHANGED
@@ -18,3 +18,28 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
|
23
|
+
The matchers and expectations are licensed:
|
24
|
+
(The MIT License)
|
25
|
+
|
26
|
+
Copyright (c) 2005-2008 The RSpec Development Team
|
27
|
+
|
28
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
29
|
+
a copy of this software and associated documentation files (the
|
30
|
+
"Software"), to deal in the Software without restriction, including
|
31
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
32
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
33
|
+
permit persons to whom the Software is furnished to do so, subject to
|
34
|
+
the following conditions:
|
35
|
+
|
36
|
+
The above copyright notice and this permission notice shall be
|
37
|
+
included in all copies or substantial portions of the Software.
|
38
|
+
|
39
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
40
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
41
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
42
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
43
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
44
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
45
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
data/Rakefile
CHANGED
data/examples/example_helper.rb
CHANGED
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../../example_helper")
|
2
|
+
|
3
|
+
describe Micronaut::Formatters::BaseFormatter do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
@formatter = Micronaut::Formatters::BaseFormatter.new(nil, nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
class HaveInterfaceMatcher
|
10
|
+
def initialize(method)
|
11
|
+
@method = method
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :object
|
15
|
+
attr_reader :method
|
16
|
+
|
17
|
+
def matches?(object)
|
18
|
+
@object = object
|
19
|
+
object.respond_to?(@method)
|
20
|
+
end
|
21
|
+
|
22
|
+
def with(arity)
|
23
|
+
WithArity.new(self, @method, arity)
|
24
|
+
end
|
25
|
+
|
26
|
+
class WithArity
|
27
|
+
def initialize(matcher, method, arity)
|
28
|
+
@have_matcher = matcher
|
29
|
+
@method = method
|
30
|
+
@arity = arity
|
31
|
+
end
|
32
|
+
|
33
|
+
def matches?(an_object)
|
34
|
+
@have_matcher.matches?(an_object) && real_arity == @arity
|
35
|
+
end
|
36
|
+
|
37
|
+
def failure_message
|
38
|
+
"#{@have_matcher} should have method :#{@method} with #{argument_arity}, but it had #{real_arity}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def arguments
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :argument, :arguments
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def real_arity
|
50
|
+
@have_matcher.object.method(@method).arity
|
51
|
+
end
|
52
|
+
|
53
|
+
def argument_arity
|
54
|
+
if @arity == 1
|
55
|
+
"1 argument"
|
56
|
+
else
|
57
|
+
"#{@arity} arguments"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def have_interface_for(method)
|
64
|
+
HaveInterfaceMatcher.new(method)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have start as an interface with one argument" do
|
68
|
+
@formatter.should have_interface_for(:start).with(1).argument
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should have add_example_group as an interface with one argument" do
|
72
|
+
@formatter.should have_interface_for(:add_example_group).with(1).argument
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should have example_started as an interface with one argument" do
|
76
|
+
@formatter.should have_interface_for(:example_started).with(1).argument
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should have example_failed as an interface with two arguments" do
|
80
|
+
@formatter.should have_interface_for(:example_failed).with(2).arguments
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should have example_pending as an interface with two arguments" do
|
84
|
+
@formatter.should have_interface_for(:example_pending).with(2).arguments
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should have start_dump as an interface with zero arguments" do
|
88
|
+
@formatter.should have_interface_for(:start_dump).with(0).arguments
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have dump_failures as an interface with no arguments" do
|
92
|
+
@formatter.should have_interface_for(:dump_failures).with(0).arguments
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should have dump_summary as an interface with 4 arguments" do
|
96
|
+
@formatter.should have_interface_for(:dump_summary).with(4).arguments
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should have dump_pending as an interface with zero arguments" do
|
100
|
+
@formatter.should have_interface_for(:dump_pending).with(0).arguments
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should have close as an interface with zero arguments" do
|
104
|
+
@formatter.should have_interface_for(:close).with(0).arguments
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../../example_helper")
|
2
|
+
|
3
|
+
describe Micronaut::Formatters::ProgressFormatter do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@io = StringIO.new
|
7
|
+
@options = mock('options')
|
8
|
+
@options.stubs(:enable_color_in_output?).returns(false)
|
9
|
+
@formatter = Micronaut::Formatters::ProgressFormatter.new(@options, @io)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should produce line break on start dump" do
|
13
|
+
@formatter.start_dump
|
14
|
+
@io.string.should eql("\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should produce standard summary without pending when pending has a 0 count" do
|
18
|
+
@formatter.dump_summary(3, 2, 1, 0)
|
19
|
+
@io.string.should == "\nFinished in 3 seconds\n\n2 examples, 1 failure\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should produce standard summary" do
|
23
|
+
example_group = Micronaut::BehaviourGroup.describe("example_group") do
|
24
|
+
it('example') {}
|
25
|
+
end
|
26
|
+
example = example_group.examples.first
|
27
|
+
@formatter.example_pending(example, "message")
|
28
|
+
@io.rewind
|
29
|
+
@formatter.dump_summary(3, 2, 1, 1)
|
30
|
+
@io.string.should eql(%Q|
|
31
|
+
Finished in 3 seconds
|
32
|
+
|
33
|
+
2 examples, 1 failure, 1 pending
|
34
|
+
|)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should push green dot for passing spec" do
|
38
|
+
@io.expects(:tty?).returns(true)
|
39
|
+
@options.expects(:enable_color_in_output?).returns(true)
|
40
|
+
@formatter.example_passed("spec")
|
41
|
+
@io.string.should == "\e[32m.\e[0m"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should push red F for failure spec" do
|
45
|
+
@io.expects(:tty?).returns(true)
|
46
|
+
@options.expects(:enable_color_in_output?).returns(true)
|
47
|
+
@formatter.example_failed("spec", Micronaut::Expectations::ExpectationNotMetError.new)
|
48
|
+
@io.string.should eql("\e[31mF\e[0m")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should push magenta F for error spec" do
|
52
|
+
@io.expects(:tty?).returns(true)
|
53
|
+
@options.expects(:enable_color_in_output?).returns(true)
|
54
|
+
@formatter.example_failed("spec", RuntimeError.new)
|
55
|
+
@io.string.should eql("\e[35mF\e[0m")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should push nothing on start" do
|
59
|
+
@formatter.start(4)
|
60
|
+
@io.string.should eql("")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should ensure two ':' in the first backtrace" do
|
64
|
+
backtrace = ["/tmp/x.rb:1", "/tmp/x.rb:2", "/tmp/x.rb:3"]
|
65
|
+
@formatter.format_backtrace(backtrace).should eql(<<-EOE.rstrip)
|
66
|
+
/tmp/x.rb:1:
|
67
|
+
/tmp/x.rb:2:
|
68
|
+
/tmp/x.rb:3:
|
69
|
+
EOE
|
70
|
+
|
71
|
+
backtrace = ["/tmp/x.rb:1: message", "/tmp/x.rb:2", "/tmp/x.rb:3"]
|
72
|
+
@formatter.format_backtrace(backtrace).should eql(<<-EOE.rstrip)
|
73
|
+
/tmp/x.rb:1: message
|
74
|
+
/tmp/x.rb:2:
|
75
|
+
/tmp/x.rb:3:
|
76
|
+
EOE
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "outputting to custom out" do
|
80
|
+
before do
|
81
|
+
@out = mock("out")
|
82
|
+
@options = mock('options')
|
83
|
+
@out.stubs(:puts)
|
84
|
+
@formatter = Micronaut::Formatters::ProgressFormatter.new(@options, @out)
|
85
|
+
@formatter.class.__send__ :public, :output_to_tty?
|
86
|
+
end
|
87
|
+
|
88
|
+
after(:each) do
|
89
|
+
@formatter.class.__send__ :protected, :output_to_tty?
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should not throw NoMethodError on output_to_tty?" do
|
93
|
+
@out.expects(:tty?).raises(NoMethodError)
|
94
|
+
@formatter.output_to_tty?.should be_false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -36,7 +36,7 @@ describe "should have(n).items" do
|
|
36
36
|
owner
|
37
37
|
end
|
38
38
|
|
39
|
-
before
|
39
|
+
before do
|
40
40
|
unless defined?(ActiveSupport::Inflector)
|
41
41
|
@active_support_was_not_defined
|
42
42
|
module ActiveSupport
|
@@ -94,7 +94,7 @@ describe 'should have(1).item when ActiveSupport::Inflector is defined' do
|
|
94
94
|
owner
|
95
95
|
end
|
96
96
|
|
97
|
-
before
|
97
|
+
before do
|
98
98
|
unless defined?(ActiveSupport::Inflector)
|
99
99
|
@active_support_was_not_defined
|
100
100
|
module ActiveSupport
|
@@ -131,7 +131,7 @@ describe 'should have(1).item when Inflector is defined' do
|
|
131
131
|
owner
|
132
132
|
end
|
133
133
|
|
134
|
-
before
|
134
|
+
before do
|
135
135
|
unless defined?(ActiveSupport::Inflector)
|
136
136
|
@active_support_was_not_defined
|
137
137
|
module ActiveSupport
|
@@ -192,7 +192,7 @@ describe "should_not have(n).items" do
|
|
192
192
|
owner
|
193
193
|
end
|
194
194
|
|
195
|
-
before
|
195
|
+
before do
|
196
196
|
unless defined?(ActiveSupport::Inflector)
|
197
197
|
@active_support_was_not_defined
|
198
198
|
module ActiveSupport
|
@@ -240,7 +240,7 @@ describe "should have_exactly(n).items" do
|
|
240
240
|
owner
|
241
241
|
end
|
242
242
|
|
243
|
-
before
|
243
|
+
before do
|
244
244
|
unless defined?(ActiveSupport::Inflector)
|
245
245
|
@active_support_was_not_defined
|
246
246
|
module ActiveSupport
|
@@ -298,7 +298,7 @@ describe "should have_at_least(n).items" do
|
|
298
298
|
owner
|
299
299
|
end
|
300
300
|
|
301
|
-
before
|
301
|
+
before do
|
302
302
|
unless defined?(ActiveSupport::Inflector)
|
303
303
|
@active_support_was_not_defined
|
304
304
|
module ActiveSupport
|
@@ -374,7 +374,7 @@ describe "should have_at_most(n).items" do
|
|
374
374
|
owner
|
375
375
|
end
|
376
376
|
|
377
|
-
before
|
377
|
+
before do
|
378
378
|
unless defined?(ActiveSupport::Inflector)
|
379
379
|
@active_support_was_not_defined
|
380
380
|
module ActiveSupport
|
@@ -491,7 +491,7 @@ describe Micronaut::Matchers::Have, "for a collection owner that implements #sen
|
|
491
491
|
owner
|
492
492
|
end
|
493
493
|
|
494
|
-
before
|
494
|
+
before do
|
495
495
|
unless defined?(ActiveSupport::Inflector)
|
496
496
|
@active_support_was_not_defined
|
497
497
|
module ActiveSupport
|
@@ -7,9 +7,7 @@ describe "should match(expected)" do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should fail when target (String) does not match expected (Regexp)" do
|
10
|
-
lambda {
|
11
|
-
"string".should match(/rings/)
|
12
|
-
}.should fail
|
10
|
+
lambda { "string".should match(/rings/) }.should fail
|
13
11
|
end
|
14
12
|
|
15
13
|
it "should provide message, expected and actual on failure" do
|
data/lib/micronaut.rb
CHANGED
@@ -2,14 +2,14 @@ require 'micronaut/mocking/with_mocha'
|
|
2
2
|
require 'micronaut/matchers'
|
3
3
|
require 'micronaut/expectations'
|
4
4
|
require 'micronaut/example_world'
|
5
|
-
require 'micronaut/
|
5
|
+
require 'micronaut/runner'
|
6
|
+
require 'micronaut/runner_options'
|
6
7
|
require 'micronaut/behaviour_group_class_methods'
|
7
8
|
require 'micronaut/behaviour_group'
|
8
9
|
require 'micronaut/extensions/kernel'
|
10
|
+
require 'micronaut/formatters'
|
9
11
|
|
10
12
|
module Micronaut
|
11
|
-
VERSION = "0.0.2"
|
12
|
-
|
13
13
|
file = if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
|
14
14
|
File.expand_path __FILE__
|
15
15
|
elsif __FILE__ =~ /^[^\.]/ then # assume both relative
|
@@ -4,26 +4,28 @@ module Micronaut
|
|
4
4
|
include Micronaut::Matchers
|
5
5
|
include Micronaut::Mocking::WithMocha
|
6
6
|
|
7
|
-
def execute(
|
8
|
-
|
9
|
-
return result if self.class.examples.empty?
|
7
|
+
def execute(reporter)
|
8
|
+
return true if self.class.examples.empty?
|
10
9
|
self.class.all_before_alls.each { |aba| instance_eval(&aba) }
|
11
10
|
|
11
|
+
success = true
|
12
|
+
|
12
13
|
self.class.examples.each do |desc, opts, block|
|
13
14
|
execution_error = nil
|
14
|
-
|
15
|
+
reporter.example_started(self)
|
16
|
+
|
15
17
|
begin
|
16
18
|
setup_mocks
|
17
19
|
self.class.befores[:each].each { |be| instance_eval(&be) }
|
18
20
|
if block
|
19
|
-
result << '.'
|
20
21
|
instance_eval(&block)
|
22
|
+
reporter.example_passed(self)
|
21
23
|
else
|
22
|
-
|
24
|
+
reporter.example_pending([desc, self], 'Not yet implemented')
|
23
25
|
end
|
24
26
|
verify_mocks
|
25
27
|
rescue Exception => e
|
26
|
-
|
28
|
+
reporter.example_failed(self, e)
|
27
29
|
execution_error ||= e
|
28
30
|
ensure
|
29
31
|
teardown_mocks
|
@@ -32,11 +34,13 @@ module Micronaut
|
|
32
34
|
begin
|
33
35
|
self.class.afters[:each].each { |ae| instance_eval(&ae) }
|
34
36
|
rescue Exception => e
|
35
|
-
runner.complain(self, e)
|
36
37
|
execution_error ||= e
|
37
38
|
end
|
39
|
+
|
40
|
+
success &= execution_error.nil?
|
38
41
|
end
|
39
|
-
|
42
|
+
|
43
|
+
success
|
40
44
|
end
|
41
45
|
|
42
46
|
end
|
@@ -101,11 +101,11 @@ module Micronaut
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def all_before_alls
|
104
|
-
|
104
|
+
all_before_alls = []
|
105
105
|
each_ancestor do |ancestor|
|
106
|
-
|
106
|
+
all_before_alls << ancestor.before_alls
|
107
107
|
end
|
108
|
-
|
108
|
+
all_before_alls.concat(before_alls)
|
109
109
|
end
|
110
110
|
|
111
111
|
def run(runner)
|
@@ -28,7 +28,7 @@ module Micronaut
|
|
28
28
|
# it returns +false+, the spec passes and execution continues. If it returns
|
29
29
|
# +true+, then the spec fails with the message returned by <tt>matcher.negative_failure_message</tt>.
|
30
30
|
#
|
31
|
-
#
|
31
|
+
# Micronaut ships with a standard set of useful matchers, and writing your own
|
32
32
|
# matchers is quite simple. See Micronaut::Matchers for details.
|
33
33
|
module Expectations
|
34
34
|
class << self
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Formatters
|
3
|
+
# Baseclass for formatters that implements all required methods as no-ops.
|
4
|
+
class BaseFormatter
|
5
|
+
attr_accessor :example_group, :options, :where, :total_example_failed, :total_example_pending
|
6
|
+
def initialize(options, where)
|
7
|
+
@options, @where = options, where
|
8
|
+
@total_example_failed, @total_example_pending = 0, 0
|
9
|
+
end
|
10
|
+
|
11
|
+
# This method is invoked before any examples are run, right after
|
12
|
+
# they have all been collected. This can be useful for special
|
13
|
+
# formatters that need to provide progress on feedback (graphical ones)
|
14
|
+
#
|
15
|
+
# This method will only be invoked once, and the next one to be invoked
|
16
|
+
# is #add_example_group
|
17
|
+
def start(example_count)
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method is invoked at the beginning of the execution of each example_group.
|
21
|
+
# +example_group+ is the example_group.
|
22
|
+
#
|
23
|
+
# The next method to be invoked after this is #example_failed or #example_finished
|
24
|
+
def add_example_group(example_group)
|
25
|
+
@example_group = example_group
|
26
|
+
end
|
27
|
+
|
28
|
+
# This method is invoked when an +example+ starts.
|
29
|
+
def example_started(example)
|
30
|
+
end
|
31
|
+
|
32
|
+
# This method is invoked when an +example+ passes.
|
33
|
+
def example_passed(example)
|
34
|
+
end
|
35
|
+
|
36
|
+
# This method is invoked when an +example+ fails, i.e. an exception occurred
|
37
|
+
# inside it (such as a failed should or other exception). +counter+ is the
|
38
|
+
# sequence number of the failure (starting at 1) and +failure+ is the associated
|
39
|
+
# exception.
|
40
|
+
def example_failed(example, exception)
|
41
|
+
@total_example_failed += 1
|
42
|
+
end
|
43
|
+
|
44
|
+
# This method is invoked when an example is not yet implemented (i.e. has not
|
45
|
+
# been provided a block), or when an ExamplePendingError is raised.
|
46
|
+
# +message+ is the message from the ExamplePendingError, if it exists, or the
|
47
|
+
# default value of "Not Yet Implemented"
|
48
|
+
# +pending_caller+ is the file and line number of the spec which
|
49
|
+
# has called the pending method
|
50
|
+
def example_pending(example, message)
|
51
|
+
end
|
52
|
+
|
53
|
+
# This method is invoked after all of the examples have executed. The next method
|
54
|
+
# to be invoked after this one is #dump_failure (once for each failed example),
|
55
|
+
def start_dump
|
56
|
+
end
|
57
|
+
|
58
|
+
# Dumps detailed information about each example failure.
|
59
|
+
def dump_failures
|
60
|
+
end
|
61
|
+
|
62
|
+
# This method is invoked after the dumping of examples and failures.
|
63
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
64
|
+
end
|
65
|
+
|
66
|
+
# This gets invoked after the summary if option is set to do so.
|
67
|
+
def dump_pending
|
68
|
+
end
|
69
|
+
|
70
|
+
# This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
|
71
|
+
def close
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Formatters
|
3
|
+
|
4
|
+
class BaseTextFormatter < BaseFormatter
|
5
|
+
attr_reader :output, :pending_examples, :failed_examples
|
6
|
+
|
7
|
+
def initialize(options, output_to)
|
8
|
+
super
|
9
|
+
@output = output_to
|
10
|
+
@pending_examples = []
|
11
|
+
@failed_examples = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def example_pending(example, message)
|
15
|
+
super
|
16
|
+
# @pending_examples << [example.full_description, message, pending_caller]
|
17
|
+
@pending_examples << [example, message]
|
18
|
+
end
|
19
|
+
|
20
|
+
def example_failed(example, exception)
|
21
|
+
super
|
22
|
+
@failed_examples << [example, exception]
|
23
|
+
end
|
24
|
+
|
25
|
+
def dump_failures
|
26
|
+
@output.puts
|
27
|
+
@failed_examples.each_with_index do |examples_with_exception, index|
|
28
|
+
@output.puts "#{index.next})"
|
29
|
+
example, exception = examples_with_exception.first, examples_with_exception.last
|
30
|
+
@output.puts colorise("#{example}\n#{exception.message}", exception)
|
31
|
+
@output.puts format_backtrace(exception.backtrace)
|
32
|
+
@output.puts "\n"
|
33
|
+
@output.flush
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def colorise(s, failure)
|
38
|
+
if failure.is_a?(Micronaut::Expectations::ExpectationNotMetError)
|
39
|
+
red(s)
|
40
|
+
else
|
41
|
+
magenta(s)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
46
|
+
@output.puts
|
47
|
+
@output.puts "Finished in #{duration} seconds"
|
48
|
+
@output.puts
|
49
|
+
|
50
|
+
summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
|
51
|
+
summary << ", #{pending_count} pending" if pending_count > 0
|
52
|
+
|
53
|
+
if failure_count == 0
|
54
|
+
if pending_count > 0
|
55
|
+
@output.puts yellow(summary)
|
56
|
+
else
|
57
|
+
@output.puts green(summary)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
@output.puts red(summary)
|
61
|
+
end
|
62
|
+
@output.flush
|
63
|
+
end
|
64
|
+
|
65
|
+
def dump_pending
|
66
|
+
unless @pending_examples.empty?
|
67
|
+
@output.puts
|
68
|
+
@output.puts "Pending:"
|
69
|
+
@pending_examples.each do |pending_example, message|
|
70
|
+
@output.puts "\n #{pending_example.last.class.name} #{pending_example.first}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
@output.flush
|
74
|
+
end
|
75
|
+
|
76
|
+
def close
|
77
|
+
if IO === @output && @output != $stdout
|
78
|
+
@output.close
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def format_backtrace(backtrace)
|
83
|
+
return "" if backtrace.nil?
|
84
|
+
backtrace.map { |line| backtrace_line(line) }.join("\n")
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
def enable_color_in_output?
|
90
|
+
@options.enable_color_in_output?
|
91
|
+
end
|
92
|
+
|
93
|
+
def backtrace_line(line)
|
94
|
+
line.sub(/\A([^:]+:\d+)$/, '\\1:')
|
95
|
+
end
|
96
|
+
|
97
|
+
def color(text, color_code)
|
98
|
+
return text unless enable_color_in_output? && output_to_tty?
|
99
|
+
"#{color_code}#{text}\e[0m"
|
100
|
+
end
|
101
|
+
|
102
|
+
def output_to_tty?
|
103
|
+
begin
|
104
|
+
@output.tty? || ENV.has_key?("AUTOTEST")
|
105
|
+
rescue NoMethodError
|
106
|
+
false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def green(text); color(text, "\e[32m"); end
|
111
|
+
def red(text); color(text, "\e[31m"); end
|
112
|
+
def magenta(text); color(text, "\e[35m"); end
|
113
|
+
def yellow(text); color(text, "\e[33m"); end
|
114
|
+
def blue(text); color(text, "\e[34m"); end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Formatters
|
3
|
+
|
4
|
+
class ProgressFormatter < BaseTextFormatter
|
5
|
+
|
6
|
+
def example_failed(example, exception)
|
7
|
+
super
|
8
|
+
@output.print colorise('F',exception)
|
9
|
+
@output.flush
|
10
|
+
end
|
11
|
+
|
12
|
+
def example_passed(example)
|
13
|
+
@output.print green('.')
|
14
|
+
@output.flush
|
15
|
+
end
|
16
|
+
|
17
|
+
def example_pending(example, message)
|
18
|
+
super
|
19
|
+
@output.print yellow('*')
|
20
|
+
@output.flush
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_dump
|
24
|
+
@output.puts
|
25
|
+
@output.flush
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(sym, *args)
|
29
|
+
# ignore
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/micronaut/matchers.rb
CHANGED
@@ -19,7 +19,7 @@ require 'micronaut/matchers/operator_matcher'
|
|
19
19
|
|
20
20
|
module Micronaut
|
21
21
|
|
22
|
-
# We ship (courtesy of OSS and
|
22
|
+
# We ship (courtesy of OSS and Micronaut) with a number of useful Expression Matchers. An Expression Matcher
|
23
23
|
# is any object that responds to the following methods:
|
24
24
|
#
|
25
25
|
# matches?(actual)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Micronaut
|
2
|
+
|
3
|
+
class Runner
|
4
|
+
|
5
|
+
@@installed_at_exit ||= false
|
6
|
+
|
7
|
+
def self.options
|
8
|
+
@options ||= Micronaut::RunnerOptions.new(:color => true, :formatter => :progress)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.autorun
|
12
|
+
at_exit {
|
13
|
+
Micronaut::Runner.new.run(ARGV) ? exit(0) : exit(1)
|
14
|
+
} unless @@installed_at_exit
|
15
|
+
@@installed_at_exit = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def options
|
19
|
+
self.class.options
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(args = [])
|
23
|
+
@verbose = args.delete('-v')
|
24
|
+
|
25
|
+
filter = if args.first =~ /^(-n|--name)$/ then
|
26
|
+
args.shift
|
27
|
+
arg = args.shift
|
28
|
+
arg =~ /\/(.*)\// ? Regexp.new($1) : arg
|
29
|
+
else
|
30
|
+
/./ # anything - ^example_ already filtered by #examples
|
31
|
+
end
|
32
|
+
|
33
|
+
total_examples = Micronaut::ExampleWorld.example_groups.inject(0) { |sum, eg| sum + eg.examples.size }
|
34
|
+
|
35
|
+
old_sync, options.formatter.output.sync = options.formatter.output.sync, true if options.formatter.output.respond_to?(:sync=)
|
36
|
+
|
37
|
+
options.formatter.start(total_examples)
|
38
|
+
|
39
|
+
suite_success = true
|
40
|
+
|
41
|
+
starts_at = Time.now
|
42
|
+
Micronaut::ExampleWorld.example_groups.each do |example_group|
|
43
|
+
suite_success &= example_group.run(options.formatter)
|
44
|
+
end
|
45
|
+
duration = Time.now - starts_at
|
46
|
+
|
47
|
+
options.formatter.end
|
48
|
+
options.formatter.dump
|
49
|
+
|
50
|
+
options.formatter.start_dump
|
51
|
+
options.formatter.dump_pending
|
52
|
+
options.formatter.dump_failures
|
53
|
+
options.formatter.dump_summary(duration, total_examples, options.formatter.failed_examples.size, options.formatter.pending_examples.size)
|
54
|
+
|
55
|
+
options.formatter.output.sync = old_sync if options.formatter.output.respond_to? :sync=
|
56
|
+
|
57
|
+
suite_success
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Micronaut
|
2
|
+
|
3
|
+
class RunnerOptions
|
4
|
+
|
5
|
+
attr_accessor :color, :formatter
|
6
|
+
|
7
|
+
def initialize(options={})
|
8
|
+
@color = options.delete(:color)
|
9
|
+
@formatter = options.delete(:formatter)
|
10
|
+
end
|
11
|
+
|
12
|
+
def enable_color_in_output?
|
13
|
+
@color
|
14
|
+
end
|
15
|
+
|
16
|
+
def output
|
17
|
+
$stdout
|
18
|
+
end
|
19
|
+
|
20
|
+
def formatter
|
21
|
+
@formatter_instance ||= Micronaut::Formatters::ProgressFormatter.new(self, output)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spicycode-micronaut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chad Humphries
|
@@ -9,7 +9,7 @@ autorequire: micronaut
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-11-
|
12
|
+
date: 2008-11-27 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,7 +40,6 @@ files:
|
|
40
40
|
- lib/micronaut
|
41
41
|
- lib/micronaut/behaviour_group.rb
|
42
42
|
- lib/micronaut/behaviour_group_class_methods.rb
|
43
|
-
- lib/micronaut/example_runner.rb
|
44
43
|
- lib/micronaut/example_world.rb
|
45
44
|
- lib/micronaut/expectations
|
46
45
|
- lib/micronaut/expectations/differs
|
@@ -55,6 +54,11 @@ files:
|
|
55
54
|
- lib/micronaut/expectations.rb
|
56
55
|
- lib/micronaut/extensions
|
57
56
|
- lib/micronaut/extensions/kernel.rb
|
57
|
+
- lib/micronaut/formatters
|
58
|
+
- lib/micronaut/formatters/base_formatter.rb
|
59
|
+
- lib/micronaut/formatters/base_text_formatter.rb
|
60
|
+
- lib/micronaut/formatters/progress_formatter.rb
|
61
|
+
- lib/micronaut/formatters.rb
|
58
62
|
- lib/micronaut/matchers
|
59
63
|
- lib/micronaut/matchers/be.rb
|
60
64
|
- lib/micronaut/matchers/be_close.rb
|
@@ -78,6 +82,8 @@ files:
|
|
78
82
|
- lib/micronaut/matchers.rb
|
79
83
|
- lib/micronaut/mocking
|
80
84
|
- lib/micronaut/mocking/with_mocha.rb
|
85
|
+
- lib/micronaut/runner.rb
|
86
|
+
- lib/micronaut/runner_options.rb
|
81
87
|
- lib/micronaut.rb
|
82
88
|
- examples/example_helper.rb
|
83
89
|
- examples/lib
|
@@ -91,6 +97,9 @@ files:
|
|
91
97
|
- examples/lib/micronaut/expectations/extensions/object_example.rb
|
92
98
|
- examples/lib/micronaut/expectations/fail_with_example.rb
|
93
99
|
- examples/lib/micronaut/expectations/wrap_expectation_example.rb
|
100
|
+
- examples/lib/micronaut/formatters
|
101
|
+
- examples/lib/micronaut/formatters/base_formatter_example.rb
|
102
|
+
- examples/lib/micronaut/formatters/progress_formatter_example.rb
|
94
103
|
- examples/lib/micronaut/matchers
|
95
104
|
- examples/lib/micronaut/matchers/be_close_example.rb
|
96
105
|
- examples/lib/micronaut/matchers/be_example.rb
|
@@ -1,106 +0,0 @@
|
|
1
|
-
module Micronaut
|
2
|
-
class ExampleRunner
|
3
|
-
|
4
|
-
attr_accessor :report, :failures, :errors
|
5
|
-
attr_accessor :example_count
|
6
|
-
|
7
|
-
@@installed_at_exit ||= false
|
8
|
-
@@out = $stdout
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@report = []
|
12
|
-
@errors, @failures = 0, 0
|
13
|
-
@verbose = false
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.autorun
|
17
|
-
at_exit {
|
18
|
-
exit_code = Micronaut::ExampleRunner.new.run(ARGV)
|
19
|
-
exit false if exit_code && exit_code != 0
|
20
|
-
} unless @@installed_at_exit
|
21
|
-
@@installed_at_exit = true
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.output=(stream)
|
25
|
-
@@out = stream
|
26
|
-
end
|
27
|
-
|
28
|
-
def location(e)
|
29
|
-
e.backtrace.find { |s| s !~ /in .(expectations|fail)/ }.sub(/:in .*$/, '')
|
30
|
-
end
|
31
|
-
|
32
|
-
def complain(group, e)
|
33
|
-
bt = Micronaut::filter_backtrace(e.backtrace).join("\n ")
|
34
|
-
|
35
|
-
e = case e.class.to_s
|
36
|
-
when /Micronaut::Expectations/, 'Mocha::ExpectationError' then
|
37
|
-
@failures += 1
|
38
|
-
"Failure:\n#{group.class.name}(#{group.class}) [#{location(e)}]:\n#{e.message}\n #{bt}\n"
|
39
|
-
else
|
40
|
-
puts e.to_s
|
41
|
-
@errors += 1
|
42
|
-
"Error:\n#{group.class.name}(#{group.class}):\n#{e.class}: #{e.message}\n #{bt}\n"
|
43
|
-
end
|
44
|
-
@report << e
|
45
|
-
e[0, 1]
|
46
|
-
end
|
47
|
-
|
48
|
-
##
|
49
|
-
# Top level driver, controls all output and filtering.
|
50
|
-
def run(args = [])
|
51
|
-
@verbose = args.delete('-v')
|
52
|
-
|
53
|
-
filter = if args.first =~ /^(-n|--name)$/ then
|
54
|
-
args.shift
|
55
|
-
arg = args.shift
|
56
|
-
arg =~ /\/(.*)\// ? Regexp.new($1) : arg
|
57
|
-
else
|
58
|
-
/./ # anything - ^example_ already filtered by #examples
|
59
|
-
end
|
60
|
-
|
61
|
-
@@out.puts "Loading examples from #{$0}\nStarted"
|
62
|
-
|
63
|
-
start = Time.now
|
64
|
-
run_examples filter
|
65
|
-
|
66
|
-
@@out.puts
|
67
|
-
@@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
|
68
|
-
|
69
|
-
@report.each_with_index do |msg, i|
|
70
|
-
@@out.puts "\n%3d) %s" % [i + 1, msg]
|
71
|
-
end
|
72
|
-
|
73
|
-
@@out.puts
|
74
|
-
|
75
|
-
format = "%d examples, %d failures, %d errors"
|
76
|
-
@@out.puts format % [example_count, failures, errors]
|
77
|
-
|
78
|
-
return failures + errors if @example_count > 0 # or return nil...
|
79
|
-
end
|
80
|
-
|
81
|
-
def run_examples(filter = /./)
|
82
|
-
@example_count = 0
|
83
|
-
old_sync, @@out.sync = @@out.sync, true if @@out.respond_to?(:sync=)
|
84
|
-
|
85
|
-
Micronaut::ExampleWorld.example_groups.each do |example_group|
|
86
|
-
# example_group.examples.grep(filter).each do |test|
|
87
|
-
# example_group.examples.each do |example|
|
88
|
-
@@out.print "#{example_group.name}: " if @verbose
|
89
|
-
|
90
|
-
t = Time.now if @verbose
|
91
|
-
result = example_group.run(self)
|
92
|
-
|
93
|
-
@example_count += example_group.examples.size
|
94
|
-
|
95
|
-
@@out.print "%.6fs: " % (Time.now - t) if @verbose
|
96
|
-
@@out.print(result) if result
|
97
|
-
@@out.puts if @verbose
|
98
|
-
# end
|
99
|
-
end
|
100
|
-
|
101
|
-
@@out.sync = old_sync if @@out.respond_to? :sync=
|
102
|
-
@example_count
|
103
|
-
end
|
104
|
-
|
105
|
-
end
|
106
|
-
end
|