Skip to content

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 Jan 26, 2014
1 parent 00772d4 commit 861e7d5
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 21 deletions.
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 861e7d5

Please sign in to comment.