riot 0.12.5 → 0.12.6

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.
@@ -51,8 +51,11 @@ module Riot
51
51
  @parent = parent || RootContext.new([],[], "", {})
52
52
  @description = description
53
53
  @contexts, @setups, @assertions, @teardowns = [], [], [], []
54
+ @context_error = nil
54
55
  @options = @parent.option_set.dup
55
56
  prepare_middleware(&definition)
57
+ rescue Exception => e
58
+ @context_error = e
56
59
  end
57
60
 
58
61
  # Create a new test context.
@@ -88,8 +91,12 @@ module Riot
88
91
  # @return [Riot::Reporter] the given reporter
89
92
  def run(reporter)
90
93
  reporter.describe_context(self) unless @assertions.empty?
91
- local_run(reporter, situation_class.new)
92
- run_sub_contexts(reporter)
94
+ if @context_error
95
+ reporter.report("context preparation", [:context_error, @context_error])
96
+ else
97
+ local_run(reporter, situation_class.new)
98
+ run_sub_contexts(reporter)
99
+ end
93
100
  reporter
94
101
  end
95
102
 
@@ -98,7 +105,11 @@ module Riot
98
105
  # @param [Riot::Reporter] reporter the reporter to report results to
99
106
  # @param [Riot::Situation] situation the situation to use for executing the context.
100
107
  def local_run(reporter, situation)
101
- runnables.each { |runnable| reporter.report(runnable.to_s, runnable.run(situation)) }
108
+ runnables.each do |runnable|
109
+ code, response = *runnable.run(situation)
110
+ reporter.report(runnable.to_s, [code, response])
111
+ break if code == :setup_error
112
+ end
102
113
  end
103
114
 
104
115
  # Prints the full description from the context tree, grabbing the description from the parent and
@@ -19,7 +19,7 @@ module Riot
19
19
  # => "hello world whats the news"
20
20
  #
21
21
  # For every method called it is also acceptable to pass any number of arguments. These arguments will be
22
- # added to the final message after having {Kernel#inspect} called on them. Another for instance:
22
+ # added to the final message after having `inspect` called on them. Another for instance:
23
23
  #
24
24
  # message = Riot::Message.new
25
25
  # message.expected([1, 2, 3], "foo").not([3, 2, 1], "bar")
@@ -3,18 +3,18 @@ module Riot
3
3
  # Context middlewares are chainable, context preparers. This to say that a middleware knows about a single
4
4
  # neighbor and that it can prepare context before the context is "run". As a for instance, suppose you
5
5
  # wanted the following to be possible.
6
- #
6
+ #
7
7
  # context Person do
8
8
  # denies(:valid?)
9
9
  # end # Person
10
- #
11
- # Without writing a middleware, the topic in this would actually be nil, but what the context is saying is
12
- # that there should be something in the topic that responds to +:valid?+; an instance of +Person+ in this
10
+ #
11
+ # Without writing a middleware, the topic in this would actually be nil, but what the context is saying is
12
+ # that there should be something in the topic that responds to +:valid?+; an instance of +Person+ in this
13
13
  # case. We can do this with middleware like so:
14
- #
14
+ #
15
15
  # class Modelware < Riot::ContextMiddleware
16
16
  # register
17
- #
17
+ #
18
18
  # def call(context)
19
19
  # if context.description.kind_of?(Model)
20
20
  # context.setup { context.description.new }
@@ -22,37 +22,37 @@ module Riot
22
22
  # middleware.call(context)
23
23
  # end
24
24
  # end # Modelware
25
- #
26
- # That's good stuff. If you're familiar at all with the nature of Rack middleware - how to implement it,
25
+ #
26
+ # That's good stuff. If you're familiar at all with the nature of Rack middleware - how to implement it,
27
27
  # how it's executed, etc. - you'll be familiar with Context middleware as the principles are similar:
28
- #
28
+ #
29
29
  # 1. Define a class that extends {Riot::ContextMiddleware}
30
30
  # 2. Call +register+
31
31
  # 3. Implement a +call+ method that accepts the Context that is about to be executed
32
32
  # 4. Do stuff, but make sure to pass the call along with +middleware.call(context)+
33
- #
33
+ #
34
34
  # Steps 1, 2, and 3 should be pretty straight-forward. Currently, +context+ is the only argument to +call+.
35
35
  # When your middleware is initialized it is given the next registered middleware in the chain (which is
36
36
  # where the `middleware` method gets its value from).
37
- #
37
+ #
38
38
  # So, "Do stuff" from step 4 is the where we start breaking things down. What can you actually do? Well,
39
39
  # you can do anything to the context that you could do if you were writing a Riot test; and I do mean
40
40
  # anything.
41
- #
41
+ #
42
42
  # * Add setup blocks (as many as you like)
43
43
  # * Add teardown blocks (as many as you like)
44
44
  # * Add hookup blocks (as many as you like)
45
45
  # * Add helpers (as many as you like)
46
46
  # * Add assertions
47
- #
47
+ #
48
48
  # The context in question will not run before all middleware have been applied to the context; this is
49
- # different behavior than that of Rack middleware. {Riot::ContextMiddleware} is only about preparing a
50
- # context, not about executing it. Thus, where in your method you actually pass the call off to the next
51
- # middleware in the chain has impact on how the context is set up. Basically, whatever you do before
52
- # calling `middleware.call(context)` is done before any other middleware gets setup and before the innards
53
- # of the context itself are applied. Whatever you do after that call is done after all that, but still
49
+ # different behavior than that of Rack middleware. {Riot::ContextMiddleware} is only about preparing a
50
+ # context, not about executing it. Thus, where in your method you actually pass the call off to the next
51
+ # middleware in the chain has impact on how the context is set up. Basically, whatever you do before
52
+ # calling `middleware.call(context)` is done before any other middleware gets setup and before the innards
53
+ # of the context itself are applied. Whatever you do after that call is done after all that, but still
54
54
  # before the actual setups, hookups, assertions, and teardowns are run.
55
- #
55
+ #
56
56
  # Do not expect the same instance of middleware to exist from one {Riot::Context} instance to the next. It
57
57
  # is highly likely that each {Riot::Context} will instantiate their own middleware instances.
58
58
  class ContextMiddleware
@@ -82,7 +82,7 @@ module Riot
82
82
  end
83
83
 
84
84
  # The magic happens here. Because you have access to the Context, you can add your own setups, hookups,
85
- # etc. +call+ will be called before any tests are run, but after the Context is configured. Though
85
+ # etc. +call+ will be called before any tests are run, but after the Context is configured. Though
86
86
  # something will likely be returned, do not put any faith in what that will be.
87
87
  #
88
88
  # @param [Riot::Context] context the Context instance that will be prepared by registered middleware
@@ -2,7 +2,7 @@ module Riot
2
2
 
3
3
  # A Reporter decides how to output the result of a test. When a context is set to be executed, the
4
4
  # {Riot::Reporter#describe_context} method is called with the context that will be running; this remains
5
- # so until the next context is executed. After each {Riot#Assertion#evaluate assertion is evaluated},
5
+ # so until the next context is executed. After each {Riot::AssertionMacro#evaluate assertion is evaluated},
6
6
  # {Riot::Reporter#report} is called with the description of the assertion and the resulting response.
7
7
  #
8
8
  # The general idea is that a sub-class of Reporter should be defined that knows specifically how to
@@ -22,9 +22,10 @@ module Riot
22
22
  attr_accessor :current_context
23
23
 
24
24
  # Creates a new Reporter instance and initializes counts to zero
25
- def initialize
25
+ def initialize(*args)
26
+ @options = args.extract_options!
26
27
  @passes = @failures = @errors = 0
27
- @current_context = ""
28
+ @current_context = Riot::RootContext.new
28
29
  end
29
30
 
30
31
  def new(*args, &block); self; end
@@ -69,7 +70,7 @@ module Riot
69
70
  @failures += 1
70
71
  message, line, file = *response[1..-1]
71
72
  fail(description, message, line, file)
72
- when :error then
73
+ when :error, :setup_error, :context_error then
73
74
  @errors += 1
74
75
  error(description, result)
75
76
  end
@@ -13,8 +13,8 @@ module Riot
13
13
  # @param [IO] writer the writer to use for results
14
14
  # @param [Hash] options options for reporter
15
15
  def initialize(*args)
16
- super()
17
- @options = (args.last.kind_of?(Hash) ? args.pop : {})
16
+ super
17
+ @options = args.extract_options!
18
18
  @writer = (args.shift || STDOUT)
19
19
  end
20
20
 
@@ -45,17 +45,14 @@ module Riot
45
45
  line ? "(on line #{line} in #{file})" : ""
46
46
  end
47
47
 
48
- # Generates a message for assertions that error out. However, in the additional stacktrace, any mentions
48
+ # Generates a message for assertions that error out. However, in the additional stacktrace, any mentions
49
49
  # of Riot and Rake framework methods calls are removed. Makes for a more readable error response.
50
50
  #
51
51
  # @param [Exception] e the exception to generate the backtrace from
52
52
  # @return [String] the error response message
53
53
  def format_error(e)
54
- format = []
55
- format << " #{e.class.name} occurred"
56
- format << "#{e.to_s}"
54
+ format = [" #{e.class.name} occurred", "#{e.to_s}"]
57
55
  filter_backtrace(e.backtrace) { |line| format << " at #{line}" }
58
-
59
56
  format.join("\n")
60
57
  end
61
58
 
@@ -64,13 +61,8 @@ module Riot
64
61
  # @param [Array] backtrace an exception's backtrace
65
62
  # @param [lambda] &line_handler called each time a good line is found
66
63
  def filter_backtrace(backtrace, &line_handler)
67
- cleansed, bad = [], true
68
-
69
- # goal is to filter all the riot stuff/rake before the first non riot thing
70
64
  backtrace.reverse_each do |bt|
71
- # make sure we are still in the bad part
72
- bad = (bt =~ /\/lib\/riot/ || bt =~ /rake_test_loader/) if bad
73
- yield bt unless bad
65
+ yield bt unless (bt =~ /(\/lib\/riot|rake_test_loader)/)
74
66
  end
75
67
  end
76
68
 
@@ -78,7 +70,7 @@ module Riot
78
70
  def red(str); with_color(31, str); end
79
71
  def yellow(str); with_color(33, str); end
80
72
  def green(str); with_color(32, str); end
81
-
73
+
82
74
  def plain?
83
75
  (@options[:plain] || @options["plain"])
84
76
  end
@@ -30,7 +30,6 @@ module Riot
30
30
  def simple_error(e)
31
31
  format = []
32
32
  filter_backtrace(e.backtrace) { |line| format << "at #{line}" }
33
-
34
33
  format.join("\n")
35
34
  end
36
35
  end
@@ -10,6 +10,11 @@ module Riot
10
10
  # setup, yeardown, helper, hookup, or assertion.
11
11
  class Situation < Riot::Situation
12
12
  include ::RR::Adapters::RRMethods
13
+
14
+ def initialize
15
+ self.reset
16
+ super
17
+ end
13
18
  end # Situation
14
19
 
15
20
  # Binds the {Riot::Assertion} to RR so that successes and failures found by RR are inherently handled
@@ -48,6 +48,8 @@ module Riot
48
48
  def run(situation)
49
49
  situation.setup(&definition)
50
50
  [:setup]
51
+ rescue Exception => e
52
+ [:setup_error, e]
51
53
  end
52
54
  end # Setup
53
55
 
@@ -52,7 +52,7 @@ module Riot
52
52
  end
53
53
 
54
54
  # Anonymously evaluates any block given to it against the current instance of +self+. This is how
55
- # {Riot::Assertion assertion} and {Riot::AssertionMAcro assertion macro} blocks are evaluated,
55
+ # {Riot::Assertion assertion} and {Riot::AssertionMacro assertion macro} blocks are evaluated,
56
56
  # for instance.
57
57
  #
58
58
  # @param [lambda] &block the block to evaluate against +self+
@@ -1,4 +1,4 @@
1
1
  module Riot
2
- VERSION = "0.12.5"
2
+ VERSION = "0.12.6"
3
3
  end
4
4
 
@@ -23,7 +23,7 @@ context "A raises_kind_of assertion macro" do
23
23
 
24
24
  assertion_test_fails("when nothing was raised",
25
25
  "expected to raise kind of Whoops, but raised nothing") do
26
- assertion = Riot::Assertion.new("foo") { "barf" }.raises_kind_of(Whoops)
26
+ Riot::Assertion.new("foo") { "barf" }.raises_kind_of(Whoops)
27
27
  end
28
28
 
29
29
  assertion_test_passes("when provided message equals expected message",
@@ -13,7 +13,7 @@ context "A raises assertion macro" do
13
13
  end
14
14
 
15
15
  assertion_test_fails("when nothing was raised", "expected to raise Whoops, but raised nothing") do
16
- assertion = Riot::Assertion.new("foo") { "barf" }.raises(Whoops)
16
+ Riot::Assertion.new("foo") { "barf" }.raises(Whoops)
17
17
  end
18
18
 
19
19
  assertion_test_passes("when provided message equals expected message", %Q{raises Whoops with message "Mom"}) do
@@ -100,4 +100,24 @@ context "ContextMiddleware" do
100
100
 
101
101
  asserts("tests passed") { topic.passes }.equals(1)
102
102
  end # has access to options after context setup
103
+
104
+ context "that errors while preparing" do
105
+ hookup do
106
+ Class.new(Riot::ContextMiddleware) do
107
+ register
108
+ def call(context)
109
+ raise Exception.new("Banana pants")
110
+ end
111
+ end
112
+ end
113
+
114
+ setup do
115
+ Riot::Context.new("Foo") { asserts_topic.nil }.run(MockReporter.new)
116
+ end
117
+
118
+ asserts("tests passed") { topic.passes }.equals(0)
119
+ asserts("tests failed") { topic.failures }.equals(0)
120
+ asserts("tests errored") { topic.errors }.equals(1)
121
+ end # that is not meant to be used
122
+
103
123
  end # ContextMiddleware
@@ -39,6 +39,11 @@ context "A reporter" do
39
39
  topic.errors
40
40
  end.equals(1)
41
41
 
42
+ asserts("error count increase when :setup_error sent to #report") do
43
+ topic.report("", [:setup_error, ""])
44
+ topic.errors
45
+ end.equals(2)
46
+
42
47
  asserts("description sent to #error") do
43
48
  topic.report("break it down", [:error, "error time"])
44
49
  end.equals("errored(break it down, error time)")
@@ -46,6 +51,7 @@ context "A reporter" do
46
51
  context "instance" do
47
52
  setup { Riot::Reporter.new }
48
53
  should("return self invoking new") { topic.new }.equals { topic }
54
+ should("accept an options hash") { topic.new({}) }.equals { topic }
49
55
  end
50
56
 
51
57
  context "with no errors or failures" do
@@ -44,7 +44,13 @@ context "DotMatrixReporter" do
44
44
  asserts_topic('puts the full context + assertion name').matches('whatever asserts bang')
45
45
  asserts_topic('puts the exception message').matches('BOOM')
46
46
  # <file path>:<one or more number><two newlines><anything till end of line><newline> is the last thing in the stack trace
47
- asserts_topic('puts the filtered exception backtrace').matches(/#{__FILE__}:\d+:[^\n]*\n\n.*$\n\z/)
47
+ asserts_topic('puts the filtered exception backtrace').matches do
48
+ if RUBY_VERSION =~ /^1.8.\d+/
49
+ /#{__FILE__}:\d+\n\n.*$\n\z/
50
+ else
51
+ /#{__FILE__}:\d+:[^\n]*\n\n.*$\n\z/
52
+ end
53
+ end
48
54
  end
49
55
  end
50
56
 
@@ -20,20 +20,18 @@ context "StoryReporter" do
20
20
 
21
21
  context 'reporting on an empty context' do
22
22
  setup do
23
- context = Riot::Context.new('empty context') do
23
+ context = Riot::Context.new('empty context') {
24
24
  context("a nested empty context") {}
25
- end
26
- context.run(topic)
25
+ }.run(topic)
27
26
  end
28
27
  should("not output context name") { @out.string }.empty
29
28
  end
30
29
 
31
30
  context "reporting on a non-empty context" do
32
31
  setup do
33
- context = Riot::Context.new('supercontext') do
32
+ Riot::Context.new('supercontext') {
34
33
  asserts("truth") { true }
35
- end
36
- context.run(topic)
34
+ }.run(topic)
37
35
  end
38
36
 
39
37
  should('output context name') { @out.string }.matches(/supercontext/)
@@ -0,0 +1,47 @@
1
+ require 'teststrap'
2
+
3
+ context "Executing setup with an error" do
4
+ setup do
5
+ Riot::Setup.new { raise "Error in setup" }.run(Riot::Situation.new)
6
+ end
7
+
8
+ asserts("result") { topic[0] }.equals(:setup_error)
9
+ asserts("result object") { topic[1] }.kind_of(Exception)
10
+ asserts("error message") { topic[1].message }.equals("Error in setup")
11
+
12
+ end # Executing setup with an error
13
+
14
+ context "Executing a context" do
15
+ context "that errors during setup" do
16
+ setup do
17
+ Riot::Context.new("A") {
18
+ setup { raise "Whoopsie!" } # error
19
+ asserts("foo") { true } # success
20
+ asserts("bar") { false } # failure
21
+ }.run(Riot::SilentReporter.new)
22
+ end
23
+
24
+ asserts(:errors).equals(1)
25
+ asserts(:failures).equals(0)
26
+ asserts(:passes).equals(0)
27
+ end # that errors during setup
28
+
29
+ context "that errors in a parent setup" do
30
+ setup do
31
+ Riot::Context.new("A") {
32
+ setup { raise "Whoopsie!" } # error
33
+
34
+ context "B" do
35
+ asserts("foo") { true } # success
36
+ asserts("bar") { false } # failure
37
+ end
38
+ }.run(Riot::SilentReporter.new)
39
+ end
40
+
41
+ asserts(:errors).equals(2) # Same setup fails twice
42
+ asserts(:failures).equals(0)
43
+ asserts(:passes).equals(0)
44
+ end # that errors in a parent setup
45
+
46
+ end # Executing a cotext
47
+
@@ -1,7 +1,9 @@
1
1
  $:.unshift(File.dirname(__FILE__) + "/../lib/")
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+
2
5
  require 'riot'
3
6
  Riot.verbose
4
-
5
7
  Riot.pretty_dots if ENV["TM_MODE"]
6
8
 
7
9
  module Riot
metadata CHANGED
@@ -1,39 +1,41 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: riot
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.12.6
4
5
  prerelease:
5
- version: 0.12.5
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Justin 'Gus' Knowlden
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-09-13 00:00:00 -05:00
14
- default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
12
+ date: 2013-07-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
17
15
  name: rr
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
20
17
  none: false
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
25
22
  type: :runtime
26
- version_requirements: *id001
27
- description: An extremely fast, expressive, and context-driven unit-testing framework. A replacement for all other testing frameworks. Protest the slow test.
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: An extremely fast, expressive, and context-driven unit-testing framework.
31
+ A replacement for all other testing frameworks. Protest the slow test.
28
32
  email: gus@gusg.us
29
33
  executables: []
30
-
31
34
  extensions: []
32
-
33
35
  extra_rdoc_files: []
34
-
35
- files:
36
+ files:
36
37
  - .gitignore
38
+ - .travis.yml
37
39
  - .yardopts
38
40
  - CHANGELOG
39
41
  - Gemfile
@@ -112,6 +114,7 @@ files:
112
114
  - test/core/reports/story_reporter_test.rb
113
115
  - test/core/runnable/assertion_macro_test.rb
114
116
  - test/core/runnable/assertion_test.rb
117
+ - test/core/runnable/erroring_gracefully_test.rb
115
118
  - test/core/runnable/message_test.rb
116
119
  - test/core/runnable/negative_assertion_test.rb
117
120
  - test/core/runnable/setup_test.rb
@@ -119,35 +122,32 @@ files:
119
122
  - test/core/runnable/teardown_test.rb
120
123
  - test/extensions/rrriot_test.rb
121
124
  - test/teststrap.rb
122
- has_rdoc: true
123
125
  homepage: http://github.com/thumblemonks/riot
124
126
  licenses: []
125
-
126
127
  post_install_message:
127
128
  rdoc_options: []
128
-
129
- require_paths:
129
+ require_paths:
130
130
  - lib
131
- required_ruby_version: !ruby/object:Gem::Requirement
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
132
  none: false
133
- requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- version: "0"
137
- required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  none: false
139
- requirements:
140
- - - ">="
141
- - !ruby/object:Gem::Version
142
- version: "0"
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
143
  requirements: []
144
-
145
144
  rubyforge_project:
146
- rubygems_version: 1.6.2
145
+ rubygems_version: 1.8.25
147
146
  signing_key:
148
147
  specification_version: 3
149
- summary: An extremely fast, expressive, and context-driven unit-testing framework. Protest the slow test.
150
- test_files:
148
+ summary: An extremely fast, expressive, and context-driven unit-testing framework.
149
+ Protest the slow test.
150
+ test_files:
151
151
  - test/benchmark/message_concatenation.rb
152
152
  - test/benchmark/riot_vs_minitest.rb
153
153
  - test/benchmark/same_elements_vs_set.rb
@@ -186,6 +186,7 @@ test_files:
186
186
  - test/core/reports/story_reporter_test.rb
187
187
  - test/core/runnable/assertion_macro_test.rb
188
188
  - test/core/runnable/assertion_test.rb
189
+ - test/core/runnable/erroring_gracefully_test.rb
189
190
  - test/core/runnable/message_test.rb
190
191
  - test/core/runnable/negative_assertion_test.rb
191
192
  - test/core/runnable/setup_test.rb