From 31bb66a19df26409c9d47afcf37919c9a065516a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 29 Sep 2019 16:03:47 +0200 Subject: [PATCH] Update to ruby/mspec@8106083 --- spec/mspec/README.md | 2 +- spec/mspec/lib/mspec.rb | 14 +- spec/mspec/lib/mspec/commands/mspec-ci.rb | 1 + spec/mspec/lib/mspec/commands/mspec-run.rb | 1 + spec/mspec/lib/mspec/commands/mspec-tag.rb | 1 + .../lib/mspec/expectations/expectations.rb | 15 +- spec/mspec/lib/mspec/expectations/should.rb | 12 +- spec/mspec/lib/mspec/helpers/io.rb | 8 +- spec/mspec/lib/mspec/helpers/warning.rb | 10 + spec/mspec/lib/mspec/matchers/base.rb | 86 ++----- spec/mspec/lib/mspec/matchers/complain.rb | 8 +- spec/mspec/lib/mspec/matchers/eql.rb | 8 +- spec/mspec/lib/mspec/matchers/equal.rb | 8 +- .../mspec/lib/mspec/matchers/equal_element.rb | 4 +- spec/mspec/lib/mspec/matchers/raise_error.rb | 8 +- .../mspec/lib/mspec/runner/actions/timeout.rb | 60 +++++ spec/mspec/lib/mspec/utils/format.rb | 20 ++ spec/mspec/lib/mspec/utils/options.rb | 8 + spec/mspec/spec/expectations/should_spec.rb | 8 +- spec/mspec/spec/integration/run_spec.rb | 5 +- spec/mspec/spec/integration/tag_spec.rb | 10 +- spec/mspec/spec/matchers/base_spec.rb | 217 +++++++++--------- spec/mspec/spec/matchers/eql_spec.rb | 4 +- .../mspec/spec/matchers/equal_element_spec.rb | 12 +- spec/mspec/spec/matchers/equal_spec.rb | 4 +- spec/mspec/spec/matchers/raise_error_spec.rb | 2 +- spec/mspec/spec/spec_helper.rb | 2 +- spec/mspec/tool/pull-latest-mspec-spec | 3 + 28 files changed, 299 insertions(+), 242 deletions(-) create mode 100644 spec/mspec/lib/mspec/runner/actions/timeout.rb create mode 100644 spec/mspec/lib/mspec/utils/format.rb diff --git a/spec/mspec/README.md b/spec/mspec/README.md index 5a4605da98..e6fe44c6a2 100644 --- a/spec/mspec/README.md +++ b/spec/mspec/README.md @@ -58,7 +58,7 @@ ruby -S bundle install ## Running Specs 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: diff --git a/spec/mspec/lib/mspec.rb b/spec/mspec/lib/mspec.rb index 42d590c99a..d24abd96f1 100644 --- a/spec/mspec/lib/mspec.rb +++ b/spec/mspec/lib/mspec.rb @@ -1,3 +1,4 @@ +require 'mspec/utils/format' require 'mspec/matchers' require 'mspec/expectations' require 'mspec/mocks' @@ -5,16 +6,3 @@ require 'mspec/runner' require 'mspec/guards' require 'mspec/helpers' 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 diff --git a/spec/mspec/lib/mspec/commands/mspec-ci.rb b/spec/mspec/lib/mspec/commands/mspec-ci.rb index cb0193f42d..2882613350 100644 --- a/spec/mspec/lib/mspec/commands/mspec-ci.rb +++ b/spec/mspec/lib/mspec/commands/mspec-ci.rb @@ -24,6 +24,7 @@ class MSpecCI < MSpecScript options.configure { |f| load f } options.pretend options.interrupt + options.timeout options.doc "\n How to modify the guard behavior" options.unguarded diff --git a/spec/mspec/lib/mspec/commands/mspec-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb index 249f9f5771..1e62bf2a13 100644 --- a/spec/mspec/lib/mspec/commands/mspec-run.rb +++ b/spec/mspec/lib/mspec/commands/mspec-run.rb @@ -36,6 +36,7 @@ class MSpecRun < MSpecScript options.repeat options.pretend options.interrupt + options.timeout options.doc "\n How to modify the guard behavior" options.unguarded diff --git a/spec/mspec/lib/mspec/commands/mspec-tag.rb b/spec/mspec/lib/mspec/commands/mspec-tag.rb index 8bc3382e91..f5d85026ae 100644 --- a/spec/mspec/lib/mspec/commands/mspec-tag.rb +++ b/spec/mspec/lib/mspec/commands/mspec-tag.rb @@ -33,6 +33,7 @@ class MSpecTag < MSpecScript options.pretend options.unguarded options.interrupt + options.timeout options.doc "\n How to display their output" options.formatters diff --git a/spec/mspec/lib/mspec/expectations/expectations.rb b/spec/mspec/lib/mspec/expectations/expectations.rb index cfdc2b63a3..b42dfebb7f 100644 --- a/spec/mspec/lib/mspec/expectations/expectations.rb +++ b/spec/mspec/lib/mspec/expectations/expectations.rb @@ -12,10 +12,21 @@ class SpecExpectation expected_to_s = expected.to_s actual_to_s = actual.to_s 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 message = "#{expected_to_s} #{actual_to_s}" 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 diff --git a/spec/mspec/lib/mspec/expectations/should.rb b/spec/mspec/lib/mspec/expectations/should.rb index f6d83053f5..231ad15c21 100644 --- a/spec/mspec/lib/mspec/expectations/should.rb +++ b/spec/mspec/lib/mspec/expectations/should.rb @@ -4,26 +4,26 @@ class Object def should(matcher = NO_MATCHER_GIVEN) MSpec.expectation 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 expected, actual = matcher.failure_message SpecExpectation.fail_with(expected, actual) end - else - SpecPositiveOperatorMatcher.new(self) end end def should_not(matcher = NO_MATCHER_GIVEN) MSpec.expectation 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 expected, actual = matcher.negative_failure_message SpecExpectation.fail_with(expected, actual) end - else - SpecNegativeOperatorMatcher.new(self) end end end diff --git a/spec/mspec/lib/mspec/helpers/io.rb b/spec/mspec/lib/mspec/helpers/io.rb index f2c799dcab..d12d4b6ec3 100644 --- a/spec/mspec/lib/mspec/helpers/io.rb +++ b/spec/mspec/lib/mspec/helpers/io.rb @@ -78,8 +78,12 @@ end # Creates an IO instance for a temporary file name. The file # must be deleted. -def new_io(name, mode="w:utf-8") - IO.new new_fd(name, mode), mode +def new_io(name, mode = "w:utf-8") + if Hash === mode # Avoid kwargs warnings on Ruby 2.7+ + File.new(name, **mode) + else + File.new(name, mode) + end end def find_unused_fd diff --git a/spec/mspec/lib/mspec/helpers/warning.rb b/spec/mspec/lib/mspec/helpers/warning.rb index 9e093074e5..f54e4abf4d 100644 --- a/spec/mspec/lib/mspec/helpers/warning.rb +++ b/spec/mspec/lib/mspec/helpers/warning.rb @@ -5,3 +5,13 @@ def suppress_warning ensure $VERBOSE = verbose end + +if ruby_version_is("2.7") + def suppress_keyword_warning(&block) + suppress_warning(&block) + end +else + def suppress_keyword_warning + yield + end +end diff --git a/spec/mspec/lib/mspec/matchers/base.rb b/spec/mspec/lib/mspec/matchers/base.rb index fc2d36c84a..94d3b71e55 100644 --- a/spec/mspec/lib/mspec/matchers/base.rb +++ b/spec/mspec/lib/mspec/matchers/base.rb @@ -10,98 +10,52 @@ class Module include MSpecMatchers end -class SpecPositiveOperatorMatcher +class SpecPositiveOperatorMatcher < BasicObject def initialize(actual) @actual = actual end def ==(expected) - unless @actual == expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to equal #{expected.pretty_inspect}") - end + method_missing(:==, expected) end - def <(expected) - unless @actual < expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to be less than #{expected.pretty_inspect}") - end + def !=(expected) + method_missing(:!=, expected) end - def <=(expected) - unless @actual <= expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to be less than or equal to #{expected.pretty_inspect}") - end + def equal?(expected) + method_missing(:equal?, expected) end - def >(expected) - unless @actual > expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to be greater than #{expected.pretty_inspect}") - 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}") + def method_missing(name, *args, &block) + result = @actual.__send__(name, *args, &block) + unless result + ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be truthy") end end end -class SpecNegativeOperatorMatcher +class SpecNegativeOperatorMatcher < BasicObject def initialize(actual) @actual = actual end def ==(expected) - if @actual == expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to equal #{expected.pretty_inspect}") - end + method_missing(:==, expected) end - def <(expected) - if @actual < expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to be less than #{expected.pretty_inspect}") - end + def !=(expected) + method_missing(:!=, expected) end - def <=(expected) - if @actual <= expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to be less than or equal to #{expected.pretty_inspect}") - end + def equal?(expected) + method_missing(:equal?, expected) end - def >(expected) - if @actual > expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to be greater than #{expected.pretty_inspect}") - 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}") + def method_missing(name, *args, &block) + result = @actual.__send__(name, *args, &block) + if result + ::SpecExpectation.fail_predicate(@actual, name, args, block, result, "to be falsy") end end end diff --git a/spec/mspec/lib/mspec/matchers/complain.rb b/spec/mspec/lib/mspec/matchers/complain.rb index 22b8be17e1..887e72b4b0 100644 --- a/spec/mspec/lib/mspec/matchers/complain.rb +++ b/spec/mspec/lib/mspec/matchers/complain.rb @@ -17,10 +17,12 @@ class ComplainMatcher def matches?(proc) @saved_err = $stderr @verbose = $VERBOSE + err = IOStub.new + + Thread.current[:in_mspec_complain_matcher] = true + $stderr = err + $VERBOSE = @options.key?(:verbose) ? @options[:verbose] : false begin - err = $stderr = IOStub.new - $VERBOSE = @options.key?(:verbose) ? @options[:verbose] : false - Thread.current[:in_mspec_complain_matcher] = true proc.call ensure $VERBOSE = @verbose diff --git a/spec/mspec/lib/mspec/matchers/eql.rb b/spec/mspec/lib/mspec/matchers/eql.rb index a855789550..bcab88ebee 100644 --- a/spec/mspec/lib/mspec/matchers/eql.rb +++ b/spec/mspec/lib/mspec/matchers/eql.rb @@ -9,13 +9,13 @@ class EqlMatcher end def failure_message - ["Expected #{@actual.pretty_inspect}", - "to have same value and type as #{@expected.pretty_inspect}"] + ["Expected #{MSpec.format(@actual)}", + "to have same value and type as #{MSpec.format(@expected)}"] end def negative_failure_message - ["Expected #{@actual.pretty_inspect}", - "not to have same value or type as #{@expected.pretty_inspect}"] + ["Expected #{MSpec.format(@actual)}", + "not to have same value or type as #{MSpec.format(@expected)}"] end end diff --git a/spec/mspec/lib/mspec/matchers/equal.rb b/spec/mspec/lib/mspec/matchers/equal.rb index 5dc77d27ea..5ba4856d82 100644 --- a/spec/mspec/lib/mspec/matchers/equal.rb +++ b/spec/mspec/lib/mspec/matchers/equal.rb @@ -9,13 +9,13 @@ class EqualMatcher end def failure_message - ["Expected #{@actual.pretty_inspect}", - "to be identical to #{@expected.pretty_inspect}"] + ["Expected #{MSpec.format(@actual)}", + "to be identical to #{MSpec.format(@expected)}"] end def negative_failure_message - ["Expected #{@actual.pretty_inspect}", - "not to be identical to #{@expected.pretty_inspect}"] + ["Expected #{MSpec.format(@actual)}", + "not to be identical to #{MSpec.format(@expected)}"] end end diff --git a/spec/mspec/lib/mspec/matchers/equal_element.rb b/spec/mspec/lib/mspec/matchers/equal_element.rb index 1e9dfbcca1..8da2567fcf 100644 --- a/spec/mspec/lib/mspec/matchers/equal_element.rb +++ b/spec/mspec/lib/mspec/matchers/equal_element.rb @@ -37,12 +37,12 @@ class EqualElementMatcher end 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}"] end 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}"] end diff --git a/spec/mspec/lib/mspec/matchers/raise_error.rb b/spec/mspec/lib/mspec/matchers/raise_error.rb index 8350e25794..a720460091 100644 --- a/spec/mspec/lib/mspec/matchers/raise_error.rb +++ b/spec/mspec/lib/mspec/matchers/raise_error.rb @@ -52,19 +52,13 @@ class RaiseErrorMatcher exception_class_and_message(exception.class, exception.message) end - def format_result(result) - result.pretty_inspect.chomp - rescue => e - "#pretty_inspect raised #{e.class}; A #<#{result.class}>" - end - def failure_message message = ["Expected #{format_expected_exception}"] if @actual message << "but got #{format_exception(@actual)}" else - message << "but no exception was raised (#{format_result(@result)} was returned)" + message << "but no exception was raised (#{MSpec.format(@result)} was returned)" end message diff --git a/spec/mspec/lib/mspec/runner/actions/timeout.rb b/spec/mspec/lib/mspec/runner/actions/timeout.rb new file mode 100644 index 0000000000..9090efbe44 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb @@ -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 diff --git a/spec/mspec/lib/mspec/utils/format.rb b/spec/mspec/lib/mspec/utils/format.rb new file mode 100644 index 0000000000..bb75e131de --- /dev/null +++ b/spec/mspec/lib/mspec/utils/format.rb @@ -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 diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb index bbe64238c5..560826a723 100644 --- a/spec/mspec/lib/mspec/utils/options.rb +++ b/spec/mspec/lib/mspec/utils/options.rb @@ -419,6 +419,14 @@ class MSpecOptions 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 on("--report-on", "GUARD", "Report specs guarded by GUARD") do |g| MSpec.register_mode :report_on diff --git a/spec/mspec/spec/expectations/should_spec.rb b/spec/mspec/spec/expectations/should_spec.rb index 3258caf13c..2c896f1c3b 100644 --- a/spec/mspec/spec/expectations/should_spec.rb +++ b/spec/mspec/spec/expectations/should_spec.rb @@ -14,8 +14,8 @@ describe "MSpec" do @out.should include <<-EOS 1) MSpec expectation method #should causes a failue to be recorded FAILED -Expected 1 - to equal 2 +Expected 1 == 2 +to be truthy but was false EOS end @@ -33,8 +33,8 @@ EOS @out.should include <<-EOS 3) MSpec expectation method #should_not causes a failure to be recorded FAILED -Expected 1 - not to equal 1 +Expected 1 == 1 +to be falsy but was true EOS end diff --git a/spec/mspec/spec/integration/run_spec.rb b/spec/mspec/spec/integration/run_spec.rb index dc2a9933f9..6703e83150 100644 --- a/spec/mspec/spec/integration/run_spec.rb +++ b/spec/mspec/spec/integration/run_spec.rb @@ -5,9 +5,8 @@ describe "Running mspec" do 1) Foo#bar errors FAILED -Expected 1 - to equal 2 - +Expected 1 == 2 +to be truthy but was false CWD/spec/fixtures/a_spec.rb:8:in `block (2 levels) in ' CWD/spec/fixtures/a_spec.rb:2:in `' CWD/bin/mspec-run:7:in `
' diff --git a/spec/mspec/spec/integration/tag_spec.rb b/spec/mspec/spec/integration/tag_spec.rb index d980769043..1882d71e32 100644 --- a/spec/mspec/spec/integration/tag_spec.rb +++ b/spec/mspec/spec/integration/tag_spec.rb @@ -24,18 +24,16 @@ Tag#me érròrs in unicode 1) Tag#me errors FAILED -Expected 1 - to equal 2 - +Expected 1 == 2 +to be truthy but was false CWD/spec/fixtures/tagging_spec.rb:9:in `block (2 levels) in ' CWD/spec/fixtures/tagging_spec.rb:3:in `' CWD/bin/mspec-tag:7:in `
' 2) Tag#me érròrs in unicode FAILED -Expected 1 - to equal 2 - +Expected 1 == 2 +to be truthy but was false CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in ' CWD/spec/fixtures/tagging_spec.rb:3:in `' CWD/bin/mspec-tag:7:in `
' diff --git a/spec/mspec/spec/matchers/base_spec.rb b/spec/mspec/spec/matchers/base_spec.rb index cc13c29d1d..4694d754f7 100644 --- a/spec/mspec/spec/matchers/base_spec.rb +++ b/spec/mspec/spec/matchers/base_spec.rb @@ -4,222 +4,225 @@ require 'mspec/matchers' require 'time' 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 { SpecPositiveOperatorMatcher.new(1) == 2 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 1 == 2\nto be truthy but was false") end - it "provides a failure message that 'Expected x to equal y'" 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 + it "does not raise an exception when == returns true" do SpecPositiveOperatorMatcher.new(1) == 1 end end 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 { SpecPositiveOperatorMatcher.new('real') =~ /fake/ - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /fake/\nto be truthy but was nil") end - it "provides a failure message that 'Expected \"x\" to match y'" 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 + it "does not raise an exception when =~ returns true" do SpecPositiveOperatorMatcher.new('real') =~ /real/ end end 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 { SpecPositiveOperatorMatcher.new(4) > 5 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 4 > 5\nto be truthy but was false") end - it "provides a failure message that 'Expected x to be greater than y'" 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 + it "does not raise an exception when > returns true" do SpecPositiveOperatorMatcher.new(5) > 4 end end 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 { SpecPositiveOperatorMatcher.new(4) >= 5 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 4 >= 5\nto be truthy but was false") end - it "provides a failure message that 'Expected x to be greater than or equal to y'" 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 + it "does not raise an exception when > returns true" do SpecPositiveOperatorMatcher.new(5) >= 4 SpecPositiveOperatorMatcher.new(5) >= 5 end end 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 { SpecPositiveOperatorMatcher.new(5) < 4 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 5 < 4\nto be truthy but was false") end - it "provides a failure message that 'Expected x to be less than y'" 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 + it "does not raise an exception when < returns true" do SpecPositiveOperatorMatcher.new(4) < 5 end end 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 { SpecPositiveOperatorMatcher.new(5) <= 4 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 5 <= 4\nto be truthy but was false") end - it "provides a failure message that 'Expected x to be less than or equal to y'" 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 + it "does not raise an exception when < returns true" do SpecPositiveOperatorMatcher.new(4) <= 5 SpecPositiveOperatorMatcher.new(4) <= 4 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 - it "raises an SpecExpectationNotMetError when expected == actual returns true" do + it "provides a failure message that 'Expected x not to equal y'" do lambda { SpecNegativeOperatorMatcher.new(1) == 1 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 1 == 1\nto be falsy but was true") end - it "provides a failure message that 'Expected x not to equal y'" 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 + it "does not raise an exception when == returns false" do SpecNegativeOperatorMatcher.new(1) == 2 end end 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 { SpecNegativeOperatorMatcher.new('real') =~ /real/ - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /real/\nto be falsy but was 0") end - it "provides a failure message that 'Expected \"x\" not to match /y/'" 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 + it "does not raise an exception when =~ returns false" do SpecNegativeOperatorMatcher.new('real') =~ /fake/ end end 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 { SpecNegativeOperatorMatcher.new(4) < 5 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 4 < 5\nto be falsy but was true") end - it "provides a failure message that 'Expected x not to be less than y'" 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 + it "does not raise an exception when < returns false" do SpecNegativeOperatorMatcher.new(5) < 4 end end 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 { SpecNegativeOperatorMatcher.new(4) <= 5 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 4 <= 5\nto be falsy but was true") lambda { SpecNegativeOperatorMatcher.new(5) <= 5 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 5 <= 5\nto be falsy but was true") end - it "provides a failure message that 'Expected x not to be less than or equal to y'" 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 + it "does not raise an exception when <= returns false" do SpecNegativeOperatorMatcher.new(5) <= 4 end end 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 { SpecNegativeOperatorMatcher.new(5) > 4 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 5 > 4\nto be falsy but was true") end - it "provides a failure message that 'Expected x not to be greater than y'" 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 + it "does not raise an exception when > returns false" do SpecNegativeOperatorMatcher.new(4) > 5 end end 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 { SpecNegativeOperatorMatcher.new(5) >= 4 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 5 >= 4\nto be falsy but was true") lambda { SpecNegativeOperatorMatcher.new(5) >= 5 - }.should raise_error(SpecExpectationNotMetError) + }.should raise_error(SpecExpectationNotMetError, "Expected 5 >= 5\nto be falsy but was true") end - it "provides a failure message that 'Expected x not to be greater than or equal to y'" 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 + it "does not raise an exception when >= returns false" do SpecNegativeOperatorMatcher.new(4) >= 5 end end diff --git a/spec/mspec/spec/matchers/eql_spec.rb b/spec/mspec/spec/matchers/eql_spec.rb index 711ebdb679..f29e6976da 100644 --- a/spec/mspec/spec/matchers/eql_spec.rb +++ b/spec/mspec/spec/matchers/eql_spec.rb @@ -22,12 +22,12 @@ describe EqlMatcher do it "provides a useful failure message" do matcher = EqlMatcher.new("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 it "provides a useful negative failure message" do matcher = EqlMatcher.new(1) 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 diff --git a/spec/mspec/spec/matchers/equal_element_spec.rb b/spec/mspec/spec/matchers/equal_element_spec.rb index 45b8390364..06fae762c4 100644 --- a/spec/mspec/spec/matchers/equal_element_spec.rb +++ b/spec/mspec/spec/matchers/equal_element_spec.rb @@ -48,28 +48,28 @@ describe EqualElementMatcher do it "provides a useful failure message" do equal_element = EqualElementMatcher.new("A", {}, "Test") equal_element.matches?('').should be_false - equal_element.failure_message.should == [%{Expected ""\n}, %{to be a 'A' element with no attributes and "Test" as content}] + equal_element.failure_message.should == [%{Expected ""}, %{to be a 'A' element with no attributes and "Test" as content}] equal_element = EqualElementMatcher.new("A", {}, "") equal_element.matches?('Test').should be_false - equal_element.failure_message.should == [%{Expected "Test"\n}, %{to be a 'A' element with no attributes and no content}] + equal_element.failure_message.should == [%{Expected "Test"}, %{to be a 'A' element with no attributes and no content}] equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com") equal_element.matches?('Test').should be_false - equal_element.failure_message.should == [%{Expected "Test"\n}, %{to be a 'A' element with HREF="http://www.example.com" and any content}] + equal_element.failure_message.should == [%{Expected "Test"}, %{to be a 'A' element with HREF="http://www.example.com" and any content}] end it "provides a useful negative failure message" do equal_element = EqualElementMatcher.new("A", {}, "Test") equal_element.matches?('').should be_false - equal_element.negative_failure_message.should == [%{Expected ""\n}, %{not to be a 'A' element with no attributes and "Test" as content}] + equal_element.negative_failure_message.should == [%{Expected ""}, %{not to be a 'A' element with no attributes and "Test" as content}] equal_element = EqualElementMatcher.new("A", {}, "") equal_element.matches?('Test').should be_false - equal_element.negative_failure_message.should == [%{Expected "Test"\n}, %{not to be a 'A' element with no attributes and no content}] + equal_element.negative_failure_message.should == [%{Expected "Test"}, %{not to be a 'A' element with no attributes and no content}] equal_element = EqualElementMatcher.new("A", "HREF" => "http://www.example.com") equal_element.matches?('Test').should be_false - equal_element.negative_failure_message.should == [%{Expected "Test"\n}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}] + equal_element.negative_failure_message.should == [%{Expected "Test"}, %{not to be a 'A' element with HREF="http://www.example.com" and any content}] end end diff --git a/spec/mspec/spec/matchers/equal_spec.rb b/spec/mspec/spec/matchers/equal_spec.rb index ca7bf83fdd..a61432b750 100644 --- a/spec/mspec/spec/matchers/equal_spec.rb +++ b/spec/mspec/spec/matchers/equal_spec.rb @@ -21,12 +21,12 @@ describe EqualMatcher do it "provides a useful failure message" do matcher = EqualMatcher.new("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 it "provides a useful negative failure message" do matcher = EqualMatcher.new(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 diff --git a/spec/mspec/spec/matchers/raise_error_spec.rb b/spec/mspec/spec/matchers/raise_error_spec.rb index 28e1ea69a7..1ed794e0a9 100644 --- a/spec/mspec/spec/matchers/raise_error_spec.rb +++ b/spec/mspec/spec/matchers/raise_error_spec.rb @@ -111,7 +111,7 @@ describe RaiseErrorMatcher do 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 # was returned)"] + ["Expected ExpectedException (expected)", "but no exception was raised (#(#pretty_inspect raised #) was returned)"] end it "provides a useful negative failure message" do diff --git a/spec/mspec/spec/spec_helper.rb b/spec/mspec/spec/spec_helper.rb index 0d497f6627..a307eaf460 100644 --- a/spec/mspec/spec/spec_helper.rb +++ b/spec/mspec/spec/spec_helper.rb @@ -1,4 +1,4 @@ -require 'pp' +require 'mspec/utils/format' require 'mspec/helpers/io' require 'mspec/helpers/scratch' diff --git a/spec/mspec/tool/pull-latest-mspec-spec b/spec/mspec/tool/pull-latest-mspec-spec index 62c1f8fefa..67414ed8b8 100755 --- a/spec/mspec/tool/pull-latest-mspec-spec +++ b/spec/mspec/tool/pull-latest-mspec-spec @@ -15,5 +15,8 @@ rm -rf spec/ruby git clone --depth 1 https://github.com/ruby/spec.git spec/ruby commit=$(git -C spec/ruby log -n 1 --format='%h') 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 commit -m "Update to ruby/spec@${commit}"