Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' into retry-failures

* master: (24 commits)
  fix copy/paste oversight
  Don't process filters when the metadata doesn't even have the key.
  Changelog for #564
  Fix autotest when RSpec executable path contains spaces
  it was rescue false, not rescue nil
  Changelog for #556
  don't rescue from calling proc filters
  dev: need to include dev rspec in case dependent gems depend on rspec
  ci: it's gem, not rubygems
  ci: it's before_install (RTFM)
  ci: one more try ...
  ci: before_script doesn't run before bundling, so no way to run against ree for now
  ci: update rubygems if < 1.8 (needed for ZenTest in ree)
  simplify spec for #reset
  Spec for RSpec::Core::World#reset
  Changelog for prev commit
  doc formatter strips whitespace from group and example descriptions
  changelog
  Pluralization support for runtime duration output (minute).
  Added spec for patched case
  ...
  • Loading branch information...
commit 1ce51ea803cad5b905d166cecc89d8813980a228 2 parents 640a018 + b06bc35
@oggy authored
View
2  .travis.yml
@@ -1,3 +1,5 @@
+before_install:
+ - if [[ `gem -v` != 1.8.* ]]; then gem update --system; fi
script: "bin/rake --trace 2>&1"
bundler_args: "--binstubs"
rvm:
View
8 Changelog.md
@@ -1,10 +1,18 @@
### dev
+Enhancements
+
+* Support for "X minutes X seconds" spec run duration in formatter. (uzzz)
+* Strip whitespace from group and example names in doc formatter.
+
Bug fixes
* Restore `--full_backtrace` option
* Ensure that values passed to `config.filter_run` are respected when running
over DRb (using spork).
+* Ensure shared example groups are reset after a run (as example groups are).
+* Remove `rescue false` from calls to filters represented as Procs
+* Ensure described_class gets the closest constant (pyromaniac)
### 2.8.0 / 2012-01-04
View
2  Gemfile
@@ -3,7 +3,7 @@ source "http://rubygems.org"
gemspec
### rspec libs
-%w[rspec-core rspec-expectations rspec-mocks].each do |lib|
+%w[rspec rspec-core rspec-expectations rspec-mocks].each do |lib|
library_path = File.expand_path("../../#{lib}", __FILE__)
if File.exist?(library_path)
gem lib, :path => library_path
View
4 features/mock_framework_integration/use_flexmock.feature
@@ -9,7 +9,7 @@ Feature: mock with flexmock
config.mock_framework = :flexmock
end
- describe "mocking with RSpec" do
+ describe "mocking with Flexmock" do
it "passes when it should" do
receiver = flexmock('receiver')
receiver.should_receive(:message).once
@@ -27,7 +27,7 @@ Feature: mock with flexmock
config.mock_framework = :flexmock
end
- describe "mocking with RSpec" do
+ describe "mocking with Flexmock" do
it "fails when it should" do
receiver = flexmock('receiver')
receiver.should_receive(:message).once
View
4 features/step_definitions/additional_cli_steps.rb
@@ -11,8 +11,8 @@
end
Then /^the example(?:s)? should(?: all)? pass$/ do
- Then %q{the output should contain "0 failures"}
- Then %q{the exit status should be 0}
+ step %q{the output should contain "0 failures"}
+ step %q{the exit status should be 0}
end
Then /^the file "([^"]*)" should contain:$/ do |file, partial_content|
View
2  lib/autotest/rspec2.rb
@@ -47,7 +47,7 @@ def consolidate_failures(failed)
# Overrides Autotest's implementation to generate the rspec command to run
def make_test_cmd(files_to_test)
files_to_test.empty? ? '' :
- "#{prefix}#{ruby}#{suffix} -S #{RSPEC_EXECUTABLE} --tty #{normalize(files_to_test).keys.flatten.map { |f| "'#{f}'"}.join(' ')}"
+ "#{prefix}#{ruby}#{suffix} -S '#{RSPEC_EXECUTABLE}' --tty #{normalize(files_to_test).keys.flatten.map { |f| "'#{f}'"}.join(' ')}"
end
# Generates a map of filenames to Arrays for Autotest
View
40 lib/rspec/core/configuration.rb
@@ -546,10 +546,26 @@ def alias_it_should_behave_like_to(new_name, report_label = '')
# or config files (e.g. `.rspec`).
#
# @example
- # filter_run_including :x => 'y'
+ # # given this declaration
+ # describe "something", :foo => 'bar' do
+ # # ...
+ # end
+ #
+ # # any of the following will include that group
+ # config.filter_run_including :foo => 'bar'
+ # config.filter_run_including :foo => /^ba/
+ # config.filter_run_including :foo => lambda {|v| v == 'bar'}
+ # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
+ #
+ # # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
+ # config.filter_run_including :foo => lambda {|v| v == 'bar'}
+ #
+ # # given a proc with an arity of 2, the lambda is passed the value related to the key,
+ # # and the metadata itself e.g.
+ # config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
#
# # with treat_symbols_as_metadata_keys_with_true_values = true
- # filter_run_including :foo # results in {:foo => true}
+ # filter_run_including :foo # same as filter_run_including :foo => true
def filter_run_including(*args)
filter_manager.include_with_low_priority build_metadata_hash_from(args)
end
@@ -588,10 +604,26 @@ def inclusion_filter
# or config files (e.g. `.rspec`).
#
# @example
- # filter_run_excluding :x => 'y'
+ # # given this declaration
+ # describe "something", :foo => 'bar' do
+ # # ...
+ # end
+ #
+ # # any of the following will exclude that group
+ # config.filter_run_excluding :foo => 'bar'
+ # config.filter_run_excluding :foo => /^ba/
+ # config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
+ # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
+ #
+ # # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
+ # config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
+ #
+ # # given a proc with an arity of 2, the lambda is passed the value related to the key,
+ # # and the metadata itself e.g.
+ # config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
#
# # with treat_symbols_as_metadata_keys_with_true_values = true
- # filter_run_excluding :foo # results in {:foo => true}
+ # filter_run_excluding :foo # same as filter_run_excluding :foo => true
def filter_run_excluding(*args)
filter_manager.exclude_with_low_priority build_metadata_hash_from(args)
end
View
2  lib/rspec/core/filter_manager.rb
@@ -67,7 +67,7 @@ module Core
# @see Configuration#filter_run_excluding
class FilterManager
DEFAULT_EXCLUSIONS = {
- :if => lambda { |value, metadata| metadata.has_key?(:if) && !value },
+ :if => lambda { |value| !value },
:unless => lambda { |value| value }
}
View
6 lib/rspec/core/formatters/base_text_formatter.rb
@@ -35,7 +35,7 @@ def dump_summary(duration, example_count, failure_count, pending_count)
super(duration, example_count, failure_count, pending_count)
# Don't print out profiled info if there are failures, it just clutters the output
dump_profile if profile_examples? && failure_count == 0
- output.puts "\nFinished in #{format_seconds(duration)} seconds\n"
+ output.puts "\nFinished in #{format_duration(duration)}\n"
output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
dump_commands_to_rerun_failed_examples
end
@@ -142,10 +142,6 @@ def long_padding
private
- def pluralize(count, string)
- "#{count} #{string}#{'s' unless count == 1}"
- end
-
def format_caller(caller_info)
backtrace_line(caller_info.to_s.split(':in `block').first)
end
View
12 lib/rspec/core/formatters/documentation_formatter.rb
@@ -3,9 +3,7 @@
module RSpec
module Core
module Formatters
-
class DocumentationFormatter < BaseTextFormatter
-
def initialize(output)
super(output)
@group_level = 0
@@ -15,7 +13,7 @@ def example_group_started(example_group)
super(example_group)
output.puts if @group_level == 0
- output.puts "#{current_indentation}#{example_group.description}"
+ output.puts "#{current_indentation}#{example_group.description.strip}"
@group_level += 1
end
@@ -40,7 +38,7 @@ def example_failed(example)
end
def failure_output(example, exception)
- red("#{current_indentation}#{example.description} (FAILED - #{next_failure_index})")
+ red("#{current_indentation}#{example.description.strip} (FAILED - #{next_failure_index})")
end
def next_failure_index
@@ -49,11 +47,11 @@ def next_failure_index
end
def passed_output(example)
- green("#{current_indentation}#{example.description}")
+ green("#{current_indentation}#{example.description.strip}")
end
def pending_output(example, message)
- yellow("#{current_indentation}#{example.description} (PENDING: #{message})")
+ yellow("#{current_indentation}#{example.description.strip} (PENDING: #{message})")
end
def current_indentation
@@ -63,9 +61,7 @@ def current_indentation
def example_group_chain
example_group.ancestors.reverse
end
-
end
-
end
end
end
View
15 lib/rspec/core/formatters/helpers.rb
@@ -6,6 +6,17 @@ module Helpers
SUB_SECOND_PRECISION = 5
DEFAULT_PRECISION = 2
+ def format_duration(duration)
+ if duration > 60
+ minutes = duration.to_i / 60
+ seconds = duration - minutes * 60
+
+ "#{pluralize(minutes, 'minute')} #{format_seconds(seconds)} seconds"
+ else
+ "#{format_seconds(duration)} seconds"
+ end
+ end
+
def format_seconds(float)
precision ||= (float < 1) ? SUB_SECOND_PRECISION : DEFAULT_PRECISION
formatted = sprintf("%.#{precision}f", float)
@@ -17,6 +28,10 @@ def strip_trailing_zeroes(string)
stripped.empty? ? "0" : stripped
end
+ def pluralize(count, string)
+ "#{count} #{string}#{'s' unless count == 1}"
+ end
+
end
end
View
17 lib/rspec/core/metadata.rb
@@ -102,8 +102,8 @@ module GroupMetadataHash
def described_class
container_stack.each do |g|
- return g[:describes] if g.has_key?(:describes)
return g[:described_class] if g.has_key?(:described_class)
+ return g[:describes] if g.has_key?(:describes)
end
container_stack.reverse.each do |g|
@@ -174,20 +174,15 @@ def filter_applies?(key, value, metadata=self)
return metadata.location_filter_applies?(value) if key == :locations
return metadata.filters_apply?(key, value) if Hash === value
+ return false unless metadata.has_key?(key)
+
case value
when Regexp
metadata[key] =~ value
when Proc
- if value.arity == 2
- # Pass the metadata hash to allow the proc to check if it even has the key.
- # This is necessary for the implicit :if exclusion filter:
- # { } # => run the example
- # { :if => nil } # => exclude the example
- # The value of metadata[:if] is the same in these two cases but
- # they need to be treated differently.
- value.call(metadata[key], metadata) rescue false
- else
- value.call(metadata[key]) rescue false
+ case value.arity
+ when 1 then value.call(metadata[key])
+ when 2 then value.call(metadata[key], metadata)
end
when Array
value.include?(metadata[key].to_s)
View
14 lib/rspec/core/world.rb
@@ -4,12 +4,13 @@ class World
include RSpec::Core::Hooks
- attr_reader :example_groups, :filtered_examples, :wants_to_quit
- attr_writer :wants_to_quit
+ attr_reader :example_groups, :shared_example_groups, :filtered_examples
+ attr_accessor :wants_to_quit
def initialize(configuration=RSpec.configuration)
@configuration = configuration
@example_groups = [].extend(Extensions::Ordered)
+ @shared_example_groups = {}
@filtered_examples = Hash.new { |hash,group|
hash[group] = begin
examples = group.examples.dup
@@ -22,6 +23,7 @@ def initialize(configuration=RSpec.configuration)
def reset
example_groups.clear
+ shared_example_groups.clear
end
def filter_manager
@@ -45,12 +47,10 @@ def configure_group(group)
@configuration.configure_group(group)
end
- def shared_example_groups
- @shared_example_groups ||= {}
- end
-
def example_count
- example_groups.collect {|g| g.descendants}.flatten.inject(0) { |sum, g| sum += g.filtered_examples.size }
+ example_groups.collect {|g| g.descendants}.flatten.inject(0) do |sum, g|
+ sum += g.filtered_examples.size
+ end
end
def preceding_declaration_line(filter_line)
View
2  spec/autotest/rspec_spec.rb
@@ -30,7 +30,7 @@
it "makes the appropriate test command" do
actual_command = rspec_autotest.make_test_cmd(@files_to_test)
- expected_command = /#{ruby_cmd}.*#{spec_cmd} (.*)/
+ expected_command = /#{ruby_cmd}.*'#{spec_cmd}' (.*)/
actual_command.should match(expected_command)
View
16 spec/rspec/core/configuration_spec.rb
@@ -751,20 +751,16 @@ def metadata_hash(*args)
end
describe "the default :if filter" do
- it "does not exclude a spec with no :if metadata" do
- config.exclusion_filter[:if].call(nil, {}).should be_false
+ it "does not exclude a spec with { :if => true } metadata" do
+ config.exclusion_filter[:if].call(true).should be_false
end
- it "does not exclude a spec with { :if => true } metadata" do
- config.exclusion_filter[:if].call(true, {:if => true}).should be_false
+ it "excludes a spec with { :if => false } metadata" do
+ config.exclusion_filter[:if].call(false).should be_true
end
- it "excludes a spec with { :if => false } metadata" do
- config.exclusion_filter[:if].call(false, {:if => false}).should be_true
- end
-
- it "excludes a spec with { :if => nil } metadata" do
- config.exclusion_filter[:if].call(false, {:if => nil}).should be_true
+ it "excludes a spec with { :if => nil } metadata" do
+ config.exclusion_filter[:if].call(nil).should be_true
end
end
View
16 spec/rspec/core/example_group_spec.rb
@@ -293,6 +293,22 @@ def metadata_hash(*args)
group.run.should be_true
end
end
+
+ context "and metadata redefinition after `described_class` call" do
+ it "is the redefined level constant" do
+ group = ExampleGroup.describe(String) do
+ described_class
+ metadata[:example_group][:described_class] = Object
+ describe :symbol do
+ example "described_class is Object" do
+ described_class.should eq(Object)
+ end
+ end
+ end
+
+ group.run.should be_true
+ end
+ end
end
context "in a nested group" do
View
24 spec/rspec/core/formatters/documentation_formatter_spec.rb
@@ -28,7 +28,6 @@ module RSpec::Core::Formatters
end
it "represents nested group using hierarchy tree" do
-
output = StringIO.new
RSpec.configuration.stub(:color_enabled?) { false }
@@ -62,5 +61,28 @@ module RSpec::Core::Formatters
nested example 2.2
")
end
+
+ it "strips whitespace for each row" do
+ output = StringIO.new
+ RSpec.configuration.stub(:color_enabled?) { false }
+
+ formatter = RSpec::Core::Formatters::DocumentationFormatter.new(output)
+
+ group = RSpec::Core::ExampleGroup.describe(" root ")
+ context1 = group.describe(" nested ")
+ context1.example(" example 1 ") {}
+ context1.example(" example 2 ", :pending => true){}
+ context1.example(" example 3 ") { fail }
+
+ group.run(RSpec::Core::Reporter.new(formatter))
+
+ output.string.should eql("
+root
+ nested
+ example 1
+ example 2 (PENDING: No reason given)
+ example 3 (FAILED - 1)
+")
+ end
end
end
View
20 spec/rspec/core/formatters/helpers_spec.rb
@@ -4,6 +4,26 @@
describe RSpec::Core::Formatters::Helpers do
let(:helper) { Object.new.extend(RSpec::Core::Formatters::Helpers) }
+ describe "format duration" do
+ context '> 60 and < 120' do
+ it "returns 'x minute xx seconds' formatted string" do
+ helper.format_duration(70.14).should eq("1 minute 10.14 seconds")
+ end
+ end
+
+ context '> 120' do
+ it "returns 'x minutes xx seconds' formatted string" do
+ helper.format_duration(135.14).should eq("2 minutes 15.14 seconds")
+ end
+ end
+
+ context '< 60' do
+ it "returns 'xx seconds' formatted string" do
+ helper.format_duration(45.5).should eq("45.5 seconds")
+ end
+ end
+ end
+
describe "format seconds" do
context "sub second times" do
it "returns 5 digits of precision" do
View
7 spec/rspec/core/metadata_spec.rb
@@ -126,10 +126,9 @@ module Core
example_metadata.filter_applies?(:if, lambda { |v| !v }).should be_false
end
- it "passes the metadata hash as the second argument if a given proc expects 2 args" do
- passed_metadata = nil
- example_metadata.filter_applies?(:if, lambda { |v, m| passed_metadata = m })
- passed_metadata.should eq(example_metadata)
+ it "matches a proc with an arity of 2" do
+ example_metadata[:foo] = nil
+ example_metadata.filter_applies?(:foo, lambda { |v, m| m == example_metadata }).should be_true
end
context "with an Array" do
View
4 spec/rspec/core/shared_example_group_spec.rb
@@ -2,7 +2,7 @@
module RSpec::Core
describe SharedExampleGroup do
-
+
ExampleModule = Module.new
ExampleClass = Class.new
@@ -19,7 +19,7 @@ module RSpec::Core
group.send(method_name, 'shared group') {}
end.should raise_error(ArgumentError, "Shared example group 'shared group' already exists")
end
-
+
["name", :name, ExampleModule, ExampleClass].each do |object|
type = object.class.name.downcase
context "given a #{type}" do
View
12 spec/rspec/core/world_spec.rb
@@ -9,6 +9,16 @@ module RSpec::Core
let(:configuration) { RSpec::Core::Configuration.new }
let(:world) { RSpec::Core::World.new(configuration) }
+ describe '#reset' do
+ it 'clears #example_groups and #shared_example_groups' do
+ world.example_groups << :example_group
+ world.shared_example_groups[:shared] = :example_group
+ world.reset
+ world.example_groups.should be_empty
+ world.shared_example_groups.should be_empty
+ end
+ end
+
describe "#example_groups" do
it "contains all registered example groups" do
group = RSpec::Core::ExampleGroup.describe("group"){}
@@ -64,7 +74,7 @@ module RSpec::Core
context "with two exaples and the second example is registre first" do
let(:second_group_declaration_line) { second_group.metadata[:example_group][:line_number] }
- before do
+ before do
world.register(second_group)
world.register(group)
end
Please sign in to comment.
Something went wrong with that request. Please try again.