rspec-core 3.0.4 → 3.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +2 -1
- data/Changelog.md +888 -2
- data/{License.txt → LICENSE.md} +6 -5
- data/README.md +165 -24
- data/lib/rspec/autorun.rb +1 -0
- data/lib/rspec/core/backtrace_formatter.rb +19 -20
- data/lib/rspec/core/bisect/coordinator.rb +62 -0
- data/lib/rspec/core/bisect/example_minimizer.rb +173 -0
- data/lib/rspec/core/bisect/fork_runner.rb +138 -0
- data/lib/rspec/core/bisect/server.rb +61 -0
- data/lib/rspec/core/bisect/shell_command.rb +126 -0
- data/lib/rspec/core/bisect/shell_runner.rb +73 -0
- data/lib/rspec/core/bisect/utilities.rb +69 -0
- data/lib/rspec/core/configuration.rb +1287 -246
- data/lib/rspec/core/configuration_options.rb +95 -35
- data/lib/rspec/core/did_you_mean.rb +46 -0
- data/lib/rspec/core/drb.rb +21 -12
- data/lib/rspec/core/dsl.rb +10 -6
- data/lib/rspec/core/example.rb +305 -113
- data/lib/rspec/core/example_group.rb +431 -223
- data/lib/rspec/core/example_status_persister.rb +235 -0
- data/lib/rspec/core/filter_manager.rb +86 -115
- data/lib/rspec/core/flat_map.rb +6 -4
- data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
- data/lib/rspec/core/formatters/base_formatter.rb +14 -116
- data/lib/rspec/core/formatters/base_text_formatter.rb +18 -21
- data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
- data/lib/rspec/core/formatters/bisect_progress_formatter.rb +157 -0
- data/lib/rspec/core/formatters/console_codes.rb +29 -18
- data/lib/rspec/core/formatters/deprecation_formatter.rb +16 -16
- data/lib/rspec/core/formatters/documentation_formatter.rb +49 -16
- data/lib/rspec/core/formatters/exception_presenter.rb +525 -0
- data/lib/rspec/core/formatters/failure_list_formatter.rb +23 -0
- data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
- data/lib/rspec/core/formatters/helpers.rb +45 -15
- data/lib/rspec/core/formatters/html_formatter.rb +33 -28
- data/lib/rspec/core/formatters/html_printer.rb +30 -20
- data/lib/rspec/core/formatters/html_snippet_extractor.rb +120 -0
- data/lib/rspec/core/formatters/json_formatter.rb +18 -9
- data/lib/rspec/core/formatters/profile_formatter.rb +10 -9
- data/lib/rspec/core/formatters/progress_formatter.rb +5 -4
- data/lib/rspec/core/formatters/protocol.rb +182 -0
- data/lib/rspec/core/formatters/snippet_extractor.rb +113 -82
- data/lib/rspec/core/formatters/syntax_highlighter.rb +91 -0
- data/lib/rspec/core/formatters.rb +81 -41
- data/lib/rspec/core/hooks.rb +314 -244
- data/lib/rspec/core/invocations.rb +87 -0
- data/lib/rspec/core/memoized_helpers.rb +161 -51
- data/lib/rspec/core/metadata.rb +132 -61
- data/lib/rspec/core/metadata_filter.rb +224 -64
- data/lib/rspec/core/minitest_assertions_adapter.rb +6 -3
- data/lib/rspec/core/mocking_adapters/flexmock.rb +4 -2
- data/lib/rspec/core/mocking_adapters/mocha.rb +11 -9
- data/lib/rspec/core/mocking_adapters/null.rb +2 -0
- data/lib/rspec/core/mocking_adapters/rr.rb +3 -1
- data/lib/rspec/core/mocking_adapters/rspec.rb +3 -1
- data/lib/rspec/core/notifications.rb +192 -206
- data/lib/rspec/core/option_parser.rb +174 -69
- data/lib/rspec/core/ordering.rb +48 -35
- data/lib/rspec/core/output_wrapper.rb +29 -0
- data/lib/rspec/core/pending.rb +25 -33
- data/lib/rspec/core/profiler.rb +34 -0
- data/lib/rspec/core/project_initializer/.rspec +0 -2
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +59 -39
- data/lib/rspec/core/project_initializer.rb +5 -3
- data/lib/rspec/core/rake_task.rb +99 -55
- data/lib/rspec/core/reporter.rb +128 -15
- data/lib/rspec/core/ruby_project.rb +14 -6
- data/lib/rspec/core/runner.rb +96 -45
- data/lib/rspec/core/sandbox.rb +37 -0
- data/lib/rspec/core/set.rb +54 -0
- data/lib/rspec/core/shared_example_group.rb +133 -43
- data/lib/rspec/core/shell_escape.rb +49 -0
- data/lib/rspec/core/test_unit_assertions_adapter.rb +4 -4
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/warnings.rb +6 -6
- data/lib/rspec/core/world.rb +172 -68
- data/lib/rspec/core.rb +66 -21
- data.tar.gz.sig +0 -0
- metadata +93 -69
- metadata.gz.sig +0 -0
- data/lib/rspec/core/backport_random.rb +0 -336
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Core
|
|
3
|
+
# @private
|
|
4
|
+
class Profiler
|
|
5
|
+
NOTIFICATIONS = [:example_group_started, :example_group_finished, :example_started]
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@example_groups = Hash.new { |h, k| h[k] = { :count => 0 } }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
attr_reader :example_groups
|
|
12
|
+
|
|
13
|
+
def example_group_started(notification)
|
|
14
|
+
return unless notification.group.top_level?
|
|
15
|
+
|
|
16
|
+
@example_groups[notification.group][:start] = Time.now
|
|
17
|
+
@example_groups[notification.group][:description] = notification.group.top_level_description
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def example_group_finished(notification)
|
|
21
|
+
return unless notification.group.top_level?
|
|
22
|
+
|
|
23
|
+
group = @example_groups[notification.group]
|
|
24
|
+
return unless group.key?(:start)
|
|
25
|
+
group[:total_time] = Time.now - group[:start]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def example_started(notification)
|
|
29
|
+
group = notification.example.example_group.parent_groups.last
|
|
30
|
+
@example_groups[group][:count] += 1
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,29 +1,72 @@
|
|
|
1
1
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
|
2
2
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
|
3
|
-
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
|
4
|
-
# file to always be loaded, without a need to explicitly require it in any
|
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
|
4
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
|
5
|
+
# files.
|
|
5
6
|
#
|
|
6
7
|
# Given that it is always loaded, you are encouraged to keep this file as
|
|
7
8
|
# light-weight as possible. Requiring heavyweight dependencies from this file
|
|
8
9
|
# will add to the boot time of your test suite on EVERY test run, even for an
|
|
9
|
-
# individual file that may not need all of that loaded. Instead,
|
|
10
|
-
# separate helper file that requires
|
|
11
|
-
# that actually need
|
|
10
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
|
11
|
+
# a separate helper file that requires the additional dependencies and performs
|
|
12
|
+
# the additional setup, and require it from the spec files that actually need
|
|
13
|
+
# it.
|
|
12
14
|
#
|
|
13
|
-
#
|
|
14
|
-
# users commonly want.
|
|
15
|
-
#
|
|
16
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
15
|
+
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
17
16
|
RSpec.configure do |config|
|
|
17
|
+
# rspec-expectations config goes here. You can use an alternate
|
|
18
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
|
19
|
+
# assertions if you prefer.
|
|
20
|
+
config.expect_with :rspec do |expectations|
|
|
21
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
|
22
|
+
# and `failure_message` of custom matchers include text for helper methods
|
|
23
|
+
# defined using `chain`, e.g.:
|
|
24
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
|
25
|
+
# # => "be bigger than 2 and smaller than 4"
|
|
26
|
+
# ...rather than:
|
|
27
|
+
# # => "be bigger than 2"
|
|
28
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
|
32
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
|
33
|
+
config.mock_with :rspec do |mocks|
|
|
34
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
|
35
|
+
# a real object. This is generally recommended, and will default to
|
|
36
|
+
# `true` in RSpec 4.
|
|
37
|
+
mocks.verify_partial_doubles = true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
|
41
|
+
# have no way to turn it off -- the option exists only for backwards
|
|
42
|
+
# compatibility in RSpec 3). It causes shared context metadata to be
|
|
43
|
+
# inherited by the metadata hash of host groups and examples, rather than
|
|
44
|
+
# triggering implicit auto-inclusion in groups with matching metadata.
|
|
45
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
|
46
|
+
|
|
18
47
|
# The settings below are suggested to provide a good initial experience
|
|
19
48
|
# with RSpec, but feel free to customize to your heart's content.
|
|
20
49
|
=begin
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
config.
|
|
50
|
+
# This allows you to limit a spec run to individual examples or groups
|
|
51
|
+
# you care about by tagging them with `:focus` metadata. When nothing
|
|
52
|
+
# is tagged with `:focus`, all examples get run. RSpec also provides
|
|
53
|
+
# aliases for `it`, `describe`, and `context` that include `:focus`
|
|
54
|
+
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
|
55
|
+
config.filter_run_when_matching :focus
|
|
56
|
+
|
|
57
|
+
# Allows RSpec to persist some state between runs in order to support
|
|
58
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
|
59
|
+
# you configure your source control system to ignore this file.
|
|
60
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
|
61
|
+
|
|
62
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
|
63
|
+
# recommended. For more details, see:
|
|
64
|
+
# https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/
|
|
65
|
+
config.disable_monkey_patching!
|
|
66
|
+
|
|
67
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
|
68
|
+
# be too noisy due to issues in dependencies.
|
|
69
|
+
config.warnings = true
|
|
27
70
|
|
|
28
71
|
# Many RSpec users commonly either run the entire suite or an individual
|
|
29
72
|
# file, and it's useful to allow more verbose output when running an
|
|
@@ -32,7 +75,7 @@ RSpec.configure do |config|
|
|
|
32
75
|
# Use the documentation formatter for detailed output,
|
|
33
76
|
# unless a formatter has already been configured
|
|
34
77
|
# (e.g. via a command-line flag).
|
|
35
|
-
config.default_formatter =
|
|
78
|
+
config.default_formatter = "doc"
|
|
36
79
|
end
|
|
37
80
|
|
|
38
81
|
# Print the 10 slowest examples and example groups at the
|
|
@@ -51,28 +94,5 @@ RSpec.configure do |config|
|
|
|
51
94
|
# test failures related to randomization by passing the same `--seed` value
|
|
52
95
|
# as the one that triggered the failure.
|
|
53
96
|
Kernel.srand config.seed
|
|
54
|
-
|
|
55
|
-
# rspec-expectations config goes here. You can use an alternate
|
|
56
|
-
# assertion/expectation library such as wrong or the stdlib/minitest
|
|
57
|
-
# assertions if you prefer.
|
|
58
|
-
config.expect_with :rspec do |expectations|
|
|
59
|
-
# Enable only the newer, non-monkey-patching expect syntax.
|
|
60
|
-
# For more details, see:
|
|
61
|
-
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
|
62
|
-
expectations.syntax = :expect
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# rspec-mocks config goes here. You can use an alternate test double
|
|
66
|
-
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
|
67
|
-
config.mock_with :rspec do |mocks|
|
|
68
|
-
# Enable only the newer, non-monkey-patching expect syntax.
|
|
69
|
-
# For more details, see:
|
|
70
|
-
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
|
71
|
-
mocks.syntax = :expect
|
|
72
|
-
|
|
73
|
-
# Prevents you from mocking or stubbing a method that does not exist on
|
|
74
|
-
# a real object. This is generally recommended.
|
|
75
|
-
mocks.verify_partial_doubles = true
|
|
76
|
-
end
|
|
77
97
|
=end
|
|
78
98
|
end
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
RSpec::Support.require_rspec_support "directory_maker"
|
|
2
|
+
|
|
1
3
|
module RSpec
|
|
2
4
|
module Core
|
|
3
5
|
# @private
|
|
4
|
-
# Generates conventional files for an
|
|
6
|
+
# Generates conventional files for an RSpec project.
|
|
5
7
|
class ProjectInitializer
|
|
6
8
|
attr_reader :destination, :stream, :template_path
|
|
7
9
|
|
|
8
10
|
DOT_RSPEC_FILE = '.rspec'
|
|
9
11
|
SPEC_HELPER_FILE = 'spec/spec_helper.rb'
|
|
10
12
|
|
|
11
|
-
def initialize(opts
|
|
13
|
+
def initialize(opts={})
|
|
12
14
|
@destination = opts.fetch(:destination, Dir.getwd)
|
|
13
15
|
@stream = opts.fetch(:report_stream, $stdout)
|
|
14
16
|
@template_path = opts.fetch(:template_path) do
|
|
@@ -28,7 +30,7 @@ module RSpec
|
|
|
28
30
|
return report_exists(file) if File.exist?(destination_file)
|
|
29
31
|
|
|
30
32
|
report_creating(file)
|
|
31
|
-
|
|
33
|
+
RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(destination_file))
|
|
32
34
|
File.open(destination_file, 'w') do |f|
|
|
33
35
|
f.write File.read(File.join(template_path, file))
|
|
34
36
|
end
|
data/lib/rspec/core/rake_task.rb
CHANGED
|
@@ -1,69 +1,77 @@
|
|
|
1
|
-
require 'rspec/support'
|
|
2
|
-
require 'rspec/core/version'
|
|
3
|
-
RSpec::Support.require_rspec_support "warnings"
|
|
4
|
-
|
|
5
1
|
require 'rake'
|
|
6
2
|
require 'rake/tasklib'
|
|
7
|
-
require '
|
|
3
|
+
require 'rspec/support'
|
|
4
|
+
|
|
5
|
+
RSpec::Support.require_rspec_support "ruby_features"
|
|
6
|
+
|
|
7
|
+
# :nocov:
|
|
8
|
+
unless RSpec::Support.respond_to?(:require_rspec_core)
|
|
9
|
+
RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative "../#{f}" }
|
|
10
|
+
end
|
|
11
|
+
# :nocov:
|
|
12
|
+
|
|
13
|
+
RSpec::Support.require_rspec_core "shell_escape"
|
|
8
14
|
|
|
9
15
|
module RSpec
|
|
10
16
|
module Core
|
|
11
|
-
#
|
|
17
|
+
# RSpec rake task
|
|
12
18
|
#
|
|
13
19
|
# @see Rakefile
|
|
14
20
|
class RakeTask < ::Rake::TaskLib
|
|
15
21
|
include ::Rake::DSL if defined?(::Rake::DSL)
|
|
22
|
+
include RSpec::Core::ShellEscape
|
|
16
23
|
|
|
17
|
-
# Default path to the
|
|
24
|
+
# Default path to the RSpec executable.
|
|
18
25
|
DEFAULT_RSPEC_PATH = File.expand_path('../../../../exe/rspec', __FILE__)
|
|
19
26
|
|
|
20
27
|
# Default pattern for spec files.
|
|
21
|
-
DEFAULT_PATTERN = '
|
|
28
|
+
DEFAULT_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
|
|
22
29
|
|
|
23
|
-
# Name of task.
|
|
24
|
-
#
|
|
25
|
-
# default:
|
|
26
|
-
# :spec
|
|
30
|
+
# Name of task. Defaults to `:spec`.
|
|
27
31
|
attr_accessor :name
|
|
28
32
|
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# default:
|
|
32
|
-
# 'spec/**/*_spec.rb'
|
|
33
|
+
# Files matching this pattern will be loaded.
|
|
34
|
+
# Defaults to `'spec/**{,/*/**}/*_spec.rb'`.
|
|
33
35
|
attr_accessor :pattern
|
|
34
36
|
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
# Files matching this pattern will be excluded.
|
|
38
|
+
# Defaults to `nil`.
|
|
39
|
+
attr_accessor :exclude_pattern
|
|
40
|
+
|
|
41
|
+
# Whether or not to fail Rake when an error occurs (typically when
|
|
42
|
+
# examples fail). Defaults to `true`.
|
|
39
43
|
attr_accessor :fail_on_error
|
|
40
44
|
|
|
41
45
|
# A message to print to stderr when there are failures.
|
|
42
46
|
attr_accessor :failure_message
|
|
43
47
|
|
|
48
|
+
if RUBY_VERSION < "1.9.0" || Support::Ruby.jruby?
|
|
49
|
+
# Run RSpec with a clean (empty) environment is not supported
|
|
50
|
+
def with_clean_environment=(_value)
|
|
51
|
+
raise ArgumentError, "Running in a clean environment is not supported on Ruby versions before 1.9.0"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Run RSpec with a clean (empty) environment is not supported
|
|
55
|
+
def with_clean_environment
|
|
56
|
+
false
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
# Run RSpec with a clean (empty) environment.
|
|
60
|
+
attr_accessor :with_clean_environment
|
|
61
|
+
end
|
|
62
|
+
|
|
44
63
|
# Use verbose output. If this is set to true, the task will print the
|
|
45
|
-
# executed spec command to stdout.
|
|
46
|
-
#
|
|
47
|
-
# default:
|
|
48
|
-
# true
|
|
64
|
+
# executed spec command to stdout. Defaults to `true`.
|
|
49
65
|
attr_accessor :verbose
|
|
50
66
|
|
|
51
|
-
# Command line options to pass to ruby.
|
|
52
|
-
#
|
|
53
|
-
# default:
|
|
54
|
-
# nil
|
|
67
|
+
# Command line options to pass to ruby. Defaults to `nil`.
|
|
55
68
|
attr_accessor :ruby_opts
|
|
56
69
|
|
|
57
|
-
# Path to
|
|
58
|
-
#
|
|
59
|
-
# default:
|
|
60
|
-
# 'rspec'
|
|
70
|
+
# Path to RSpec. Defaults to the absolute path to the
|
|
71
|
+
# rspec binary from the loaded rspec-core gem.
|
|
61
72
|
attr_accessor :rspec_path
|
|
62
73
|
|
|
63
|
-
# Command line options to pass to
|
|
64
|
-
#
|
|
65
|
-
# default:
|
|
66
|
-
# nil
|
|
74
|
+
# Command line options to pass to RSpec. Defaults to `nil`.
|
|
67
75
|
attr_accessor :rspec_opts
|
|
68
76
|
|
|
69
77
|
def initialize(*args, &task_block)
|
|
@@ -81,24 +89,26 @@ module RSpec
|
|
|
81
89
|
# @private
|
|
82
90
|
def run_task(verbose)
|
|
83
91
|
command = spec_command
|
|
92
|
+
puts command if verbose
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
puts failure_message if failure_message
|
|
90
|
-
end
|
|
91
|
-
if fail_on_error && !success
|
|
92
|
-
$stderr.puts "#{command} failed"
|
|
93
|
-
exit $?.exitstatus
|
|
94
|
+
if with_clean_environment
|
|
95
|
+
return if system({}, command, :unsetenv_others => true)
|
|
96
|
+
else
|
|
97
|
+
return if system(command)
|
|
94
98
|
end
|
|
99
|
+
|
|
100
|
+
puts failure_message if failure_message
|
|
101
|
+
|
|
102
|
+
return unless fail_on_error
|
|
103
|
+
$stderr.puts "#{command} failed" if verbose
|
|
104
|
+
exit $?.exitstatus || 1
|
|
95
105
|
end
|
|
96
106
|
|
|
97
107
|
private
|
|
98
108
|
|
|
99
109
|
# @private
|
|
100
110
|
def define(args, &task_block)
|
|
101
|
-
desc "Run RSpec code examples" unless ::Rake.application.
|
|
111
|
+
desc "Run RSpec code examples" unless ::Rake.application.last_description
|
|
102
112
|
|
|
103
113
|
task name, *args do |_, task_args|
|
|
104
114
|
RakeFileUtils.__send__(:verbose, verbose) do
|
|
@@ -108,35 +118,69 @@ module RSpec
|
|
|
108
118
|
end
|
|
109
119
|
end
|
|
110
120
|
|
|
111
|
-
def
|
|
121
|
+
def file_inclusion_specification
|
|
112
122
|
if ENV['SPEC']
|
|
113
|
-
FileList[
|
|
123
|
+
FileList[ENV['SPEC']].sort
|
|
124
|
+
elsif String === pattern && !File.exist?(pattern)
|
|
125
|
+
return if [*rspec_opts].any? { |opt| opt =~ /--pattern/ }
|
|
126
|
+
"--pattern #{escape pattern}"
|
|
114
127
|
else
|
|
115
|
-
FileList
|
|
128
|
+
# Before RSpec 3.1, we used `FileList` to get the list of matched
|
|
129
|
+
# files, and then pass that along to the `rspec` command. Starting
|
|
130
|
+
# with 3.1, we prefer to pass along the pattern as-is to the `rspec`
|
|
131
|
+
# command, for 3 reasons:
|
|
132
|
+
#
|
|
133
|
+
# * It's *much* less verbose to pass one `--pattern` option than a
|
|
134
|
+
# long list of files.
|
|
135
|
+
# * It ensures `task.pattern` and `--pattern` have the same
|
|
136
|
+
# behavior.
|
|
137
|
+
# * It fixes a bug, where
|
|
138
|
+
# `task.pattern = pattern_that_matches_no_files` would run *all*
|
|
139
|
+
# files because it would cause no pattern or file args to get
|
|
140
|
+
# passed to `rspec`, which causes all files to get run.
|
|
141
|
+
#
|
|
142
|
+
# However, `FileList` is *far* more flexible than the `--pattern`
|
|
143
|
+
# option. Specifically, it supports individual files and directories,
|
|
144
|
+
# as well as arrays of files, directories and globs, as well as other
|
|
145
|
+
# `FileList` objects.
|
|
146
|
+
#
|
|
147
|
+
# For backwards compatibility, we have to fall back to using FileList
|
|
148
|
+
# if the user has passed a `pattern` option that will not work with
|
|
149
|
+
# `--pattern`.
|
|
150
|
+
#
|
|
151
|
+
# TODO: consider deprecating support for this and removing it in
|
|
152
|
+
# RSpec 4.
|
|
153
|
+
FileList[pattern].sort.map { |file| escape file }
|
|
116
154
|
end
|
|
117
155
|
end
|
|
118
156
|
|
|
157
|
+
def file_exclusion_specification
|
|
158
|
+
" --exclude-pattern #{escape exclude_pattern}" if exclude_pattern
|
|
159
|
+
end
|
|
160
|
+
|
|
119
161
|
def spec_command
|
|
120
162
|
cmd_parts = []
|
|
121
163
|
cmd_parts << RUBY
|
|
122
164
|
cmd_parts << ruby_opts
|
|
123
165
|
cmd_parts << rspec_load_path
|
|
124
|
-
cmd_parts <<
|
|
125
|
-
cmd_parts <<
|
|
166
|
+
cmd_parts << escape(rspec_path)
|
|
167
|
+
cmd_parts << file_inclusion_specification
|
|
168
|
+
cmd_parts << file_exclusion_specification
|
|
126
169
|
cmd_parts << rspec_opts
|
|
127
170
|
cmd_parts.flatten.reject(&blank).join(" ")
|
|
128
171
|
end
|
|
129
172
|
|
|
130
173
|
def blank
|
|
131
|
-
lambda {|s| s.nil? || s == ""}
|
|
174
|
+
lambda { |s| s.nil? || s == "" }
|
|
132
175
|
end
|
|
133
176
|
|
|
134
177
|
def rspec_load_path
|
|
135
178
|
@rspec_load_path ||= begin
|
|
136
|
-
core_and_support = $LOAD_PATH.grep
|
|
137
|
-
|
|
179
|
+
core_and_support = $LOAD_PATH.grep(
|
|
180
|
+
/#{File::SEPARATOR}rspec-(core|support)[^#{File::SEPARATOR}]*#{File::SEPARATOR}lib/
|
|
181
|
+
).uniq
|
|
138
182
|
|
|
139
|
-
"-I#{core_and_support.map
|
|
183
|
+
"-I#{core_and_support.map { |file| escape file }.join(File::PATH_SEPARATOR)}"
|
|
140
184
|
end
|
|
141
185
|
end
|
|
142
186
|
end
|
data/lib/rspec/core/reporter.rb
CHANGED
|
@@ -2,24 +2,38 @@ module RSpec::Core
|
|
|
2
2
|
# A reporter will send notifications to listeners, usually formatters for the
|
|
3
3
|
# spec suite run.
|
|
4
4
|
class Reporter
|
|
5
|
+
# @private
|
|
6
|
+
RSPEC_NOTIFICATIONS = Set.new(
|
|
7
|
+
[
|
|
8
|
+
:close, :deprecation, :deprecation_summary, :dump_failures, :dump_pending,
|
|
9
|
+
:dump_profile, :dump_summary, :example_failed, :example_group_finished,
|
|
10
|
+
:example_group_started, :example_passed, :example_pending, :example_started,
|
|
11
|
+
:message, :seed, :start, :start_dump, :stop, :example_finished
|
|
12
|
+
])
|
|
5
13
|
|
|
6
14
|
def initialize(configuration)
|
|
7
15
|
@configuration = configuration
|
|
8
|
-
@listeners = Hash.new { |h,k| h[k] = Set.new }
|
|
16
|
+
@listeners = Hash.new { |h, k| h[k] = Set.new }
|
|
9
17
|
@examples = []
|
|
10
18
|
@failed_examples = []
|
|
11
19
|
@pending_examples = []
|
|
12
20
|
@duration = @start = @load_time = nil
|
|
21
|
+
@non_example_exception_count = 0
|
|
22
|
+
@setup_default = lambda {}
|
|
23
|
+
@setup = false
|
|
24
|
+
@profiler = nil
|
|
13
25
|
end
|
|
14
26
|
|
|
15
27
|
# @private
|
|
16
28
|
attr_reader :examples, :failed_examples, :pending_examples
|
|
17
29
|
|
|
18
|
-
# Registers a listener to a list of notifications. The reporter will send
|
|
19
|
-
# events to all registered listeners
|
|
30
|
+
# Registers a listener to a list of notifications. The reporter will send
|
|
31
|
+
# notification of events to all registered listeners.
|
|
20
32
|
#
|
|
21
|
-
# @param listener [Object] An
|
|
22
|
-
#
|
|
33
|
+
# @param listener [Object] An object that wishes to be notified of reporter
|
|
34
|
+
# events
|
|
35
|
+
# @param notifications [Array] Array of symbols represents the events a
|
|
36
|
+
# listener wishes to subscribe too
|
|
23
37
|
def register_listener(listener, *notifications)
|
|
24
38
|
notifications.each do |notification|
|
|
25
39
|
@listeners[notification.to_sym] << listener
|
|
@@ -27,12 +41,18 @@ module RSpec::Core
|
|
|
27
41
|
true
|
|
28
42
|
end
|
|
29
43
|
|
|
44
|
+
# @private
|
|
45
|
+
def prepare_default(loader, output_stream, deprecation_stream)
|
|
46
|
+
@setup_default = lambda do
|
|
47
|
+
loader.setup_default output_stream, deprecation_stream
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
30
51
|
# @private
|
|
31
52
|
def registered_listeners(notification)
|
|
32
53
|
@listeners[notification].to_a
|
|
33
54
|
end
|
|
34
55
|
|
|
35
|
-
# @api
|
|
36
56
|
# @overload report(count, &block)
|
|
37
57
|
# @overload report(count, &block)
|
|
38
58
|
# @param expected_example_count [Integer] the number of examples being run
|
|
@@ -57,18 +77,42 @@ module RSpec::Core
|
|
|
57
77
|
end
|
|
58
78
|
end
|
|
59
79
|
|
|
80
|
+
# @param exit_code [Integer] the exit_code to be return by the reporter
|
|
81
|
+
#
|
|
82
|
+
# Reports a run that exited early without having run any examples.
|
|
83
|
+
#
|
|
84
|
+
def exit_early(exit_code)
|
|
85
|
+
report(0) { exit_code }
|
|
86
|
+
end
|
|
87
|
+
|
|
60
88
|
# @private
|
|
61
|
-
def start(expected_example_count, time
|
|
89
|
+
def start(expected_example_count, time=RSpec::Core::Time.now)
|
|
62
90
|
@start = time
|
|
63
91
|
@load_time = (@start - @configuration.start_time).to_f
|
|
92
|
+
notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?)
|
|
64
93
|
notify :start, Notifications::StartNotification.new(expected_example_count, @load_time)
|
|
65
94
|
end
|
|
66
95
|
|
|
67
|
-
# @
|
|
96
|
+
# @param message [#to_s] A message object to send to formatters
|
|
97
|
+
#
|
|
98
|
+
# Send a custom message to supporting formatters.
|
|
68
99
|
def message(message)
|
|
69
100
|
notify :message, Notifications::MessageNotification.new(message)
|
|
70
101
|
end
|
|
71
102
|
|
|
103
|
+
# @param event [Symbol] Name of the custom event to trigger on formatters
|
|
104
|
+
# @param options [Hash] Hash of arguments to provide via `CustomNotification`
|
|
105
|
+
#
|
|
106
|
+
# Publish a custom event to supporting registered formatters.
|
|
107
|
+
# @see RSpec::Core::Notifications::CustomNotification
|
|
108
|
+
def publish(event, options={})
|
|
109
|
+
if RSPEC_NOTIFICATIONS.include? event
|
|
110
|
+
raise "RSpec::Core::Reporter#publish is intended for sending custom " \
|
|
111
|
+
"events not internal RSpec ones, please rename your custom event."
|
|
112
|
+
end
|
|
113
|
+
notify event, Notifications::CustomNotification.for(options)
|
|
114
|
+
end
|
|
115
|
+
|
|
72
116
|
# @private
|
|
73
117
|
def example_group_started(group)
|
|
74
118
|
notify :example_group_started, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty?
|
|
@@ -85,6 +129,11 @@ module RSpec::Core
|
|
|
85
129
|
notify :example_started, Notifications::ExampleNotification.for(example)
|
|
86
130
|
end
|
|
87
131
|
|
|
132
|
+
# @private
|
|
133
|
+
def example_finished(example)
|
|
134
|
+
notify :example_finished, Notifications::ExampleNotification.for(example)
|
|
135
|
+
end
|
|
136
|
+
|
|
88
137
|
# @private
|
|
89
138
|
def example_passed(example)
|
|
90
139
|
notify :example_passed, Notifications::ExampleNotification.for(example)
|
|
@@ -107,24 +156,46 @@ module RSpec::Core
|
|
|
107
156
|
notify :deprecation, Notifications::DeprecationNotification.from_hash(hash)
|
|
108
157
|
end
|
|
109
158
|
|
|
159
|
+
# @private
|
|
160
|
+
# Provides a way to notify of an exception that is not tied to any
|
|
161
|
+
# particular example (such as an exception encountered in a :suite hook).
|
|
162
|
+
# Exceptions will be formatted the same way they normally are.
|
|
163
|
+
def notify_non_example_exception(exception, context_description)
|
|
164
|
+
@configuration.world.non_example_failure = true
|
|
165
|
+
@non_example_exception_count += 1
|
|
166
|
+
|
|
167
|
+
example = Example.new(AnonymousExampleGroup, context_description, {})
|
|
168
|
+
presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 0)
|
|
169
|
+
message presenter.fully_formatted(nil)
|
|
170
|
+
end
|
|
171
|
+
|
|
110
172
|
# @private
|
|
111
173
|
def finish
|
|
112
|
-
|
|
174
|
+
close_after do
|
|
113
175
|
stop
|
|
114
176
|
notify :start_dump, Notifications::NullNotification
|
|
115
177
|
notify :dump_pending, Notifications::ExamplesNotification.new(self)
|
|
116
178
|
notify :dump_failures, Notifications::ExamplesNotification.new(self)
|
|
117
179
|
notify :deprecation_summary, Notifications::NullNotification
|
|
118
|
-
notify :dump_summary, Notifications::SummaryNotification.new(@duration, @examples, @failed_examples, @pending_examples, @load_time)
|
|
119
180
|
unless mute_profile_output?
|
|
120
|
-
notify :dump_profile, Notifications::ProfileNotification.new(@duration, @examples,
|
|
181
|
+
notify :dump_profile, Notifications::ProfileNotification.new(@duration, @examples,
|
|
182
|
+
@configuration.profile_examples,
|
|
183
|
+
@profiler.example_groups)
|
|
121
184
|
end
|
|
185
|
+
notify :dump_summary, Notifications::SummaryNotification.new(@duration, @examples, @failed_examples,
|
|
186
|
+
@pending_examples, @load_time,
|
|
187
|
+
@non_example_exception_count)
|
|
122
188
|
notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?)
|
|
123
|
-
ensure
|
|
124
|
-
notify :close, Notifications::NullNotification
|
|
125
189
|
end
|
|
126
190
|
end
|
|
127
191
|
|
|
192
|
+
# @private
|
|
193
|
+
def close_after
|
|
194
|
+
yield
|
|
195
|
+
ensure
|
|
196
|
+
close
|
|
197
|
+
end
|
|
198
|
+
|
|
128
199
|
# @private
|
|
129
200
|
def stop
|
|
130
201
|
@duration = (RSpec::Core::Time.now - @start).to_f if @start
|
|
@@ -133,20 +204,62 @@ module RSpec::Core
|
|
|
133
204
|
|
|
134
205
|
# @private
|
|
135
206
|
def notify(event, notification)
|
|
207
|
+
ensure_listeners_ready
|
|
136
208
|
registered_listeners(event).each do |formatter|
|
|
137
209
|
formatter.__send__(event, notification)
|
|
138
210
|
end
|
|
139
211
|
end
|
|
140
212
|
|
|
213
|
+
# @private
|
|
214
|
+
def abort_with(msg, exit_status)
|
|
215
|
+
message(msg)
|
|
216
|
+
close
|
|
217
|
+
exit!(exit_status)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @private
|
|
221
|
+
def fail_fast_limit_met?
|
|
222
|
+
return false unless (fail_fast = @configuration.fail_fast)
|
|
223
|
+
|
|
224
|
+
if fail_fast == true
|
|
225
|
+
@failed_examples.any?
|
|
226
|
+
else
|
|
227
|
+
fail_fast <= @failed_examples.size
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
141
231
|
private
|
|
142
232
|
|
|
233
|
+
def ensure_listeners_ready
|
|
234
|
+
return if @setup
|
|
235
|
+
|
|
236
|
+
@setup_default.call
|
|
237
|
+
@profiler = Profiler.new
|
|
238
|
+
register_listener @profiler, *Profiler::NOTIFICATIONS
|
|
239
|
+
@setup = true
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def close
|
|
243
|
+
notify :close, Notifications::NullNotification
|
|
244
|
+
end
|
|
245
|
+
|
|
143
246
|
def mute_profile_output?
|
|
144
|
-
# Don't print out profiled info if there are failures and `--fail-fast` is
|
|
145
|
-
|
|
247
|
+
# Don't print out profiled info if there are failures and `--fail-fast` is
|
|
248
|
+
# used, it just clutters the output.
|
|
249
|
+
!@configuration.profile_examples? || fail_fast_limit_met?
|
|
146
250
|
end
|
|
147
251
|
|
|
148
252
|
def seed_used?
|
|
149
253
|
@configuration.seed && @configuration.seed_used?
|
|
150
254
|
end
|
|
151
255
|
end
|
|
256
|
+
|
|
257
|
+
# @private
|
|
258
|
+
# # Used in place of a {Reporter} for situations where we don't want reporting output.
|
|
259
|
+
class NullReporter
|
|
260
|
+
def self.method_missing(*)
|
|
261
|
+
# ignore
|
|
262
|
+
end
|
|
263
|
+
private_class_method :method_missing
|
|
264
|
+
end
|
|
152
265
|
end
|