This commit is contained in:
Benoit Daloze 2019-09-29 16:03:47 +02:00
parent a27dc83113
commit 31bb66a19d
28 changed files with 299 additions and 242 deletions

View File

@ -58,7 +58,7 @@ ruby -S bundle install
## Running Specs ## Running Specs
Use RSpec to run the MSpec specs. There are no plans currently to make the Use RSpec to run the MSpec specs. There are no plans currently to make the
MSpec specs runnable by MSpec. MSpec specs runnable by MSpec: https://github.com/ruby/mspec/issues/19.
After installing the gem dependencies, the specs can be run as follows: After installing the gem dependencies, the specs can be run as follows:

View File

@ -1,3 +1,4 @@
require 'mspec/utils/format'
require 'mspec/matchers' require 'mspec/matchers'
require 'mspec/expectations' require 'mspec/expectations'
require 'mspec/mocks' require 'mspec/mocks'
@ -5,16 +6,3 @@ require 'mspec/runner'
require 'mspec/guards' require 'mspec/guards'
require 'mspec/helpers' require 'mspec/helpers'
require 'mspec/version' require 'mspec/version'
# If the implementation on which the specs are run cannot
# load pp from the standard library, add a pp.rb file that
# defines the #pretty_inspect method on Object or Kernel.
begin
require 'pp'
rescue LoadError
module Kernel
def pretty_inspect
inspect
end
end
end

View File

@ -24,6 +24,7 @@ class MSpecCI < MSpecScript
options.configure { |f| load f } options.configure { |f| load f }
options.pretend options.pretend
options.interrupt options.interrupt
options.timeout
options.doc "\n How to modify the guard behavior" options.doc "\n How to modify the guard behavior"
options.unguarded options.unguarded

View File

@ -36,6 +36,7 @@ class MSpecRun < MSpecScript
options.repeat options.repeat
options.pretend options.pretend
options.interrupt options.interrupt
options.timeout
options.doc "\n How to modify the guard behavior" options.doc "\n How to modify the guard behavior"
options.unguarded options.unguarded

View File

@ -33,6 +33,7 @@ class MSpecTag < MSpecScript
options.pretend options.pretend
options.unguarded options.unguarded
options.interrupt options.interrupt
options.timeout
options.doc "\n How to display their output" options.doc "\n How to display their output"
options.formatters options.formatters

View File

@ -12,10 +12,21 @@ class SpecExpectation
expected_to_s = expected.to_s expected_to_s = expected.to_s
actual_to_s = actual.to_s actual_to_s = actual.to_s
if expected_to_s.size + actual_to_s.size > 80 if expected_to_s.size + actual_to_s.size > 80
message = "#{expected_to_s.chomp}\n#{actual_to_s}" message = "#{expected_to_s}\n#{actual_to_s}"
else else
message = "#{expected_to_s} #{actual_to_s}" message = "#{expected_to_s} #{actual_to_s}"
end end
Kernel.raise SpecExpectationNotMetError, message raise SpecExpectationNotMetError, message
end
def self.fail_predicate(receiver, predicate, args, block, result, expectation)
receiver_to_s = MSpec.format(receiver)
before_method = predicate.to_s =~ /^[a-z]/ ? "." : " "
predicate_to_s = "#{before_method}#{predicate}"
predicate_to_s += " " unless args.empty?
args_to_s = args.map { |arg| MSpec.format(arg) }.join(', ')
args_to_s += " { ... }" if block
result_to_s = MSpec.format(result)
raise SpecExpectationNotMetError, "Expected #{receiver_to_s}#{predicate_to_s}#{args_to_s}\n#{expectation} but was #{result_to_s}"
end end
end end

View File

@ -4,26 +4,26 @@ class Object
def should(matcher = NO_MATCHER_GIVEN) def should(matcher = NO_MATCHER_GIVEN)
MSpec.expectation MSpec.expectation
MSpec.actions :expectation, MSpec.current.state MSpec.actions :expectation, MSpec.current.state
unless matcher.equal? NO_MATCHER_GIVEN if NO_MATCHER_GIVEN.equal?(matcher)
SpecPositiveOperatorMatcher.new(self)
else
unless matcher.matches? self unless matcher.matches? self
expected, actual = matcher.failure_message expected, actual = matcher.failure_message
SpecExpectation.fail_with(expected, actual) SpecExpectation.fail_with(expected, actual)
end end
else
SpecPositiveOperatorMatcher.new(self)
end end
end end
def should_not(matcher = NO_MATCHER_GIVEN) def should_not(matcher = NO_MATCHER_GIVEN)
MSpec.expectation MSpec.expectation
MSpec.actions :expectation, MSpec.current.state MSpec.actions :expectation, MSpec.current.state
unless matcher.equal? NO_MATCHER_GIVEN if NO_MATCHER_GIVEN.equal?(matcher)
SpecNegativeOperatorMatcher.new(self)
else
if matcher.matches? self if matcher.matches? self
expected, actual = matcher.negative_failure_message expected, actual = matcher.negative_failure_message
SpecExpectation.fail_with(expected, actual) SpecExpectation.fail_with(expected, actual)
end end
else
SpecNegativeOperatorMatcher.new(self)
end end
end end
end end

View File

@ -78,8 +78,12 @@ end
# Creates an IO instance for a temporary file name. The file # Creates an IO instance for a temporary file name. The file
# must be deleted. # must be deleted.
def new_io(name, mode="w:utf-8") def new_io(name, mode = "w:utf-8")
IO.new new_fd(name, mode), mode if Hash === mode # Avoid kwargs warnings on Ruby 2.7+
File.new(name, **mode)
else
File.new(name, mode)
end
end end
def find_unused_fd def find_unused_fd

View File

@ -5,3 +5,13 @@ def suppress_warning
ensure ensure
$VERBOSE = verbose $VERBOSE = verbose
end end
if ruby_version_is("2.7")
def suppress_keyword_warning(&block)
suppress_warning(&block)
end
else
def suppress_keyword_warning
yield
end
end

View File

@ -10,98 +10,52 @@ class Module
include MSpecMatchers include MSpecMatchers
end end
class SpecPositiveOperatorMatcher class SpecPositiveOperatorMatcher < BasicObject
def initialize(actual) def initialize(actual)
@actual = actual @actual = actual
end end
def ==(expected) def ==(expected)
unless @actual == expected method_missing(:==, expected)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"to equal #{expected.pretty_inspect}")
end
end end
def <(expected) def !=(expected)
unless @actual < expected method_missing(:!=, expected)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"to be less than #{expected.pretty_inspect}")
end
end end
def <=(expected) def equal?(expected)
unless @actual <= expected method_missing(:equal?, expected)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"to be less than or equal to #{expected.pretty_inspect}")
end
end end
def >(expected) def method_missing(name, *args, &block)
unless @actual > expected result = @actual.__send__(name, *args, &block)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", unless result
"to be greater than #{expected.pretty_inspect}") ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be truthy")
end
end
def >=(expected)
unless @actual >= expected
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"to be greater than or equal to #{expected.pretty_inspect}")
end
end
def =~(expected)
unless @actual =~ expected
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"to match #{expected.pretty_inspect}")
end end
end end
end end
class SpecNegativeOperatorMatcher class SpecNegativeOperatorMatcher < BasicObject
def initialize(actual) def initialize(actual)
@actual = actual @actual = actual
end end
def ==(expected) def ==(expected)
if @actual == expected method_missing(:==, expected)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"not to equal #{expected.pretty_inspect}")
end
end end
def <(expected) def !=(expected)
if @actual < expected method_missing(:!=, expected)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"not to be less than #{expected.pretty_inspect}")
end
end end
def <=(expected) def equal?(expected)
if @actual <= expected method_missing(:equal?, expected)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"not to be less than or equal to #{expected.pretty_inspect}")
end
end end
def >(expected) def method_missing(name, *args, &block)
if @actual > expected result = @actual.__send__(name, *args, &block)
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", if result
"not to be greater than #{expected.pretty_inspect}") ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be falsy")
end
end
def >=(expected)
if @actual >= expected
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"not to be greater than or equal to #{expected.pretty_inspect}")
end
end
def =~(expected)
if @actual =~ expected
SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}",
"not to match #{expected.pretty_inspect}")
end end
end end
end end

View File

@ -17,10 +17,12 @@ class ComplainMatcher
def matches?(proc) def matches?(proc)
@saved_err = $stderr @saved_err = $stderr
@verbose = $VERBOSE @verbose = $VERBOSE
err = IOStub.new
Thread.current[:in_mspec_complain_matcher] = true
$stderr = err
$VERBOSE = @options.key?(:verbose) ? @options[:verbose] : false
begin begin
err = $stderr = IOStub.new
$VERBOSE = @options.key?(:verbose) ? @options[:verbose] : false
Thread.current[:in_mspec_complain_matcher] = true
proc.call proc.call
ensure ensure
$VERBOSE = @verbose $VERBOSE = @verbose

View File

@ -9,13 +9,13 @@ class EqlMatcher
end end
def failure_message def failure_message
["Expected #{@actual.pretty_inspect}", ["Expected #{MSpec.format(@actual)}",
"to have same value and type as #{@expected.pretty_inspect}"] "to have same value and type as #{MSpec.format(@expected)}"]
end end
def negative_failure_message def negative_failure_message
["Expected #{@actual.pretty_inspect}", ["Expected #{MSpec.format(@actual)}",
"not to have same value or type as #{@expected.pretty_inspect}"] "not to have same value or type as #{MSpec.format(@expected)}"]
end end
end end

View File

@ -9,13 +9,13 @@ class EqualMatcher
end end
def failure_message def failure_message
["Expected #{@actual.pretty_inspect}", ["Expected #{MSpec.format(@actual)}",
"to be identical to #{@expected.pretty_inspect}"] "to be identical to #{MSpec.format(@expected)}"]
end end
def negative_failure_message def negative_failure_message
["Expected #{@actual.pretty_inspect}", ["Expected #{MSpec.format(@actual)}",
"not to be identical to #{@expected.pretty_inspect}"] "not to be identical to #{MSpec.format(@expected)}"]
end end
end end

View File

@ -37,12 +37,12 @@ class EqualElementMatcher
end end
def failure_message def failure_message
["Expected #{@actual.pretty_inspect}", ["Expected #{MSpec.format(@actual)}",
"to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"] "to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"]
end end
def negative_failure_message def negative_failure_message
["Expected #{@actual.pretty_inspect}", ["Expected #{MSpec.format(@actual)}",
"not to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"] "not to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"]
end end

View File

@ -52,19 +52,13 @@ 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 (#{format_result(@result)} was returned)" message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
end end
message message

View File

@ -0,0 +1,60 @@
class TimeoutAction
def initialize(timeout)
@timeout = timeout
@queue = Queue.new
@started = now
end
def register
MSpec.register :start, self
MSpec.register :before, self
MSpec.register :finish, self
end
private def now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
private def fetch_item
@queue.pop(true)
rescue ThreadError
nil
end
def start
@thread = Thread.new do
loop do
if action = fetch_item
action.call
else
wakeup_at = @started + @timeout
left = wakeup_at - now
sleep left if left > 0
Thread.pass # Let the main thread run
if @queue.empty?
elapsed = now - @started
if elapsed > @timeout
STDERR.puts "\n#{@current_state.description}"
STDERR.flush
abort "Example took #{now - @started}s, which is longer than the timeout of #{@timeout}s"
end
end
end
end
end
end
def before(state=nil)
time = now
@queue << -> do
@current_state = state
@started = time
end
end
def finish
@thread.kill
@thread.join
end
end

View File

@ -0,0 +1,20 @@
# If the implementation on which the specs are run cannot
# load pp from the standard library, add a pp.rb file that
# defines the #pretty_inspect method on Object or Kernel.
begin
require 'pp'
rescue LoadError
module Kernel
def pretty_inspect
inspect
end
end
end
module MSpec
def self.format(obj)
obj.pretty_inspect.chomp
rescue => e
"#<#{obj.class}>(#pretty_inspect raised #{e.inspect})"
end
end

View File

@ -419,6 +419,14 @@ class MSpecOptions
end end
end end
def timeout
on("--timeout", "TIMEOUT", "Abort if a spec takes longer than TIMEOUT seconds") do |timeout|
require 'mspec/runner/actions/timeout'
timeout = Float(timeout)
TimeoutAction.new(timeout).register
end
end
def verify def verify
on("--report-on", "GUARD", "Report specs guarded by GUARD") do |g| on("--report-on", "GUARD", "Report specs guarded by GUARD") do |g|
MSpec.register_mode :report_on MSpec.register_mode :report_on

View File

@ -14,8 +14,8 @@ describe "MSpec" do
@out.should include <<-EOS @out.should include <<-EOS
1) 1)
MSpec expectation method #should causes a failue to be recorded FAILED MSpec expectation method #should causes a failue to be recorded FAILED
Expected 1 Expected 1 == 2
to equal 2 to be truthy but was false
EOS EOS
end end
@ -33,8 +33,8 @@ EOS
@out.should include <<-EOS @out.should include <<-EOS
3) 3)
MSpec expectation method #should_not causes a failure to be recorded FAILED MSpec expectation method #should_not causes a failure to be recorded FAILED
Expected 1 Expected 1 == 1
not to equal 1 to be falsy but was true
EOS EOS
end end

View File

@ -5,9 +5,8 @@ describe "Running mspec" do
1) 1)
Foo#bar errors FAILED Foo#bar errors FAILED
Expected 1 Expected 1 == 2
to equal 2 to be truthy but was false
CWD/spec/fixtures/a_spec.rb:8:in `block (2 levels) in <top (required)>' CWD/spec/fixtures/a_spec.rb:8:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>' CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>'
CWD/bin/mspec-run:7:in `<main>' CWD/bin/mspec-run:7:in `<main>'

View File

@ -24,18 +24,16 @@ Tag#me érròrs in unicode
1) 1)
Tag#me errors FAILED Tag#me errors FAILED
Expected 1 Expected 1 == 2
to equal 2 to be truthy but was false
CWD/spec/fixtures/tagging_spec.rb:9:in `block (2 levels) in <top (required)>' CWD/spec/fixtures/tagging_spec.rb:9:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>' CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>'
CWD/bin/mspec-tag:7:in `<main>' CWD/bin/mspec-tag:7:in `<main>'
2) 2)
Tag#me érròrs in unicode FAILED Tag#me érròrs in unicode FAILED
Expected 1 Expected 1 == 2
to equal 2 to be truthy but was false
CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in <top (required)>' CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>' CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>'
CWD/bin/mspec-tag:7:in `<main>' CWD/bin/mspec-tag:7:in `<main>'

View File

@ -4,222 +4,225 @@ require 'mspec/matchers'
require 'time' require 'time'
describe SpecPositiveOperatorMatcher, "== operator" do describe SpecPositiveOperatorMatcher, "== operator" do
it "raises an SpecExpectationNotMetError when expected == actual returns false" do it "provides a failure message that 'Expected x to equal y'" do
lambda { lambda {
SpecPositiveOperatorMatcher.new(1) == 2 SpecPositiveOperatorMatcher.new(1) == 2
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 1 == 2\nto be truthy but was false")
end end
it "provides a failure message that 'Expected x to equal y'" do it "does not raise an exception when == returns true" do
SpecExpectation.should_receive(:fail_with).with("Expected 1\n", "to equal 2\n")
SpecPositiveOperatorMatcher.new(1) == 2
end
it "does not raise an exception when expected == actual returns true" do
SpecPositiveOperatorMatcher.new(1) == 1 SpecPositiveOperatorMatcher.new(1) == 1
end end
end end
describe SpecPositiveOperatorMatcher, "=~ operator" do describe SpecPositiveOperatorMatcher, "=~ operator" do
it "raises an SpecExpectationNotMetError when expected =~ actual returns false" do it "provides a failure message that 'Expected \"x\" to match y'" do
lambda { lambda {
SpecPositiveOperatorMatcher.new('real') =~ /fake/ SpecPositiveOperatorMatcher.new('real') =~ /fake/
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /fake/\nto be truthy but was nil")
end end
it "provides a failure message that 'Expected \"x\" to match y'" do it "does not raise an exception when =~ returns true" do
SpecExpectation.should_receive(:fail_with).with(
"Expected \"real\"\n", "to match /fake/\n")
SpecPositiveOperatorMatcher.new('real') =~ /fake/
end
it "does not raise an exception when expected =~ actual returns true" do
SpecPositiveOperatorMatcher.new('real') =~ /real/ SpecPositiveOperatorMatcher.new('real') =~ /real/
end end
end end
describe SpecPositiveOperatorMatcher, "> operator" do describe SpecPositiveOperatorMatcher, "> operator" do
it "raises an SpecExpectationNotMetError when expected > actual returns false" do it "provides a failure message that 'Expected x to be greater than y'" do
lambda { lambda {
SpecPositiveOperatorMatcher.new(4) > 5 SpecPositiveOperatorMatcher.new(4) > 5
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 4 > 5\nto be truthy but was false")
end end
it "provides a failure message that 'Expected x to be greater than y'" do it "does not raise an exception when > returns true" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 4\n", "to be greater than 5\n")
SpecPositiveOperatorMatcher.new(4) > 5
end
it "does not raise an exception when expected > actual returns true" do
SpecPositiveOperatorMatcher.new(5) > 4 SpecPositiveOperatorMatcher.new(5) > 4
end end
end end
describe SpecPositiveOperatorMatcher, ">= operator" do describe SpecPositiveOperatorMatcher, ">= operator" do
it "raises an SpecExpectationNotMetError when expected >= actual returns false" do it "provides a failure message that 'Expected x to be greater than or equal to y'" do
lambda { lambda {
SpecPositiveOperatorMatcher.new(4) >= 5 SpecPositiveOperatorMatcher.new(4) >= 5
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 4 >= 5\nto be truthy but was false")
end end
it "provides a failure message that 'Expected x to be greater than or equal to y'" do it "does not raise an exception when > returns true" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 4\n", "to be greater than or equal to 5\n")
SpecPositiveOperatorMatcher.new(4) >= 5
end
it "does not raise an exception when expected > actual returns true" do
SpecPositiveOperatorMatcher.new(5) >= 4 SpecPositiveOperatorMatcher.new(5) >= 4
SpecPositiveOperatorMatcher.new(5) >= 5 SpecPositiveOperatorMatcher.new(5) >= 5
end end
end end
describe SpecPositiveOperatorMatcher, "< operater" do describe SpecPositiveOperatorMatcher, "< operater" do
it "raises an SpecExpectationNotMetError when expected < actual returns false" do it "provides a failure message that 'Expected x to be less than y'" do
lambda { lambda {
SpecPositiveOperatorMatcher.new(5) < 4 SpecPositiveOperatorMatcher.new(5) < 4
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 5 < 4\nto be truthy but was false")
end end
it "provides a failure message that 'Expected x to be less than y'" do it "does not raise an exception when < returns true" do
SpecExpectation.should_receive(:fail_with).with("Expected 5\n", "to be less than 4\n")
SpecPositiveOperatorMatcher.new(5) < 4
end
it "does not raise an exception when expected < actual returns true" do
SpecPositiveOperatorMatcher.new(4) < 5 SpecPositiveOperatorMatcher.new(4) < 5
end end
end end
describe SpecPositiveOperatorMatcher, "<= operater" do describe SpecPositiveOperatorMatcher, "<= operater" do
it "raises an SpecExpectationNotMetError when expected < actual returns false" do it "provides a failure message that 'Expected x to be less than or equal to y'" do
lambda { lambda {
SpecPositiveOperatorMatcher.new(5) <= 4 SpecPositiveOperatorMatcher.new(5) <= 4
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 5 <= 4\nto be truthy but was false")
end end
it "provides a failure message that 'Expected x to be less than or equal to y'" do it "does not raise an exception when < returns true" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 5\n", "to be less than or equal to 4\n")
SpecPositiveOperatorMatcher.new(5) <= 4
end
it "does not raise an exception when expected < actual returns true" do
SpecPositiveOperatorMatcher.new(4) <= 5 SpecPositiveOperatorMatcher.new(4) <= 5
SpecPositiveOperatorMatcher.new(4) <= 4 SpecPositiveOperatorMatcher.new(4) <= 4
end end
end end
describe SpecPositiveOperatorMatcher, "arbitrary predicates" do
it "do not raise an exception when the predicate is truthy" do
SpecPositiveOperatorMatcher.new(2).eql?(2)
SpecPositiveOperatorMatcher.new(2).equal?(2)
SpecPositiveOperatorMatcher.new([1, 2, 3]).include?(2)
SpecPositiveOperatorMatcher.new("abc").start_with?("ab")
SpecPositiveOperatorMatcher.new("abc").start_with?("d", "a")
SpecPositiveOperatorMatcher.new(3).odd?
SpecPositiveOperatorMatcher.new([1, 2]).any? { |e| e.even? }
end
it "provide a failure message when the predicate returns a falsy value" do
lambda {
SpecPositiveOperatorMatcher.new(2).eql?(3)
}.should raise_error(SpecExpectationNotMetError, "Expected 2.eql? 3\nto be truthy but was false")
lambda {
SpecPositiveOperatorMatcher.new(2).equal?(3)
}.should raise_error(SpecExpectationNotMetError, "Expected 2.equal? 3\nto be truthy but was false")
lambda {
SpecPositiveOperatorMatcher.new([1, 2, 3]).include?(4)
}.should raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 4\nto be truthy but was false")
lambda {
SpecPositiveOperatorMatcher.new("abc").start_with?("de")
}.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"de\"\nto be truthy but was false")
lambda {
SpecPositiveOperatorMatcher.new("abc").start_with?("d", "e")
}.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"e\"\nto be truthy but was false")
lambda {
SpecPositiveOperatorMatcher.new(2).odd?
}.should raise_error(SpecExpectationNotMetError, "Expected 2.odd?\nto be truthy but was false")
lambda {
SpecPositiveOperatorMatcher.new([1, 3]).any? { |e| e.even? }
}.should raise_error(SpecExpectationNotMetError, "Expected [1, 3].any? { ... }\nto be truthy but was false")
end
end
describe SpecNegativeOperatorMatcher, "arbitrary predicates" do
it "do not raise an exception when the predicate returns a falsy value" do
SpecNegativeOperatorMatcher.new(2).eql?(3)
SpecNegativeOperatorMatcher.new(2).equal?(3)
SpecNegativeOperatorMatcher.new([1, 2, 3]).include?(4)
SpecNegativeOperatorMatcher.new("abc").start_with?("de")
SpecNegativeOperatorMatcher.new("abc").start_with?("d", "e")
SpecNegativeOperatorMatcher.new(2).odd?
SpecNegativeOperatorMatcher.new([1, 3]).any? { |e| e.even? }
end
it "provide a failure message when the predicate returns a truthy value" do
lambda {
SpecNegativeOperatorMatcher.new(2).eql?(2)
}.should raise_error(SpecExpectationNotMetError, "Expected 2.eql? 2\nto be falsy but was true")
lambda {
SpecNegativeOperatorMatcher.new(2).equal?(2)
}.should raise_error(SpecExpectationNotMetError, "Expected 2.equal? 2\nto be falsy but was true")
lambda {
SpecNegativeOperatorMatcher.new([1, 2, 3]).include?(2)
}.should raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 2\nto be falsy but was true")
lambda {
SpecNegativeOperatorMatcher.new("abc").start_with?("ab")
}.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"ab\"\nto be falsy but was true")
lambda {
SpecNegativeOperatorMatcher.new("abc").start_with?("d", "a")
}.should raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"a\"\nto be falsy but was true")
lambda {
SpecNegativeOperatorMatcher.new(3).odd?
}.should raise_error(SpecExpectationNotMetError, "Expected 3.odd?\nto be falsy but was true")
lambda {
SpecNegativeOperatorMatcher.new([1, 2]).any? { |e| e.even? }
}.should raise_error(SpecExpectationNotMetError, "Expected [1, 2].any? { ... }\nto be falsy but was true")
end
end
describe SpecNegativeOperatorMatcher, "== operator" do describe SpecNegativeOperatorMatcher, "== operator" do
it "raises an SpecExpectationNotMetError when expected == actual returns true" do it "provides a failure message that 'Expected x not to equal y'" do
lambda { lambda {
SpecNegativeOperatorMatcher.new(1) == 1 SpecNegativeOperatorMatcher.new(1) == 1
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 1 == 1\nto be falsy but was true")
end end
it "provides a failure message that 'Expected x not to equal y'" do it "does not raise an exception when == returns false" do
SpecExpectation.should_receive(:fail_with).with("Expected 1\n", "not to equal 1\n")
SpecNegativeOperatorMatcher.new(1) == 1
end
it "does not raise an exception when expected == actual returns false" do
SpecNegativeOperatorMatcher.new(1) == 2 SpecNegativeOperatorMatcher.new(1) == 2
end end
end end
describe SpecNegativeOperatorMatcher, "=~ operator" do describe SpecNegativeOperatorMatcher, "=~ operator" do
it "raises an SpecExpectationNotMetError when expected =~ actual returns true" do it "provides a failure message that 'Expected \"x\" not to match /y/'" do
lambda { lambda {
SpecNegativeOperatorMatcher.new('real') =~ /real/ SpecNegativeOperatorMatcher.new('real') =~ /real/
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /real/\nto be falsy but was 0")
end end
it "provides a failure message that 'Expected \"x\" not to match /y/'" do it "does not raise an exception when =~ returns false" do
SpecExpectation.should_receive(:fail_with).with(
"Expected \"real\"\n", "not to match /real/\n")
SpecNegativeOperatorMatcher.new('real') =~ /real/
end
it "does not raise an exception when expected =~ actual returns false" do
SpecNegativeOperatorMatcher.new('real') =~ /fake/ SpecNegativeOperatorMatcher.new('real') =~ /fake/
end end
end end
describe SpecNegativeOperatorMatcher, "< operator" do describe SpecNegativeOperatorMatcher, "< operator" do
it "raises an SpecExpectationNotMetError when expected < actual returns true" do it "provides a failure message that 'Expected x not to be less than y'" do
lambda { lambda {
SpecNegativeOperatorMatcher.new(4) < 5 SpecNegativeOperatorMatcher.new(4) < 5
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 4 < 5\nto be falsy but was true")
end end
it "provides a failure message that 'Expected x not to be less than y'" do it "does not raise an exception when < returns false" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 4\n", "not to be less than 5\n")
SpecNegativeOperatorMatcher.new(4) < 5
end
it "does not raise an exception when expected < actual returns false" do
SpecNegativeOperatorMatcher.new(5) < 4 SpecNegativeOperatorMatcher.new(5) < 4
end end
end end
describe SpecNegativeOperatorMatcher, "<= operator" do describe SpecNegativeOperatorMatcher, "<= operator" do
it "raises an SpecExpectationNotMetError when expected <= actual returns true" do it "provides a failure message that 'Expected x not to be less than or equal to y'" do
lambda { lambda {
SpecNegativeOperatorMatcher.new(4) <= 5 SpecNegativeOperatorMatcher.new(4) <= 5
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 4 <= 5\nto be falsy but was true")
lambda { lambda {
SpecNegativeOperatorMatcher.new(5) <= 5 SpecNegativeOperatorMatcher.new(5) <= 5
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 5 <= 5\nto be falsy but was true")
end end
it "provides a failure message that 'Expected x not to be less than or equal to y'" do it "does not raise an exception when <= returns false" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 4\n", "not to be less than or equal to 5\n")
SpecNegativeOperatorMatcher.new(4) <= 5
end
it "does not raise an exception when expected <= actual returns false" do
SpecNegativeOperatorMatcher.new(5) <= 4 SpecNegativeOperatorMatcher.new(5) <= 4
end end
end end
describe SpecNegativeOperatorMatcher, "> operator" do describe SpecNegativeOperatorMatcher, "> operator" do
it "raises an SpecExpectationNotMetError when expected > actual returns true" do it "provides a failure message that 'Expected x not to be greater than y'" do
lambda { lambda {
SpecNegativeOperatorMatcher.new(5) > 4 SpecNegativeOperatorMatcher.new(5) > 4
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 5 > 4\nto be falsy but was true")
end end
it "provides a failure message that 'Expected x not to be greater than y'" do it "does not raise an exception when > returns false" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 5\n", "not to be greater than 4\n")
SpecNegativeOperatorMatcher.new(5) > 4
end
it "does not raise an exception when expected > actual returns false" do
SpecNegativeOperatorMatcher.new(4) > 5 SpecNegativeOperatorMatcher.new(4) > 5
end end
end end
describe SpecNegativeOperatorMatcher, ">= operator" do describe SpecNegativeOperatorMatcher, ">= operator" do
it "raises an SpecExpectationNotMetError when expected >= actual returns true" do it "provides a failure message that 'Expected x not to be greater than or equal to y'" do
lambda { lambda {
SpecNegativeOperatorMatcher.new(5) >= 4 SpecNegativeOperatorMatcher.new(5) >= 4
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 5 >= 4\nto be falsy but was true")
lambda { lambda {
SpecNegativeOperatorMatcher.new(5) >= 5 SpecNegativeOperatorMatcher.new(5) >= 5
}.should raise_error(SpecExpectationNotMetError) }.should raise_error(SpecExpectationNotMetError, "Expected 5 >= 5\nto be falsy but was true")
end end
it "provides a failure message that 'Expected x not to be greater than or equal to y'" do it "does not raise an exception when >= returns false" do
SpecExpectation.should_receive(:fail_with).with(
"Expected 5\n", "not to be greater than or equal to 4\n")
SpecNegativeOperatorMatcher.new(5) >= 4
end
it "does not raise an exception when expected >= actual returns false" do
SpecNegativeOperatorMatcher.new(4) >= 5 SpecNegativeOperatorMatcher.new(4) >= 5
end end
end end

View File

@ -22,12 +22,12 @@ describe EqlMatcher do
it "provides a useful failure message" do it "provides a useful failure message" do
matcher = EqlMatcher.new("red") matcher = EqlMatcher.new("red")
matcher.matches?("red") matcher.matches?("red")
matcher.failure_message.should == ["Expected \"red\"\n", "to have same value and type as \"red\"\n"] matcher.failure_message.should == ["Expected \"red\"", "to have same value and type as \"red\""]
end end
it "provides a useful negative failure message" do it "provides a useful negative failure message" do
matcher = EqlMatcher.new(1) matcher = EqlMatcher.new(1)
matcher.matches?(1.0) matcher.matches?(1.0)
matcher.negative_failure_message.should == ["Expected 1.0\n", "not to have same value or type as 1\n"] matcher.negative_failure_message.should == ["Expected 1.0", "not to have same value or type as 1"]
end end
end end

View File

@ -48,28 +48,28 @@ describe EqualElementMatcher do
it "provides a useful failure message" do it "provides a useful failure message" do
equal_element = EqualElementMatcher.new("A", {}, "Test") equal_element = EqualElementMatcher.new("A", {}, "Test")
equal_element.matches?('<A></A>').should be_false equal_element.matches?('<A></A>').should be_false
equal_element.failure_message.should == [%{Expected "<A></A>"\n}, %{to be a 'A' element with no attributes and "Test" as content}] equal_element.failure_message.should == [%{Expected "<A></A>"}, %{to be a 'A' element with no attributes and "Test" as content}]
equal_element = EqualElementMatcher.new("A", {}, "") equal_element = EqualElementMatcher.new("A", {}, "")
equal_element.matches?('<A>Test</A>').should be_false equal_element.matches?('<A>Test</A>').should be_false
equal_element.failure_message.should == [%{Expected "<A>Test</A>"\n}, %{to be a 'A' element with no attributes and no content}] equal_element.failure_message.should == [%{Expected "<A>Test</A>"}, %{to be a 'A' element with no attributes and no content}]
equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com") equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com")
equal_element.matches?('<A>Test</A>').should be_false equal_element.matches?('<A>Test</A>').should be_false
equal_element.failure_message.should == [%{Expected "<A>Test</A>"\n}, %{to be a 'A' element with HREF="http://www.example.com" and any content}] equal_element.failure_message.should == [%{Expected "<A>Test</A>"}, %{to be a 'A' element with HREF="http://www.example.com" and any content}]
end end
it "provides a useful negative failure message" do it "provides a useful negative failure message" do
equal_element = EqualElementMatcher.new("A", {}, "Test") equal_element = EqualElementMatcher.new("A", {}, "Test")
equal_element.matches?('<A></A>').should be_false equal_element.matches?('<A></A>').should be_false
equal_element.negative_failure_message.should == [%{Expected "<A></A>"\n}, %{not to be a 'A' element with no attributes and "Test" as content}] equal_element.negative_failure_message.should == [%{Expected "<A></A>"}, %{not to be a 'A' element with no attributes and "Test" as content}]
equal_element = EqualElementMatcher.new("A", {}, "") equal_element = EqualElementMatcher.new("A", {}, "")
equal_element.matches?('<A>Test</A>').should be_false equal_element.matches?('<A>Test</A>').should be_false
equal_element.negative_failure_message.should == [%{Expected "<A>Test</A>"\n}, %{not to be a 'A' element with no attributes and no content}] equal_element.negative_failure_message.should == [%{Expected "<A>Test</A>"}, %{not to be a 'A' element with no attributes and no content}]
equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com") equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com")
equal_element.matches?('<A>Test</A>').should be_false equal_element.matches?('<A>Test</A>').should be_false
equal_element.negative_failure_message.should == [%{Expected "<A>Test</A>"\n}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}] equal_element.negative_failure_message.should == [%{Expected "<A>Test</A>"}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}]
end end
end end

View File

@ -21,12 +21,12 @@ describe EqualMatcher do
it "provides a useful failure message" do it "provides a useful failure message" do
matcher = EqualMatcher.new("red") matcher = EqualMatcher.new("red")
matcher.matches?("red") matcher.matches?("red")
matcher.failure_message.should == ["Expected \"red\"\n", "to be identical to \"red\"\n"] matcher.failure_message.should == ["Expected \"red\"", "to be identical to \"red\""]
end end
it "provides a useful negative failure message" do it "provides a useful negative failure message" do
matcher = EqualMatcher.new(1) matcher = EqualMatcher.new(1)
matcher.matches?(1) matcher.matches?(1)
matcher.negative_failure_message.should == ["Expected 1\n", "not to be identical to 1\n"] matcher.negative_failure_message.should == ["Expected 1", "not to be identical to 1"]
end end
end end

View File

@ -111,7 +111,7 @@ describe RaiseErrorMatcher do
matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matches?(proc) matcher.matches?(proc)
matcher.failure_message.should == matcher.failure_message.should ==
["Expected ExpectedException (expected)", "but no exception was raised (#pretty_inspect raised ArgumentError; A #<Object> was returned)"] ["Expected ExpectedException (expected)", "but no exception was raised (#<Object>(#pretty_inspect raised #<ArgumentError: bad>) was returned)"]
end end
it "provides a useful negative failure message" do it "provides a useful negative failure message" do

View File

@ -1,4 +1,4 @@
require 'pp' require 'mspec/utils/format'
require 'mspec/helpers/io' require 'mspec/helpers/io'
require 'mspec/helpers/scratch' require 'mspec/helpers/scratch'

View File

@ -15,5 +15,8 @@ rm -rf spec/ruby
git clone --depth 1 https://github.com/ruby/spec.git spec/ruby git clone --depth 1 https://github.com/ruby/spec.git spec/ruby
commit=$(git -C spec/ruby log -n 1 --format='%h') commit=$(git -C spec/ruby log -n 1 --format='%h')
rm -rf spec/ruby/.git rm -rf spec/ruby/.git
rm -f spec/ruby/appveyor.yml
rm -f spec/ruby/.travis.yml
rm -rf spec/ruby/.github
git add spec/ruby git add spec/ruby
git commit -m "Update to ruby/spec@${commit}" git commit -m "Update to ruby/spec@${commit}"