Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

Commit

Permalink
Pending blocks will now be executed and marked as failed if they
Browse files Browse the repository at this point in the history
succeed.

This is a backwards incompatible change that makes the behaviour of a
top-level `pending` call the sames as one used within an `it` block.

The old "never run this example" behaviour is still available via the
`xit` method or the `:skip` metadata option.

Implements #1208.
  • Loading branch information
xaviershay committed Feb 1, 2014
1 parent d8b6f34 commit 8de02e3
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 21 deletions.
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ Breaking Changes for 3.0.0:
* Remove support for deprecated `--configure` CLI option. (Myron Marston)
* Remove support for deprecated `RSpec::Core::RakeTask#spec_opts=`.
(Myron Marston)
* A top-level `pending` block or `:pending` metadata now behaves the same as
a `pending` block inside an example: it will be executed and cause a failure
if it passes, otherwise it will be pending if it fails. The old "never run"
behaviour is still available via the `xit` method or `:skip` metadata option.
(Xavier Shay)

Enhancements:

Expand Down
2 changes: 1 addition & 1 deletion features/command_line/format_option.feature
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Feature: --format option
end
it "does something that is pending", :pending => true do
expect(5).to be > 3
expect(5).to be < 3
end
end
"""
Expand Down
18 changes: 17 additions & 1 deletion features/pending/pending_examples.feature
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ Feature: pending examples
And the output should contain "Expected pending 'something else getting finished' to fail. No Error was raised."
And the output should contain "pending_with_passing_block_spec.rb:3"

Scenario: pending any arbitrary reason, with a top-level block that passes
Given a file named "pending_with_passing_block_spec.rb" with:
"""ruby
describe "an example" do
pending("something else getting finished") do
expect(1).to eq(1)
end
end
"""
When I run `rspec pending_with_passing_block_spec.rb`
Then the exit status should not be 0
And the output should contain "1 example, 1 failure"
And the output should contain "FIXED"
And the output should contain "Expected pending 'something else getting finished' to fail. No Error was raised."
And the output should contain "pending_with_passing_block_spec.rb:2"

Scenario: temporarily pending by prefixing `it`, `specify`, or `example` with an x
Given a file named "temporarily_pending_spec.rb" with:
"""ruby
Expand Down Expand Up @@ -138,7 +154,7 @@ Feature: pending examples
expect(3+4).to eq(7)
end
pending do
expect("string".reverse).to eq("gnirts")
fail
end
end
"""
Expand Down
15 changes: 4 additions & 11 deletions lib/rspec/core/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ def self.delegate_to_metadata(*keys)
keys.each { |key| define_method(key) { @metadata[key] } }
end

delegate_to_metadata :full_description, :execution_result, :file_path, :location, :skip

def pending
@metadata.fetch(:pending, skip)
end
delegate_to_metadata :full_description, :execution_result, :file_path, :location, :skip, :pending

# Returns the string submitted to `example` or its aliases (e.g.
# `specify`, `it`, etc). If no string is submitted (e.g. `it { is_expected.to
Expand Down Expand Up @@ -98,11 +94,8 @@ def example_group
@example_group_class
end

def skipped?
pending || skip
end

alias_method :pending?, :skipped?
alias_method :pending?, :pending
alias_method :skipped?, :skip

# @api private
# instance_evals the block passed to the constructor in the context of
Expand Down Expand Up @@ -269,7 +262,7 @@ def finish(reporter)
reporter.example_pending self
true
elsif skipped?
record_finished 'pending', :pending_message => String === pending ? pending : Pending::NO_REASON_GIVEN
record_finished 'pending', :pending_message => String === skip ? skip : Pending::NO_REASON_GIVEN
reporter.example_pending self
true
else
Expand Down
37 changes: 35 additions & 2 deletions lib/rspec/core/example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,52 @@ def description
# @private
alias_method :describes, :described_class

# @private
def self.wrap_pending_block(pending, block)
reason = if String === pending
pending
else
RSpec::Core::Pending::NO_REASON_GIVEN
end

lambda {|*args|
pending(reason) do
if block
instance_exec(&block)
else
fail
end
end
}
end

# @private
# @macro [attach] define_example_method
# @param [String] name
# @param [Hash] extra_options
# @param [Block] implementation
# @yield [Example] the example object
def self.define_example_method(name, extra_options={})
this = self
define_method(name) do |*all_args, &block|
desc, *args = *all_args
options = Metadata.build_hash_from(args)
options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
options.update(extra_options)
examples << RSpec::Core::Example.new(self, desc, options, block)

pending = if name == :pending
desc || options[:pending]
else
options[:pending]
end

callback = if pending
this.wrap_pending_block(pending, block)
else
block
end

examples << RSpec::Core::Example.new(self, desc, options, callback)
examples.last
end
end
Expand Down Expand Up @@ -102,7 +135,7 @@ def self.define_example_method(name, extra_options={})

# Shortcut to define an example with :pending => true
# @see example
define_example_method :pending, :skip => true
define_example_method :pending, :pending => true
# Shortcut to define an example with :pending => 'Temporarily disabled with xexample'
# @see example
define_example_method :xexample, :skip => 'Temporarily disabled with xexample'
Expand Down
22 changes: 18 additions & 4 deletions spec/rspec/core/example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -888,24 +888,38 @@ def define_and_run_group(define_outer_example = false)
end
end

%w[pending xit xspecify xexample].each do |method_name|
%w[pending].each do |method_name|
describe "::#{method_name}" do
before do
@group = ExampleGroup.describe
@group.send(method_name, "is pending") { }
@group.send(method_name) { fail }
end

it "generates a pending example" do
@group.run
expect(@group.examples.first).to be_pending
end

it "sets the pending message", :if => method_name == 'pending' do
it "sets the pending message" do
@group.run
expect(@group.examples.first.metadata[:execution_result][:pending_message]).to eq(RSpec::Core::Pending::NO_REASON_GIVEN)
end
end
end

%w[xit xspecify xexample].each do |method_name|
describe "::#{method_name}" do
before do
@group = ExampleGroup.describe
@group.send(method_name, "is pending") { }
end

it "generates a skipped example" do
@group.run
expect(@group.examples.first).to be_skipped
end

it "sets the pending message", :unless => method_name == 'pending' do
it "sets the pending message" do
@group.run
expect(@group.examples.first.metadata[:execution_result][:pending_message]).to eq("Temporarily disabled with #{method_name}")
end
Expand Down
2 changes: 1 addition & 1 deletion spec/rspec/core/formatters/documentation_formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ module RSpec::Core::Formatters
group = RSpec::Core::ExampleGroup.describe(" root ")
context1 = group.describe(" nested ")
context1.example(" example 1 ") {}
context1.example(" example 2 ", :pending => true){}
context1.example(" example 2 ", :pending => true){ fail }
context1.example(" example 3 ") { fail }

group.run(reporter)
Expand Down
14 changes: 13 additions & 1 deletion spec/rspec/core/pending_example_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@
end
end

matcher :be_skipped_with do |message|
match do |example|
example.skipped? && example.metadata[:execution_result][:pending_message] == message
end

failure_message_for_should do |example|
"expected: example skipped with #{message.inspect}\n got: #{example.metadata[:execution_result][:pending_message].inspect}"
end
end

context "declared pending with metadata" do
it "uses the value assigned to :pending as the message" do
group = RSpec::Core::ExampleGroup.describe('group') do
example "example", :pending => 'just because' do
fail
end
end
example = group.examples.first
Expand All @@ -25,6 +36,7 @@
it "sets the message to 'No reason given' if :pending => true" do
group = RSpec::Core::ExampleGroup.describe('group') do
example "example", :pending => true do
fail
end
end
example = group.examples.first
Expand All @@ -40,7 +52,7 @@
end
example = group.examples.first
example.run(group.new, double.as_null_object)
expect(example).to be_pending_with('Not yet implemented')
expect(example).to be_skipped_with('Not yet implemented')
end
end

Expand Down

0 comments on commit 8de02e3

Please sign in to comment.