diff --git a/.gitignore b/.gitignore index d127824c7e..103edbc792 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ bin .yardoc vendor Gemfile-custom +.idea +bundle diff --git a/.travis.yml b/.travis.yml index 0c51876e69..392ec1ce66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,13 @@ before_install: - if [[ `gem -v` != 1.8.* ]]; then gem update --system; fi -script: "bin/rake --trace 2>&1" +script: "script/test_all 2>&1 && bin/rake cucumber --backtrace 2>&1" bundler_args: "--binstubs" rvm: - 1.8.7 - 1.9.2 - 1.9.3 - ree - - jruby + - jruby-18mode + - jruby-19mode + - rbx-18mode + - rbx-19mode diff --git a/Changelog.md b/Changelog.md index d48db17ae9..6b0d15da62 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,62 @@ +### 2.12.0 / 2012-11-12 +[full changelog](http://github.com/rspec/rspec-core/compare/v2.11.1...2.12.0) + +Enhancements + +* Add support for custom ordering strategies for groups and examples. + (Myron Marston) +* JSON Formatter (Alex Chaffee) +* Refactor rake task internals (Sam Phippen) +* Refactor HtmlFormatter (Pete Hodgson) +* Autotest supports a path to Ruby that contains spaces (dsisnero) +* Provide a helpful warning when a shared example group is redefined. + (Mark Burns). +* `--default_path` can be specified as `--default-line`. `--line_number` can be + specified as `--line-number`. Hyphens are more idiomatic command line argument + separators (Sam Phippen). +* A more useful error message is shown when an invalid command line option is + used (Jordi Polo). +* Add `format_docstrings { |str| }` config option. It can be used to + apply formatting rules to example group and example docstrings. + (Alex Tan) +* Add support for an `.rspec-local` options file. This is intended to + allow individual developers to set options in a git-ignored file that + override the common project options in `.rspec`. (Sam Phippen) +* Support for mocha 0.13.0. (Andy Lindeman) + +Bug fixes + +* Remove override of `ExampleGroup#ancestors`. This is a core ruby method that + RSpec shouldn't override. Instead, define `ExampleGroup#parent_groups`. (Myron + Marston) +* Limit monkey patching of shared example/context declaration methods + (`shared_examples_for`, etc.) to just the objects that need it rather than + every object in the system (Myron Marston). +* Fix Metadata#fetch to support computed values (Sam Goldman). +* Named subject can now be referred to from within subject block in a nested + group (tomykaira). +* Fix `fail_fast` so that it properly exits when an error occurs in a + `before(:all) hook` (Bradley Schaefer). +* Make the order spec files are loaded consistent, regardless of the + order of the files returned by the OS or the order passed at + the command line (Jo Liss and Sam Phippen). +* Ensure instance variables from `before(:all)` are always exposed + from `after(:all)`, even if an error occurs in `before(:all)` + (Sam Phippen). +* `rspec --init` no longer generates an incorrect warning about `--configure` + being deprecated (Sam Phippen). +* Fix pluralization of `1 seconds` (Odin Dutton) +* Fix ANSICON url (Jarmo Pertman) +* Use dup of Time so reporting isn't clobbered by examples that modify Time + without properly restoring it. (David Chelimsky) + +Deprecations + +* `share_as` is no longer needed. `shared_context` and/or + `RSpec::SharedContext` provide better mechanisms (Sam Phippen). +* Deprecate `RSpec.configuration` with a block (use `RSpec.configure`). + + ### 2.11.1 / 2012-07-18 [full changelog](http://github.com/rspec/rspec-core/compare/v2.11.0...v2.11.1) diff --git a/Gemfile b/Gemfile index 0288d0d8c8..bd984ca04e 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source "http://rubygems.org" gemspec -%w[rspec rspec-core rspec-expectations rspec-mocks].each do |lib| +%w[rspec rspec-expectations rspec-mocks].each do |lib| library_path = File.expand_path("../../#{lib}", __FILE__) if File.exist?(library_path) gem lib, :path => library_path diff --git a/Gemfile-custom.sample b/Gemfile-custom.sample index cf0bca45c1..a5017674b5 100644 --- a/Gemfile-custom.sample +++ b/Gemfile-custom.sample @@ -1,34 +1,19 @@ group :development do gem 'interactive_rspec' - gem 'relish', '~> 0.5.0' - gem 'guard-rspec', '0.5.0' + gem 'relish', '~> 0.6.0' + gem 'guard-rspec', '~> 1.2.1' gem 'growl', '1.0.3' gem 'spork', '0.9.0' platform :mri do - gem 'rb-fsevent', '~> 0.4.3.1' + gem 'rb-fsevent', '~> 0.9.0' gem 'ruby-prof', '~> 0.10.0' case RUBY_VERSION when /^1.8/ gem 'ruby-debug' - when '1.9.2' - gem 'ruby-debug19', '0.11.6' - gem 'ruby-debug-base19', '0.11.25' - gem 'linecache19', '0.5.12' - when '1.9.3' - gem 'ruby-debug19', '0.11.6' - # NOTE - as of 2012-03-17 the following two gems have not been released, - # so if you see either of these errors when trying to install the bundle: - # - # Could not find gem 'ruby-debug-base19 (= 0.11.26) ruby' in the gems available on this machine. - # Could not find gem 'linecache19 (= 0.5.13) ruby' in the gems available on this machine. - # - # ... run 'script/download-ruby-debug-19-dependencies' and try again - # - # See http://blog.wyeworks.com/2011/11/1/ruby-1-9-3-and-ruby-debug for more info. - gem 'ruby-debug-base19', '0.11.26' - gem 'linecache19', '0.5.13' + when /^1.9/ + gem 'debugger' end end end diff --git a/README.md b/README.md index 4daa27b927..fba05db32c 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,28 @@ the command line. rspec-core ships with an Autotest extension, which is loaded automatically if there is a `.rspec` file in the project's root directory. +## rcov integration + +rcov is best integrated via the [rcov rake +task](http://www.rubydoc.info/github/relevance/rcov/master/Rcov/RcovTask). + +rcov can also be integrated via the rspec rake task, but it requires a bit +more setup: + +```ruby +# Rakefile +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) do |config| + config.rcov = true +end + +task :default => :spec + +# spec/spec_helper.rb +require 'rspec/autorun' # **add this** +``` + ## get started Start with a simple example of behavior you expect from your system. Do diff --git a/Rakefile b/Rakefile index 544db88090..7d5b9a1a8c 100644 --- a/Rakefile +++ b/Rakefile @@ -22,6 +22,11 @@ namespace :spec do t.ruby_opts = %w[-w] t.rspec_opts = %w[--tag ui] end + + desc "Runs all specs together and then file-by-file" + task :ci do + sh "script/test_all" + end end if RUBY_VERSION.to_f == 1.8 @@ -64,8 +69,13 @@ desc "Push docs/cukes to relishapp using the relish-client-gem" task :relish, :version do |t, args| raise "rake relish[VERSION]" unless args[:version] sh "cp Changelog.md features/" + if `relish versions rspec/rspec-core`.split.map(&:strip).include? args[:version] + puts "Version #{args[:version]} already exists" + else + sh "relish versions:add rspec/rspec-core:#{args[:version]}" + end sh "relish push rspec/rspec-core:#{args[:version]}" sh "rm features/Changelog.md" end -task :default => [:spec, "spec:ui", :cucumber] +task :default => ["spec:ci", :cucumber] diff --git a/features/command_line/example_name_option.feature b/features/command_line/example_name_option.feature index 1ae4eead8f..1d2bbbc424 100644 --- a/features/command_line/example_name_option.feature +++ b/features/command_line/example_name_option.feature @@ -13,21 +13,21 @@ Feature: --example option Background: Given a file named "first_spec.rb" with: - """ + """ruby describe "first group" do it "first example in first group" do; end it "second example in first group" do; end end """ And a file named "second_spec.rb" with: - """ + """ruby describe "second group" do it "first example in second group" do; end it "second example in second group" do; end end """ And a file named "third_spec.rb" with: - """ + """ruby describe "third group" do it "first example in third group" do; end context "nested group" do @@ -37,7 +37,7 @@ Feature: --example option end """ And a file named "fourth_spec.rb" with: - """ + """ruby describe Array do describe "#length" do it "is the number of items" do @@ -98,4 +98,4 @@ Feature: --example option And the output should not contain any of these: |first example in third group| |nested group first example in nested group| - |nested group second example in nested group| \ No newline at end of file + |nested group second example in nested group| diff --git a/features/command_line/exit_status.feature b/features/command_line/exit_status.feature index d6392973d4..7f77f434f8 100644 --- a/features/command_line/exit_status.feature +++ b/features/command_line/exit_status.feature @@ -6,7 +6,7 @@ Feature: exit status Scenario: exit with 0 when all examples pass Given a file named "ok_spec.rb" with: - """ + """ruby describe "ok" do it "passes" do end @@ -18,7 +18,7 @@ Feature: exit status Scenario: exit with 1 when one example fails Given a file named "ko_spec.rb" with: - """ + """ruby describe "KO" do it "fails" do raise "KO" @@ -31,7 +31,7 @@ Feature: exit status Scenario: exit with 1 when a nested examples fails Given a file named "nested_ko_spec.rb" with: - """ + """ruby describe "KO" do describe "nested" do it "fails" do @@ -46,7 +46,7 @@ Feature: exit status Scenario: exit with 0 when no examples are run Given a file named "a_no_examples_spec.rb" with: - """ + """ruby """ When I run `rspec a_no_examples_spec.rb` Then the exit status should be 0 @@ -54,7 +54,7 @@ Feature: exit status Scenario: exit with 2 when one example fails and --failure-exit-code is 2 Given a file named "ko_spec.rb" with: - """ + """ruby describe "KO" do it "fails" do raise "KO" @@ -68,7 +68,7 @@ Feature: exit status @wip Scenario: exit with rspec's exit code when an at_exit hook is added upstream Given a file named "exit_at_spec.rb" with: - """ + """ruby require 'rspec/autorun' describe "exit 0 at_exit" do diff --git a/features/command_line/format_option.feature b/features/command_line/format_option.feature index 71a2afa044..89b15beeb2 100644 --- a/features/command_line/format_option.feature +++ b/features/command_line/format_option.feature @@ -17,7 +17,7 @@ Feature: --format option You can also specify an output target (STDOUT by default) by appending a filename to the argument: - $ rspec spec --format documentation:rspec.output.txt + $ rspec spec --format documentation --out rspec.txt `rspec --help` lists available formatters: @@ -29,7 +29,7 @@ Feature: --format option Background: Given a file named "example_spec.rb" with: - """ + """ruby describe "something" do it "does something that passes" do 5.should eq(5) diff --git a/features/command_line/line_number_appended_to_path.feature b/features/command_line/line_number_appended_to_path.feature index 84a05089d6..9790e61e06 100644 --- a/features/command_line/line_number_appended_to_path.feature +++ b/features/command_line/line_number_appended_to_path.feature @@ -6,7 +6,7 @@ Feature: line number appended to file path Background: Given a file named "example_spec.rb" with: - """ + """ruby describe "outer group" do it "first example in outer group" do @@ -28,7 +28,7 @@ Feature: line number appended to file path end """ And a file named "example2_spec.rb" with: - """ + """ruby describe "yet another group" do it "first example in second file" do end diff --git a/features/command_line/line_number_option.feature b/features/command_line/line_number_option.feature index 85d7d443d7..fd64d1974d 100644 --- a/features/command_line/line_number_option.feature +++ b/features/command_line/line_number_option.feature @@ -8,7 +8,7 @@ Feature: --line_number option Scenario: standard examples Given a file named "example_spec.rb" with: - """ + """ruby require "rspec/expectations" describe 9 do @@ -41,7 +41,7 @@ Feature: --line_number option Scenario: one liner Given a file named "example_spec.rb" with: - """ + """ruby require "rspec/expectations" describe 9 do diff --git a/features/command_line/pattern_option.feature b/features/command_line/pattern_option.feature index dfb6fa3d54..cc0b54491e 100644 --- a/features/command_line/pattern_option.feature +++ b/features/command_line/pattern_option.feature @@ -8,7 +8,7 @@ Feature: pattern option Scenario: default pattern Given a file named "spec/example_spec.rb" with: - """ + """ruby describe "addition" do it "adds things" do (1 + 2).should eq(3) @@ -20,7 +20,7 @@ Feature: pattern option Scenario: override the default pattern on the command line Given a file named "spec/example.spec" with: - """ + """ruby describe "addition" do it "adds things" do (1 + 2).should eq(3) diff --git a/features/command_line/rake_task.feature b/features/command_line/rake_task.feature index 0934894c5e..c56e658bae 100644 --- a/features/command_line/rake_task.feature +++ b/features/command_line/rake_task.feature @@ -4,7 +4,7 @@ Feature: rake task Scenario: default options with passing spec (prints command and exit status is 0) Given a file named "Rakefile" with: - """ + """ruby require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) @@ -12,7 +12,7 @@ Feature: rake task task :default => :spec """ And a file named "spec/thing_spec.rb" with: - """ + """ruby describe "something" do it "does something" do # pass @@ -20,12 +20,12 @@ Feature: rake task end """ When I run `rake` - Then the output should contain "ruby -S rspec" + Then the output should match /(ruby|rbx) -S rspec/ Then the exit status should be 0 Scenario: default options with failing spec (exit status is 1) Given a file named "Rakefile" with: - """ + """ruby require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) @@ -33,7 +33,7 @@ Feature: rake task task :default => :spec """ And a file named "spec/thing_spec.rb" with: - """ + """ruby describe "something" do it "does something" do fail @@ -45,7 +45,7 @@ Feature: rake task Scenario: fail_on_error = false with failing spec (exit status is 0) Given a file named "Rakefile" with: - """ + """ruby require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) do |t| @@ -55,7 +55,7 @@ Feature: rake task task :default => :spec """ And a file named "spec/thing_spec.rb" with: - """ + """ruby describe "something" do it "does something" do fail @@ -64,5 +64,59 @@ Feature: rake task """ When I run `rake` Then the exit status should be 0 - + Scenario: rspec_opts is specified in order to pass args to the rspec command + Given a file named "Rakefile" with: + """ruby + require 'rspec/core/rake_task' + + RSpec::Core::RakeTask.new(:spec) do |t| + t.rspec_opts = "--tag fast" + end + """ + And a file named "spec/thing_spec.rb" with: + """ruby + describe "something" do + it "has a tag", :fast => true do + # pass + end + + it "does not have a tag" do + fail + end + end + """ + When I run `rake spec` + Then the exit status should be 0 + Then the output should match: + """ + (ruby|rbx) -S rspec ./spec/thing_spec.rb --tag fast + """ + + Scenario: rspec_opts is specified using arguments to the rake task + Given a file named "Rakefile" with: + """ruby + require 'rspec/core/rake_task' + + RSpec::Core::RakeTask.new(:spec, :tag) do |t, task_args| + t.rspec_opts = "--tag #{task_args[:tag]}" + end + """ + And a file named "spec/thing_spec.rb" with: + """ruby + describe "something" do + it "has a tag", :fast => true do + # pass + end + + it "does not have a tag" do + fail + end + end + """ + When I run `rake spec[fast]` + Then the exit status should be 0 + Then the output should match: + """ + (ruby|rbx) -S rspec ./spec/thing_spec.rb --tag fast + """ diff --git a/features/command_line/ruby.feature b/features/command_line/ruby.feature index e9c31db254..65ea033269 100644 --- a/features/command_line/ruby.feature +++ b/features/command_line/ruby.feature @@ -9,7 +9,7 @@ Feature: run with ruby command Scenario: Given a file named "example_spec.rb" with: - """ + """ruby require 'rspec/autorun' describe 1 do diff --git a/features/command_line/tag.feature b/features/command_line/tag.feature index cb910ca1d7..34cd3b3297 100644 --- a/features/command_line/tag.feature +++ b/features/command_line/tag.feature @@ -16,7 +16,7 @@ Feature: --tag option Background: Given a file named "tagged_spec.rb" with: - """ + """ruby describe "group with tagged specs" do it "example I'm working now", :focus => true do; end it "special example with string", :type => 'special' do; end diff --git a/features/configuration/alias_example_to.feature b/features/configuration/alias_example_to.feature index 5fe274f07d..c488eeb638 100644 --- a/features/configuration/alias_example_to.feature +++ b/features/configuration/alias_example_to.feature @@ -8,7 +8,7 @@ Feature: alias_example_to Scenario: Use alias_example_to to define focused example Given a file named "alias_example_to_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.alias_example_to :fit, :focused => true c.filter_run :focused => true @@ -28,7 +28,7 @@ Feature: alias_example_to Scenario: use symbols as metadata Given a file named "use_symbols_as_metadata_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.treat_symbols_as_metadata_keys_with_true_values = true c.alias_example_to :fit, :focused diff --git a/features/configuration/custom_settings.feature b/features/configuration/custom_settings.feature index d3ad97812b..23772fc592 100644 --- a/features/configuration/custom_settings.feature +++ b/features/configuration/custom_settings.feature @@ -4,7 +4,7 @@ Feature: custom settings Scenario: simple setting (with defaults) Given a file named "additional_setting_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.add_setting :custom_setting end @@ -34,7 +34,7 @@ Feature: custom settings Scenario: default to true Given a file named "additional_setting_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.add_setting :custom_setting, :default => true end @@ -60,7 +60,7 @@ Feature: custom settings Scenario: overridden in a subsequent RSpec.configure block Given a file named "additional_setting_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.add_setting :custom_setting end diff --git a/features/configuration/default_path.feature b/features/configuration/default_path.feature index 6e6284cfed..4f2ae8451f 100644 --- a/features/configuration/default_path.feature +++ b/features/configuration/default_path.feature @@ -13,7 +13,7 @@ Feature: default_path Scenario: run `rspec` with default default_path (`spec` directory) Given a file named "spec/example_spec.rb" with: - """ + """ruby describe "an example" do it "passes" do end @@ -21,14 +21,14 @@ Feature: default_path """ When I run `rspec` Then the output should contain "1 example, 0 failures" - + Scenario: run `rspec` with customized default_path Given a file named ".rspec" with: """ --default_path behavior """ Given a file named "behavior/example_spec.rb" with: - """ + """ruby describe "an example" do it "passes" do end diff --git a/features/configuration/fail_fast.feature b/features/configuration/fail_fast.feature index a0deff28a1..c0cd1ec57d 100644 --- a/features/configuration/fail_fast.feature +++ b/features/configuration/fail_fast.feature @@ -6,13 +6,13 @@ Feature: fail fast Background: Given a file named "spec/spec_helper.rb" with: - """ + """ruby RSpec.configure {|c| c.fail_fast = true} """ Scenario: fail_fast with no failures (runs all examples) Given a file named "spec/example_spec.rb" with: - """ + """ruby describe "something" do it "passes" do end @@ -26,7 +26,7 @@ Feature: fail fast Scenario: fail_fast with first example failing (only runs the one example) Given a file named "spec/example_spec.rb" with: - """ + """ruby require "spec_helper" describe "something" do it "fails" do @@ -42,7 +42,7 @@ Feature: fail fast Scenario: fail_fast with multiple files, second example failing (only runs the first two examples) Given a file named "spec/example_1_spec.rb" with: - """ + """ruby require "spec_helper" describe "something" do it "passes" do @@ -60,7 +60,7 @@ Feature: fail fast end """ And a file named "spec/example_2_spec.rb" with: - """ + """ruby require "spec_helper" describe "something" do it "passes" do diff --git a/features/configuration/read_options_from_file.feature b/features/configuration/read_options_from_file.feature index 08211e239b..9ea4fd92b7 100644 --- a/features/configuration/read_options_from_file.feature +++ b/features/configuration/read_options_from_file.feature @@ -15,7 +15,7 @@ Feature: read command line configuration options from files --color """ And a file named "spec/example_spec.rb" with: - """ + """ruby describe "color_enabled" do context "when set with RSpec.configure" do before do @@ -39,7 +39,7 @@ Feature: read command line configuration options from files --format documentation """ And a file named "spec/example_spec.rb" with: - """ + """ruby describe "formatter set in custom options file" do it "sets formatter" do RSpec.configuration.formatters.first. @@ -60,7 +60,7 @@ Feature: read command line configuration options from files --color """ And a file named "spec/example_spec.rb" with: - """ + """ruby describe "custom options file" do it "causes .rspec to be ignored" do RSpec.configuration.color_enabled.should be_false @@ -76,7 +76,7 @@ Feature: read command line configuration options from files --format <%= true ? 'documentation' : 'progress' %> """ And a file named "spec/example_spec.rb" with: - """ + """ruby describe "formatter" do it "is set to documentation" do RSpec.configuration.formatters.first.should be_an(RSpec::Core::Formatters::DocumentationFormatter) diff --git a/features/example_groups/basic_structure.feature b/features/example_groups/basic_structure.feature index 3d3ca65d46..ad155ef19d 100644 --- a/features/example_groups/basic_structure.feature +++ b/features/example_groups/basic_structure.feature @@ -17,7 +17,7 @@ Feature: basic structure (describe/it) Scenario: one group, one example Given a file named "sample_spec.rb" with: - """ + """ruby describe "something" do it "does something" do end @@ -32,7 +32,7 @@ Feature: basic structure (describe/it) Scenario: nested example groups (using context) Given a file named "nested_example_groups_spec.rb" with: - """ + """ruby describe "something" do context "in one context" do it "does one thing" do diff --git a/features/example_groups/shared_context.feature b/features/example_groups/shared_context.feature index 476583b6c4..491faa8693 100644 --- a/features/example_groups/shared_context.feature +++ b/features/example_groups/shared_context.feature @@ -6,7 +6,7 @@ Feature: shared context Background: Given a file named "shared_stuff.rb" with: - """ + """ruby shared_context "shared stuff", :a => :b do before { @some_var = :some_value } def shared_method @@ -21,7 +21,7 @@ Feature: shared context Scenario: declare shared context and include it with include_context Given a file named "shared_context_example.rb" with: - """ + """ruby require "./shared_stuff.rb" describe "group that includes a shared context using 'include_context'" do @@ -49,7 +49,7 @@ Feature: shared context Scenario: declare shared context and include it with metadata Given a file named "shared_context_example.rb" with: - """ + """ruby require "./shared_stuff.rb" describe "group that includes a shared context using metadata", :a => :b do diff --git a/features/example_groups/shared_examples.feature b/features/example_groups/shared_examples.feature index 10c36bfafe..3ce834bcf2 100644 --- a/features/example_groups/shared_examples.feature +++ b/features/example_groups/shared_examples.feature @@ -6,10 +6,11 @@ Feature: shared examples needs to run. A shared group is included in another group using any of: - + include_examples "name" # include the examples in the current context it_behaves_like "name" # include the examples in a nested context it_should_behave_like "name" # include the examples in a nested context + matching metadata # include the examples in the current context WARNING: Files containing shared groups must be loaded before the files that use them. While there are conventions to handle this, RSpec does _not_ do @@ -27,7 +28,7 @@ Feature: shared examples 2. Put files containing shared examples in `spec/support/` and require files in that directory from `spec/spec_helper.rb`: - Dir["./spec/support/**/*.rb"].each {|f| require f} + Dir["./spec/support/**/*.rb"].sort.each {|f| require f} This is included in the generated `spec/spec_helper.rb` file in `rspec-rails` @@ -37,7 +38,7 @@ Feature: shared examples Scenario: shared examples group included in two groups in one file Given a file named "collection_spec.rb" with: - """ + """ruby require "set" shared_examples "a collection" do @@ -99,7 +100,7 @@ Feature: shared examples Scenario: Providing context to a shared group using a block Given a file named "shared_example_group_spec.rb" with: - """ + """ruby require "set" shared_examples "a collection object" do @@ -107,7 +108,7 @@ Feature: shared examples it "adds objects to the end of the collection" do collection << 1 collection << 2 - collection.to_a.should eq([1,2]) + expect(collection.to_a).to match_array([1, 2]) end end end @@ -141,7 +142,7 @@ Feature: shared examples Scenario: Passing parameters to a shared example group Given a file named "shared_example_group_params_spec.rb" with: - """ + """ruby shared_examples "a measurable object" do |measurement, measurement_methods| measurement_methods.each do |measurement_method| it "should return #{measurement} from ##{measurement_method}" do @@ -177,7 +178,7 @@ Feature: shared examples Scenario: Aliasing "it_should_behave_like" to "it_has_behavior" Given a file named "shared_example_group_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:' end @@ -202,3 +203,20 @@ Feature: shared examples has behavior: sortability responds to <=> """ + + Scenario: Sharing metadata automatically includes shared example groups + Given a file named "shared_example_metadata_spec.rb" with: + """ruby + shared_examples "shared stuff", :a => :b do + it 'runs wherever the metadata is shared' do + end + end + + describe String, :a => :b do + end + """ + When I run `rspec shared_example_metadata_spec.rb` + Then the output should contain: + """ + 1 example, 0 failures + """ diff --git a/features/expectation_framework_integration/configure_expectation_framework.feature b/features/expectation_framework_integration/configure_expectation_framework.feature index ba3d520897..d0d6cbe810 100644 --- a/features/expectation_framework_integration/configure_expectation_framework.feature +++ b/features/expectation_framework_integration/configure_expectation_framework.feature @@ -7,7 +7,7 @@ Feature: configure expectation framework * stdlib assertions * test/unit assertions in ruby 1.8 * minitest assertions in ruby 1.9 - * rspec/expecations _and_ stlib assertions + * rspec/expectations _and_ stlib assertions Note that when you do not use rspec-expectations, you must explicitly provide a description to every example. You cannot rely on the generated @@ -15,7 +15,7 @@ Feature: configure expectation framework Scenario: rspec-expectations can be used by default if nothing is configured Given a file named "example_spec.rb" with: - """ + """ruby RSpec::Matchers.define :be_a_multiple_of do |factor| match do |actual| actual % factor == 0 @@ -31,7 +31,7 @@ Feature: configure expectation framework Scenario: configure rspec-expectations (explicitly) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.expect_with :rspec end @@ -47,7 +47,7 @@ Feature: configure expectation framework Scenario: configure test/unit assertions (passing examples) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.expect_with :stdlib end @@ -65,7 +65,7 @@ Feature: configure expectation framework Scenario: configure test/unit assertions (failing examples) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.expect_with :stdlib end @@ -83,7 +83,7 @@ Feature: configure expectation framework Scenario: configure rspec/expecations AND test/unit assertions Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.expect_with :rspec, :stdlib end diff --git a/features/filtering/exclusion_filters.feature b/features/filtering/exclusion_filters.feature index 6ebfd40ed8..d79ca65658 100644 --- a/features/filtering/exclusion_filters.feature +++ b/features/filtering/exclusion_filters.feature @@ -8,7 +8,7 @@ Feature: exclusion filters Scenario: exclude an example Given a file named "spec/sample_spec.rb" with: - """ + """ruby RSpec.configure do |c| # declare an exclusion filter c.filter_run_excluding :broken => true @@ -29,7 +29,7 @@ Feature: exclusion filters Scenario: exclude a group Given a file named "spec/sample_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end @@ -54,7 +54,7 @@ Feature: exclusion filters Scenario: exclude multiple groups Given a file named "spec/sample_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end @@ -88,7 +88,7 @@ Feature: exclusion filters Scenario: before/after(:all) hooks in excluded example group are not run Given a file named "spec/before_after_all_exclusion_filter_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end @@ -119,7 +119,7 @@ Feature: exclusion filters Scenario: Use symbols as metadata Given a file named "symbols_as_metadata_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.treat_symbols_as_metadata_keys_with_true_values = true c.filter_run_excluding :broken diff --git a/features/filtering/if_and_unless.feature b/features/filtering/if_and_unless.feature index fd55667aa6..154a2b4bc5 100644 --- a/features/filtering/if_and_unless.feature +++ b/features/filtering/if_and_unless.feature @@ -5,7 +5,7 @@ Feature: :if and :unless Scenario: implicit :if filter Given a file named "implicit_if_filter_spec.rb" with: - """ + """ruby describe ":if => true group", :if => true do it(":if => true group :if => true example", :if => true) { } it(":if => true group :if => false example", :if => false) { } @@ -39,7 +39,7 @@ Feature: :if and :unless Scenario: implicit :unless filter Given a file named "implicit_unless_filter_spec.rb" with: - """ + """ruby describe ":unless => true group", :unless => true do it(":unless => true group :unless => true example", :unless => true) { } it(":unless => true group :unless => false example", :unless => false) { } @@ -73,7 +73,7 @@ Feature: :if and :unless Scenario: combining implicit filter with explicit inclusion filter Given a file named "explicit_inclusion_filter_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run :focus => true end @@ -106,7 +106,7 @@ Feature: :if and :unless Scenario: combining implicit filter with explicit exclusion filter Given a file named "explicit_exclusion_filter_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run_excluding :broken => true end @@ -139,7 +139,7 @@ Feature: :if and :unless Scenario: override implicit :if and :unless exclusion filters Given a file named "override_implicit_filters_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run_excluding :if => :exclude_me, :unless => :exclude_me_for_unless end diff --git a/features/filtering/inclusion_filters.feature b/features/filtering/inclusion_filters.feature index 2aca9ce5d8..4bef6ee0f8 100644 --- a/features/filtering/inclusion_filters.feature +++ b/features/filtering/inclusion_filters.feature @@ -9,7 +9,7 @@ Feature: inclusion filters Background: Given a file named "spec/spec_helper.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run_including :focus => true end @@ -17,7 +17,7 @@ Feature: inclusion filters Scenario: focus on an example Given a file named "spec/sample_spec.rb" with: - """ + """ruby require "spec_helper" describe "something" do @@ -34,7 +34,7 @@ Feature: inclusion filters Scenario: focus on a group Given a file named "spec/sample_spec.rb" with: - """ + """ruby require "spec_helper" describe "group 1", :focus => true do @@ -57,7 +57,7 @@ Feature: inclusion filters Scenario: before/after(:all) hooks in unmatched example group are not run Given a file named "spec/before_after_all_inclusion_filter_spec.rb" with: - """ + """ruby require "spec_helper" describe "group 1", :focus => true do @@ -86,7 +86,7 @@ Feature: inclusion filters Scenario: Use symbols as metadata Given a file named "symbols_as_metadata_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.treat_symbols_as_metadata_keys_with_true_values = true c.filter_run :current_example diff --git a/features/filtering/run_all_when_everything_filtered.feature b/features/filtering/run_all_when_everything_filtered.feature index f6a1008f61..e22263bc9c 100644 --- a/features/filtering/run_all_when_everything_filtered.feature +++ b/features/filtering/run_all_when_everything_filtered.feature @@ -1,12 +1,12 @@ Feature: run all when everything filtered - Use the run_all_when_everything_filtered configuration option to do just + Use the `run_all_when_everything_filtered` configuration option to do just that. This works well when paired with an inclusion filter like ":focus => true", as it will run all the examples when none match the inclusion filter. Background: Given a file named "spec/spec_helper.rb" with: - """ + """ruby RSpec.configure do |c| c.filter_run :focus => true c.run_all_when_everything_filtered = true @@ -15,7 +15,7 @@ Feature: run all when everything filtered Scenario: no examples match filter (runs all examples) Given a file named "spec/sample_spec.rb" with: - """ + """ruby require "spec_helper" describe "group 1" do diff --git a/features/formatters/custom_formatter.feature b/features/formatters/custom_formatter.feature index a9157443f0..a95a852f6c 100644 --- a/features/formatters/custom_formatter.feature +++ b/features/formatters/custom_formatter.feature @@ -11,7 +11,7 @@ Feature: custom formatters Scenario: custom formatter Given a file named "custom_formatter.rb" with: - """ + """ruby require "rspec/core/formatters/base_text_formatter" class CustomFormatter < RSpec::Core::Formatters::BaseTextFormatter @@ -25,7 +25,7 @@ Feature: custom formatters end """ And a file named "example_spec.rb" with: - """ + """ruby describe "my group" do specify "my example" do end diff --git a/features/formatters/json_formatter.feature b/features/formatters/json_formatter.feature new file mode 100644 index 0000000000..9bac429976 --- /dev/null +++ b/features/formatters/json_formatter.feature @@ -0,0 +1,30 @@ +Feature: JSON formatter + + Scenario: Formatting example names for retry + Given a file named "various_spec.rb" with: + """ruby + describe "Various" do + it "fails" do + "fail".should eq("succeed") + end + + it "succeeds" do + "succeed".should eq("succeed") + end + + it "pends" + end + """ + When I run `rspec various_spec.rb --format j` + Then the output should contain all of these: + |"summary_line":"3 examples, 1 failure, 1 pending"| + |"examples":[ | + |"description":"fails" | + |"full_description":"Various fails" | + |"status":"failed" | + |"file_path":"./various_spec.rb" | + |"line_number":2 | + |"exception":{ | + |"class":"RSpec::Expectations::ExpectationNotMetError"| + + And the exit status should be 1 diff --git a/features/formatters/text_formatter.feature b/features/formatters/text_formatter.feature index e94390e43c..6ae1fb7e34 100644 --- a/features/formatters/text_formatter.feature +++ b/features/formatters/text_formatter.feature @@ -6,7 +6,7 @@ Feature: text formatter Scenario: Backtrace formatting for failing specs in multiple files Given a file named "string_spec.rb" with: - """ + """ruby describe String do it "has a failing example" do "foo".reverse.should eq("ofo") @@ -14,7 +14,7 @@ Feature: text formatter end """ And a file named "integer_spec.rb" with: - """ + """ruby describe Integer do it "has a failing example" do (7 + 5).should eq(11) @@ -24,8 +24,6 @@ Feature: text formatter When I run `rspec integer_spec.rb string_spec.rb` Then the backtrace-normalized output should contain: """ - Failures: - 1) Integer has a failing example Failure/Error: (7 + 5).should eq(11) @@ -34,7 +32,9 @@ Feature: text formatter (compared using ==) # ./integer_spec.rb:3 - + """ + And the backtrace-normalized output should contain: + """ 2) String has a failing example Failure/Error: "foo".reverse.should eq("ofo") diff --git a/features/helper_methods/arbitrary_methods.feature b/features/helper_methods/arbitrary_methods.feature index 1b6105e7c8..26968b4fe0 100644 --- a/features/helper_methods/arbitrary_methods.feature +++ b/features/helper_methods/arbitrary_methods.feature @@ -7,7 +7,7 @@ Feature: arbitrary helper methods Scenario: use a method defined in the same group Given a file named "example_spec.rb" with: - """ + """ruby describe "an example" do def help :available @@ -23,7 +23,7 @@ Feature: arbitrary helper methods Scenario: use a method defined in a parent group Given a file named "example_spec.rb" with: - """ + """ruby describe "an example" do def help :available diff --git a/features/helper_methods/let.feature b/features/helper_methods/let.feature index f5a58c9e28..26f5f7cb0f 100644 --- a/features/helper_methods/let.feature +++ b/features/helper_methods/let.feature @@ -9,7 +9,7 @@ Feature: let and let! Scenario: use let to define memoized helper method Given a file named "let_spec.rb" with: - """ + """ruby $count = 0 describe "let" do let(:count) { $count += 1 } @@ -29,7 +29,7 @@ Feature: let and let! Scenario: use let! to define a memoized helper method that is called in a before hook Given a file named "let_bang_spec.rb" with: - """ + """ruby $count = 0 describe "let!" do invocation_order = [] diff --git a/features/helper_methods/modules.feature b/features/helper_methods/modules.feature index f56ecc8546..ce7294a9bd 100644 --- a/features/helper_methods/modules.feature +++ b/features/helper_methods/modules.feature @@ -15,7 +15,7 @@ Feature: Define helper methods in a module Background: Given a file named "helpers.rb" with: - """ + """ruby module Helpers def help :available @@ -25,7 +25,7 @@ Feature: Define helper methods in a module Scenario: include a module in all example groups Given a file named "include_module_spec.rb" with: - """ + """ruby require './helpers' RSpec.configure do |c| @@ -43,7 +43,7 @@ Feature: Define helper methods in a module Scenario: extend a module in all example groups Given a file named "extend_module_spec.rb" with: - """ + """ruby require './helpers' RSpec.configure do |c| @@ -64,7 +64,7 @@ Feature: Define helper methods in a module Scenario: include a module in only some example groups Given a file named "include_module_in_some_groups_spec.rb" with: - """ + """ruby require './helpers' RSpec.configure do |c| @@ -88,7 +88,7 @@ Feature: Define helper methods in a module Scenario: extend a module in only some example groups Given a file named "extend_module_in_only_some_groups_spec.rb" with: - """ + """ruby require './helpers' RSpec.configure do |c| @@ -118,7 +118,7 @@ Feature: Define helper methods in a module Scenario: use symbols as metadata Given a file named "symbols_as_metadata_spec.rb" with: - """ + """ruby require './helpers' RSpec.configure do |c| diff --git a/features/hooks/around_hooks.feature b/features/hooks/around_hooks.feature index 97cac2f283..d367e77d0f 100644 --- a/features/hooks/around_hooks.feature +++ b/features/hooks/around_hooks.feature @@ -18,7 +18,7 @@ Feature: around hooks Scenario: use the example as a proc within the block passed to around() Given a file named "example_spec.rb" with: - """ + """ruby class Database def self.transaction puts "open transaction" @@ -47,7 +47,7 @@ Feature: around hooks Scenario: invoke the example using run() Given a file named "example_spec.rb" with: - """ + """ruby describe "around hook" do around(:each) do |example| puts "around each before" @@ -70,7 +70,7 @@ Feature: around hooks Scenario: access the example metadata Given a file named "example_spec.rb" with: - """ + """ruby describe "something" do around(:each) do |example| puts example.metadata[:foo] @@ -86,7 +86,7 @@ Feature: around hooks Scenario: define a global around hook Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.around(:each) do |example| puts "around each before" @@ -111,7 +111,7 @@ Feature: around hooks Scenario: before/after(:each) hooks are wrapped by the around hook Given a file named "example_spec.rb" with: - """ + """ruby describe "around filter" do around(:each) do |example| puts "around each before" @@ -144,7 +144,7 @@ Feature: around hooks Scenario: before/after(:all) hooks are NOT wrapped by the around hook Given a file named "example_spec.rb" with: - """ + """ruby describe "around filter" do around(:each) do |example| puts "around each before" @@ -177,7 +177,7 @@ Feature: around hooks Scenario: examples run by an around block are run in the configured context Given a file named "example_spec.rb" with: - """ + """ruby module IncludedInConfigureBlock def included_in_configure_block; true; end end @@ -201,7 +201,7 @@ Feature: around hooks Scenario: implicitly pending examples are detected as Not yet implemented Given a file named "example_spec.rb" with: - """ + """ruby describe "implicit pending example" do around(:each) do |example| example.run @@ -222,7 +222,7 @@ Feature: around hooks Scenario: explicitly pending examples are detected as pending Given a file named "example_spec.rb" with: - """ + """ruby describe "explicit pending example" do around(:each) do |example| example.run @@ -243,7 +243,7 @@ Feature: around hooks Scenario: multiple around hooks in the same scope Given a file named "example_spec.rb" with: - """ + """ruby describe "if there are multiple around hooks in the same scope" do around(:each) do |example| puts "first around hook before" @@ -276,7 +276,7 @@ Feature: around hooks Scenario: around hooks in multiple scopes Given a file named "example_spec.rb" with: - """ + """ruby describe "if there are around hooks in an outer scope" do around(:each) do |example| puts "first outermost around hook before" diff --git a/features/hooks/before_and_after_hooks.feature b/features/hooks/before_and_after_hooks.feature index 4edd9c715d..1de846cb91 100644 --- a/features/hooks/before_and_after_hooks.feature +++ b/features/hooks/before_and_after_hooks.feature @@ -21,9 +21,13 @@ Feature: before and after hooks `before` and `after` hooks can be defined directly in the example groups they should run in, or in a global RSpec.configure block. + Setting instance variables are not supported in `before(:suite)`. + + Mocks are only supported in `before(:each)`. + Scenario: define before(:each) block Given a file named "before_each_spec.rb" with: - """ + """ruby require "rspec/expectations" class Thing @@ -57,7 +61,7 @@ Feature: before and after hooks Scenario: define before(:all) block in example group Given a file named "before_all_spec.rb" with: - """ + """ruby require "rspec/expectations" class Thing @@ -94,7 +98,7 @@ Feature: before and after hooks Scenario: failure in before(:all) block Given a file named "before_all_spec.rb" with: - """ + """ruby describe "an error in before(:all)" do before(:all) do raise "oops" @@ -149,7 +153,7 @@ Feature: before and after hooks Scenario: failure in after(:all) block Given a file named "after_all_spec.rb" with: - """ + """ruby describe "an error in after(:all)" do after(:all) do raise StandardError.new("Boom!") @@ -172,7 +176,7 @@ Feature: before and after hooks Scenario: define before and after blocks in configuration Given a file named "befores_in_configuration_spec.rb" with: - """ + """ruby require "rspec/expectations" RSpec.configure do |config| @@ -202,7 +206,7 @@ Feature: before and after hooks Scenario: before/after blocks are run in order Given a file named "ensure_block_order_spec.rb" with: - """ + """ruby require "rspec/expectations" describe "before and after callbacks" do @@ -238,7 +242,7 @@ Feature: before and after hooks Scenario: before/after blocks defined in config are run in order Given a file named "configuration_spec.rb" with: - """ + """ruby require "rspec/expectations" RSpec.configure do |config| @@ -285,7 +289,7 @@ Feature: before and after hooks Scenario: before/after all blocks are run once Given a file named "before_and_after_all_spec.rb" with: - """ + """ruby describe "before and after callbacks" do before(:all) do puts "outer before all" @@ -343,7 +347,7 @@ Feature: before and after hooks Scenario: nested examples have access to state set in outer before(:all) Given a file named "before_all_spec.rb" with: - """ + """ruby describe "something" do before :all do @value = 123 @@ -373,7 +377,7 @@ Feature: before and after hooks Scenario: before/after all blocks have access to state Given a file named "before_and_after_all_spec.rb" with: - """ + """ruby describe "before and after callbacks" do before(:all) do @outer_state = "set in outer before all" @@ -408,7 +412,7 @@ Feature: before and after hooks Scenario: exception in before(:each) is captured and reported as failure Given a file named "error_in_before_each_spec.rb" with: - """ + """ruby describe "error in before(:each)" do before(:each) do raise "this error" diff --git a/features/hooks/filtering.feature b/features/hooks/filtering.feature index 94deacab19..4c2a6cb6ab 100644 --- a/features/hooks/filtering.feature +++ b/features/hooks/filtering.feature @@ -17,7 +17,7 @@ Feature: filters Scenario: filter `before(:each)` hooks using arbitrary metadata Given a file named "filter_before_each_hooks_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.before(:each, :foo => :bar) do invoked_hooks << :before_each_foo_bar @@ -49,7 +49,7 @@ Feature: filters Scenario: filter `after(:each)` hooks using arbitrary metadata Given a file named "filter_after_each_hooks_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.after(:each, :foo => :bar) do raise "boom!" @@ -79,7 +79,7 @@ Feature: filters Scenario: filter around(:each) hooks using arbitrary metadata Given a file named "filter_around_each_hooks_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.around(:each, :foo => :bar) do |example| order << :before_around_each_foo_bar @@ -115,7 +115,7 @@ Feature: filters Scenario: filter before(:all) hooks using arbitrary metadata Given a file named "filter_before_all_hooks_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.before(:all, :foo => :bar) { @hook = :before_all_foo_bar } end @@ -151,7 +151,7 @@ Feature: filters Scenario: filter after(:all) hooks using arbitrary metadata Given a file named "filter_after_all_hooks_spec.rb" with: - """ + """ruby example_msgs = [] RSpec.configure do |config| @@ -195,7 +195,7 @@ Feature: filters Scenario: Use symbols as metadata Given a file named "less_verbose_metadata_filter.rb" with: - """ + """ruby RSpec.configure do |c| c.treat_symbols_as_metadata_keys_with_true_values = true c.before(:each, :before_each) { puts "before each" } diff --git a/features/metadata/current_example.feature b/features/metadata/current_example.feature index bac8c702e4..5fee6b46e3 100644 --- a/features/metadata/current_example.feature +++ b/features/metadata/current_example.feature @@ -5,7 +5,7 @@ Feature: current example Scenario: access the example object from within an example Given a file named "spec/example_spec.rb" with: - """ + """ruby describe "an example" do it "knows itself as example" do example.description.should eq("knows itself as example") diff --git a/features/metadata/described_class.feature b/features/metadata/described_class.feature index 7a2675be13..237d4cf0b9 100644 --- a/features/metadata/described_class.feature +++ b/features/metadata/described_class.feature @@ -5,7 +5,7 @@ Feature: described class Scenario: access the described class from the example Given a file named "spec/example_spec.rb" with: - """ + """ruby describe Fixnum do it "is available as described_class" do described_class.should eq(Fixnum) diff --git a/features/metadata/user_defined.feature b/features/metadata/user_defined.feature index a37f4f8abf..faa6634e08 100644 --- a/features/metadata/user_defined.feature +++ b/features/metadata/user_defined.feature @@ -23,7 +23,7 @@ Feature: User-defined metadata Scenario: define group metadata using a hash Given a file named "define_group_metadata_with_hash_spec.rb" with: - """ + """ruby describe "a group with user-defined metadata", :foo => 17 do it 'has access to the metadata in the example' do example.metadata[:foo].should eq(17) @@ -49,7 +49,7 @@ Feature: User-defined metadata Scenario: define example metadata using a hash Given a file named "define_example_metadata_with_hash_spec.rb" with: - """ + """ruby describe "a group with no user-defined metadata" do it 'has an example with metadata', :foo => 17 do example.metadata[:foo].should eq(17) @@ -68,7 +68,7 @@ Feature: User-defined metadata Scenario: override user-defined metadata Given a file named "override_metadata_spec.rb" with: - """ + """ruby describe "a group with user-defined metadata", :foo => 'bar' do it 'can be overridden by an example', :foo => 'bazz' do example.metadata[:foo].should == 'bazz' @@ -86,7 +86,7 @@ Feature: User-defined metadata Scenario: less verbose metadata Given a file named "less_verbose_metadata_spec.rb" with: - """ + """ruby RSpec.configure do |c| c.treat_symbols_as_metadata_keys_with_true_values = true end diff --git a/features/mock_framework_integration/use_any_framework.feature b/features/mock_framework_integration/use_any_framework.feature index ab4a4d1224..473e6ac7f0 100644 --- a/features/mock_framework_integration/use_any_framework.feature +++ b/features/mock_framework_integration/use_any_framework.feature @@ -6,20 +6,20 @@ Feature: mock with an alternative framework A mock framework adapter must expose three methods: - * setup_mocks_for_rspec + * `setup_mocks_for_rspec` * called before each example is run - * verify_mocks_for_rspec + * `verify_mocks_for_rspec` * called after each example is run * this is where message expectation failures should result in an error with the appropriate failure message - * teardown_mocks_for_rspec - * called after verify_mocks_for_rspec + * `teardown_mocks_for_rspec` + * called after `verify_mocks_for_rspec` * use this to clean up resources, restore objects to earlier state, etc * guaranteed to run even if there are failures Scenario: Mock with alternate framework Given a file named "expector.rb" with: - """ + """ruby class Expector class << self def expectors @@ -80,7 +80,7 @@ Feature: mock with an alternative framework """ Given a file named "example_spec.rb" with: - """ + """ruby require File.expand_path("../expector", __FILE__) RSpec.configure do |config| diff --git a/features/mock_framework_integration/use_flexmock.feature b/features/mock_framework_integration/use_flexmock.feature index 261832e5c2..408b055c04 100644 --- a/features/mock_framework_integration/use_flexmock.feature +++ b/features/mock_framework_integration/use_flexmock.feature @@ -4,7 +4,7 @@ Feature: mock with flexmock Scenario: passing message expectation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :flexmock end @@ -22,7 +22,7 @@ Feature: mock with flexmock Scenario: failing message expecation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :flexmock end @@ -39,7 +39,7 @@ Feature: mock with flexmock Scenario: failing message expectation in pending block (remains pending) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :flexmock end @@ -59,7 +59,7 @@ Feature: mock with flexmock Scenario: passing message expectation in pending block (fails) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :flexmock end @@ -81,7 +81,7 @@ Feature: mock with flexmock Scenario: accessing RSpec.configuration.mock_framework.framework_name Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :flexmock end diff --git a/features/mock_framework_integration/use_mocha.feature b/features/mock_framework_integration/use_mocha.feature index c1595166c2..bb29e9412c 100644 --- a/features/mock_framework_integration/use_mocha.feature +++ b/features/mock_framework_integration/use_mocha.feature @@ -4,7 +4,7 @@ Feature: mock with mocha Scenario: passing message expectation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :mocha end @@ -22,7 +22,7 @@ Feature: mock with mocha Scenario: failing message expecation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :mocha end @@ -39,7 +39,7 @@ Feature: mock with mocha Scenario: failing message expectation in pending block (remains pending) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :mocha end @@ -59,7 +59,7 @@ Feature: mock with mocha Scenario: passing message expectation in pending block (fails) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :mocha end @@ -81,7 +81,7 @@ Feature: mock with mocha Scenario: accessing RSpec.configuration.mock_framework.framework_name Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :mocha end diff --git a/features/mock_framework_integration/use_rr.feature b/features/mock_framework_integration/use_rr.feature index c3cf175e05..08c4e19d34 100644 --- a/features/mock_framework_integration/use_rr.feature +++ b/features/mock_framework_integration/use_rr.feature @@ -4,7 +4,7 @@ Feature: mock with rr Scenario: passing message expectation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rr end @@ -22,7 +22,7 @@ Feature: mock with rr Scenario: failing message expecation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rr end @@ -39,7 +39,7 @@ Feature: mock with rr Scenario: failing message expectation in pending block (remains pending) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rr end @@ -59,7 +59,7 @@ Feature: mock with rr Scenario: passing message expectation in pending block (fails) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rr end @@ -81,7 +81,7 @@ Feature: mock with rr Scenario: accessing RSpec.configuration.mock_framework.framework_name Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rr end diff --git a/features/mock_framework_integration/use_rspec.feature b/features/mock_framework_integration/use_rspec.feature index 79d44214db..9ade6e7d5b 100644 --- a/features/mock_framework_integration/use_rspec.feature +++ b/features/mock_framework_integration/use_rspec.feature @@ -5,7 +5,7 @@ Feature: mock with rspec Scenario: passing message expectation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rspec end @@ -23,7 +23,7 @@ Feature: mock with rspec Scenario: failing message expecation Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rspec end @@ -40,7 +40,7 @@ Feature: mock with rspec Scenario: failing message expectation in pending block (remains pending) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rspec end @@ -60,7 +60,7 @@ Feature: mock with rspec Scenario: passing message expectation in pending block (fails) Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rspec end @@ -82,7 +82,7 @@ Feature: mock with rspec Scenario: accessing RSpec.configuration.mock_framework.framework_name Given a file named "example_spec.rb" with: - """ + """ruby RSpec.configure do |config| config.mock_framework = :rspec end diff --git a/features/pending/pending_examples.feature b/features/pending/pending_examples.feature index 78f952a897..68b9db24da 100644 --- a/features/pending/pending_examples.feature +++ b/features/pending/pending_examples.feature @@ -5,7 +5,7 @@ Feature: pending examples Scenario: pending implementation Given a file named "example_without_block_spec.rb" with: - """ + """ruby describe "an example" do it "is a pending example" end @@ -16,9 +16,9 @@ Feature: pending examples And the output should contain "Not yet implemented" And the output should contain "example_without_block_spec.rb:2" - Scenario: pending any arbitary reason, with no block + Scenario: pending any arbitrary reason, with no block Given a file named "pending_without_block_spec.rb" with: - """ + """ruby describe "an example" do it "is implemented but waiting" do pending("something else getting finished") @@ -37,9 +37,9 @@ Feature: pending examples # ./pending_without_block_spec.rb:2 """ - Scenario: pending any arbitary reason, with a block that fails + Scenario: pending any arbitrary reason, with a block that fails Given a file named "pending_with_failing_block_spec.rb" with: - """ + """ruby describe "an example" do it "is implemented but waiting" do pending("something else getting finished") do @@ -59,9 +59,9 @@ Feature: pending examples # ./pending_with_failing_block_spec.rb:2 """ - Scenario: pending any arbitary reason, with a block that passes + Scenario: pending any arbitrary reason, with a block that passes Given a file named "pending_with_passing_block_spec.rb" with: - """ + """ruby describe "an example" do it "is implemented but waiting" do pending("something else getting finished") do @@ -79,7 +79,7 @@ Feature: pending examples Scenario: temporarily pending by prefixing `it`, `specify`, or `example` with an x Given a file named "temporarily_pending_spec.rb" with: - """ + """ruby describe "an example" do xit "is pending using xit" do end @@ -110,7 +110,7 @@ Feature: pending examples Scenario: example with no docstring and pending method using documentation formatter Given a file named "pending_with_no_docstring_spec.rb" with: - """ + """ruby describe "an example" do it "checks something" do (3+4).should eq(7) @@ -132,7 +132,7 @@ Feature: pending examples Scenario: pending with no docstring using documentation formatter Given a file named "pending_with_no_docstring_spec.rb" with: - """ + """ruby describe "an example" do it "checks something" do (3+4).should eq(7) @@ -154,7 +154,7 @@ Feature: pending examples Scenario: conditionally pending examples Given a file named "conditionally_pending_spec.rb" with: - """ + """ruby describe "a failing spec" do def run_test; raise "failure"; end diff --git a/features/spec_files/arbitrary_file_suffix.feature b/features/spec_files/arbitrary_file_suffix.feature index 915d05fbbc..1e3439ccf7 100644 --- a/features/spec_files/arbitrary_file_suffix.feature +++ b/features/spec_files/arbitrary_file_suffix.feature @@ -2,7 +2,7 @@ Feature: arbitrary file suffix Scenario: .spec Given a file named "a.spec" with: - """ + """ruby describe "something" do it "does something" do 3.should eq(3) diff --git a/features/step_definitions/additional_cli_steps.rb b/features/step_definitions/additional_cli_steps.rb index bbbe14e370..9603587602 100644 --- a/features/step_definitions/additional_cli_steps.rb +++ b/features/step_definitions/additional_cli_steps.rb @@ -1,3 +1,5 @@ +require 'rspec/core' # to fix annoying "undefined method `configuration' for RSpec:Module (NoMethodError)" + Then /^the output should contain all of these:$/ do |table| table.raw.flatten.each do |string| assert_partial_output(string, all_output) diff --git a/features/subject/attribute_of_subject.feature b/features/subject/attribute_of_subject.feature index 0f09049c5b..b7788c62e7 100644 --- a/features/subject/attribute_of_subject.feature +++ b/features/subject/attribute_of_subject.feature @@ -23,7 +23,7 @@ Feature: attribute of subject Scenario: specify value of an attribute Given a file named "example_spec.rb" with: - """ + """ruby describe Array do context "when first created" do its(:size) { should eq(0) } @@ -41,7 +41,7 @@ Feature: attribute of subject Scenario: specify value of a nested attribute Given a file named "example_spec.rb" with: - """ + """ruby class Person attr_reader :phone_numbers def initialize @@ -72,7 +72,7 @@ Feature: attribute of subject Scenario: specify value of an attribute of a hash Given a file named "example_spec.rb" with: - """ + """ruby describe Hash do context "with two items" do subject do @@ -88,7 +88,7 @@ Feature: attribute of subject Scenario: specify value for key in a hash Given a file named "example_spec.rb" with: - """ + """ruby describe Hash do context "with keys :one and 'two'" do subject do @@ -105,7 +105,7 @@ Feature: attribute of subject Scenario: specify value for key in a hash-like object Given a file named "example_spec.rb" with: - """ + """ruby require 'matrix' describe Matrix do diff --git a/features/subject/explicit_subject.feature b/features/subject/explicit_subject.feature index cdf8ae69b5..ee14febefe 100644 --- a/features/subject/explicit_subject.feature +++ b/features/subject/explicit_subject.feature @@ -9,7 +9,7 @@ Feature: explicit subject Scenario: subject in top level group Given a file named "top_level_subject_spec.rb" with: - """ + """ruby describe Array, "with some elements" do subject { [1,2,3] } it "should have the prescribed elements" do @@ -22,7 +22,7 @@ Feature: explicit subject Scenario: subject in a nested group Given a file named "nested_subject_spec.rb" with: - """ + """ruby describe Array do subject { [1,2,3] } describe "with some elements" do @@ -37,7 +37,7 @@ Feature: explicit subject Scenario: access subject from before block Given a file named "top_level_subject_spec.rb" with: - """ + """ruby describe Array, "with some elements" do subject { [] } before { subject.push(1,2,3) } @@ -51,7 +51,7 @@ Feature: explicit subject Scenario: invoke helper method from subject block Given a file named "helper_subject_spec.rb" with: - """ + """ruby describe Array do def prepared_array; [1,2,3] end subject { prepared_array } @@ -67,7 +67,7 @@ Feature: explicit subject Scenario: subject block is invoked at most once per example Given a file named "nil_subject_spec.rb" with: - """ + """ruby describe Array do describe "#[]" do context "with index out of bounds" do diff --git a/features/subject/implicit_receiver.feature b/features/subject/implicit_receiver.feature index 5f9518d521..209bbe6536 100644 --- a/features/subject/implicit_receiver.feature +++ b/features/subject/implicit_receiver.feature @@ -5,7 +5,7 @@ Feature: implicit receiver Scenario: implicit subject Given a file named "example_spec.rb" with: - """ + """ruby describe Array do describe "when first created" do it { should be_empty } @@ -17,7 +17,7 @@ Feature: implicit receiver Scenario: explicit subject Given a file named "example_spec.rb" with: - """ + """ruby describe Array do describe "with 3 items" do subject { [1,2,3] } diff --git a/features/subject/implicit_subject.feature b/features/subject/implicit_subject.feature index c7f3ceca55..b8ec5af316 100644 --- a/features/subject/implicit_subject.feature +++ b/features/subject/implicit_subject.feature @@ -9,7 +9,7 @@ Feature: implicitly defined subject Scenario: subject exposed in top level group Given a file named "top_level_subject_spec.rb" with: - """ + """ruby describe Array do it "should be empty when first created" do subject.should be_empty @@ -21,7 +21,7 @@ Feature: implicitly defined subject Scenario: subject in a nested group Given a file named "nested_subject_spec.rb" with: - """ + """ruby describe Array do describe "when first created" do it "should be empty" do @@ -35,7 +35,7 @@ Feature: implicitly defined subject Scenario: subject in a nested group with a different class (outermost wins) Given a file named "nested_subject_spec.rb" with: - """ + """ruby class ArrayWithOneElement < Array def initialize(*) super diff --git a/lib/autotest/rspec2.rb b/lib/autotest/rspec2.rb index 50d07f6c1c..70a301f295 100644 --- a/lib/autotest/rspec2.rb +++ b/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 diff --git a/lib/rspec/core.rb b/lib/rspec/core.rb index a39a06e253..63bdf0e8bb 100644 --- a/lib/rspec/core.rb +++ b/lib/rspec/core.rb @@ -1,43 +1,45 @@ -if defined?(require_relative) - # @private - def require_rspec(path) +require_rspec = if defined?(require_relative) + lambda do |path| require_relative path end else - # @private - def require_rspec(path) + lambda do |path| require "rspec/#{path}" end end require 'set' require 'rbconfig' -require_rspec 'core/filter_manager' -require_rspec 'core/dsl' -require_rspec 'core/extensions' -require_rspec 'core/load_path' -require_rspec 'core/deprecation' -require_rspec 'core/backward_compatibility' -require_rspec 'core/reporter' - -require_rspec 'core/metadata_hash_builder' -require_rspec 'core/hooks' -require_rspec 'core/subject' -require_rspec 'core/let' -require_rspec 'core/metadata' -require_rspec 'core/pending' - -require_rspec 'core/world' -require_rspec 'core/configuration' -require_rspec 'core/project_initializer' -require_rspec 'core/option_parser' -require_rspec 'core/configuration_options' -require_rspec 'core/command_line' -require_rspec 'core/runner' -require_rspec 'core/example' -require_rspec 'core/shared_example_group' -require_rspec 'core/example_group' -require_rspec 'core/version' +require_rspec['core/filter_manager'] +require_rspec['core/dsl'] +require_rspec['core/extensions/kernel'] +require_rspec['core/extensions/instance_eval_with_args'] +require_rspec['core/extensions/module_eval_with_args'] +require_rspec['core/extensions/ordered'] +require_rspec['core/load_path'] +require_rspec['core/deprecation'] +require_rspec['core/backward_compatibility'] +require_rspec['core/reporter'] + +require_rspec['core/metadata_hash_builder'] +require_rspec['core/hooks'] +require_rspec['core/subject'] +require_rspec['core/let'] +require_rspec['core/metadata'] +require_rspec['core/pending'] +require_rspec['core/formatters'] + +require_rspec['core/world'] +require_rspec['core/configuration'] +require_rspec['core/project_initializer'] +require_rspec['core/option_parser'] +require_rspec['core/configuration_options'] +require_rspec['core/command_line'] +require_rspec['core/runner'] +require_rspec['core/example'] +require_rspec['core/shared_example_group'] +require_rspec['core/example_group'] +require_rspec['core/version'] module RSpec autoload :SharedContext, 'rspec/core/shared_context' @@ -77,6 +79,20 @@ def self.reset # @see RSpec.configure # @see Core::Configuration def self.configuration + if block_given? + RSpec.warn_deprecation <<-WARNING + +***************************************************************** +DEPRECATION WARNING + +* RSpec.configuration with a block is deprecated and has no effect. +* please use RSpec.configure with a block instead. + +Called from #{caller(0)[1]} +***************************************************************** + +WARNING + end @configuration ||= RSpec::Core::Configuration.new end @@ -104,6 +120,11 @@ def self.windows_os? end module Core + # @private + # This avoids issues with reporting time caused by examples that + # change the value/meaning of Time.now without properly restoring + # it. + Time = ::Time.dup end def self.const_missing(name) @@ -123,4 +144,4 @@ def self.const_missing(name) end end -require_rspec 'core/backward_compatibility' +require_rspec['core/backward_compatibility'] diff --git a/lib/rspec/core/configuration.rb b/lib/rspec/core/configuration.rb index fa87ed7908..be4e4052b6 100644 --- a/lib/rspec/core/configuration.rb +++ b/lib/rspec/core/configuration.rb @@ -405,17 +405,21 @@ def full_backtrace=(true_or_false) @backtrace_clean_patterns = true_or_false ? [] : DEFAULT_BACKTRACE_PATTERNS end - def color - return false unless output_to_tty? + def color(output=output_stream) + # rspec's built-in formatters all call this with the output argument, + # but defaulting to output_stream for backward compatibility with + # formatters in extension libs + return false unless output_to_tty?(output) value_for(:color, @color) end def color=(bool) if bool - @color = true if RSpec.windows_os? and not ENV['ANSICON'] - warn "You must use ANSICON 1.31 or later (http://adoxa.110mb.com/ansicon/) to use colour on Windows" + warn "You must use ANSICON 1.31 or later (http://adoxa.3eeweb.com/ansicon/) to use colour on Windows" @color = false + else + @color = true end end end @@ -500,7 +504,7 @@ def reporter # @private def files_or_directories_to_run=(*files) files = files.flatten - files << default_path if command == 'rspec' && default_path && files.empty? + files << default_path if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty? self.files_to_run = get_files_to_run(files) end @@ -777,10 +781,29 @@ def configure_expectation_framework # @private def load_spec_files - files_to_run.uniq.map {|f| load File.expand_path(f) } + files_to_run.uniq.each {|f| load File.expand_path(f) } raise_if_rspec_1_is_loaded end + # @private + DEFAULT_FORMATTER = lambda { |string| string } + + # Formats the docstring output using the block provided. + # + # @example + # # This will strip the descriptions of both examples and example groups. + # RSpec.configure do |config| + # config.format_docstrings { |s| s.strip } + # end + def format_docstrings(&block) + @format_docstrings_block = block_given? ? block : DEFAULT_FORMATTER + end + + # @private + def format_docstrings_block + @format_docstrings_block ||= DEFAULT_FORMATTER + end + # @api # # Sets the seed value and sets `order='rand'` @@ -799,6 +822,79 @@ def randomize? order.to_s.match(/rand/) end + # @private + DEFAULT_ORDERING = lambda { |list| list } + + # @private + RANDOM_ORDERING = lambda do |list| + Kernel.srand RSpec.configuration.seed + list.sort_by { Kernel.rand(list.size) } + end + + # Sets a strategy by which to order examples. + # + # @example + # RSpec.configure do |config| + # config.order_examples do |examples| + # examples.reverse + # end + # end + # + # @see #order_groups + # @see #order_groups_and_examples + # @see #order= + # @see #seed= + def order_examples(&block) + @example_ordering_block = block + @order = "custom" unless built_in_orderer?(block) + end + + # @private + def example_ordering_block + @example_ordering_block ||= DEFAULT_ORDERING + end + + # Sets a strategy by which to order groups. + # + # @example + # RSpec.configure do |config| + # config.order_groups do |groups| + # groups.reverse + # end + # end + # + # @see #order_examples + # @see #order_groups_and_examples + # @see #order= + # @see #seed= + def order_groups(&block) + @group_ordering_block = block + @order = "custom" unless built_in_orderer?(block) + end + + # @private + def group_ordering_block + @group_ordering_block ||= DEFAULT_ORDERING + end + + # Sets a strategy by which to order groups and examples. + # + # @example + # RSpec.configure do |config| + # config.order_groups_and_examples do |groups_or_examples| + # groups_or_examples.reverse + # end + # end + # + # @see #order_groups + # @see #order_examples + # @see #order= + # @see #seed= + def order_groups_and_examples(&block) + order_groups(&block) + order_examples(&block) + end + private def get_files_to_run(paths) @@ -806,12 +902,12 @@ def get_files_to_run(paths) paths.map do |path| path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR File.directory?(path) ? gather_directories(path, patterns) : extract_location(path) - end.flatten + end.flatten.sort end def gather_directories(path, patterns) patterns.map do |pattern| - pattern =~ /^#{path}/ ? Dir[pattern.strip] : Dir["#{path}/{#{pattern.strip}}"] + pattern =~ /^#{path}/ ? Dir[pattern.strip].sort : Dir["#{path}/{#{pattern.strip}}"].sort end end @@ -856,12 +952,8 @@ def raise_if_rspec_1_is_loaded end end - def output_to_tty? - begin - output_stream.tty? || tty? - rescue NoMethodError - false - end + def output_to_tty?(output=output_stream) + tty? || (output.respond_to?(:tty?) && output.tty?) end def built_in_formatter(key) @@ -878,6 +970,9 @@ def built_in_formatter(key) when 'p', 'progress' require 'rspec/core/formatters/progress_formatter' RSpec::Core::Formatters::ProgressFormatter + when 'j', 'json' + require 'rspec/core/formatters/json_formatter' + RSpec::Core::Formatters::JsonFormatter end end @@ -923,7 +1018,9 @@ def file_at(path) end def order_and_seed_from_seed(value) + order_groups_and_examples(&RANDOM_ORDERING) @order, @seed = 'rand', value.to_i + [@order, @seed] end def set_order_and_seed(hash) @@ -935,10 +1032,21 @@ def order_and_seed_from_order(type) order, seed = type.to_s.split(':') @order = order @seed = seed = seed.to_i if seed - @order, @seed = nil, nil if order == 'default' + + if randomize? + order_groups_and_examples(&RANDOM_ORDERING) + elsif order == 'default' + @order, @seed = nil, nil + order_groups_and_examples(&DEFAULT_ORDERING) + end + return order, seed end + def built_in_orderer?(block) + [DEFAULT_ORDERING, RANDOM_ORDERING].include?(block) + end + end end end diff --git a/lib/rspec/core/configuration_options.rb b/lib/rspec/core/configuration_options.rb index 25ecfe3dd3..b38c01451d 100644 --- a/lib/rspec/core/configuration_options.rb +++ b/lib/rspec/core/configuration_options.rb @@ -9,6 +9,13 @@ class ConfigurationOptions def initialize(args) @args = args + if args.include?("--default_path") + args[args.index("--default_path")] = "--default-path" + end + + if args.include?("--line_number") + args[args.index("--line_number")] = "--line-number" + end end def configure(config) @@ -71,7 +78,7 @@ def all_configs end def file_options - custom_options_file ? [custom_options] : [global_options, local_options] + custom_options_file ? [custom_options] : [global_options, project_options, local_options] end def env_options @@ -90,6 +97,10 @@ def local_options @local_options ||= options_from(local_options_file) end + def project_options + @project_options ||= options_from(project_options_file) + end + def global_options @global_options ||= options_from(global_options_file) end @@ -112,10 +123,14 @@ def custom_options_file command_line_options[:custom_options_file] end - def local_options_file + def project_options_file ".rspec" end + def local_options_file + ".rspec-local" + end + def global_options_file begin File.join(File.expand_path("~"), ".rspec") diff --git a/lib/rspec/core/example.rb b/lib/rspec/core/example.rb index 698c49d578..2219dd3a9b 100644 --- a/lib/rspec/core/example.rb +++ b/lib/rspec/core/example.rb @@ -49,7 +49,8 @@ def self.delegate_to_metadata(*keys) # there is one, otherwise returns a message including the location of the # example. def description - metadata[:description].to_s.empty? ? "example at #{location}" : metadata[:description] + description = metadata[:description].to_s.empty? ? "example at #{location}" : metadata[:description] + RSpec.configuration.format_docstrings_block.call(description) end # @attr_reader @@ -260,7 +261,7 @@ def with_around_each_hooks(&block) def start(reporter) reporter.example_started(self) - record :started_at => Time.now + record :started_at => RSpec::Core::Time.now end # @private @@ -290,8 +291,8 @@ def finish(reporter) end def record_finished(status, results={}) - finished_at = Time.now - record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - execution_result[:started_at])) + finished_at = RSpec::Core::Time.now + record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - execution_result[:started_at]).to_f) end def run_before_each diff --git a/lib/rspec/core/example_group.rb b/lib/rspec/core/example_group.rb index e7fef9dba9..fb2de4e179 100644 --- a/lib/rspec/core/example_group.rb +++ b/lib/rspec/core/example_group.rb @@ -22,6 +22,7 @@ class ExampleGroup include Subject::ExampleMethods include Pending include Let + include SharedExampleGroup # @private def self.world @@ -43,7 +44,12 @@ def self.delegate_to_metadata(*names) end end - delegate_to_metadata :description, :described_class, :file_path + def description + description = metadata[:example_group][:description] + RSpec.configuration.format_docstrings_block.call(description) + end + + delegate_to_metadata :described_class, :file_path alias_method :display_name, :description # @private alias_method :describes, :described_class @@ -241,7 +247,7 @@ def self.subclass(parent, args, &example_group_block) # @private def self.children - @children ||= [].extend(Extensions::Ordered) + @children ||= [].extend(Extensions::Ordered::ExampleGroups) end # @private @@ -249,9 +255,9 @@ def self.descendants @_descendants ||= [self] + children.inject([]) {|list, c| list + c.descendants} end - # @private - def self.ancestors - @_ancestors ||= super().select {|a| a < RSpec::Core::ExampleGroup} + ## @private + def self.parent_groups + @parent_groups ||= ancestors.select {|a| a < RSpec::Core::ExampleGroup} end # @private @@ -308,9 +314,12 @@ def self.assign_before_all_ivars(ivars, example_group_instance) # @private def self.run_before_all_hooks(example_group_instance) return if descendant_filtered_examples.empty? - assign_before_all_ivars(superclass.before_all_ivars, example_group_instance) - run_hook(:before, :all, example_group_instance) - store_before_all_ivars(example_group_instance) + begin + assign_before_all_ivars(superclass.before_all_ivars, example_group_instance) + run_hook(:before, :all, example_group_instance) + ensure + store_before_all_ivars(example_group_instance) + end end # @private @@ -361,6 +370,7 @@ def self.run(reporter) results_for_descendants = children.ordered.map {|child| child.run(reporter)}.all? result_for_this_group && results_for_descendants rescue Exception => ex + RSpec.wants_to_quit = true if fail_fast? fail_filtered_examples(ex, reporter) ensure run_after_all_hooks(new) @@ -417,7 +427,7 @@ def self.declaration_line_numbers # @private def self.top_level_description - ancestors.last.description + parent_groups.last.description end # @private diff --git a/lib/rspec/core/extensions.rb b/lib/rspec/core/extensions.rb deleted file mode 100644 index ecc75bbd46..0000000000 --- a/lib/rspec/core/extensions.rb +++ /dev/null @@ -1,4 +0,0 @@ -require_rspec 'core/extensions/kernel' -require_rspec 'core/extensions/instance_eval_with_args' -require_rspec 'core/extensions/module_eval_with_args' -require_rspec 'core/extensions/ordered' diff --git a/lib/rspec/core/extensions/ordered.rb b/lib/rspec/core/extensions/ordered.rb index ca58c8fdb2..7264909597 100644 --- a/lib/rspec/core/extensions/ordered.rb +++ b/lib/rspec/core/extensions/ordered.rb @@ -7,12 +7,18 @@ module Extensions # strategies like randomization. module Ordered # @private - def ordered - if RSpec.configuration.randomize? - Kernel.srand RSpec.configuration.seed - sort_by { Kernel.rand size } - else - self + module ExampleGroups + # @private + def ordered + RSpec.configuration.group_ordering_block.call(self) + end + end + + # @private + module Examples + # @private + def ordered + RSpec.configuration.example_ordering_block.call(self) end end end diff --git a/lib/rspec/core/formatters.rb b/lib/rspec/core/formatters.rb new file mode 100644 index 0000000000..5c54177568 --- /dev/null +++ b/lib/rspec/core/formatters.rb @@ -0,0 +1,55 @@ +# ## Built-in Formatters +# +# * progress (default) - prints dots for passing examples, `F` for failures, `*` for pending +# * documentation - prints the docstrings passed to `describe` and `it` methods (and their aliases) +# * html +# * textmate - html plus links to editor +# * json - useful for archiving data for subsequent analysis +# +# The progress formatter is the default, but you can choose any one or more of +# the other formatters by passing with the `--format` (or `-f` for short) +# command-line option, e.g. +# +# rspec --format documentation +# +# You can also send the output of multiple formatters to different streams, e.g. +# +# rspec --format documentation --format html --out results.html +# +# This example sends the output of the documentation formatter to `STDOUT`, and +# the output of the html formatter to results.html. +# +# ## Custom Formatters +# +# You can tell RSpec to use a custom formatter by passing its path and name to +# the `rspec` commmand. For example, if you define MyCustomFormatter in +# path/to/my_custom_formatter.rb, you would type this command: +# +# rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter +# +# The reporter calls every formatter with this protocol: +# +# * `start(expected_example_count)` +# * zero or more of the following +# * `example_group_started(group)` +# * `example_started(example)` +# * `example_passed(example)` +# * `example_failed(example)` +# * `example_pending(example)` +# * `message(string)` +# * `stop` +# * `start_dump` +# * `dump_pending` +# * `dump_failures` +# * `dump_summary(duration, example_count, failure_count, pending_count)` +# * `seed(value)` +# * `close` +# +# You can either implement all of those methods or subclass +# `RSpec::Core::Formatters::BaseTextFormatter` and override the methods you want +# to enhance. +# +# @see RSpec::Core::Formatters::BaseTextFormatter +# @see RSpec::Core::Reporter +module RSpec::Core::Formatters +end diff --git a/lib/rspec/core/formatters/base_formatter.rb b/lib/rspec/core/formatters/base_formatter.rb index 5afed53221..7b1ac1dd34 100644 --- a/lib/rspec/core/formatters/base_formatter.rb +++ b/lib/rspec/core/formatters/base_formatter.rb @@ -4,7 +4,12 @@ module RSpec module Core module Formatters - + # RSpec's built-in formatters are all subclasses of RSpec::Core::Formatters::BaseTextFormatter, + # but the BaseTextFormatter documents all of the methods needed to be implemented by a formatter, + # as they are called from the reporter. + # + # @see RSpec::Core::Formatters::BaseTextFormatter + # @see RSpec::Core::Reporter class BaseFormatter include Helpers attr_accessor :example_group @@ -21,54 +26,68 @@ def initialize(output) @example_group = nil end - # This method is invoked before any examples are run, right after - # they have all been collected. This can be useful for special - # formatters that need to provide progress on feedback (graphical ones) + # Invoked before any examples are run, right after they have all + # been collected. This can be useful for formatters that provide + # feedback on progress through a suite. # - # This will only be invoked once, and the next one to be invoked - # is #example_group_started + # @param example_count def start(example_count) start_sync_output @example_count = example_count end - # This method is invoked at the beginning of the execution of each example group. - # +example_group+ is the example_group. + # Invoked at the beginning of the execution of each example + # group. # - # The next method to be invoked after this is +example_passed+, - # +example_pending+, or +example_finished+ + # @param example_group subclass of `RSpec::Core::ExampleGroup` def example_group_started(example_group) @example_group = example_group end - # This method is invoked at the end of the execution of each example group. - # +example_group+ is the example_group. + # Invoked at the end of the execution of each example group. + # + # @param example_group subclass of `RSpec::Core::ExampleGroup` def example_group_finished(example_group) end + + # Invoked at the beginning of the execution of each example. + # + # @param example instance of subclass of `RSpec::Core::ExampleGroup` def example_started(example) examples << example end + # Invoked when an example passes. + # + # @param example instance of subclass of `RSpec::Core::ExampleGroup` def example_passed(example) end + # Invoked when an example is pending. + # + # @param example instance of subclass of `RSpec::Core::ExampleGroup` def example_pending(example) @pending_examples << example end + # Invoked when an example fails. + # + # @param example instance of subclass of `RSpec::Core::ExampleGroup` def example_failed(example) @failed_examples << example end + # Used by the reporter to send messages to the output stream. + # @param [String] message def message(message) end + # Invoked after all examples have executed, before dumping post-run reports. def stop end - # This method is invoked after all of the examples have executed. The next method - # to be invoked after this one is #dump_failure (once for each failed example), + # Invoked after all of the examples have executed (after `stop`). def start_dump end @@ -76,7 +95,7 @@ def start_dump def dump_failures end - # This method is invoked after the dumping of examples and failures. + # Invoked after the dumping of examples and failures. def dump_summary(duration, example_count, failure_count, pending_count) @duration = duration @example_count = example_count @@ -84,41 +103,26 @@ def dump_summary(duration, example_count, failure_count, pending_count) @pending_count = pending_count end - # This gets invoked after the summary if option is set to do so. + # Invoked after the summary if option is set to do so. def dump_pending end + # @private not intended for use outside RSpec. def seed(number) end - # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams. + # Invoked at the very end, `close` allows the formatter to clean + # up resources, e.g. open streams, etc. def close restore_sync_output end - def format_backtrace(backtrace, example) - return "" unless backtrace - return backtrace if example.metadata[:full_backtrace] == true - - if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE) - backtrace = backtrace[0, at_exit_index] - end - - cleansed = backtrace.map { |line| backtrace_line(line) }.compact - cleansed.empty? ? backtrace : cleansed - end - protected def configuration RSpec.configuration end - def backtrace_line(line) - return nil if configuration.cleaned_from_backtrace?(line) - RSpec::Core::Metadata::relative_path(line) - end - def read_failed_line(exception, example) unless matching_line = find_failed_line(exception.backtrace, example.file_path) return "Unable to find matching line from backtrace" @@ -127,10 +131,13 @@ def read_failed_line(exception, example) file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2] if File.exist?(file_path) - File.readlines(file_path)[line_number.to_i - 1] + File.readlines(file_path)[line_number.to_i - 1] || + "Unable to find matching line in #{file_path}" else "Unable to find #{file_path} to read failed line" end + rescue SecurityError + "Unable to read failed line" end def find_failed_line(backtrace, path) @@ -158,11 +165,9 @@ def profile_examples? end def color_enabled? - configuration.color_enabled? + configuration.color_enabled?(output) end - end - end end end diff --git a/lib/rspec/core/formatters/base_text_formatter.rb b/lib/rspec/core/formatters/base_text_formatter.rb index cb96ff42cb..fceebc8c5e 100644 --- a/lib/rspec/core/formatters/base_text_formatter.rb +++ b/lib/rspec/core/formatters/base_text_formatter.rb @@ -4,8 +4,12 @@ module RSpec module Core module Formatters + # Base for all of RSpec's built-in formatters. See RSpec::Core::Formatters::BaseFormatter + # to learn more about all of the methods called by the reporter. + # + # @see RSpec::Core::Formatters::BaseFormatter + # @see RSpec::Core::Reporter class BaseTextFormatter < BaseFormatter - def message(message) output.puts message end @@ -156,7 +160,7 @@ def format_caller(caller_info) end def dump_backtrace(example) - format_backtrace(example.execution_result[:exception].backtrace, example).each do |backtrace_info| + format_backtrace(example.execution_result[:exception].backtrace, example.metadata).each do |backtrace_info| output.puts cyan("#{long_padding}# #{backtrace_info}") end end @@ -191,11 +195,11 @@ def dump_shared_failure_info(group) end def find_shared_group(example) - group_and_ancestors(example).find {|group| group.metadata[:shared_group_name]} + group_and_parent_groups(example).find {|group| group.metadata[:shared_group_name]} end - def group_and_ancestors(example) - example.example_group.ancestors + [example.example_group] + def group_and_parent_groups(example) + example.example_group.parent_groups + [example.example_group] end end end diff --git a/lib/rspec/core/formatters/documentation_formatter.rb b/lib/rspec/core/formatters/documentation_formatter.rb index f65d2dfd2e..4e61a9be6e 100644 --- a/lib/rspec/core/formatters/documentation_formatter.rb +++ b/lib/rspec/core/formatters/documentation_formatter.rb @@ -59,7 +59,7 @@ def current_indentation end def example_group_chain - example_group.ancestors.reverse + example_group.parent_groups.reverse end end end diff --git a/lib/rspec/core/formatters/helpers.rb b/lib/rspec/core/formatters/helpers.rb index 5da56896fb..21a8f1b6e5 100644 --- a/lib/rspec/core/formatters/helpers.rb +++ b/lib/rspec/core/formatters/helpers.rb @@ -1,8 +1,34 @@ module RSpec module Core - module Formatters + module BacktraceFormatter + extend self + + def format_backtrace(backtrace, options = {}) + return "" unless backtrace + return backtrace if options[:full_backtrace] == true + + if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE) + backtrace = backtrace[0, at_exit_index] + end + + cleansed = backtrace.map { |line| backtrace_line(line) }.compact + cleansed.empty? ? backtrace : cleansed + end + + protected + def backtrace_line(line) + return nil if RSpec.configuration.cleaned_from_backtrace?(line) + RSpec::Core::Metadata::relative_path(line) + rescue SecurityError + nil + end + end + + module Formatters module Helpers + include BacktraceFormatter + SUB_SECOND_PRECISION = 5 DEFAULT_PRECISION = 2 @@ -11,9 +37,9 @@ def format_duration(duration) minutes = duration.to_i / 60 seconds = duration - minutes * 60 - "#{pluralize(minutes, 'minute')} #{format_seconds(seconds)} seconds" + "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds), 'second')}" else - "#{format_seconds(duration)} seconds" + pluralize(format_seconds(duration), 'second') end end @@ -29,9 +55,8 @@ def strip_trailing_zeroes(string) end def pluralize(count, string) - "#{count} #{string}#{'s' unless count == 1}" + "#{count} #{string}#{'s' unless count.to_f == 1}" end - end end diff --git a/lib/rspec/core/formatters/html_formatter.rb b/lib/rspec/core/formatters/html_formatter.rb index b24b033071..bb58a7266d 100644 --- a/lib/rspec/core/formatters/html_formatter.rb +++ b/lib/rspec/core/formatters/html_formatter.rb @@ -1,17 +1,17 @@ -require 'erb' require 'rspec/core/formatters/base_text_formatter' +require 'rspec/core/formatters/html_printer' module RSpec module Core module Formatters class HtmlFormatter < BaseTextFormatter - include ERB::Util # for the #h method def initialize(output) super(output) @example_group_number = 0 @example_number = 0 @header_red = nil + @printer = HtmlPrinter.new(output) end private @@ -35,29 +35,25 @@ def example_number def start(example_count) super(example_count) - @output.puts html_header - @output.puts report_header - @output.flush + @printer.print_html_start + @printer.flush end def example_group_started(example_group) super(example_group) @example_group_red = false @example_group_number += 1 + unless example_group_number == 1 - @output.puts " " - @output.puts "" + @printer.print_example_group_end end - @output.puts "
#{format_backtrace(exception.backtrace, example).join("\n")}
#{@snippet_extractor.snippet(backtrace)}
"
end
- def move_progress
- @output.puts " "
- @output.flush
- end
-
def percent_done
result = 100.0
if @example_count > 0
@@ -134,329 +139,14 @@ def dump_pending
end
def dump_summary(duration, example_count, failure_count, pending_count)
- # TODO - kill dry_run?
- if dry_run?
- totals = "This was a dry-run"
- else
- totals = "#{example_count} example#{'s' unless example_count == 1}, "
- totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
- totals << ", #{pending_count} pending" if pending_count > 0
- end
- @output.puts ""
- @output.puts ""
- @output.puts ""
- @output.puts ""
- @output.puts "