rspec-core 3.0.4 → 3.12.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|