1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
require 'rake'
require 'rake/tasklib'
require 'rspec/support'
RSpec::Support.require_rspec_support "ruby_features"
# :nocov:
unless RSpec::Support.respond_to?(:require_rspec_core)
RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative "../#{f}" }
end
# :nocov:
RSpec::Support.require_rspec_core "shell_escape"
module RSpec
module Core
# RSpec rake task
#
# @see Rakefile
class RakeTask < ::Rake::TaskLib
include ::Rake::DSL if defined?(::Rake::DSL)
include RSpec::Core::ShellEscape
# Default path to the RSpec executable.
DEFAULT_RSPEC_PATH = File.expand_path('../../../../exe/rspec', __FILE__)
# Default pattern for spec files.
DEFAULT_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
# Name of task. Defaults to `:spec`.
attr_accessor :name
# Files matching this pattern will be loaded.
# Defaults to `'spec/**{,/*/**}/*_spec.rb'`.
attr_accessor :pattern
# Files matching this pattern will be excluded.
# Defaults to `nil`.
attr_accessor :exclude_pattern
# Whether or not to fail Rake when an error occurs (typically when
# examples fail). Defaults to `true`.
attr_accessor :fail_on_error
# A message to print to stderr when there are failures.
attr_accessor :failure_message
if RUBY_VERSION < "1.9.0" || Support::Ruby.jruby?
# Run RSpec with a clean (empty) environment is not supported
def with_clean_environment=(_value)
raise ArgumentError, "Running in a clean environment is not supported on Ruby versions before 1.9.0"
end
# Run RSpec with a clean (empty) environment is not supported
def with_clean_environment
false
end
else
# Run RSpec with a clean (empty) environment.
attr_accessor :with_clean_environment
end
# Use verbose output. If this is set to true, the task will print the
# executed spec command to stdout. Defaults to `true`.
attr_accessor :verbose
# Command line options to pass to ruby. Defaults to `nil`.
attr_accessor :ruby_opts
# Path to RSpec. Defaults to the absolute path to the
# rspec binary from the loaded rspec-core gem.
attr_accessor :rspec_path
# Command line options to pass to RSpec. Defaults to `nil`.
attr_accessor :rspec_opts
def initialize(*args, &task_block)
@name = args.shift || :spec
@ruby_opts = nil
@rspec_opts = nil
@verbose = true
@fail_on_error = true
@rspec_path = DEFAULT_RSPEC_PATH
@pattern = DEFAULT_PATTERN
define(args, &task_block)
end
# @private
def run_task(verbose)
command = spec_command
puts command if verbose
if with_clean_environment
return if system({}, command, :unsetenv_others => true)
else
return if system(command)
end
puts failure_message if failure_message
return unless fail_on_error
$stderr.puts "#{command} failed" if verbose
exit $?.exitstatus || 1
end
private
# @private
def define(args, &task_block)
desc "Run RSpec code examples" unless ::Rake.application.last_description
task name, *args do |_, task_args|
RakeFileUtils.__send__(:verbose, verbose) do
task_block.call(*[self, task_args].slice(0, task_block.arity)) if task_block
run_task verbose
end
end
end
def file_inclusion_specification
if ENV['SPEC']
FileList[ENV['SPEC']].sort
elsif String === pattern && !File.exist?(pattern)
return if [*rspec_opts].any? { |opt| opt =~ /--pattern/ }
"--pattern #{escape pattern}"
else
# Before RSpec 3.1, we used `FileList` to get the list of matched
# files, and then pass that along to the `rspec` command. Starting
# with 3.1, we prefer to pass along the pattern as-is to the `rspec`
# command, for 3 reasons:
#
# * It's *much* less verbose to pass one `--pattern` option than a
# long list of files.
# * It ensures `task.pattern` and `--pattern` have the same
# behavior.
# * It fixes a bug, where
# `task.pattern = pattern_that_matches_no_files` would run *all*
# files because it would cause no pattern or file args to get
# passed to `rspec`, which causes all files to get run.
#
# However, `FileList` is *far* more flexible than the `--pattern`
# option. Specifically, it supports individual files and directories,
# as well as arrays of files, directories and globs, as well as other
# `FileList` objects.
#
# For backwards compatibility, we have to fall back to using FileList
# if the user has passed a `pattern` option that will not work with
# `--pattern`.
#
# TODO: consider deprecating support for this and removing it in
# RSpec 4.
FileList[pattern].sort.map { |file| escape file }
end
end
def file_exclusion_specification
" --exclude-pattern #{escape exclude_pattern}" if exclude_pattern
end
def spec_command
cmd_parts = []
cmd_parts << RUBY
cmd_parts << ruby_opts
cmd_parts << rspec_load_path
cmd_parts << escape(rspec_path)
cmd_parts << file_inclusion_specification
cmd_parts << file_exclusion_specification
cmd_parts << rspec_opts
cmd_parts.flatten.reject(&blank).join(" ")
end
def blank
lambda { |s| s.nil? || s == "" }
end
def rspec_load_path
@rspec_load_path ||= begin
core_and_support = $LOAD_PATH.grep(
/#{File::SEPARATOR}rspec-(core|support)[^#{File::SEPARATOR}]*#{File::SEPARATOR}lib/
).uniq
"-I#{core_and_support.map { |file| escape file }.join(File::PATH_SEPARATOR)}"
end
end
end
end
end
|