git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60523 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-10-28 15:14:55 +00:00
parent ad1b64d35d
commit 974e862db9
12 changed files with 89 additions and 60 deletions

View File

@ -7,12 +7,12 @@ script:
- bundle exec rspec - bundle exec rspec
matrix: matrix:
include: include:
- rvm: 2.2.7 - rvm: 2.2.8
- rvm: 2.3.4 - rvm: 2.3.5
- rvm: 2.4.1 - rvm: 2.4.2
- rvm: ruby-head - rvm: ruby-head
- jdk: oraclejdk8 - jdk: oraclejdk8
install: install:
- curl -L https://github.com/graalvm/truffleruby/releases/download/vm-enterprise-0.27/truffleruby-testing-0.27.tar.gz | tar xz - curl -L https://github.com/graalvm/truffleruby/releases/download/vm-enterprise-0.28/truffleruby-testing-0.28.tar.gz | tar xz
- source truffleruby/setup_env - source truffleruby/setup_env
- bundle install - bundle install

View File

@ -37,7 +37,7 @@ class MSpecMain < MSpecScript
options.targets options.targets
options.on("--warnings", "Don't supress warnings") do options.on("--warnings", "Don't suppress warnings") do
config[:flags] << '-w' config[:flags] << '-w'
ENV['OUTPUT_WARNINGS'] = '1' ENV['OUTPUT_WARNINGS'] = '1'
end end
@ -171,6 +171,7 @@ class MSpecMain < MSpecScript
exit multi_exec(argv) exit multi_exec(argv)
else else
$stderr.puts "$ #{argv.join(' ')}" $stderr.puts "$ #{argv.join(' ')}"
$stderr.flush
exec(*argv, close_others: false) exec(*argv, close_others: false)
end end
end end

View File

@ -7,44 +7,48 @@ class ComplainMatcher
def matches?(proc) def matches?(proc)
@saved_err = $stderr @saved_err = $stderr
@stderr = $stderr = IOStub.new
@verbose = $VERBOSE @verbose = $VERBOSE
$VERBOSE = false begin
err = $stderr = IOStub.new
proc.call $VERBOSE = false
Thread.current[:in_mspec_complain_matcher] = true
proc.call
ensure
$VERBOSE = @verbose
$stderr = @saved_err
Thread.current[:in_mspec_complain_matcher] = false
end
@warning = err.to_s
unless @complaint.nil? unless @complaint.nil?
case @complaint case @complaint
when Regexp when Regexp
return false unless $stderr =~ @complaint return false unless @warning =~ @complaint
else else
return false unless $stderr == @complaint return false unless @warning == @complaint
end end
end end
return $stderr.empty? ? false : true return @warning.empty? ? false : true
ensure
$VERBOSE = @verbose
$stderr = @saved_err
end end
def failure_message def failure_message
if @complaint.nil? if @complaint.nil?
["Expected a warning", "but received none"] ["Expected a warning", "but received none"]
elsif @complaint.kind_of? Regexp elsif @complaint.kind_of? Regexp
["Expected warning to match: #{@complaint.inspect}", "but got: #{@stderr.chomp.inspect}"] ["Expected warning to match: #{@complaint.inspect}", "but got: #{@warning.chomp.inspect}"]
else else
["Expected warning: #{@complaint.inspect}", "but got: #{@stderr.chomp.inspect}"] ["Expected warning: #{@complaint.inspect}", "but got: #{@warning.chomp.inspect}"]
end end
end end
def negative_failure_message def negative_failure_message
if @complaint.nil? if @complaint.nil?
["Unexpected warning: ", @stderr.chomp.inspect] ["Unexpected warning: ", @warning.chomp.inspect]
elsif @complaint.kind_of? Regexp elsif @complaint.kind_of? Regexp
["Expected warning not to match: #{@complaint.inspect}", "but got: #{@stderr.chomp.inspect}"] ["Expected warning not to match: #{@complaint.inspect}", "but got: #{@warning.chomp.inspect}"]
else else
["Expected warning: #{@complaint.inspect}", "but got: #{@stderr.chomp.inspect}"] ["Expected warning: #{@complaint.inspect}", "but got: #{@warning.chomp.inspect}"]
end end
end end
end end

View File

@ -53,13 +53,19 @@ class RaiseErrorMatcher
exception_class_and_message(exception.class, exception.message) exception_class_and_message(exception.class, exception.message)
end end
def format_result(result)
result.pretty_inspect.chomp
rescue => e
"#pretty_inspect raised #{e.class}; A #<#{result.class}>"
end
def failure_message def failure_message
message = ["Expected #{format_expected_exception}"] message = ["Expected #{format_expected_exception}"]
if @actual if @actual
message << "but got #{format_exception(@actual)}" message << "but got #{format_exception(@actual)}"
else else
message << "but no exception was raised (#{@result.pretty_inspect.chomp} was returned)" message << "but no exception was raised (#{format_result(@result)} was returned)"
end end
message message

View File

@ -6,7 +6,7 @@
#-- #--
# A note on naming: this is named _ContextState_ rather # A note on naming: this is named _ContextState_ rather
# than _DescribeState_ because +describe+ is the keyword # than _DescribeState_ because +describe+ is the keyword
# in the DSL for refering to the context in which an example # in the DSL for referring to the context in which an example
# is evaluated, just as +it+ refers to the example itself. # is evaluated, just as +it+ refers to the example itself.
#++ #++
class ContextState class ContextState

View File

@ -1,4 +1,5 @@
require 'mspec/guards/guard' require 'mspec/guards/guard'
require 'mspec/guards/version'
require 'mspec/utils/warnings' require 'mspec/utils/warnings'
# MSpecScript provides a skeleton for all the MSpec runner scripts. # MSpecScript provides a skeleton for all the MSpec runner scripts.
@ -38,7 +39,7 @@ class MSpecScript
end end
def initialize def initialize
if RUBY_VERSION < '2.2' ruby_version_is ""..."2.2" do
abort "MSpec needs Ruby 2.2 or more recent" abort "MSpec needs Ruby 2.2 or more recent"
end end
@ -200,27 +201,30 @@ class MSpecScript
abort "Could not find spec file #{partial}" abort "Could not find spec file #{partial}"
end end
# Resolves each entry in +list+ to a set of files. # Resolves each entry in +patterns+ to a set of files.
# #
# If the entry has a leading '^' character, the list of files # If the pattern has a leading '^' character, the list of files
# is subtracted from the list of files accumulated to that point. # is subtracted from the list of files accumulated to that point.
# #
# If the entry has a leading ':' character, the corresponding # If the entry has a leading ':' character, the corresponding
# key is looked up in the config object and the entries in the # key is looked up in the config object and the entries in the
# value retrieved are processed through #entries. # value retrieved are processed through #entries.
def files(list) def files(patterns)
list.inject([]) do |files, item| list = []
case item[0] patterns.each do |pattern|
case pattern[0]
when ?^ when ?^
files -= entries(item[1..-1]) list -= entries(pattern[1..-1])
when ?: when ?:
key = item[1..-1].to_sym key = pattern[1..-1].to_sym
files += files(Array(config[key])) value = config[key]
abort "Key #{pattern} not found in mspec config." unless value
list += files(Array(value))
else else
files += entries(item) list += entries(pattern)
end end
files
end end
list
end end
def files_from_patterns(patterns) def files_from_patterns(patterns)
@ -231,12 +235,10 @@ class MSpecScript
if patterns.empty? and File.directory? "./spec" if patterns.empty? and File.directory? "./spec"
patterns = ["spec/"] patterns = ["spec/"]
end end
if patterns.empty?
puts "No files specified."
exit 1
end
end end
files patterns list = files(patterns)
abort "No files specified." if list.empty?
list
end end
def cores(max) def cores(max)

View File

@ -1,6 +1,6 @@
require 'mspec/guards/version' require 'mspec/guards/version'
if RUBY_ENGINE == "ruby" and RUBY_VERSION >= "2.4.0" if RUBY_ENGINE == "ruby" and ruby_version_is("2.4")
ruby_version_is "2.4"..."2.5" do ruby_version_is "2.4"..."2.5" do
# Kernel#warn does not delegate to Warning.warn in 2.4 # Kernel#warn does not delegate to Warning.warn in 2.4
module Kernel module Kernel
@ -16,9 +16,19 @@ if RUBY_ENGINE == "ruby" and RUBY_VERSION >= "2.4.0"
end end
def Warning.warn(message) def Warning.warn(message)
if Thread.current[:in_mspec_complain_matcher]
return $stderr.write(message)
end
case message case message
# $VERBOSE = true warnings # $VERBOSE = true warnings
when /possibly useless use of (<|<=|==|>=|>|\+|-) in void context/ when /(.+\.rb):(\d+):.+possibly useless use of (<|<=|==|>=|>) in void context/
# Make sure there is a .should otherwise it is missing
line_nb = Integer($2)
unless File.exist?($1) and /\.should(_not)? (<|<=|==|>=|>)/ === File.readlines($1)[line_nb-1]
$stderr.write message
end
when /possibly useless use of (\+|-) in void context/
when /assigned but unused variable/ when /assigned but unused variable/
when /method redefined/ when /method redefined/
when /previous definition of/ when /previous definition of/

View File

@ -17,8 +17,6 @@ end
describe MSpecRun, "#options" do describe MSpecRun, "#options" do
before :each do before :each do
@stdout, $stdout = $stdout, IOStub.new
@argv = [one_spec, two_spec] @argv = [one_spec, two_spec]
@options, @config = new_option @options, @config = new_option
MSpecOptions.stub(:new).and_return(@options) MSpecOptions.stub(:new).and_return(@options)
@ -27,10 +25,6 @@ describe MSpecRun, "#options" do
@script.stub(:config).and_return(@config) @script.stub(:config).and_return(@config)
end end
after :each do
$stdout = @stdout
end
it "enables the filter options" do it "enables the filter options" do
@options.should_receive(:filters) @options.should_receive(:filters)
@script.options @argv @script.options @argv
@ -114,15 +108,14 @@ describe MSpecRun, "#options" do
it "exits if there are no files to process and './spec' is not a directory" do it "exits if there are no files to process and './spec' is not a directory" do
File.should_receive(:directory?).with("./spec").and_return(false) File.should_receive(:directory?).with("./spec").and_return(false)
@options.should_receive(:parse).and_return([]) @options.should_receive(:parse).and_return([])
@script.should_receive(:exit) @script.should_receive(:abort).with("No files specified.")
@script.options @script.options
$stdout.should include "No files specified"
end end
it "process 'spec/' if it is a directory and no files were specified" do it "process 'spec/' if it is a directory and no files were specified" do
File.should_receive(:directory?).with("./spec").and_return(true) File.should_receive(:directory?).with("./spec").and_return(true)
@options.should_receive(:parse).and_return([]) @options.should_receive(:parse).and_return([])
@script.should_receive(:files).with(["spec/"]) @script.should_receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"])
@script.options @script.options
end end

View File

@ -90,6 +90,18 @@ describe RaiseErrorMatcher do
["Expected ExpectedException (expected)", "but no exception was raised (nil was returned)"] ["Expected ExpectedException (expected)", "but no exception was raised (nil was returned)"]
end end
it "provides a useful failure message when no exception is raised and the result raises in #pretty_inspect" do
result = Object.new
def result.pretty_inspect
raise ArgumentError, "bad"
end
proc = Proc.new { result }
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matches?(proc)
matcher.failure_message.should ==
["Expected ExpectedException (expected)", "but no exception was raised (#pretty_inspect raised ArgumentError; A #<Object> was returned)"]
end
it "provides a useful negative failure message" do it "provides a useful negative failure message" do
proc = Proc.new { raise ExpectedException, "expected" } proc = Proc.new { raise ExpectedException, "expected" }
matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher = RaiseErrorMatcher.new(ExpectedException, "expected")

View File

@ -284,21 +284,21 @@ describe Mock, ".verify_call" do
ScratchPad.recorded.should == 1 ScratchPad.recorded.should == 1
end end
it "raises an expection when it is expected to yield but no block is given" do it "raises an exception when it is expected to yield but no block is given" do
@proxy.and_yield(1, 2, 3) @proxy.and_yield(1, 2, 3)
lambda { lambda {
Mock.verify_call(@mock, :method_call) Mock.verify_call(@mock, :method_call)
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError)
end end
it "raises an expection when it is expected to yield more arguments than the block can take" do it "raises an exception when it is expected to yield more arguments than the block can take" do
@proxy.and_yield(1, 2, 3) @proxy.and_yield(1, 2, 3)
lambda { lambda {
Mock.verify_call(@mock, :method_call) {|a, b|} Mock.verify_call(@mock, :method_call) {|a, b|}
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError)
end end
it "does not raise an expection when it is expected to yield to a block that can take any number of arguments" do it "does not raise an exception when it is expected to yield to a block that can take any number of arguments" do
@proxy.and_yield(1, 2, 3) @proxy.and_yield(1, 2, 3)
expect { expect {
Mock.verify_call(@mock, :method_call) {|*a|} Mock.verify_call(@mock, :method_call) {|*a|}

View File

@ -15,25 +15,25 @@ describe ProfileFilter, "#find" do
@filter.find(@file).should == @file @filter.find(@file).should == @file
end end
it "attemps to locate the file in 'spec/profiles'" do it "attempts to locate the file in 'spec/profiles'" do
path = File.join "spec/profiles", @file path = File.join "spec/profiles", @file
File.should_receive(:exist?).with(path).and_return(true) File.should_receive(:exist?).with(path).and_return(true)
@filter.find(@file).should == path @filter.find(@file).should == path
end end
it "attemps to locate the file in 'spec'" do it "attempts to locate the file in 'spec'" do
path = File.join "spec", @file path = File.join "spec", @file
File.should_receive(:exist?).with(path).and_return(true) File.should_receive(:exist?).with(path).and_return(true)
@filter.find(@file).should == path @filter.find(@file).should == path
end end
it "attemps to locate the file in 'profiles'" do it "attempts to locate the file in 'profiles'" do
path = File.join "profiles", @file path = File.join "profiles", @file
File.should_receive(:exist?).with(path).and_return(true) File.should_receive(:exist?).with(path).and_return(true)
@filter.find(@file).should == path @filter.find(@file).should == path
end end
it "attemps to locate the file in '.'" do it "attempts to locate the file in '.'" do
path = File.join ".", @file path = File.join ".", @file
File.should_receive(:exist?).with(path).and_return(true) File.should_receive(:exist?).with(path).and_return(true)
@filter.find(@file).should == path @filter.find(@file).should == path

View File

@ -172,7 +172,7 @@ describe MSpecScript, "#load" do
@script.load(@base).should == :loaded @script.load(@base).should == :loaded
end end
it "attemps to locate the file in '.'" do it "attempts to locate the file in '.'" do
path = File.expand_path @file, "." path = File.expand_path @file, "."
File.should_receive(:exist?).with(path).and_return(true) File.should_receive(:exist?).with(path).and_return(true)
Kernel.should_receive(:load).with(path).and_return(:loaded) Kernel.should_receive(:load).with(path).and_return(:loaded)
@ -186,7 +186,7 @@ describe MSpecScript, "#load" do
@script.load(@base).should == :loaded @script.load(@base).should == :loaded
end end
it "attemps to locate the file in 'spec'" do it "attempts to locate the file in 'spec'" do
path = File.expand_path @file, "spec" path = File.expand_path @file, "spec"
File.should_receive(:exist?).with(path).and_return(true) File.should_receive(:exist?).with(path).and_return(true)
Kernel.should_receive(:load).with(path).and_return(:loaded) Kernel.should_receive(:load).with(path).and_return(:loaded)
@ -438,8 +438,9 @@ describe MSpecScript, "#files" do
@script.files([":files"]).should == ["file1", "file2"] @script.files([":files"]).should == ["file1", "file2"]
end end
it "returns an empty list if the config key is not set" do it "aborts if the config key is not set" do
@script.files([":all_files"]).should == [] @script.should_receive(:abort).with("Key :all_files not found in mspec config.")
@script.files([":all_files"])
end end
end end