diff options
Diffstat (limited to 'spec/mspec')
219 files changed, 5951 insertions, 4356 deletions
diff --git a/spec/mspec/.gitignore b/spec/mspec/.gitignore deleted file mode 100644 index 5c5ecd9731..0000000000 --- a/spec/mspec/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -pkg -*.rbc -*.iml -*.iws -*.ipr -*.sw? - -.rbx - -# ctags dir -/tags - -*.gem -.bundle -.config -.yardoc -InstalledFiles -_yardoc -coverage -doc/ -lib/bundler/man -rdoc -spec/reports -test/tmp -test/version_tmp -tmp diff --git a/spec/mspec/.rspec b/spec/mspec/.rspec new file mode 100644 index 0000000000..4e1e0d2f72 --- /dev/null +++ b/spec/mspec/.rspec @@ -0,0 +1 @@ +--color diff --git a/spec/mspec/.travis.yml b/spec/mspec/.travis.yml deleted file mode 100644 index 73f141d2ae..0000000000 --- a/spec/mspec/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -sudo: false -language: ruby -before_script: - # https://github.com/travis-ci/travis-ci/issues/8408 - - unset _JAVA_OPTIONS -script: - - bundle exec rspec -matrix: - include: - - rvm: 2.2.8 - - rvm: 2.3.5 - - rvm: 2.4.2 - - rvm: ruby-head - - jdk: oraclejdk8 - install: - - 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 - - bundle install diff --git a/spec/mspec/Gemfile b/spec/mspec/Gemfile index 3dc3c4145b..617a995cad 100644 --- a/spec/mspec/Gemfile +++ b/spec/mspec/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' -gem "rake", "~> 10.0" -gem "rspec", "~> 2.14.1" +gem "rake", "~> 12.3" +gem "rspec", "~> 3.0" diff --git a/spec/mspec/Gemfile.lock b/spec/mspec/Gemfile.lock index d07c04638b..cd39906044 100644 --- a/spec/mspec/Gemfile.lock +++ b/spec/mspec/Gemfile.lock @@ -1,24 +1,26 @@ GEM remote: https://rubygems.org/ specs: - diff-lcs (1.2.5) - rake (10.4.2) - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.8) - rspec-expectations (2.14.5) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.6) + diff-lcs (1.4.4) + rake (12.3.3) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-support (3.10.2) PLATFORMS java ruby DEPENDENCIES - rake (~> 10.0) - rspec (~> 2.14.1) - -BUNDLED WITH - 1.14.5 + rake (~> 12.3) + rspec (~> 3.0) diff --git a/spec/mspec/README.md b/spec/mspec/README.md index 18ca8fcdd3..94ab608031 100644 --- a/spec/mspec/README.md +++ b/spec/mspec/README.md @@ -1,14 +1,13 @@ -[](https://travis-ci.org/ruby/mspec) - ## Overview -MSpec is a specialized framework that is syntax-compatible with RSpec for -basic things like 'describe', 'it' blocks and 'before', 'after' actions. MSpec -contains additional features that assist in writing the RubySpecs used by -multiple Ruby implementations. +MSpec is a specialized framework that is syntax-compatible with RSpec 2 for +basic things like `describe`, `it` blocks and `before`, `after` actions. +MSpec contains additional features that assist in writing specs for +Ruby implementations in [ruby/spec](https://github.com/ruby/spec). MSpec attempts to use the simplest Ruby language features so that beginning -Ruby implementations can run the Ruby specs. +Ruby implementations can run the Ruby specs. For example, no file from the +standard library or RubyGems is necessary to run MSpec. MSpec is not intended as a replacement for RSpec. MSpec attempts to provide a subset of RSpec's features in some cases and a superset in others. It does not @@ -23,8 +22,6 @@ specs in a manner compatible with multiple Ruby implementations. 2. MSpec provides a different shared spec implementation specifically designed to ease writing specs for the numerous aliased methods in Ruby. - The MSpec shared spec implementation should not conflict with RSpec's own - shared behavior facility. 3. MSpec provides various helper methods to simplify some specs, for example, creating temporary file names. @@ -33,9 +30,13 @@ specs in a manner compatible with multiple Ruby implementations. configuration facility with a default project file and user-specific overrides. + 5. MSpec support "tagging", that is excluding specs known as failing on + a particular Ruby implementation, and automatically adding and removing tags + while running the specs. + ## Requirements -MSpec requires Ruby 2.2 or more recent. +MSpec requires Ruby 2.6 or more recent. ## Bundler @@ -52,10 +53,10 @@ To install the gem dependencies with Bundler, run the following: ruby -S bundle install ``` -## Running Specs +## Development 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: @@ -63,29 +64,21 @@ After installing the gem dependencies, the specs can be run as follows: ruby -S bundle exec rspec ``` -Or - -```bash -ruby -S rake -``` - To run an individual spec file, use the following example: ```bash ruby -S bundle exec rspec spec/helpers/ruby_exe_spec.rb ``` - ## Documentation -See http://ruby.github.io/rubyspec.github.io/ - +See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) in ruby/spec +for a list of matchers and how to use `mspec`. ## Source Code See https://github.com/ruby/mspec - ## License See the LICENSE in the source code. diff --git a/spec/mspec/Rakefile b/spec/mspec/Rakefile index 0e294cde8e..6a9de7a95e 100644 --- a/spec/mspec/Rakefile +++ b/spec/mspec/Rakefile @@ -1,4 +1,3 @@ -require 'bundler/gem_tasks' require 'bundler/setup' require 'rspec/core/rake_task' diff --git a/spec/mspec/bin/mspec b/spec/mspec/bin/mspec index f833257bb0..5bd753c06d 100755 --- a/spec/mspec/bin/mspec +++ b/spec/mspec/bin/mspec @@ -4,4 +4,4 @@ $:.unshift File.expand_path('../../lib', __FILE__) require 'mspec/commands/mspec' -MSpecMain.main +MSpecMain.main(false) 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/mkspec.rb b/spec/mspec/lib/mspec/commands/mkspec.rb index 7a943aa1fe..f75e683b19 100755..100644 --- a/spec/mspec/lib/mspec/commands/mkspec.rb +++ b/spec/mspec/lib/mspec/commands/mkspec.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'rbconfig' require 'mspec/version' require 'mspec/utils/options' @@ -19,7 +17,7 @@ class MkSpec @map = NameMap.new true end - def options(argv=ARGV) + def options(argv = ARGV) options = MSpecOptions.new "mkspec [options]", 32 options.on("-c", "--constant", "CONSTANT", @@ -75,7 +73,7 @@ class MkSpec parents = '../' * (sub.split('/').length + 1) File.open(file, 'w') do |f| - f.puts "require File.expand_path('../#{parents}spec_helper', __FILE__)" + f.puts "require_relative '#{parents}spec_helper'" config[:requires].each do |lib| f.puts "require '#{lib}'" end @@ -95,7 +93,9 @@ class MkSpec def write_spec(file, meth, exists) if exists - out = `#{ruby} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e '#{meth}' #{file}` + command = "#{RbConfig.ruby} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e '#{meth}' #{file}" + puts "$ #{command}" if $DEBUG + out = `#{command}` return if out.include?(meth) end @@ -133,18 +133,6 @@ EOS end end - ## - # Determine and return the path of the ruby executable. - - def ruby - ruby = File.join(RbConfig::CONFIG['bindir'], - RbConfig::CONFIG['ruby_install_name']) - - ruby.gsub! File::SEPARATOR, File::ALT_SEPARATOR if File::ALT_SEPARATOR - - return ruby - end - def self.main ENV['MSPEC_RUNNER'] = '1' diff --git a/spec/mspec/lib/mspec/commands/mspec-ci.rb b/spec/mspec/lib/mspec/commands/mspec-ci.rb index cb0193f42d..8951572f69 100644 --- a/spec/mspec/lib/mspec/commands/mspec-ci.rb +++ b/spec/mspec/lib/mspec/commands/mspec-ci.rb @@ -1,14 +1,10 @@ -#!/usr/bin/env ruby - -$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' class MSpecCI < MSpecScript - def options(argv=ARGV) + def options(argv = ARGV) options = MSpecOptions.new "mspec ci [options] (FILE|DIRECTORY|GLOB)+", 30, config options.doc " Ask yourself:" @@ -22,8 +18,10 @@ class MSpecCI < MSpecScript options.chdir options.prefix options.configure { |f| load f } + 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-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb index 249f9f5771..0fb338fa23 100644 --- a/spec/mspec/lib/mspec/commands/mspec-run.rb +++ b/spec/mspec/lib/mspec/commands/mspec-run.rb @@ -1,7 +1,3 @@ -#!/usr/bin/env ruby - -$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' @@ -14,7 +10,7 @@ class MSpecRun < MSpecScript config[:files] = [] end - def options(argv=ARGV) + def options(argv = ARGV) options = MSpecOptions.new "mspec run [options] (FILE|DIRECTORY|GLOB)+", 30, config options.doc " Ask yourself:" @@ -32,10 +28,12 @@ class MSpecRun < MSpecScript options.chdir options.prefix options.configure { |f| load f } + options.env options.randomize options.repeat options.pretend options.interrupt + options.timeout options.doc "\n How to modify the guard behavior" options.unguarded @@ -51,6 +49,9 @@ class MSpecRun < MSpecScript options.doc "\n When to perform it" options.action_filters + options.doc "\n Launchable" + options.launchable + options.doc "\n Help!" options.debug options.version MSpec::VERSION diff --git a/spec/mspec/lib/mspec/commands/mspec-tag.rb b/spec/mspec/lib/mspec/commands/mspec-tag.rb index 8bc3382e91..9ce9f048c6 100644 --- a/spec/mspec/lib/mspec/commands/mspec-tag.rb +++ b/spec/mspec/lib/mspec/commands/mspec-tag.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' @@ -15,7 +13,7 @@ class MSpecTag < MSpecScript config[:ltags] = [] end - def options(argv=ARGV) + def options(argv = ARGV) options = MSpecOptions.new "mspec tag [options] (FILE|DIRECTORY|GLOB)+", 30, config options.doc " Ask yourself:" @@ -33,6 +31,7 @@ class MSpecTag < MSpecScript options.pretend options.unguarded options.interrupt + options.timeout options.doc "\n How to display their output" options.formatters @@ -113,6 +112,7 @@ class MSpecTag < MSpecScript MSpec.register_mode :pretend MSpec.register_mode :unguarded config[:formatter] = false + config[:xtags] = [] else raise ArgumentError, "No recognized action given" end diff --git a/spec/mspec/lib/mspec/commands/mspec.rb b/spec/mspec/lib/mspec/commands/mspec.rb index 6cb1e87a58..a9d94ca354 100755..100644 --- a/spec/mspec/lib/mspec/commands/mspec.rb +++ b/spec/mspec/lib/mspec/commands/mspec.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' @@ -21,10 +19,11 @@ class MSpecMain < MSpecScript config[:launch] = [] end - def options(argv=ARGV) + def options(argv = ARGV) config[:command] = argv.shift if ["ci", "run", "tag"].include?(argv[0]) options = MSpecOptions.new "mspec [COMMAND] [options] (FILE|DIRECTORY|GLOB)+", 30, config + @options = options options.doc " The mspec command sets up and invokes the sub-commands" options.doc " (see below) to enable, for instance, running the specs" @@ -37,11 +36,6 @@ class MSpecMain < MSpecScript options.targets - options.on("--warnings", "Don't suppress warnings") do - config[:flags] << '-w' - ENV['OUTPUT_WARNINGS'] = '1' - end - options.on("-j", "--multi", "Run multiple (possibly parallel) subprocesses") do config[:multi] = true end @@ -89,72 +83,12 @@ class MSpecMain < MSpecScript def register; end def multi_exec(argv) - MSpec.register_files @files - require 'mspec/runner/formatters/multi' - formatter = MultiFormatter.new - if config[:formatter] - warn "formatter options is ignored due to multi option" - end + formatter = config_formatter.extend(MultiFormatter) - output_files = [] + require 'mspec/runner/parallel' processes = cores(@files.size) - children = processes.times.map { |i| - name = tmp "mspec-multi-#{i}" - output_files << name - - env = { - "SPEC_TEMP_DIR" => "rubyspec_temp_#{i}", - "MSPEC_MULTI" => i.to_s - } - command = argv + ["-fy", "-o", name] - $stderr.puts "$ #{command.join(' ')}" if $MSPEC_DEBUG - IO.popen([env, *command, close_others: false], "rb+") - } - - puts children.map { |child| child.gets }.uniq - formatter.start - last_files = {} - - until @files.empty? - IO.select(children)[0].each { |io| - reply = io.read(1) - case reply - when '.' - formatter.unload - when nil - raise "Worker died!" - else - while chunk = (io.read_nonblock(4096) rescue nil) - reply += chunk - end - reply.chomp!('.') - msg = "A child mspec-run process printed unexpected output on STDOUT" - if last_file = last_files[io] - msg += " while running #{last_file}" - end - abort "\n#{msg}: #{reply.inspect}" - end - - unless @files.empty? - file = @files.shift - last_files[io] = file - io.puts file - end - } - end - - success = true - children.each { |child| - child.puts "QUIT" - _pid, status = Process.wait2(child.pid) - success &&= status.success? - child.close - } - - formatter.aggregate_results(output_files) - formatter.finish - success + ParallelRunner.new(@files, processes, formatter, argv).run end def run @@ -170,8 +104,9 @@ class MSpecMain < MSpecScript if config[:multi] exit multi_exec(argv) else - $stderr.puts "$ #{argv.join(' ')}" - $stderr.flush + log = config[:options].include?('--error-output') ? $stdout : $stderr + log.puts "$ #{argv.join(' ')}" + log.flush exec(*argv, close_others: false) end end diff --git a/spec/mspec/lib/mspec/expectations/expectations.rb b/spec/mspec/lib/mspec/expectations/expectations.rb index cfdc2b63a3..09852ab557 100644 --- a/spec/mspec/lib/mspec/expectations/expectations.rb +++ b/spec/mspec/lib/mspec/expectations/expectations.rb @@ -7,15 +7,33 @@ class SpecExpectationNotFoundError < StandardError end end +class SkippedSpecError < StandardError +end + class SpecExpectation def self.fail_with(expected, actual) 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 + + def self.fail_single_arg_predicate(receiver, predicate, arg, result, expectation) + fail_predicate(receiver, predicate, [arg], nil, result, expectation) end end diff --git a/spec/mspec/lib/mspec/expectations/should.rb b/spec/mspec/lib/mspec/expectations/should.rb index f6d83053f5..c1790e0ac8 100644 --- a/spec/mspec/lib/mspec/expectations/should.rb +++ b/spec/mspec/lib/mspec/expectations/should.rb @@ -1,29 +1,41 @@ class Object NO_MATCHER_GIVEN = Object.new - def should(matcher = NO_MATCHER_GIVEN) + def should(matcher = NO_MATCHER_GIVEN, &block) MSpec.expectation - MSpec.actions :expectation, MSpec.current.state - unless matcher.equal? NO_MATCHER_GIVEN + state = MSpec.current.state + raise "should outside example" unless state + MSpec.actions :expectation, state + + if NO_MATCHER_GIVEN.equal?(matcher) + SpecPositiveOperatorMatcher.new(self) + else + # The block was given to #should syntactically, but it was intended for a matcher like #raise_error + matcher.block = block if block + 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) + def should_not(matcher = NO_MATCHER_GIVEN, &block) MSpec.expectation - MSpec.actions :expectation, MSpec.current.state - unless matcher.equal? NO_MATCHER_GIVEN + state = MSpec.current.state + raise "should_not outside example" unless state + MSpec.actions :expectation, state + + if NO_MATCHER_GIVEN.equal?(matcher) + SpecNegativeOperatorMatcher.new(self) + else + # The block was given to #should_not syntactically, but it was intended for the matcher + matcher.block = block if block + 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/guards/bug.rb b/spec/mspec/lib/mspec/guards/bug.rb index b1bfc6413e..a6af0ef964 100644 --- a/spec/mspec/lib/mspec/guards/bug.rb +++ b/spec/mspec/lib/mspec/guards/bug.rb @@ -1,28 +1,29 @@ require 'mspec/guards/version' class BugGuard < VersionGuard - def initialize(bug, version) + def initialize(bug, requirement) @bug = bug - if String === version + if String === requirement MSpec.deprecate "ruby_bug with a single version", 'an exclusive range ("2.1"..."2.3")' - @version = SpecVersion.new version, true + super(FULL_RUBY_VERSION, requirement) + @requirement = SpecVersion.new requirement, true else - super(version) + super(FULL_RUBY_VERSION, requirement) end - @parameters = [@bug, @version] end def match? return false if MSpec.mode? :no_ruby_bug return false unless PlatformGuard.standard? - if Range === @version + + if Range === @requirement super else - FULL_RUBY_VERSION <= @version + FULL_RUBY_VERSION <= @requirement end end end -def ruby_bug(bug, version, &block) - BugGuard.new(bug, version).run_unless(:ruby_bug, &block) +def ruby_bug(bug, requirement, &block) + BugGuard.new(bug, requirement).run_unless(:ruby_bug, &block) end diff --git a/spec/mspec/lib/mspec/guards/conflict.rb b/spec/mspec/lib/mspec/guards/conflict.rb index 7a27671c1e..4930e5734d 100644 --- a/spec/mspec/lib/mspec/guards/conflict.rb +++ b/spec/mspec/lib/mspec/guards/conflict.rb @@ -1,6 +1,12 @@ require 'mspec/guards/guard' +require 'mspec/utils/deprecate' class ConflictsGuard < SpecGuard + def initialize(*args) + MSpec.deprecate 'conflicts_with', 'guard -> { condition } do' + super(*args) + end + def match? # Always convert constants to symbols regardless of version. constants = Object.constants.map { |x| x.to_sym } diff --git a/spec/mspec/lib/mspec/guards/feature.rb b/spec/mspec/lib/mspec/guards/feature.rb index 30984e0cc5..d4c6dd1cde 100644 --- a/spec/mspec/lib/mspec/guards/feature.rb +++ b/spec/mspec/lib/mspec/guards/feature.rb @@ -39,3 +39,7 @@ end def with_feature(*features, &block) FeatureGuard.new(*features).run_if(:with_feature, &block) end + +def without_feature(*features, &block) + FeatureGuard.new(*features).run_unless(:without_feature, &block) +end diff --git a/spec/mspec/lib/mspec/guards/guard.rb b/spec/mspec/lib/mspec/guards/guard.rb index 322a08145d..3a6372a660 100644 --- a/spec/mspec/lib/mspec/guards/guard.rb +++ b/spec/mspec/lib/mspec/guards/guard.rb @@ -111,7 +111,7 @@ class SpecGuard def add(example) record example.description - MSpec.retrieve(:formatter).tally.counter.guards! + MSpec.formatter.tally.counter.guards! end def unregister diff --git a/spec/mspec/lib/mspec/guards/platform.rb b/spec/mspec/lib/mspec/guards/platform.rb index 96176b8753..fadd8d75ef 100644 --- a/spec/mspec/lib/mspec/guards/platform.rb +++ b/spec/mspec/lib/mspec/guards/platform.rb @@ -6,10 +6,8 @@ class PlatformGuard < SpecGuard case name when :rubinius RUBY_ENGINE.start_with?('rbx') - when :ruby, :jruby, :truffleruby, :ironruby, :macruby, :maglev, :topaz, :opal - RUBY_ENGINE.start_with?(name.to_s) else - raise "unknown implementation #{name}" + RUBY_ENGINE.start_with?(name.to_s) end end end @@ -18,20 +16,23 @@ class PlatformGuard < SpecGuard implementation? :ruby end - HOST_OS = begin + PLATFORM = if RUBY_ENGINE == "jruby" require 'rbconfig' - RbConfig::CONFIG['host_os'] || RUBY_PLATFORM - rescue LoadError + "#{RbConfig::CONFIG['host_cpu']}-#{RbConfig::CONFIG['host_os']}" + else RUBY_PLATFORM - end.downcase + end def self.os?(*oses) oses.any? do |os| raise ":java is not a valid OS" if os == :java - if os == :windows - HOST_OS =~ /(mswin|mingw)/ + case os + when :windows + PLATFORM =~ /(mswin|mingw)/ + when :wsl + wsl? else - HOST_OS.include?(os.to_s) + PLATFORM.include?(os.to_s) end end end @@ -40,8 +41,48 @@ class PlatformGuard < SpecGuard os?(:windows) end + def self.wasi? + os?(:wasi) + end + + def self.wsl? + if defined?(@wsl_p) + @wsl_p + else + @wsl_p = `uname -r`.match?(/microsoft/i) + end + end + + # In bits + WORD_SIZE = 1.size * 8 + deprecate_constant :WORD_SIZE + + # In bits + POINTER_SIZE = begin + require 'rbconfig/sizeof' + RbConfig::SIZEOF["void*"] * 8 + rescue LoadError + [0].pack('j').size * 8 + end + + # In bits + C_LONG_SIZE = if defined?(RbConfig::SIZEOF[]) + RbConfig::SIZEOF["long"] * 8 + else + [0].pack('l!').size * 8 + end + def self.wordsize?(size) - size == 8 * 1.size + warn "#wordsize? is deprecated, use #c_long_size?" + size == WORD_SIZE + end + + def self.pointer_size?(size) + size == POINTER_SIZE + end + + def self.c_long_size?(size) + size == C_LONG_SIZE end def initialize(*args) @@ -59,8 +100,13 @@ class PlatformGuard < SpecGuard case key when :os match &&= PlatformGuard.os?(*value) + when :pointer_size + match &&= PlatformGuard.pointer_size? value when :wordsize + warn ":wordsize is deprecated, use :c_long_size" match &&= PlatformGuard.wordsize? value + when :c_long_size + match &&= PlatformGuard::c_long_size? value end end match diff --git a/spec/mspec/lib/mspec/guards/superuser.rb b/spec/mspec/lib/mspec/guards/superuser.rb index e92ea7e862..24daf9b26c 100644 --- a/spec/mspec/lib/mspec/guards/superuser.rb +++ b/spec/mspec/lib/mspec/guards/superuser.rb @@ -6,10 +6,20 @@ class SuperUserGuard < SpecGuard end end +class RealSuperUserGuard < SpecGuard + def match? + Process.uid == 0 + end +end + def as_superuser(&block) SuperUserGuard.new.run_if(:as_superuser, &block) end +def as_real_superuser(&block) + RealSuperUserGuard.new.run_if(:as_real_superuser, &block) +end + def as_user(&block) SuperUserGuard.new.run_unless(:as_user, &block) end diff --git a/spec/mspec/lib/mspec/guards/version.rb b/spec/mspec/lib/mspec/guards/version.rb index cb08fdac73..f5ea1988ae 100644 --- a/spec/mspec/lib/mspec/guards/version.rb +++ b/spec/mspec/lib/mspec/guards/version.rb @@ -5,33 +5,68 @@ require 'mspec/guards/guard' class VersionGuard < SpecGuard FULL_RUBY_VERSION = SpecVersion.new SpecGuard.ruby_version(:full) - def initialize(version) - case version + def initialize(version, requirement) + version = SpecVersion.new(version) unless SpecVersion === version + @version = version + + case requirement when String - @version = SpecVersion.new version + @requirement = SpecVersion.new requirement when Range - MSpec.deprecate "an empty version range end", 'a specific version' if version.end.empty? - a = SpecVersion.new version.begin - b = SpecVersion.new version.end - unless version.exclude_end? + MSpec.deprecate "an empty version range end", 'a specific version' if requirement.end.empty? + a = SpecVersion.new requirement.begin + b = SpecVersion.new requirement.end + unless requirement.exclude_end? MSpec.deprecate "ruby_version_is with an inclusive range", 'an exclusive range ("2.1"..."2.3")' end - @version = version.exclude_end? ? a...b : a..b + @requirement = requirement.exclude_end? ? a...b : a..b else - raise "version must be a String or Range but was a #{version.class}" + raise "version must be a String or Range but was a #{requirement.class}" end - @parameters = [version] + super(@version, @requirement) end def match? - if Range === @version - @version.include? FULL_RUBY_VERSION + if Range === @requirement + @requirement.include? @version + else + @version >= @requirement + end + end + + @kernel_version = nil + def self.kernel_version + if @kernel_version + @kernel_version else - FULL_RUBY_VERSION >= @version + if v = RUBY_PLATFORM[/darwin(\d+)/, 1] # build time version + uname = v + else + begin + require 'etc' + etc = true + rescue LoadError + etc = false + end + if etc and Etc.respond_to?(:uname) + uname = Etc.uname.fetch(:release) + else + uname = `uname -r`.chomp + end + end + @kernel_version = uname end end end -def ruby_version_is(*args, &block) - VersionGuard.new(*args).run_if(:ruby_version_is, &block) +def version_is(base_version, requirement, &block) + VersionGuard.new(base_version, requirement).run_if(:version_is, &block) +end + +def ruby_version_is(requirement, &block) + VersionGuard.new(VersionGuard::FULL_RUBY_VERSION, requirement).run_if(:ruby_version_is, &block) +end + +def kernel_version_is(requirement, &block) + VersionGuard.new(VersionGuard.kernel_version, requirement).run_if(:kernel_version_is, &block) end diff --git a/spec/mspec/lib/mspec/helpers/datetime.rb b/spec/mspec/lib/mspec/helpers/datetime.rb index 1520b971ea..84ac86b686 100644 --- a/spec/mspec/lib/mspec/helpers/datetime.rb +++ b/spec/mspec/lib/mspec/helpers/datetime.rb @@ -6,7 +6,7 @@ # # Possible keys are: # :year, :month, :day, :hour, :minute, :second, :offset and :sg. -def new_datetime(opts={}) +def new_datetime(opts = {}) require 'date' value = { @@ -25,6 +25,7 @@ def new_datetime(opts={}) end def with_timezone(name, offset = nil, daylight_saving_zone = "") + skip "WASI doesn't have TZ concept" if PlatformGuard.wasi? zone = name.dup if offset diff --git a/spec/mspec/lib/mspec/helpers/flunk.rb b/spec/mspec/lib/mspec/helpers/flunk.rb index 68fb3cadac..84fb3ab39c 100644 --- a/spec/mspec/lib/mspec/helpers/flunk.rb +++ b/spec/mspec/lib/mspec/helpers/flunk.rb @@ -1,3 +1,3 @@ -def flunk(msg="This example is a failure") +def flunk(msg = "This example is a failure") SpecExpectation.fail_with "Failed:", msg end diff --git a/spec/mspec/lib/mspec/helpers/fs.rb b/spec/mspec/lib/mspec/helpers/fs.rb index fb2c0f702c..67453eb302 100644 --- a/spec/mspec/lib/mspec/helpers/fs.rb +++ b/spec/mspec/lib/mspec/helpers/fs.rb @@ -1,12 +1,6 @@ # Copies a file def cp(source, dest) - File.open(dest, "wb") do |d| - File.open(source, "rb") do |s| - while data = s.read(1024) - d.write data - end - end - end + IO.copy_stream source, dest end # Creates each directory in path that does not exist. @@ -61,7 +55,7 @@ end # Creates a file +name+. Creates the directory for +name+ # if it does not exist. -def touch(name, mode="w") +def touch(name, mode = "w") mkdir_p File.dirname(name) File.open(name, mode) do |f| diff --git a/spec/mspec/lib/mspec/helpers/io.rb b/spec/mspec/lib/mspec/helpers/io.rb index 57dc0d53a4..2ad14f47a1 100644 --- a/spec/mspec/lib/mspec/helpers/io.rb +++ b/spec/mspec/lib/mspec/helpers/io.rb @@ -7,7 +7,7 @@ class IOStub end def write(*str) - self << str.join + self << str.join('') end def << str @@ -16,7 +16,7 @@ class IOStub end def print(*str) - write(str.join + $\.to_s) + write(str.join('') + $\.to_s) end def method_missing(name, *args, &block) @@ -64,9 +64,7 @@ end # Creates a "bare" file descriptor (i.e. one that is not associated # with any Ruby object). The file descriptor can safely be passed # to IO.new without creating a Ruby object alias to the fd. -def new_fd(name, mode="w:utf-8") - mode = options_or_mode(mode) - +def new_fd(name, mode = "w:utf-8") if mode.kind_of? Hash if mode.key? :mode mode = mode[:mode] @@ -75,37 +73,15 @@ def new_fd(name, mode="w:utf-8") end end - IO.sysopen name, fmode(mode) + IO.sysopen name, mode 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, options_or_mode(mode)), options_or_mode(mode) -end - -# This helper simplifies passing file access modes regardless of -# whether the :encoding feature is enabled. Only the access specifier -# itself will be returned if :encoding is not enabled. Otherwise, -# the full mode string will be returned (i.e. the helper is a no-op). -def fmode(mode) - if FeatureGuard.enabled? :encoding - mode - else - mode.split(':').first - end -end - -# This helper simplifies passing file access modes or options regardless of -# whether the :encoding feature is enabled. Only the access specifier itself -# will be returned if :encoding is not enabled. Otherwise, the full mode -# string or option will be returned (i.e. the helper is a no-op). -def options_or_mode(oom) - return fmode(oom) if oom.kind_of? String - - if FeatureGuard.enabled? :encoding - oom +def new_io(name, mode = "w:utf-8") + if Hash === mode # Avoid kwargs warnings on Ruby 2.7+ + File.new(name, **mode) else - fmode(oom[:mode] || "r:utf-8") + File.new(name, mode) end end diff --git a/spec/mspec/lib/mspec/helpers/numeric.rb b/spec/mspec/lib/mspec/helpers/numeric.rb index 312aafae35..0b47855cd2 100644 --- a/spec/mspec/lib/mspec/helpers/numeric.rb +++ b/spec/mspec/lib/mspec/helpers/numeric.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'mspec/guards/platform' def nan_value @@ -8,8 +9,18 @@ def infinity_value 1/0.0 end -def bignum_value(plus=0) - 0x8000_0000_0000_0000 + plus +def bignum_value(plus = 0) + # Must be >= fixnum_max + 2, so -bignum_value is < fixnum_min + # A fixed value has the advantage to be the same numeric value for all Rubies and is much easier to spec + (2**64) + plus +end + +def max_long + 2**(PlatformGuard::C_LONG_SIZE - 1) - 1 +end + +def min_long + -(2**(PlatformGuard::C_LONG_SIZE - 1)) end # This is a bit hairy, but we need to be able to write specs that cover the @@ -18,7 +29,24 @@ end # specs based on the relationship between values rather than specific # values. if PlatformGuard.standard? or PlatformGuard.implementation? :topaz - if PlatformGuard.wordsize? 32 + limits_available = begin + require 'rbconfig/sizeof' + defined?(RbConfig::LIMITS.[]) && ['FIXNUM_MAX', 'FIXNUM_MIN'].all? do |key| + Integer === RbConfig::LIMITS[key] + end + rescue LoadError + false + end + + if limits_available + def fixnum_max + RbConfig::LIMITS['FIXNUM_MAX'] + end + + def fixnum_min + RbConfig::LIMITS['FIXNUM_MIN'] + end + elsif PlatformGuard.c_long_size? 32 def fixnum_max (2**30) - 1 end @@ -26,7 +54,7 @@ if PlatformGuard.standard? or PlatformGuard.implementation? :topaz def fixnum_min -(2**30) end - elsif PlatformGuard.wordsize? 64 + elsif PlatformGuard.c_long_size? 64 def fixnum_max (2**62) - 1 end diff --git a/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/spec/mspec/lib/mspec/helpers/ruby_exe.rb index f74ed014ce..2e499d6f9a 100644 --- a/spec/mspec/lib/mspec/helpers/ruby_exe.rb +++ b/spec/mspec/lib/mspec/helpers/ruby_exe.rb @@ -2,11 +2,12 @@ require 'mspec/guards/platform' require 'mspec/helpers/tmp' # The ruby_exe helper provides a wrapper for invoking the -# same Ruby interpreter with the same falgs as the one running +# same Ruby interpreter with the same flags as the one running # the specs and getting the output from running the code. +# # If +code+ is a file that exists, it will be run. -# Otherwise, +code+ should be Ruby code that will be run with -# the -e command line option. For example: +# Otherwise, +code+ will be written to a temporary file and be run. +# For example: # # ruby_exe('path/to/some/file.rb') # @@ -14,27 +15,24 @@ require 'mspec/helpers/tmp' # # `#{RUBY_EXE} 'path/to/some/file.rb'` # -# while -# -# ruby_exe('puts "hello, world."') -# -# will be executed as -# -# `#{RUBY_EXE} -e 'puts "hello, world."'` +# The ruby_exe helper also accepts an options hash with four +# keys: :options, :args :env and :exception. # -# The ruby_exe helper also accepts an options hash with three -# keys: :options, :args and :env. For example: +# For example: # # ruby_exe('file.rb', :options => "-w", -# :args => "> file.txt", +# :args => "arg1 arg2", # :env => { :FOO => "bar" }) # # will be executed as # -# `#{RUBY_EXE} -w #{'file.rb'} > file.txt` +# `#{RUBY_EXE} -w file.rb arg1 arg2` # # with access to ENV["FOO"] with value "bar". # +# When `exception: false` and Ruby command fails then exception will not be +# raised. +# # If +nil+ is passed for the first argument, the command line # will be built only from the options hash. # @@ -49,38 +47,18 @@ require 'mspec/helpers/tmp' # The RUBY_EXE constant is setup by mspec automatically # and is used by ruby_exe and ruby_cmd. The mspec runner script # will set ENV['RUBY_EXE'] to the name of the executable used -# to invoke the mspec-run script. The value of RUBY_EXE will be -# constructed as follows: -# -# 1. the value of ENV['RUBY_EXE'] -# 2. an explicit value based on RUBY_ENGINE -# 3. cwd/(RUBY_ENGINE + $(EXEEXT) || $(exeext) || '') -# 4. $(bindir)/$(RUBY_INSTALL_NAME) +# to invoke the mspec-run script. # # The value will only be used if the file exists and is executable. -# The flags will then be appended to the resulting value. -# -# These 4 ways correspond to the following scenarios: -# -# 1. Using the MSpec runner scripts, the name of the -# executable is explicitly passed by ENV['RUBY_EXE'] -# so there is no ambiguity. -# -# Otherwise, if using RSpec (or something else) -# -# 2. Running the specs while developing an alternative -# Ruby implementation. This explicitly names the -# executable in the development directory based on -# the value of RUBY_ENGINE. -# 3. Running the specs within the source directory for -# some implementation. (E.g. a local build directory.) -# 4. Running the specs against some installed Ruby -# implementation. +# The flags will then be appended to the resulting value, such that +# the RUBY_EXE constant contains both the executable and the flags. # # Additionally, the flags passed to mspec # (with -T on the command line or in the config with set :flags) # will be appended to RUBY_EXE so that the interpreter # is always called with those flags. +# +# Failure of a Ruby command leads to raising exception by default. def ruby_exe_options(option) case option @@ -101,12 +79,12 @@ def ruby_exe_options(option) end when :name require 'rbconfig' - bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '') + bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || '') File.join(".", bin) when :install_name require 'rbconfig' bin = RbConfig::CONFIG["RUBY_INSTALL_NAME"] || RbConfig::CONFIG["ruby_install_name"] - bin << (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '') + bin << (RbConfig::CONFIG['EXEEXT'] || '') File.join(RbConfig::CONFIG['bindir'], bin) end end @@ -129,7 +107,13 @@ def resolve_ruby_exe raise Exception, "Unable to find a suitable ruby executable." end +unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE + RUBY_EXE = resolve_ruby_exe +end + def ruby_exe(code = :not_given, opts = {}) + skip "WASI doesn't provide subprocess" if PlatformGuard.wasi? + if opts[:dir] raise "ruby_exe(..., dir: dir) is no longer supported, use Dir.chdir" end @@ -153,10 +137,47 @@ def ruby_exe(code = :not_given, opts = {}) code = tmpfile end + expected_status = opts.fetch(:exit_status, 0) + begin - platform_is_not :opal do - `#{ruby_cmd(code, opts)}` + command = ruby_cmd(code, opts) + + # Try to avoid the extra shell for 2>&1 + # This is notably useful for TimeoutAction which can then signal the ruby subprocess and not the shell + popen_options = [] + if command.end_with?(' 2>&1') + command = command[0...-5] + popen_options = [{ err: [:child, :out] }] end + + output = IO.popen(command, *popen_options) do |io| + pid = io.pid + MSpec.subprocesses << pid + begin + io.read + ensure + MSpec.subprocesses.delete(pid) + end + end + + status = Process.last_status + + exit_status = if status.exited? + status.exitstatus + elsif status.signaled? + signame = Signal.signame status.termsig + raise "No signal name?" unless signame + :"SIG#{signame}" + else + raise SpecExpectationNotMetError, "#{exit_status.inspect} is neither exited? nor signaled?" + end + if exit_status != expected_status + formatted_output = output.lines.map { |line| " #{line}" }.join + raise SpecExpectationNotMetError, + "Expected exit status is #{expected_status.inspect} but actual is #{exit_status.inspect} for command ruby_exe(#{command.inspect})\nOutput:\n#{formatted_output}" + end + + output ensure saved_env.each { |key, value| ENV[key] = value } env.keys.each do |key| @@ -178,9 +199,7 @@ def ruby_cmd(code, opts = {}) body = "-e #{code.inspect}" end - [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ') -end - -unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE - RUBY_EXE = resolve_ruby_exe + command = [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ') + STDERR.puts "\nruby_cmd: #{command}" if ENV["DEBUG_MSPEC_RUBY_CMD"] == "true" + command end diff --git a/spec/mspec/lib/mspec/helpers/scratch.rb b/spec/mspec/lib/mspec/helpers/scratch.rb index a6b0c02748..0da3315cd8 100644 --- a/spec/mspec/lib/mspec/helpers/scratch.rb +++ b/spec/mspec/lib/mspec/helpers/scratch.rb @@ -14,4 +14,8 @@ module ScratchPad def self.recorded @record end + + def self.inspect + "<ScratchPad @record=#{@record.inspect}>" + end end diff --git a/spec/mspec/lib/mspec/helpers/tmp.rb b/spec/mspec/lib/mspec/helpers/tmp.rb index 4e1273dcfe..e903dd9f50 100644 --- a/spec/mspec/lib/mspec/helpers/tmp.rb +++ b/spec/mspec/lib/mspec/helpers/tmp.rb @@ -3,11 +3,16 @@ # should clean up any temporary files created so that the temp # directory is empty when the process exits. -SPEC_TEMP_DIR = File.expand_path(ENV["SPEC_TEMP_DIR"] || "rubyspec_temp") +SPEC_TEMP_DIR_PID = Process.pid -SPEC_TEMP_UNIQUIFIER = "0" +if spec_temp_dir = ENV["SPEC_TEMP_DIR"] + spec_temp_dir = File.realdirpath(spec_temp_dir) +else + spec_temp_dir = "#{File.realpath(Dir.pwd)}/rubyspec_temp/#{SPEC_TEMP_DIR_PID}" +end +SPEC_TEMP_DIR = spec_temp_dir -SPEC_TEMP_DIR_PID = Process.pid +SPEC_TEMP_UNIQUIFIER = +"0" at_exit do begin @@ -30,12 +35,26 @@ all specs are cleaning up temporary files: end end -def tmp(name, uniquify=true) - Dir.mkdir SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR +def tmp(name, uniquify = true) + if Dir.exist? SPEC_TEMP_DIR + stat = File.stat(SPEC_TEMP_DIR) + if stat.world_writable? and !stat.sticky? + raise ArgumentError, "SPEC_TEMP_DIR (#{SPEC_TEMP_DIR}) is world writable but not sticky" + end + else + platform_is_not :windows do + umask = File.umask + if (umask & 0002) == 0 # o+w + raise ArgumentError, "File.umask #=> #{umask.to_s(8)} (world-writable)" + end + end + mkdir_p SPEC_TEMP_DIR + end if uniquify and !name.empty? slash = name.rindex "/" index = slash ? slash + 1 : 0 + name = +name name.insert index, "#{SPEC_TEMP_UNIQUIFIER.succ!}-" end diff --git a/spec/mspec/lib/mspec/helpers/warning.rb b/spec/mspec/lib/mspec/helpers/warning.rb index 9e093074e5..e3d72b78bd 100644 --- a/spec/mspec/lib/mspec/helpers/warning.rb +++ b/spec/mspec/lib/mspec/helpers/warning.rb @@ -1,3 +1,7 @@ +require 'mspec/guards/version' + +# You might be looking for #silence_warnings, use #suppress_warning instead. +# MSpec calls it #suppress_warning for consistency with EnvUtil.suppress_warning in CRuby test/. def suppress_warning verbose = $VERBOSE $VERBOSE = nil @@ -5,3 +9,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.rb b/spec/mspec/lib/mspec/matchers.rb index 8eab73198a..356e4a9f32 100644 --- a/spec/mspec/lib/mspec/matchers.rb +++ b/spec/mspec/lib/mspec/matchers.rb @@ -25,6 +25,7 @@ require 'mspec/matchers/have_protected_instance_method' require 'mspec/matchers/have_public_instance_method' require 'mspec/matchers/have_singleton_method' require 'mspec/matchers/include' +require 'mspec/matchers/include_any_of' require 'mspec/matchers/infinity' require 'mspec/matchers/match_yaml' require 'mspec/matchers/raise_error' @@ -33,3 +34,4 @@ require 'mspec/matchers/output_to_fd' require 'mspec/matchers/respond_to' require 'mspec/matchers/signed_zero' require 'mspec/matchers/block_caller' +require 'mspec/matchers/skip' diff --git a/spec/mspec/lib/mspec/matchers/base.rb b/spec/mspec/lib/mspec/matchers/base.rb index fc2d36c84a..3534520d88 100644 --- a/spec/mspec/lib/mspec/matchers/base.rb +++ b/spec/mspec/lib/mspec/matchers/base.rb @@ -10,98 +10,86 @@ 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}") + result = @actual == expected + unless result + ::SpecExpectation.fail_single_arg_predicate(@actual, :==, expected, result, "to be truthy") end end - def <(expected) - unless @actual < expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to be less than #{expected.pretty_inspect}") + def !=(expected) + result = @actual != expected + unless result + ::SpecExpectation.fail_single_arg_predicate(@actual, :!=, expected, result, "to be truthy") end end - def <=(expected) - unless @actual <= expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to be less than or equal to #{expected.pretty_inspect}") + def equal?(expected) + result = @actual.equal?(expected) + unless result + ::SpecExpectation.fail_single_arg_predicate(@actual, :equal?, expected, result, "to be truthy") end end - def >(expected) - unless @actual > expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "to be greater than #{expected.pretty_inspect}") + def raise(exception = ::Exception, message = nil, options = nil, &block) + matcher = ::RaiseErrorMatcher.new(exception, message, options, &block) + unless matcher.matches? @actual + expected, actual = matcher.failure_message + ::SpecExpectation.fail_with(expected, actual) 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 - end - - def <(expected) - if @actual < expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to be less than #{expected.pretty_inspect}") + result = @actual == expected + if result + ::SpecExpectation.fail_single_arg_predicate(@actual, :==, expected, result, "to be falsy") end end - def <=(expected) - if @actual <= expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to be less than or equal to #{expected.pretty_inspect}") + def !=(expected) + result = @actual != expected + if result + ::SpecExpectation.fail_single_arg_predicate(@actual, :!=, expected, result, "to be falsy") end end - def >(expected) - if @actual > expected - SpecExpectation.fail_with("Expected #{@actual.pretty_inspect}", - "not to be greater than #{expected.pretty_inspect}") + def equal?(expected) + result = @actual.equal?(expected) + if result + ::SpecExpectation.fail_single_arg_predicate(@actual, :equal?, expected, 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}") + def raise(exception = ::Exception, message = nil, options = nil, &block) + matcher = ::RaiseErrorMatcher.new(exception, message, options, &block) + if matcher.matches? @actual + expected, actual = matcher.negative_failure_message + ::SpecExpectation.fail_with(expected, actual) 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/be_close.rb b/spec/mspec/lib/mspec/matchers/be_close.rb index 2cf0fba41f..d6a6626f31 100644 --- a/spec/mspec/lib/mspec/matchers/be_close.rb +++ b/spec/mspec/lib/mspec/matchers/be_close.rb @@ -1,4 +1,6 @@ TOLERANCE = 0.00003 unless Object.const_defined?(:TOLERANCE) +# To account for GC, context switches, other processes, load, etc. +TIME_TOLERANCE = 20.0 unless Object.const_defined?(:TIME_TOLERANCE) class BeCloseMatcher def initialize(expected, tolerance) @@ -8,15 +10,15 @@ class BeCloseMatcher def matches?(actual) @actual = actual - (@actual - @expected).abs < @tolerance + (@actual - @expected).abs <= @tolerance end def failure_message - ["Expected #{@expected}", "to be within +/- #{@tolerance} of #{@actual}"] + ["Expected #{@actual}", "to be within #{@expected} +/- #{@tolerance}"] end def negative_failure_message - ["Expected #{@expected}", "not to be within +/- #{@tolerance} of #{@actual}"] + ["Expected #{@actual}", "not to be within #{@expected} +/- #{@tolerance}"] end end diff --git a/spec/mspec/lib/mspec/matchers/block_caller.rb b/spec/mspec/lib/mspec/matchers/block_caller.rb index 017bce3cb7..30fab4fc68 100644 --- a/spec/mspec/lib/mspec/matchers/block_caller.rb +++ b/spec/mspec/lib/mspec/matchers/block_caller.rb @@ -1,22 +1,24 @@ class BlockingMatcher def matches?(block) - started = false - blocking = true - - thread = Thread.new do - started = true + t = Thread.new do block.call - - blocking = false end - while !started and status = thread.status and status != "sleep" - Thread.pass + loop do + case t.status + when "sleep" # blocked + t.kill + t.join + return true + when false # terminated normally, so never blocked + t.join + return false + when nil # terminated exceptionally + t.value + else + Thread.pass + end end - thread.kill - thread.join - - blocking end def failure_message @@ -29,7 +31,7 @@ class BlockingMatcher end module MSpecMatchers - private def block_caller(timeout = 0.1) + private def block_caller BlockingMatcher.new end end diff --git a/spec/mspec/lib/mspec/matchers/complain.rb b/spec/mspec/lib/mspec/matchers/complain.rb index 4bcb255040..19310c0bbb 100644 --- a/spec/mspec/lib/mspec/matchers/complain.rb +++ b/spec/mspec/lib/mspec/matchers/complain.rb @@ -1,22 +1,31 @@ require 'mspec/helpers/io' class ComplainMatcher - def initialize(complaint) - @complaint = complaint + def initialize(complaint = nil, options = nil) + # the proper solution is to use double splat operator e.g. + # def initialize(complaint = nil, **options) + # but we are trying to minimize language features required to run MSpec + if complaint.is_a?(Hash) + @complaint = nil + @options = complaint + else + @complaint = complaint + @options = options || {} + end end def matches?(proc) @saved_err = $stderr @verbose = $VERBOSE + err = IOStub.new + + $stderr = err + $VERBOSE = @options.key?(:verbose) ? @options[:verbose] : false begin - err = $stderr = IOStub.new - $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 @@ -54,7 +63,7 @@ class ComplainMatcher end module MSpecMatchers - private def complain(complaint=nil) - ComplainMatcher.new(complaint) + private def complain(complaint = nil, options = nil) + ComplainMatcher.new(complaint, options) end end 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/have_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_instance_method.rb index 636aaf3e47..9a5a31aa0f 100644 --- a/spec/mspec/lib/mspec/matchers/have_instance_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_instance_method.rb @@ -18,7 +18,7 @@ class HaveInstanceMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_instance_method(method, include_super=true) + private def have_instance_method(method, include_super = true) HaveInstanceMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/have_method.rb b/spec/mspec/lib/mspec/matchers/have_method.rb index 35dae03af0..e962e69e0a 100644 --- a/spec/mspec/lib/mspec/matchers/have_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_method.rb @@ -18,7 +18,7 @@ class HaveMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_method(method, include_super=true) + private def have_method(method, include_super = true) HaveMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb index 4eb7133055..d32db76c6a 100644 --- a/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_private_instance_method.rb @@ -18,7 +18,7 @@ class HavePrivateInstanceMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_private_instance_method(method, include_super=true) + private def have_private_instance_method(method, include_super = true) HavePrivateInstanceMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/have_private_method.rb b/spec/mspec/lib/mspec/matchers/have_private_method.rb index 3433d982cc..c74165cfc7 100644 --- a/spec/mspec/lib/mspec/matchers/have_private_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_private_method.rb @@ -18,7 +18,7 @@ class HavePrivateMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_private_method(method, include_super=true) + private def have_private_method(method, include_super = true) HavePrivateMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb index 641d4d0dc2..1deb2f995d 100644 --- a/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_protected_instance_method.rb @@ -18,7 +18,7 @@ class HaveProtectedInstanceMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_protected_instance_method(method, include_super=true) + private def have_protected_instance_method(method, include_super = true) HaveProtectedInstanceMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb b/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb index 501c0a418e..0e620532c0 100644 --- a/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_public_instance_method.rb @@ -18,7 +18,7 @@ class HavePublicInstanceMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_public_instance_method(method, include_super=true) + private def have_public_instance_method(method, include_super = true) HavePublicInstanceMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/have_singleton_method.rb b/spec/mspec/lib/mspec/matchers/have_singleton_method.rb index 95d78709ff..b60dd2536b 100644 --- a/spec/mspec/lib/mspec/matchers/have_singleton_method.rb +++ b/spec/mspec/lib/mspec/matchers/have_singleton_method.rb @@ -18,7 +18,7 @@ class HaveSingletonMethodMatcher < MethodMatcher end module MSpecMatchers - private def have_singleton_method(method, include_super=true) + private def have_singleton_method(method, include_super = true) HaveSingletonMethodMatcher.new method, include_super end end diff --git a/spec/mspec/lib/mspec/matchers/include.rb b/spec/mspec/lib/mspec/matchers/include.rb index 0b7eaf3ce2..3f07f35548 100644 --- a/spec/mspec/lib/mspec/matchers/include.rb +++ b/spec/mspec/lib/mspec/matchers/include.rb @@ -15,11 +15,11 @@ class IncludeMatcher end def failure_message - ["Expected #{@actual.inspect}", "to include #{@element.inspect}"] + ["Expected #{MSpec.format(@actual)}", "to include #{MSpec.format(@element)}"] end def negative_failure_message - ["Expected #{@actual.inspect}", "not to include #{@element.inspect}"] + ["Expected #{MSpec.format(@actual)}", "not to include #{MSpec.format(@element)}"] end end diff --git a/spec/mspec/lib/mspec/matchers/include_any_of.rb b/spec/mspec/lib/mspec/matchers/include_any_of.rb new file mode 100644 index 0000000000..ce097ccf0f --- /dev/null +++ b/spec/mspec/lib/mspec/matchers/include_any_of.rb @@ -0,0 +1,29 @@ +class IncludeAnyOfMatcher + def initialize(*expected) + @expected = expected + end + + def matches?(actual) + @actual = actual + @expected.each do |e| + if @actual.include?(e) + return true + end + end + return false + end + + def failure_message + ["Expected #{@actual.inspect}", "to include any of #{@expected.inspect}"] + end + + def negative_failure_message + ["Expected #{@actual.inspect}", "not to include any of #{@expected.inspect}"] + end +end + +module MSpecMatchers + private def include_any_of(*expected) + IncludeAnyOfMatcher.new(*expected) + end +end diff --git a/spec/mspec/lib/mspec/matchers/match_yaml.rb b/spec/mspec/lib/mspec/matchers/match_yaml.rb index 920d85a14f..30561627c3 100644 --- a/spec/mspec/lib/mspec/matchers/match_yaml.rb +++ b/spec/mspec/lib/mspec/matchers/match_yaml.rb @@ -30,7 +30,11 @@ class MatchYAMLMatcher def valid_yaml?(obj) require 'yaml' begin - YAML.load(obj) + if YAML.respond_to?(:unsafe_load) + YAML.unsafe_load(obj) + else + YAML.load(obj) + end rescue false else diff --git a/spec/mspec/lib/mspec/matchers/method.rb b/spec/mspec/lib/mspec/matchers/method.rb index e8cdfa62ff..2b54419faa 100644 --- a/spec/mspec/lib/mspec/matchers/method.rb +++ b/spec/mspec/lib/mspec/matchers/method.rb @@ -1,5 +1,5 @@ class MethodMatcher - def initialize(method, include_super=true) + def initialize(method, include_super = true) @include_super = include_super @method = method.to_sym end diff --git a/spec/mspec/lib/mspec/matchers/output.rb b/spec/mspec/lib/mspec/matchers/output.rb index b89b6ca0f6..5bb5d55027 100644 --- a/spec/mspec/lib/mspec/matchers/output.rb +++ b/spec/mspec/lib/mspec/matchers/output.rb @@ -42,12 +42,12 @@ class OutputMatcher expected_out = "\n" actual_out = "\n" unless @out.nil? - expected_out += " $stdout: #{@out.inspect}\n" - actual_out += " $stdout: #{@stdout.inspect}\n" + expected_out += " $stdout: #{MSpec.format(@out)}\n" + actual_out += " $stdout: #{MSpec.format(@stdout.to_s)}\n" end unless @err.nil? - expected_out += " $stderr: #{@err.inspect}\n" - actual_out += " $stderr: #{@stderr.inspect}\n" + expected_out += " $stderr: #{MSpec.format(@err)}\n" + actual_out += " $stderr: #{MSpec.format(@stderr.to_s)}\n" end ["Expected:#{expected_out}", " got:#{actual_out}"] end @@ -61,7 +61,7 @@ class OutputMatcher end module MSpecMatchers - private def output(stdout=nil, stderr=nil) + private def output(stdout = nil, stderr = nil) OutputMatcher.new(stdout, stderr) end end diff --git a/spec/mspec/lib/mspec/matchers/raise_error.rb b/spec/mspec/lib/mspec/matchers/raise_error.rb index 2f9afdc687..8cba842ce3 100644 --- a/spec/mspec/lib/mspec/matchers/raise_error.rb +++ b/spec/mspec/lib/mspec/matchers/raise_error.rb @@ -1,71 +1,105 @@ -require 'mspec/utils/deprecate' - class RaiseErrorMatcher - def initialize(exception, message, &block) + FAILURE_MESSAGE_FOR_EXCEPTION = {}.compare_by_identity + UNDEF_CAUSE = Object.new + + attr_writer :block + + def initialize(exception, message = nil, options = nil, &block) + if message.is_a? Hash + @message = nil + options = message + else + @message = message + end + @cause = options ? options.fetch(:cause, UNDEF_CAUSE) : UNDEF_CAUSE @exception = exception - @message = message @block = block @actual = nil end + # This #matches? method is unusual because it doesn't always return a boolean but instead + # re-raises the original exception if proc.call raises an exception and #matching_exception? is false. + # The reasoning is the original exception class matters and we don't want to change it by raising another exception, + # so instead we attach the #failure_message and extract it in ExceptionState#message. def matches?(proc) @result = proc.call return false - rescue Exception => actual + rescue Object => actual @actual = actual + if matching_exception?(actual) + # The block has its own expectations and will throw an exception if it fails + @block[actual] if @block return true else + FAILURE_MESSAGE_FOR_EXCEPTION[actual] = failure_message raise actual end end - def matching_exception?(exc) - return false unless @exception === exc - if @message then - case @message - when String - return false if @message != exc.message - when Regexp - return false if @message !~ exc.message - end + def matching_class?(exc) + @exception === exc + end + + def matching_message?(exc) + case @message + when String + @message == exc.message + when Regexp + @message =~ exc.message + else + true end + end - # The block has its own expectations and will throw an exception if it fails - @block[exc] if @block + def matching_cause?(exc) + case @cause + when UNDEF_CAUSE + true + else + @cause == exc.cause + end + end - return true + def matching_exception?(exc) + matching_class?(exc) and matching_message?(exc) and matching_cause?(exc) end - def exception_class_and_message(exception_class, message) - if message - "#{exception_class} (#{message})" - else - "#{exception_class}" + def exception_class_and_message_and_cause(exception_class, message, cause) + string = "#{exception_class}" + prefixed = false + prefix = -> { prefixed ? ", " : prefixed = "(" } + + if message != nil + string << "#{prefix.()}#{message.inspect}" end + + if cause != UNDEF_CAUSE + string << "#{prefix.()}cause: #{cause.inspect}" + end + + string << ")" if prefixed + + string end def format_expected_exception - exception_class_and_message(@exception, @message) + exception_class_and_message_and_cause(@exception, @message, @cause) end def format_exception(exception) - 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}>" + exception_class_and_message_and_cause(exception.class, + @message == nil ? nil : exception.message, + @cause == UNDEF_CAUSE ? UNDEF_CAUSE : exception.cause) end def failure_message message = ["Expected #{format_expected_exception}"] if @actual - message << "but got #{format_exception(@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 @@ -74,14 +108,25 @@ class RaiseErrorMatcher def negative_failure_message message = ["Expected to not get #{format_expected_exception}", ""] unless @actual.class == @exception - message[1] = "but got #{format_exception(@actual)}" + message[1] = "but got: #{format_exception(@actual)}" end message end end module MSpecMatchers - private def raise_error(exception=Exception, message=nil, &block) - RaiseErrorMatcher.new(exception, message, &block) + private def raise_error(exception = Exception, message = nil, options = nil, &block) + RaiseErrorMatcher.new(exception, message, options, &block) + end + + # CRuby < 4.1 has inconsistent coercion errors: + # https://bugs.ruby-lang.org/issues/21864 + # This matcher ignores the message on CRuby < 4.1 + # and checks the message for all other cases, including other Rubies + private def raise_consistent_error(exception = Exception, message = nil, options = nil, &block) + if RUBY_ENGINE == "ruby" and ruby_version_is ""..."4.1" + message = nil + end + RaiseErrorMatcher.new(exception, message, options, &block) end end diff --git a/spec/mspec/lib/mspec/matchers/skip.rb b/spec/mspec/lib/mspec/matchers/skip.rb new file mode 100644 index 0000000000..7c175d358d --- /dev/null +++ b/spec/mspec/lib/mspec/matchers/skip.rb @@ -0,0 +1,5 @@ +module MSpecMatchers + private def skip(reason = 'no reason') + raise SkippedSpecError, reason + end +end diff --git a/spec/mspec/lib/mspec/mocks/mock.rb b/spec/mspec/lib/mspec/mocks/mock.rb index b11d469186..c61ba35ea7 100644 --- a/spec/mspec/lib/mspec/mocks/mock.rb +++ b/spec/mspec/lib/mspec/mocks/mock.rb @@ -18,20 +18,16 @@ module Mock @stubs ||= Hash.new { |h,k| h[k] = [] } end - def self.replaced_name(obj, sym) - :"__mspec_#{obj.__id__}_#{sym}__" + def self.replaced_name(key) + :"__mspec_#{key.last}__" end def self.replaced_key(obj, sym) - [replaced_name(obj, sym), sym] + [obj.__id__, sym] end - def self.has_key?(keys, sym) - !!keys.find { |k| k.first == sym } - end - - def self.replaced?(sym) - has_key?(mocks.keys, sym) or has_key?(stubs.keys, sym) + def self.replaced?(key) + mocks.include?(key) or stubs.include?(key) end def self.clear_replaced(key) @@ -40,22 +36,28 @@ module Mock end def self.mock_respond_to?(obj, sym, include_private = false) - name = replaced_name(obj, :respond_to?) - if replaced? name + key = replaced_key(obj, :respond_to?) + if replaced? key + name = replaced_name(key) obj.__send__ name, sym, include_private else obj.respond_to? sym, include_private end end - def self.install_method(obj, sym, type=nil) + def self.install_method(obj, sym, type = nil) meta = obj.singleton_class key = replaced_key obj, sym sym = sym.to_sym - if (sym == :respond_to? or mock_respond_to?(obj, sym, true)) and !replaced?(key.first) - meta.__send__ :alias_method, key.first, sym + if type == :stub and mocks.key?(key) + # Defining a stub and there is already a mock, ignore the stub + return + end + + if (sym == :respond_to? or mock_respond_to?(obj, sym, true)) and !replaced?(key) + meta.__send__ :alias_method, replaced_name(key), sym end suppress_warning { @@ -73,6 +75,11 @@ module Mock MSpec.actions :expectation, MSpec.current.state end + if proxy.mock? and stubs.key?(key) + # Defining a mock and there is already a stub, remove the stub + stubs.delete key + end + if proxy.stub? stubs[key].unshift proxy else @@ -87,6 +94,10 @@ module Mock obj.instance_variable_get(:@name) || obj.inspect end + def self.inspect_args(args) + "(#{Array(args).map(&:inspect).join(', ')})" + end + def self.verify_count mocks.each do |key, proxies| obj = objects[key] @@ -106,7 +117,7 @@ module Mock end unless pass SpecExpectation.fail_with( - "Mock '#{name_or_inspect obj}' expected to receive '#{key.last}' " + \ + "Mock '#{name_or_inspect obj}' expected to receive #{key.last}#{inspect_args proxy.arguments} " + \ "#{qualifier.to_s.sub('_', ' ')} #{count} times", "but received it #{proxy.calls} times") end @@ -120,7 +131,7 @@ module Mock key = replaced_key obj, sym [mocks, stubs].each do |proxies| - proxies[key].each do |proxy| + proxies.fetch(key, []).each do |proxy| pass = case proxy.arguments when :any_args true @@ -166,7 +177,7 @@ module Mock mock_respond_to? obj, *args else SpecExpectation.fail_with("Mock '#{name_or_inspect obj}': method #{sym}\n", - "called with unexpected arguments (#{Array(compare).join(' ')})") + "called with unexpected arguments #{inspect_args args}") end end @@ -177,7 +188,7 @@ module Mock next end - replaced = key.first + replaced = replaced_name(key) sym = key.last meta = obj.singleton_class diff --git a/spec/mspec/lib/mspec/mocks/object.rb b/spec/mspec/lib/mspec/mocks/object.rb index 19a50ac4e1..fcaa1caef0 100644 --- a/spec/mspec/lib/mspec/mocks/object.rb +++ b/spec/mspec/lib/mspec/mocks/object.rb @@ -15,7 +15,7 @@ class Object end end -def mock(name, options={}) +def mock(name, options = {}) MockObject.new name, options end @@ -23,6 +23,6 @@ def mock_int(val) MockIntObject.new(val) end -def mock_numeric(name, options={}) +def mock_numeric(name, options = {}) NumericMockObject.new name, options end diff --git a/spec/mspec/lib/mspec/mocks/proxy.rb b/spec/mspec/lib/mspec/mocks/proxy.rb index f5acc89d62..8473132b0b 100644 --- a/spec/mspec/lib/mspec/mocks/proxy.rb +++ b/spec/mspec/lib/mspec/mocks/proxy.rb @@ -1,5 +1,5 @@ class MockObject - def initialize(name, options={}) + def initialize(name, options = {}) @name = name @null = options[:null_object] end @@ -11,7 +11,7 @@ class MockObject end class NumericMockObject < Numeric - def initialize(name, options={}) + def initialize(name, options = {}) @name = name @null = options[:null_object] end @@ -50,7 +50,7 @@ end class MockProxy attr_reader :raising, :yielding - def initialize(type=nil) + def initialize(type = nil) @multiple_returns = nil @returning = nil @raising = nil diff --git a/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb b/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb new file mode 100644 index 0000000000..abfb6dd0ee --- /dev/null +++ b/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb @@ -0,0 +1,84 @@ +class ConstantsLockFile + LOCK_FILE_NAME = '.mspec.constants' + + def self.lock_file + @prefix ||= File.expand_path(MSpecScript.get(:prefix) || '.') + "#{@prefix}/#{LOCK_FILE_NAME}" + end + + def self.load + if File.exist?(lock_file) + File.readlines(lock_file).map(&:chomp) + else + [] + end + end + + def self.dump(ary) + contents = ary.map(&:to_s).uniq.sort.join("\n") + "\n" + File.write(lock_file, contents) + end +end + +class ConstantLeakError < StandardError +end + +class ConstantsLeakCheckerAction + def initialize(save) + @save = save + @check = !save + @constants_locked = ConstantsLockFile.load + @exclude_patterns = MSpecScript.get(:toplevel_constants_excludes) || [] + end + + def register + MSpec.register :start, self + MSpec.register :before, self + MSpec.register :after, self + MSpec.register :finish, self + end + + def start + @constants_start = constants_now + end + + def before(state) + @constants_before = constants_now + end + + def after(state) + constants = remove_excludes(constants_now - @constants_before - @constants_locked) + + if @check && !constants.empty? + MSpec.protect 'Constants leak check' do + raise ConstantLeakError, "Top level constants leaked: #{constants.join(', ')}" + end + end + end + + def finish + constants = remove_excludes(constants_now - @constants_start - @constants_locked) + + if @save + ConstantsLockFile.dump(@constants_locked + constants) + end + + if @check && !constants.empty? + MSpec.protect 'Global constants leak check' do + raise ConstantLeakError, "Top level constants leaked in the whole test suite: #{constants.join(', ')}" + end + end + end + + private + + def constants_now + Object.constants.map(&:to_s) + end + + def remove_excludes(constants) + constants.reject { |name| + @exclude_patterns.any? { |pattern| pattern === name } + } + end +end diff --git a/spec/mspec/lib/mspec/runner/actions/filter.rb b/spec/mspec/lib/mspec/runner/actions/filter.rb index 35899c8dc8..b0ad7080da 100644 --- a/spec/mspec/lib/mspec/runner/actions/filter.rb +++ b/spec/mspec/lib/mspec/runner/actions/filter.rb @@ -10,7 +10,7 @@ require 'mspec/runner/filters/match' # trigger the action. class ActionFilter - def initialize(tags=nil, descs=nil) + def initialize(tags = nil, descs = nil) @tags = Array(tags) descs = Array(descs) @sfilter = descs.empty? ? nil : MatchFilter.new(nil, *descs) diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb index e947cda9ff..0a8c9c3252 100644 --- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb +++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb @@ -24,29 +24,36 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. +class LeakError < StandardError +end + class LeakChecker + attr_reader :leaks + def initialize @fd_info = find_fds @tempfile_info = find_tempfiles @thread_info = find_threads @env_info = find_env @argv_info = find_argv + @globals_info = find_globals @encoding_info = find_encodings end - def check(test_name) - @no_leaks = true - leaks = [ - check_fd_leak(test_name), - check_tempfile_leak(test_name), - check_thread_leak(test_name), - check_process_leak(test_name), - check_env(test_name), - check_argv(test_name), - check_encodings(test_name) - ] - GC.start if leaks.any? - return leaks.none? + def check(state) + @state = state + @leaks = [] + check_fd_leak + check_tempfile_leak + check_thread_leak + check_process_leak + check_env + check_argv + check_globals + check_encodings + check_tracepoints + GC.start unless @leaks.empty? + @leaks.empty? end private @@ -66,8 +73,7 @@ class LeakChecker end end - def check_fd_leak(test_name) - leaked = false + def check_fd_leak live1 = @fd_info if IO.respond_to?(:console) and (m = IO.method(:console)).arity.nonzero? m[:close] @@ -76,12 +82,11 @@ class LeakChecker fd_closed = live1 - live2 if !fd_closed.empty? fd_closed.each {|fd| - puts "Closed file descriptor: #{test_name}: #{fd}" + leak "Closed file descriptor: #{fd}" } end fd_leaked = live2 - live1 if !fd_leaked.empty? - leaked = true h = {} ObjectSpace.each_object(IO) {|io| inspect = io.inspect @@ -105,19 +110,18 @@ class LeakChecker str << s } end - puts "Leaked file descriptor: #{test_name}: #{fd}#{str}" + leak "Leaked file descriptor: #{fd}#{str}" } #system("lsof -p #$$") if !fd_leaked.empty? h.each {|fd, list| next if list.length <= 1 if 1 < list.count {|io, autoclose, inspect| autoclose } str = list.map {|io, autoclose, inspect| " #{inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join - puts "Multiple autoclose IO object for a file descriptor:#{str}" + leak "Multiple autoclose IO object for a file descriptor:#{str}" end } end @fd_info = live2 - return leaked end def extend_tempfile_counter @@ -128,19 +132,19 @@ class LeakChecker attr_accessor :count end - def new(data) + def new(...) LeakChecker::TempfileCounter.count += 1 - super(data) + super end } LeakChecker.const_set(:TempfileCounter, m) - class << Tempfile::Remover + class << Tempfile prepend LeakChecker::TempfileCounter end end - def find_tempfiles(prev_count=-1) + def find_tempfiles(prev_count = -1) return [prev_count, []] unless defined? Tempfile extend_tempfile_counter count = TempfileCounter.count @@ -152,132 +156,141 @@ class LeakChecker end end - def check_tempfile_leak(test_name) + def check_tempfile_leak return false unless defined? Tempfile count1, initial_tempfiles = @tempfile_info count2, current_tempfiles = find_tempfiles(count1) - leaked = false tempfiles_leaked = current_tempfiles - initial_tempfiles if !tempfiles_leaked.empty? - leaked = true list = tempfiles_leaked.map {|t| t.inspect }.sort list.each {|str| - puts "Leaked tempfile: #{test_name}: #{str}" + leak "Leaked tempfile: #{str}" } tempfiles_leaked.each {|t| t.close! } end @tempfile_info = [count2, initial_tempfiles] - return leaked end def find_threads Thread.list.find_all {|t| - t != Thread.current && t.alive? + t != Thread.current && t.alive? && + !(t.thread_variable?(:"\0__detached_thread__") && t.thread_variable_get(:"\0__detached_thread__")) } end - def check_thread_leak(test_name) + def check_thread_leak live1 = @thread_info live2 = find_threads thread_finished = live1 - live2 - leaked = false if !thread_finished.empty? list = thread_finished.map {|t| t.inspect }.sort list.each {|str| - puts "Finished thread: #{test_name}: #{str}" + leak "Finished thread: #{str}" } end thread_leaked = live2 - live1 if !thread_leaked.empty? - leaked = true list = thread_leaked.map {|t| t.inspect }.sort list.each {|str| - puts "Leaked thread: #{test_name}: #{str}" + leak "Leaked thread: #{str}" } end @thread_info = live2 - return leaked end - def check_process_leak(test_name) + def check_process_leak subprocesses_leaked = Process.waitall subprocesses_leaked.each { |pid, status| - puts "Leaked subprocess: #{pid}: #{status}" + leak "Leaked subprocess: #{pid}: #{status}" } - return !subprocesses_leaked.empty? end def find_env ENV.to_h end - def check_env(test_name) + def check_env old_env = @env_info new_env = find_env - return false if old_env == new_env + return if old_env == new_env + (old_env.keys | new_env.keys).sort.each {|k| if old_env.has_key?(k) if new_env.has_key?(k) if old_env[k] != new_env[k] - puts "Environment variable changed: #{test_name} : #{k.inspect} changed : #{old_env[k].inspect} -> #{new_env[k].inspect}" + leak "Environment variable changed : #{k.inspect} changed : #{old_env[k].inspect} -> #{new_env[k].inspect}" end else - puts "Environment variable changed: #{test_name} : #{k.inspect} deleted" + leak "Environment variable changed: #{k.inspect} deleted" end else if new_env.has_key?(k) - puts "Environment variable changed: #{test_name} : #{k.inspect} added" + leak "Environment variable changed: #{k.inspect} added" else flunk "unreachable" end end } @env_info = new_env - return true end def find_argv ARGV.map { |e| e.dup } end - def check_argv(test_name) + def check_argv old_argv = @argv_info new_argv = find_argv - leaked = false if new_argv != old_argv - puts "ARGV changed: #{test_name} : #{old_argv.inspect} to #{new_argv.inspect}" + leak "ARGV changed: #{old_argv.inspect} to #{new_argv.inspect}" @argv_info = new_argv - leaked = true end - return leaked + end + + def find_globals + { verbose: $VERBOSE, debug: $DEBUG } + end + + def check_globals + old_globals = @globals_info + new_globals = find_globals + if new_globals != old_globals + leak "Globals changed: #{old_globals.inspect} to #{new_globals.inspect}" + @globals_info = new_globals + end end def find_encodings [Encoding.default_internal, Encoding.default_external] end - def check_encodings(test_name) + def check_encodings old_internal, old_external = @encoding_info new_internal, new_external = find_encodings - leaked = false if new_internal != old_internal - leaked = true - puts "Encoding.default_internal changed: #{test_name} : #{old_internal} to #{new_internal}" + leak "Encoding.default_internal changed: #{old_internal.inspect} to #{new_internal.inspect}" end if new_external != old_external - leaked = true - puts "Encoding.default_external changed: #{test_name} : #{old_external} to #{new_external}" + leak "Encoding.default_external changed: #{old_external.inspect} to #{new_external.inspect}" end @encoding_info = [new_internal, new_external] - return leaked end - def puts(*args) - if @no_leaks - @no_leaks = false - print "\n" + def check_tracepoints + ObjectSpace.each_object(TracePoint) do |tp| + if tp.enabled? + leak "TracePoint is still enabled: #{tp.inspect}" + end + end + end + + def leak(message) + if @leaks.empty? + $stderr.puts "\n" + $stderr.puts @state.description end - super(*args) + @leaks << message + $stderr.puts message end end @@ -288,14 +301,77 @@ class LeakCheckerAction end def start + disable_nss_modules @checker = LeakChecker.new end def after(state) - unless @checker.check(state.description) + unless @checker.check(state) + leak_messages = @checker.leaks + location = state.description if state.example - puts state.example.source_location.join(':') + location = "#{location}\n#{state.example.source_location.join(':')}" + end + MSpec.protect(location) do + raise LeakError, leak_messages.join("\n") end end end + + private + + # This function is intended to disable all NSS modules when ruby is compiled + # against glibc. NSS modules allow the system administrator to load custom + # shared objects into all processes using glibc, and use them to customise + # the behaviour of username, groupname, hostname, etc lookups. This is + # normally configured in the file /etc/nsswitch.conf. + # These modules often do things like open cache files or connect to system + # daemons like sssd or dbus, which of course means they have open file + # descriptors of their own. This can cause the leak-checking functionality + # in this file to report that such descriptors have been leaked, and fail + # the test suite. + # This function uses glibc's __nss_configure_lookup function to override any + # configuration in /etc/nsswitch.conf, and just use the built in files/dns + # name lookup functionality (which is of course perfectly sufficient for + # running ruby/spec). + def disable_nss_modules + begin + require 'fiddle' + rescue LoadError + # Make sure it's possible to run the test suite on a ruby implementation + # which does not (yet?) have Fiddle. + return + end + + begin + libc = Fiddle.dlopen(nil) + # Older versions of fiddle don't have Fiddle::Type (and instead rely on Fiddle::TYPE_) + # Even older versions of fiddle don't have CONST_STRING, + string_type = defined?(Fiddle::TYPE_CONST_STRING) ? Fiddle::TYPE_CONST_STRING : Fiddle::TYPE_VOIDP + nss_configure_lookup = Fiddle::Function.new( + libc['__nss_configure_lookup'], + [string_type, string_type], + Fiddle::TYPE_INT + ) + rescue Fiddle::DLError + # We're not running with glibc - no need to do this. + return + end + + nss_configure_lookup.call 'passwd', 'files' + nss_configure_lookup.call 'shadow', 'files' + nss_configure_lookup.call 'group', 'files' + nss_configure_lookup.call 'hosts', 'files dns' + nss_configure_lookup.call 'services', 'files' + nss_configure_lookup.call 'netgroup', 'files' + nss_configure_lookup.call 'automount', 'files' + nss_configure_lookup.call 'aliases', 'files' + nss_configure_lookup.call 'ethers', 'files' + nss_configure_lookup.call 'gshadow', 'files' + nss_configure_lookup.call 'initgroups', 'files' + nss_configure_lookup.call 'networks', 'files dns' + nss_configure_lookup.call 'protocols', 'files' + nss_configure_lookup.call 'publickey', 'files' + nss_configure_lookup.call 'rpc', 'files' + end end diff --git a/spec/mspec/lib/mspec/runner/actions/profile.rb b/spec/mspec/lib/mspec/runner/actions/profile.rb new file mode 100644 index 0000000000..c743d6e3e8 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/actions/profile.rb @@ -0,0 +1,60 @@ +class ProfileAction + def initialize + @describe_name = nil + @describe_time = nil + @describes = [] + @its = [] + end + + def register + MSpec.register :enter, self + MSpec.register :before,self + MSpec.register :after, self + MSpec.register :finish,self + end + + def enter(describe) + if @describe_time + @describes << [@describe_name, now - @describe_time] + end + + @describe_name = describe + @describe_time = now + end + + def before(state) + @it_name = state.it + @it_time = now + end + + def after(state = nil) + @its << [@describe_name, @it_name, now - @it_time] + end + + def finish + puts "\nProfiling info:" + + desc = @describes.sort { |a,b| b.last <=> a.last } + desc.delete_if { |a| a.last <= 0.001 } + show = desc[0, 100] + + puts "Top #{show.size} describes:" + + show.each do |des, time| + printf "%3.3f - %s\n", time, des + end + + its = @its.sort { |a,b| b.last <=> a.last } + its.delete_if { |a| a.last <= 0.001 } + show = its[0, 100] + + puts "\nTop #{show.size} its:" + show.each do |des, it, time| + printf "%3.3f - %s %s\n", time, des, it + end + end + + def now + Time.now.to_f + end +end diff --git a/spec/mspec/lib/mspec/runner/actions/tag.rb b/spec/mspec/lib/mspec/runner/actions/tag.rb index 760152b2a3..d40d562451 100644 --- a/spec/mspec/lib/mspec/runner/actions/tag.rb +++ b/spec/mspec/lib/mspec/runner/actions/tag.rb @@ -22,7 +22,7 @@ require 'mspec/runner/actions/filter' # spec description strings class TagAction < ActionFilter - def initialize(action, outcome, tag, comment, tags=nil, descs=nil) + def initialize(action, outcome, tag, comment, tags = nil, descs = nil) super tags, descs @action = action @outcome = outcome diff --git a/spec/mspec/lib/mspec/runner/actions/taglist.rb b/spec/mspec/lib/mspec/runner/actions/taglist.rb index c1aba53794..3097e655d5 100644 --- a/spec/mspec/lib/mspec/runner/actions/taglist.rb +++ b/spec/mspec/lib/mspec/runner/actions/taglist.rb @@ -4,7 +4,7 @@ require 'mspec/runner/actions/filter' # tagged with +tags+. If +tags+ is an empty list, prints out # descriptions for any specs that are tagged. class TagListAction - def initialize(tags=nil) + def initialize(tags = nil) @tags = tags.nil? || tags.empty? ? nil : Array(tags) @filter = nil end diff --git a/spec/mspec/lib/mspec/runner/actions/tally.rb b/spec/mspec/lib/mspec/runner/actions/tally.rb index 33f937293c..d6ada53bab 100644 --- a/spec/mspec/lib/mspec/runner/actions/tally.rb +++ b/spec/mspec/lib/mspec/runner/actions/tally.rb @@ -5,31 +5,31 @@ class Tally @files = @examples = @expectations = @failures = @errors = @guards = @tagged = 0 end - def files!(add=1) + def files!(add = 1) @files += add end - def examples!(add=1) + def examples!(add = 1) @examples += add end - def expectations!(add=1) + def expectations!(add = 1) @expectations += add end - def failures!(add=1) + def failures!(add = 1) @failures += add end - def errors!(add=1) + def errors!(add = 1) @errors += add end - def guards!(add=1) + def guards!(add = 1) @guards += add end - def tagged!(add=1) + def tagged!(add = 1) @tagged += add end 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..1200926872 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb @@ -0,0 +1,145 @@ +class TimeoutAction + def initialize(timeout) + @timeout = timeout + @queue = Queue.new + @started = now + @fail = false + @error_message = "took longer than the configured timeout of #{@timeout}s" + end + + def register + MSpec.register :start, self + MSpec.register :before, self + MSpec.register :after, 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 + if @current_state + STDERR.puts "\nExample #{@error_message}:" + STDERR.puts "#{@current_state.description}" + else + STDERR.puts "\nSome code outside an example #{@error_message}" + end + STDERR.flush + + show_backtraces + if MSpec.subprocesses.empty? + exit! 2 + else + # Do not exit but signal the subprocess so we can get their output + MSpec.subprocesses.each do |pid| + kill_wait_one_second :SIGTERM, pid + hard_kill :SIGKILL, pid + end + @fail = true + @current_state = nil + break # stop this thread, will fail in #after + end + end + end + end + end + end + end + + def before(state = nil) + time = now + @queue << -> do + @current_state = state + @started = time + end + end + + def after(state = nil) + @queue << -> do + @current_state = nil + end + + if @fail + STDERR.puts "\n\nThe last example #{@error_message}. See above for the subprocess stacktrace." + exit! 2 + end + end + + def finish + @thread.kill + @thread.join + end + + private def hard_kill(signal, pid) + begin + Process.kill signal, pid + rescue Errno::ESRCH + # Process already terminated + end + end + + private def kill_wait_one_second(signal, pid) + begin + Process.kill signal, pid + sleep 1 + rescue Errno::ESRCH + # Process already terminated + end + end + + private def show_backtraces + java_stacktraces = -> pid { + if RUBY_ENGINE == 'truffleruby' || RUBY_ENGINE == 'jruby' + STDERR.puts 'Java stacktraces:' + kill_wait_one_second :SIGQUIT, pid + end + } + + if MSpec.subprocesses.empty? + java_stacktraces.call Process.pid + + STDERR.puts "\nRuby backtraces:" + if defined?(Truffle::Debug.show_backtraces) + Truffle::Debug.show_backtraces + else + Thread.list.each do |thread| + unless thread == Thread.current + STDERR.puts thread.inspect, thread.backtrace, '' + end + end + end + else + MSpec.subprocesses.each do |pid| + STDERR.puts "\nFor subprocess #{pid}" + java_stacktraces.call pid + + if RUBY_ENGINE == 'truffleruby' + STDERR.puts "\nRuby backtraces:" + kill_wait_one_second :SIGALRM, pid + else + STDERR.puts "Don't know how to print backtraces of a subprocess on #{RUBY_ENGINE}" + end + end + end + end +end diff --git a/spec/mspec/lib/mspec/runner/context.rb b/spec/mspec/lib/mspec/runner/context.rb index 30d8a4ad1b..bcd83b2465 100644 --- a/spec/mspec/lib/mspec/runner/context.rb +++ b/spec/mspec/lib/mspec/runner/context.rb @@ -12,15 +12,14 @@ class ContextState attr_reader :state, :parent, :parents, :children, :examples, :to_s - def initialize(mod, options=nil) - @to_s = mod.to_s - if options.is_a? Hash - @options = options - else - @to_s += "#{".:#".include?(options[0,1]) ? "" : " "}#{options}" if options - @options = { } - end - @options[:shared] ||= false + MOCK_VERIFY = -> { Mock.verify_count } + MOCK_CLEANUP = -> { Mock.cleanup } + EXPECTATION_MISSING = -> { raise SpecExpectationNotFoundError } + + def initialize(description, options = nil) + raise "#describe options should be a Hash or nil" unless Hash === options or options.nil? + @to_s = description.to_s + @shared = options && options[:shared] @parsed = false @before = { :all => [], :each => [] } @@ -28,13 +27,10 @@ class ContextState @pre = {} @post = {} @examples = [] + @state = nil @parent = nil @parents = [self] @children = [] - - @mock_verify = Proc.new { Mock.verify_count } - @mock_cleanup = Proc.new { Mock.cleanup } - @expectation_missing = Proc.new { raise SpecExpectationNotFoundError } end # Remove caching when a ContextState is dup'd for shared specs. @@ -46,7 +42,7 @@ class ContextState # Returns true if this is a shared +ContextState+. Essentially, when # created with: describe "Something", :shared => true { ... } def shared? - return @options[:shared] + @shared end # Set the parent (enclosing) +ContextState+ for this state. Creates @@ -127,6 +123,7 @@ class ContextState # Creates an ExampleState instance for the block and stores it # in a list of examples to evaluate unless the example is filtered. def it(desc, &block) + raise "nested #it" if @state example = ExampleState.new(self, desc, block) MSpec.actions :add, example return if MSpec.guarded? @@ -174,7 +171,7 @@ class ContextState # so that exceptions are handled and tallied. Returns true and does # NOT evaluate any blocks if +check+ is true and # <tt>MSpec.mode?(:pretend)</tt> is true. - def protect(what, blocks, check=true) + def protect(what, blocks, check = true) return true if check and MSpec.mode? :pretend Array(blocks).all? { |block| MSpec.protect what, &block } end @@ -205,7 +202,7 @@ class ContextState if protect "before :all", pre(:all) @examples.each do |state| MSpec.repeat do - @state = state + @state = state example = state.example MSpec.actions :before, state @@ -213,21 +210,22 @@ class ContextState MSpec.clear_expectations if example passed = protect nil, example + passed = protect nil, -> { MSpec.actions :passed, state, example } if passed MSpec.actions :example, state, example - protect nil, @expectation_missing unless MSpec.expectation? or !passed + protect nil, EXPECTATION_MISSING if !MSpec.expectation? and passed end end protect "after :each", post(:each) - protect "Mock.verify_count", @mock_verify + protect "Mock.verify_count", MOCK_VERIFY - protect "Mock.cleanup", @mock_cleanup + protect "Mock.cleanup", MOCK_CLEANUP MSpec.actions :after, state @state = nil end end protect "after :all", post(:all) else - protect "Mock.cleanup", @mock_cleanup + protect "Mock.cleanup", MOCK_CLEANUP end MSpec.actions :leave diff --git a/spec/mspec/lib/mspec/runner/evaluate.rb b/spec/mspec/lib/mspec/runner/evaluate.rb index ecf7460a90..396a84c118 100644 --- a/spec/mspec/lib/mspec/runner/evaluate.rb +++ b/spec/mspec/lib/mspec/runner/evaluate.rb @@ -19,7 +19,7 @@ class SpecEvaluate # single quotes to set if off from the rest of the description string. If # the source does contain newline characters, sets the indent level to four # characters. - def format(ruby, newline=true) + def format(ruby, newline = true) if ruby.include?("\n") lines = ruby.each_line.to_a if /( *)/ =~ lines.first @@ -49,6 +49,6 @@ class SpecEvaluate end end -def evaluate(str, desc=nil, &block) +def evaluate(str, desc = nil, &block) SpecEvaluate.new(str, desc).define(&block) end diff --git a/spec/mspec/lib/mspec/runner/example.rb b/spec/mspec/lib/mspec/runner/example.rb index 19eb29b079..0d9f0d618c 100644 --- a/spec/mspec/lib/mspec/runner/example.rb +++ b/spec/mspec/lib/mspec/runner/example.rb @@ -3,12 +3,12 @@ require 'mspec/runner/mspec' # Holds some of the state of the example (i.e. +it+ block) that is # being evaluated. See also +ContextState+. class ExampleState - attr_reader :context, :it, :example + attr_reader :context, :it, :example - def initialize(context, it, example=nil) - @context = context - @it = it - @example = example + def initialize(context, it, example = nil) + @context = context + @it = it + @example = example end def context=(context) @@ -25,8 +25,8 @@ class ExampleState end def filtered? - incl = MSpec.retrieve(:include) || [] - excl = MSpec.retrieve(:exclude) || [] + incl = MSpec.include + excl = MSpec.exclude included = incl.empty? || incl.any? { |f| f === description } included &&= excl.empty? || !excl.any? { |f| f === description } !included diff --git a/spec/mspec/lib/mspec/runner/exception.rb b/spec/mspec/lib/mspec/runner/exception.rb index 0d9bb43105..23375733e6 100644 --- a/spec/mspec/lib/mspec/runner/exception.rb +++ b/spec/mspec/lib/mspec/runner/exception.rb @@ -6,6 +6,7 @@ class ExceptionState def initialize(state, location, exception) @exception = exception + @failure = exception.class == SpecExpectationNotMetError || exception.class == SpecExpectationNotFoundError @description = location ? "An exception occurred during: #{location}" : "" if state @@ -19,25 +20,35 @@ class ExceptionState end def failure? - [SpecExpectationNotMetError, SpecExpectationNotFoundError].any? { |e| @exception.is_a? e } + @failure end def message - if @exception.message.empty? - "<No message>" - elsif @exception.class == SpecExpectationNotMetError || - @exception.class == SpecExpectationNotFoundError - @exception.message + message = @exception.message + message = "<No message>" if message.empty? + + if @failure + message + elsif raise_error_message = RaiseErrorMatcher::FAILURE_MESSAGE_FOR_EXCEPTION[@exception] + raise_error_message.join("\n") else - "#{@exception.class}: #{@exception.message}" + "#{@exception.class}: #{message}" end end def backtrace - @backtrace_filter ||= MSpecScript.config[:backtrace_filter] + @backtrace_filter ||= MSpecScript.config[:backtrace_filter] || %r{(?:/bin/mspec|/lib/mspec/)} bt = @exception.backtrace || [] - - bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n") + unless $MSPEC_DEBUG + # Exclude <internal: entries inside MSpec code, so only after the first ignored entry + first_excluded_line = bt.index { |line| @backtrace_filter =~ line } + if first_excluded_line + bt = bt[0...first_excluded_line] + bt[first_excluded_line..-1].reject { |line| + @backtrace_filter =~ line || /^<internal:/ =~ line + } + end + end + bt.join("\n") end end diff --git a/spec/mspec/lib/mspec/runner/filters/regexp.rb b/spec/mspec/lib/mspec/runner/filters/regexp.rb index 2bd1448d3f..097ec6a755 100644 --- a/spec/mspec/lib/mspec/runner/filters/regexp.rb +++ b/spec/mspec/lib/mspec/runner/filters/regexp.rb @@ -1,7 +1,23 @@ -require 'mspec/runner/filters/match' +class RegexpFilter + def initialize(what, *regexps) + @what = what + @regexps = to_regexp(*regexps) + end + + def ===(string) + @regexps.any? { |regexp| regexp === string } + end + + def register + MSpec.register @what, self + end + + def unregister + MSpec.unregister @what, self + end -class RegexpFilter < MatchFilter - def to_regexp(*strings) - strings.map { |str| Regexp.new str } + def to_regexp(*regexps) + regexps.map { |str| Regexp.new str } end + private :to_regexp end diff --git a/spec/mspec/lib/mspec/runner/formatters.rb b/spec/mspec/lib/mspec/runner/formatters.rb index d085031a12..66f515ddff 100644 --- a/spec/mspec/lib/mspec/runner/formatters.rb +++ b/spec/mspec/lib/mspec/runner/formatters.rb @@ -7,6 +7,7 @@ require 'mspec/runner/formatters/summary' require 'mspec/runner/formatters/unit' require 'mspec/runner/formatters/spinner' require 'mspec/runner/formatters/method' +require 'mspec/runner/formatters/stats' require 'mspec/runner/formatters/yaml' require 'mspec/runner/formatters/profile' require 'mspec/runner/formatters/junit' diff --git a/spec/mspec/lib/mspec/runner/formatters/base.rb b/spec/mspec/lib/mspec/runner/formatters/base.rb new file mode 100644 index 0000000000..882e15c8c2 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/formatters/base.rb @@ -0,0 +1,150 @@ +require 'mspec/expectations/expectations' +require 'mspec/runner/actions/timer' +require 'mspec/runner/actions/tally' +require 'mspec/utils/options' + +if ENV['CHECK_LEAKS'] + require 'mspec/runner/actions/leakchecker' +end + +if ENV['CHECK_LEAKS'] || ENV['CHECK_CONSTANT_LEAKS'] + require 'mspec/runner/actions/constants_leak_checker' +end + +class BaseFormatter + attr_reader :exceptions, :timer, :tally + + def initialize(out = nil) + @current_state = nil + @exception = false + @failure = false + @exceptions = [] + + @count = 0 # For subclasses + + if out + @out = File.open out, "w" + else + @out = $stdout + end + + err = MSpecOptions.latest && MSpecOptions.latest.config[:error_output] + if err + @err = (err == 'stderr') ? $stderr : File.open(err, "w") + else + @err = @out + end + end + + # Creates the +TimerAction+ and +TallyAction+ instances and registers them. + def register + (@timer = TimerAction.new).register + (@tally = TallyAction.new).register + @counter = @tally.counter + + if ENV['CHECK_LEAKS'] + LeakCheckerAction.new.register + end + + if (ENV['CHECK_LEAKS'] || ENV['CHECK_CONSTANT_LEAKS']) && ENV['CHECK_CONSTANT_LEAKS'] != 'false' + save = ENV['CHECK_LEAKS'] == 'save' || ENV['CHECK_CONSTANT_LEAKS'] == 'save' + ConstantsLeakCheckerAction.new(save).register + end + + MSpec.register :abort, self + MSpec.register :before, self + MSpec.register :after, self + MSpec.register :exception, self + MSpec.register :finish, self + end + + def abort + if @current_state + puts "\naborting example: #{@current_state.description}" + end + end + + # Returns true if any exception is raised while running + # an example. This flag is reset before each example + # is evaluated. + def exception? + @exception + end + + # Returns true if all exceptions during the evaluation + # of an example are failures rather than errors. See + # <tt>ExceptionState#failure</tt>. This flag is reset + # before each example is evaluated. + def failure? + @failure + end + + # Callback for the MSpec :before event. Resets the + # +#exception?+ and +#failure+ flags. + def before(state = nil) + @current_state = state + @failure = @exception = false + end + + # Callback for the MSpec :exception event. Stores the + # +ExceptionState+ object to generate the list of backtraces + # after all the specs are run. Also updates the internal + # +#exception?+ and +#failure?+ flags. + def exception(exception) + @count += 1 + @failure = @exception ? @failure && exception.failure? : exception.failure? + @exception = true + @exceptions << exception + end + + # Callback for the MSpec :after event. + def after(state = nil) + @current_state = nil + end + + # Callback for the MSpec :start event. Calls :after event. + # Defined here, in the base class, and used by MultiFormatter. + def start + after + end + + # Callback for the MSpec :unload event. Calls :after event. + # Defined here, in the base class, and used by MultiFormatter. + def unload + after + end + + # Callback for the MSpec :finish event. Prints a description + # and backtrace for every exception that occurred while + # evaluating the examples. + def finish + print "\n" + + if MSpecOptions.latest && MSpecOptions.latest.config[:print_skips] + print "\nSkips:\n" unless MSpec.skips.empty? + MSpec.skips.each do |skip, block| + print "#{skip.message} in #{(block.source_location || ['?']).join(':')}\n" + end + end + + count = 0 + @exceptions.each do |exc| + count += 1 + print_exception(exc, count) + end + print "\n#{@timer.format}\n\n#{@tally.format}\n" + end + + def print_exception(exc, count) + outcome = exc.failure? ? "FAILED" : "ERROR" + @err.print "\n#{count})\n#{exc.description} #{outcome}\n" + @err.print exc.message, "\n" + @err.print exc.backtrace, "\n" + end + + # A convenience method to allow printing to different outputs. + def print(*args) + @out.print(*args) + @out.flush + end +end diff --git a/spec/mspec/lib/mspec/runner/formatters/describe.rb b/spec/mspec/lib/mspec/runner/formatters/describe.rb index 176bd79279..fc4122d13b 100644 --- a/spec/mspec/lib/mspec/runner/formatters/describe.rb +++ b/spec/mspec/lib/mspec/runner/formatters/describe.rb @@ -1,5 +1,4 @@ require 'mspec/runner/formatters/dotted' -require 'mspec/runner/actions/tally' class DescribeFormatter < DottedFormatter # Callback for the MSpec :finish event. Prints a summary of diff --git a/spec/mspec/lib/mspec/runner/formatters/dotted.rb b/spec/mspec/lib/mspec/runner/formatters/dotted.rb index 61c8e4c27c..672cdf81dc 100644 --- a/spec/mspec/lib/mspec/runner/formatters/dotted.rb +++ b/spec/mspec/lib/mspec/runner/formatters/dotted.rb @@ -1,77 +1,9 @@ -require 'mspec/expectations/expectations' -require 'mspec/runner/actions/timer' -require 'mspec/runner/actions/tally' -require 'mspec/runner/actions/leakchecker' if ENV['CHECK_LEAKS'] +require 'mspec/runner/formatters/base' -class DottedFormatter - attr_reader :exceptions, :timer, :tally - - def initialize(out=nil) - @exception = @failure = false - @exceptions = [] - @count = 0 # For subclasses - if out.nil? - @out = $stdout - else - @out = File.open out, "w" - end - - @current_state = nil - end - - # Creates the +TimerAction+ and +TallyAction+ instances and - # registers them. Registers +self+ for the +:exception+, - # +:before+, +:after+, and +:finish+ actions. +class DottedFormatter < BaseFormatter def register - (@timer = TimerAction.new).register - (@tally = TallyAction.new).register - LeakCheckerAction.new.register if ENV['CHECK_LEAKS'] - @counter = @tally.counter - - MSpec.register :exception, self - MSpec.register :before, self - MSpec.register :after, self - MSpec.register :finish, self - MSpec.register :abort, self - end - - def abort - if @current_state - puts "\naborting example: #{@current_state.description}" - end - end - - # Returns true if any exception is raised while running - # an example. This flag is reset before each example - # is evaluated. - def exception? - @exception - end - - # Returns true if all exceptions during the evaluation - # of an example are failures rather than errors. See - # <tt>ExceptionState#failure</tt>. This flag is reset - # before each example is evaluated. - def failure? - @failure - end - - # Callback for the MSpec :before event. Resets the - # +#exception?+ and +#failure+ flags. - def before(state=nil) - @current_state = state - @failure = @exception = false - end - - # Callback for the MSpec :exception event. Stores the - # +ExceptionState+ object to generate the list of backtraces - # after all the specs are run. Also updates the internal - # +#exception?+ and +#failure?+ flags. - def exception(exception) - @count += 1 - @failure = @exception ? @failure && exception.failure? : exception.failure? - @exception = true - @exceptions << exception + super + MSpec.register :after, self end # Callback for the MSpec :after event. Prints an indicator @@ -80,38 +12,12 @@ class DottedFormatter # F = An SpecExpectationNotMetError was raised # E = Any exception other than SpecExpectationNotMetError def after(state = nil) - @current_state = nil + super(state) - unless exception? - print "." - else + if exception? print failure? ? "F" : "E" + else + print "." end end - - # Callback for the MSpec :finish event. Prints a description - # and backtrace for every exception that occurred while - # evaluating the examples. - def finish - print "\n" - count = 0 - @exceptions.each do |exc| - count += 1 - print_exception(exc, count) - end - print "\n#{@timer.format}\n\n#{@tally.format}\n" - end - - def print_exception(exc, count) - outcome = exc.failure? ? "FAILED" : "ERROR" - print "\n#{count})\n#{exc.description} #{outcome}\n" - print exc.message, "\n" - print exc.backtrace, "\n" - end - - # A convenience method to allow printing to different outputs. - def print(*args) - @out.print(*args) - @out.flush - end end diff --git a/spec/mspec/lib/mspec/runner/formatters/file.rb b/spec/mspec/lib/mspec/runner/formatters/file.rb index 6db72af4ff..65cfb1f75b 100644 --- a/spec/mspec/lib/mspec/runner/formatters/file.rb +++ b/spec/mspec/lib/mspec/runner/formatters/file.rb @@ -14,6 +14,11 @@ class FileFormatter < DottedFormatter MSpec.register :unload, self end - alias_method :load, :before - alias_method :unload, :after + def load(state = nil) + before(state) + end + + def unload(state = nil) + after(state) + end end diff --git a/spec/mspec/lib/mspec/runner/formatters/html.rb b/spec/mspec/lib/mspec/runner/formatters/html.rb index fd64cd0d20..e37e89a088 100644 --- a/spec/mspec/lib/mspec/runner/formatters/html.rb +++ b/spec/mspec/lib/mspec/runner/formatters/html.rb @@ -1,7 +1,6 @@ -require 'mspec/expectations/expectations' -require 'mspec/runner/formatters/dotted' +require 'mspec/runner/formatters/base' -class HtmlFormatter < DottedFormatter +class HtmlFormatter < BaseFormatter def register super MSpec.register :start, self @@ -44,13 +43,14 @@ EOH end def exception(exception) - super + super(exception) outcome = exception.failure? ? "FAILED" : "ERROR" print %[<li class="fail">- #{exception.it} (<a href="#details-#{@count}">] print %[#{outcome} - #{@count}</a>)</li>\n] end - def after(state) + def after(state = nil) + super(state) print %[<li class="pass">- #{state.it}</li>\n] unless exception? end diff --git a/spec/mspec/lib/mspec/runner/formatters/junit.rb b/spec/mspec/lib/mspec/runner/formatters/junit.rb index 76d46c2414..6351ccbce9 100644 --- a/spec/mspec/lib/mspec/runner/formatters/junit.rb +++ b/spec/mspec/lib/mspec/runner/formatters/junit.rb @@ -1,19 +1,18 @@ -require 'mspec/expectations/expectations' require 'mspec/runner/formatters/yaml' class JUnitFormatter < YamlFormatter - def initialize(out=nil) - super + def initialize(out = nil) + super(out) @tests = [] end def after(state = nil) - super + super(state) @tests << {:test => state, :exception => false} unless exception? end def exception(exception) - super + super(exception) @tests << {:test => exception, :exception => true} end @@ -25,7 +24,7 @@ class JUnitFormatter < YamlFormatter errors = @tally.counter.errors failures = @tally.counter.failures - printf <<-XML + print <<-XML <?xml version="1.0" encoding="UTF-8" ?> <testsuites @@ -43,8 +42,8 @@ class JUnitFormatter < YamlFormatter @tests.each do |h| description = encode_for_xml h[:test].description - printf <<-XML, "Spec", description, 0.0 - <testcase classname="%s" name="%s" time="%f"> + print <<-XML + <testcase classname="Spec" name="#{description}" time="0.0"> XML if h[:exception] outcome = h[:test].failure? ? "failure" : "error" diff --git a/spec/mspec/lib/mspec/runner/formatters/launchable.rb b/spec/mspec/lib/mspec/runner/formatters/launchable.rb new file mode 100644 index 0000000000..f738781c71 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/formatters/launchable.rb @@ -0,0 +1,88 @@ +module LaunchableFormatter + def self.extend_object(obj) + super + obj.init + end + + def self.setDir(dir) + @@path = File.join(dir, "#{rand.to_s}.json") + self + end + + def init + @timer = nil + @tests = [] + end + + def before(state = nil) + super + @timer = TimerAction.new + @timer.start + end + + def after(state = nil) + super + @timer.finish + file = MSpec.file + return if file.nil? || state&.example.nil? || exception? + + @tests << {:test => state, :file => file, :exception => false, duration: @timer.elapsed} + end + + def exception(exception) + super + @timer.finish + file = MSpec.file + return if file.nil? + + @tests << {:test => exception, :file => file, :exception => true, duration: @timer.elapsed} + end + + def finish + super + + require_relative '../../../../../../tool/lib/launchable' + + @writer = writer = Launchable::JsonStreamWriter.new(@@path) + @writer.write_array('testCases') + at_exit { + @writer.close + } + + repo_path = File.expand_path("#{__dir__}/../../../../../../") + + @tests.each do |t| + testcase = t[:test].description + relative_path = t[:file].delete_prefix("#{repo_path}/") + # The test path is a URL-encoded representation. + # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18 + test_path = {file: relative_path, testcase: testcase}.map{|key, val| + "#{encode_test_path_component(key)}=#{encode_test_path_component(val)}" + }.join('#') + + status = 'TEST_PASSED' + if t[:exception] + message = t[:test].message + backtrace = t[:test].backtrace + e = "#{message}\n#{backtrace}" + status = 'TEST_FAILED' + end + + @writer.write_object( + { + testPath: test_path, + status: status, + duration: t[:duration], + createdAt: Time.now.to_s, + stderr: e, + stdout: nil + } + ) + end + end + + private + def encode_test_path_component component + component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26').tr("\x00-\x08", "") + end +end diff --git a/spec/mspec/lib/mspec/runner/formatters/method.rb b/spec/mspec/lib/mspec/runner/formatters/method.rb index ff115193fd..925858c845 100644 --- a/spec/mspec/lib/mspec/runner/formatters/method.rb +++ b/spec/mspec/lib/mspec/runner/formatters/method.rb @@ -1,18 +1,18 @@ -require 'mspec/runner/formatters/dotted' +require 'mspec/runner/formatters/base' -class MethodFormatter < DottedFormatter +class MethodFormatter < BaseFormatter attr_accessor :methods - def initialize(out=nil) - super + def initialize(out = nil) + super(out) @methods = Hash.new do |h, k| - hash = {} - hash[:examples] = 0 - hash[:expectations] = 0 - hash[:failures] = 0 - hash[:errors] = 0 - hash[:exceptions] = [] - h[k] = hash + h[k] = { + examples: 0, + expectations: 0, + failures: 0, + errors: 0, + exceptions: [] + } end end @@ -34,7 +34,7 @@ class MethodFormatter < DottedFormatter # Resets the tallies so the counts are only for this # example. def before(state) - super + super(state) # The pattern for a method name is not correctly # restrictive but it is simplistic and useful @@ -60,7 +60,9 @@ class MethodFormatter < DottedFormatter # Callback for the MSpec :after event. Sets or adds to # tallies for the example block. - def after(state) + def after(state = nil) + super(state) + h = methods[@key] h[:examples] += tally.counter.examples h[:expectations] += tally.counter.expectations diff --git a/spec/mspec/lib/mspec/runner/formatters/multi.rb b/spec/mspec/lib/mspec/runner/formatters/multi.rb index f69055025f..fa1da3766b 100644 --- a/spec/mspec/lib/mspec/runner/formatters/multi.rb +++ b/spec/mspec/lib/mspec/runner/formatters/multi.rb @@ -1,13 +1,24 @@ -require 'mspec/runner/formatters/spinner' +module MultiFormatter + def self.extend_object(obj) + super + obj.multi_initialize + end -class MultiFormatter < SpinnerFormatter - def initialize(out=nil) - super(out) - @counter = @tally = Tally.new + def multi_initialize + @tally = TallyAction.new + @counter = @tally.counter @timer = TimerAction.new @timer.start end + def register + super + + MSpec.register :start, self + MSpec.register :unload, self + MSpec.unregister :before, self + end + def aggregate_results(files) require 'yaml' @@ -15,23 +26,22 @@ class MultiFormatter < SpinnerFormatter @exceptions = [] files.each do |file| - d = File.open(file, "r") { |f| YAML.load f } + contents = File.read(file) + d = YAML.load(contents) File.delete file - @exceptions += Array(d['exceptions']) - @tally.files! d['files'] - @tally.examples! d['examples'] - @tally.expectations! d['expectations'] - @tally.errors! d['errors'] - @tally.failures! d['failures'] + if d # The file might be empty if the child process died + @exceptions += Array(d['exceptions']) + @counter.files! d['files'] + @counter.examples! d['examples'] + @counter.expectations! d['expectations'] + @counter.errors! d['errors'] + @counter.failures! d['failures'] + end end end def print_exception(exc, count) - print "\n#{count})\n#{exc}\n" - end - - def finish - super(false) + @err.print "\n#{count})\n#{exc}\n" end end diff --git a/spec/mspec/lib/mspec/runner/formatters/profile.rb b/spec/mspec/lib/mspec/runner/formatters/profile.rb index 498cd4a3b7..38ef5b12ed 100644 --- a/spec/mspec/lib/mspec/runner/formatters/profile.rb +++ b/spec/mspec/lib/mspec/runner/formatters/profile.rb @@ -1,9 +1,9 @@ -require 'mspec/expectations/expectations' require 'mspec/runner/formatters/dotted' +require 'mspec/runner/actions/profile' class ProfileFormatter < DottedFormatter - def initialize(out=nil) - super + def initialize(out = nil) + super(out) @describe_name = nil @describe_time = nil @@ -12,59 +12,7 @@ class ProfileFormatter < DottedFormatter end def register - super - MSpec.register :enter, self - end - - # Callback for the MSpec :enter event. Prints the - # +describe+ block string. - def enter(describe) - if @describe_time - @describes << [@describe_name, Time.now.to_f - @describe_time] - end - - @describe_name = describe - @describe_time = Time.now.to_f - end - - # Callback for the MSpec :before event. Prints the - # +it+ block string. - def before(state) - super - - @it_name = state.it - @it_time = Time.now.to_f - end - - # Callback for the MSpec :after event. Prints a - # newline to finish the description string output. - def after(state) - @its << [@describe_name, @it_name, Time.now.to_f - @it_time] - super - end - - def finish - puts "\nProfiling info:" - - desc = @describes.sort { |a,b| b.last <=> a.last } - desc.delete_if { |a| a.last <= 0.001 } - show = desc[0, 100] - - puts "Top #{show.size} describes:" - - show.each do |des, time| - printf "%3.3f - %s\n", time, des - end - - its = @its.sort { |a,b| b.last <=> a.last } - its.delete_if { |a| a.last <= 0.001 } - show = its[0, 100] - - puts "\nTop #{show.size} its:" - show.each do |des, it, time| - printf "%3.3f - %s %s\n", time, des, it - end - + (@profile = ProfileAction.new).register super end end diff --git a/spec/mspec/lib/mspec/runner/formatters/specdoc.rb b/spec/mspec/lib/mspec/runner/formatters/specdoc.rb index 29adde3c5c..d3a5c3d729 100644 --- a/spec/mspec/lib/mspec/runner/formatters/specdoc.rb +++ b/spec/mspec/lib/mspec/runner/formatters/specdoc.rb @@ -1,7 +1,6 @@ -require 'mspec/expectations/expectations' -require 'mspec/runner/formatters/dotted' +require 'mspec/runner/formatters/base' -class SpecdocFormatter < DottedFormatter +class SpecdocFormatter < BaseFormatter def register super MSpec.register :enter, self @@ -16,7 +15,7 @@ class SpecdocFormatter < DottedFormatter # Callback for the MSpec :before event. Prints the # +it+ block string. def before(state) - super + super(state) print "- #{state.it}" end @@ -25,17 +24,18 @@ class SpecdocFormatter < DottedFormatter # the sequential number of the exception raised. If # there has already been an exception raised while # evaluating this example, it prints another +it+ - # block description string so that each discription + # block description string so that each description # string has an associated 'ERROR' or 'FAILED' def exception(exception) print "\n- #{exception.it}" if exception? - super + super(exception) print " (#{exception.failure? ? 'FAILED' : 'ERROR'} - #{@count})" end # Callback for the MSpec :after event. Prints a # newline to finish the description string output. - def after(state) + def after(state = nil) + super(state) print "\n" end end diff --git a/spec/mspec/lib/mspec/runner/formatters/spinner.rb b/spec/mspec/lib/mspec/runner/formatters/spinner.rb index f6f35cc476..817d8c02be 100644 --- a/spec/mspec/lib/mspec/runner/formatters/spinner.rb +++ b/spec/mspec/lib/mspec/runner/formatters/spinner.rb @@ -1,14 +1,13 @@ -require 'mspec/expectations/expectations' -require 'mspec/runner/formatters/dotted' +require 'mspec/runner/formatters/base' -class SpinnerFormatter < DottedFormatter +class SpinnerFormatter < BaseFormatter attr_reader :length Spins = %w!| / - \\! HOUR = 3600 MIN = 60 - def initialize(out=nil) + def initialize(out = nil) super(nil) @which = 0 @@ -28,7 +27,6 @@ class SpinnerFormatter < DottedFormatter MSpec.register :start, self MSpec.register :unload, self - MSpec.unregister :before, self end def length=(length) @@ -80,7 +78,7 @@ class SpinnerFormatter < DottedFormatter # Callback for the MSpec :start event. Stores the total # number of files that will be processed. def start - @total = MSpec.retrieve(:files).size + @total = MSpec.files_array.size compute_progress print progress_line end @@ -102,16 +100,12 @@ class SpinnerFormatter < DottedFormatter clear_progress_line print_exception(exception, @count) + exceptions.clear end # Callback for the MSpec :after event. Updates the spinner. - def after(state) + def after(state = nil) + super(state) print progress_line end - - def finish(printed_exceptions = true) - # We already printed the exceptions - @exceptions = [] if printed_exceptions - super() - end end diff --git a/spec/mspec/lib/mspec/runner/formatters/stats.rb b/spec/mspec/lib/mspec/runner/formatters/stats.rb new file mode 100644 index 0000000000..8cff96d145 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/formatters/stats.rb @@ -0,0 +1,57 @@ +require 'mspec/runner/formatters/base' + +class StatsPerFileFormatter < BaseFormatter + def initialize(out = nil) + super(out) + @data = {} + @root = File.expand_path(MSpecScript.get(:prefix) || '.') + end + + def register + super + MSpec.register :load, self + MSpec.register :unload, self + end + + # Resets the tallies so the counts are only for this file. + def load + tally.counter.examples = 0 + tally.counter.errors = 0 + tally.counter.failures = 0 + tally.counter.tagged = 0 + end + + def unload + file = format_file MSpec.file + + raise if @data.key?(file) + @data[file] = { + examples: tally.counter.examples, + errors: tally.counter.errors, + failures: tally.counter.failures, + tagged: tally.counter.tagged, + } + end + + def finish + width = @data.keys.max_by(&:size).size + f = "%3d" + @data.each_pair do |file, data| + total = data[:examples] + passing = total - data[:errors] - data[:failures] - data[:tagged] + puts "#{file.ljust(width)} #{f % passing}/#{f % total}" + end + + require 'yaml' + yaml = YAML.dump(@data) + File.write "results-#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}.yml", yaml + end + + private def format_file(file) + if file.start_with?(@root) + file[@root.size+1..-1] + else + raise file + end + end +end diff --git a/spec/mspec/lib/mspec/runner/formatters/summary.rb b/spec/mspec/lib/mspec/runner/formatters/summary.rb index 0c9207194c..41819d2158 100644 --- a/spec/mspec/lib/mspec/runner/formatters/summary.rb +++ b/spec/mspec/lib/mspec/runner/formatters/summary.rb @@ -1,11 +1,4 @@ -require 'mspec/expectations/expectations' -require 'mspec/runner/formatters/dotted' +require 'mspec/runner/formatters/base' -class SummaryFormatter < DottedFormatter - # Callback for the MSpec :after event. Overrides the - # callback provided by +DottedFormatter+ and does not - # print any output for each example evaluated. - def after(state) - # do nothing - end +class SummaryFormatter < BaseFormatter end diff --git a/spec/mspec/lib/mspec/runner/formatters/unit.rb b/spec/mspec/lib/mspec/runner/formatters/unit.rb index cebc18a49b..d03ae79e9f 100644 --- a/spec/mspec/lib/mspec/runner/formatters/unit.rb +++ b/spec/mspec/lib/mspec/runner/formatters/unit.rb @@ -1,4 +1,3 @@ -require 'mspec/expectations/expectations' require 'mspec/runner/formatters/dotted' class UnitdiffFormatter < DottedFormatter diff --git a/spec/mspec/lib/mspec/runner/formatters/yaml.rb b/spec/mspec/lib/mspec/runner/formatters/yaml.rb index 090a9b1b9d..6c05cc902f 100644 --- a/spec/mspec/lib/mspec/runner/formatters/yaml.rb +++ b/spec/mspec/lib/mspec/runner/formatters/yaml.rb @@ -1,8 +1,7 @@ -require 'mspec/expectations/expectations' -require 'mspec/runner/formatters/dotted' +require 'mspec/runner/formatters/base' -class YamlFormatter < DottedFormatter - def initialize(out=nil) +class YamlFormatter < BaseFormatter + def initialize(out = nil) super(nil) if out.nil? @@ -16,9 +15,6 @@ class YamlFormatter < DottedFormatter @out = @finish end - def after(state) - end - def finish switch diff --git a/spec/mspec/lib/mspec/runner/mspec.rb b/spec/mspec/lib/mspec/runner/mspec.rb index d47657326b..0e016c67a7 100644 --- a/spec/mspec/lib/mspec/runner/mspec.rb +++ b/spec/mspec/lib/mspec/runner/mspec.rb @@ -10,7 +10,6 @@ class MSpecEnv end module MSpec - @exit = nil @abort = nil @start = nil @@ -20,26 +19,35 @@ module MSpec @after = nil @leave = nil @finish = nil - @exclude = nil - @include = nil + @exclude = [] + @include = [] @leave = nil @load = nil @unload = nil @tagged = nil @current = nil + @passed = nil @example = nil @modes = [] @shared = {} @guarded = [] @features = {} @exception = nil - @randomize = nil - @repeat = nil + @randomize = false + @repeat = 1 @expectation = nil @expectations = false + @skips = [] + @subprocesses = [] + + class << self + attr_reader :file, :include, :exclude, :skips, :subprocesses + attr_writer :repeat, :randomize + attr_accessor :formatter + end - def self.describe(mod, options=nil, &block) - state = ContextState.new mod, options + def self.describe(description, options = nil, &block) + state = ContextState.new description, options state.parent = current MSpec.register_current state @@ -50,17 +58,21 @@ module MSpec def self.process STDOUT.puts RUBY_DESCRIPTION + STDOUT.flush actions :start files actions :finish end + def self.files_array + @files + end + def self.each_file(&block) if ENV["MSPEC_MULTI"] - STDOUT.print "." - STDOUT.flush - while file = STDIN.gets and file = file.chomp + while file = STDIN.gets + file = file.chomp return if file == "QUIT" yield file begin @@ -74,7 +86,7 @@ module MSpec # The parent closed the connection without QUIT abort "the parent did not send QUIT" else - return unless files = retrieve(:files) + return unless files = @files shuffle files if randomize? files.each(&block) end @@ -83,10 +95,11 @@ module MSpec def self.files each_file do |file| setup_env - store :file, file + @file = file actions :load protect("loading #{file}") { Kernel.load file } actions :unload + raise "#{file} was executed but did not reset the current example: #{@current}" if @current end end @@ -101,11 +114,14 @@ module MSpec def self.protect(location, &block) begin - @env.instance_eval(&block) + @env.instance_exec(&block) return true rescue SystemExit => e raise e - rescue Exception => exc + rescue SkippedSpecError => e + @skips << [e, block] + return false + rescue Object => exc register_exit 1 actions :exception, ExceptionState.new(current && current.state, location, exc) return false @@ -128,22 +144,24 @@ module MSpec # Sets the toplevel ContextState to +state+. def self.register_current(state) - store :current, state + @current = state end # Sets the toplevel ContextState to +nil+. def self.clear_current - store :current, nil + @current = nil end # Returns the toplevel ContextState. def self.current - retrieve :current + @current end # Stores the shared ContextState keyed by description. def self.register_shared(state) - @shared[state.to_s] = state + name = state.to_s + raise "duplicated shared #describe: #{name}" if @shared.key?(name) + @shared[name] = state end # Returns the shared ContextState matching description. @@ -153,17 +171,17 @@ module MSpec # Stores the exit code used by the runner scripts. def self.register_exit(code) - store :exit, code + @exit = code end # Retrieves the stored exit code. def self.exit_code - retrieve(:exit).to_i + @exit.to_i end # Stores the list of files to be evaluated. def self.register_files(files) - store :files, files + @files = files end # Stores one or more substitution patterns for transforming @@ -174,7 +192,7 @@ module MSpec # # See also +tags_file+. def self.register_tags_patterns(patterns) - store :tags_patterns, patterns + @tags_patterns = patterns end # Registers an operating mode. Modes recognized by MSpec: @@ -185,30 +203,30 @@ module MSpec # :report - specs that are guarded are reported # :unguarded - all guards are forced off def self.register_mode(mode) - modes = retrieve :modes + modes = @modes modes << mode unless modes.include? mode end # Clears all registered modes. def self.clear_modes - store :modes, [] + @modes = [] end # Returns +true+ if +mode+ is registered. def self.mode?(mode) - retrieve(:modes).include? mode + @modes.include? mode end def self.enable_feature(feature) - retrieve(:features)[feature] = true + @features[feature] = true end def self.disable_feature(feature) - retrieve(:features)[feature] = false + @features[feature] = false end def self.feature_enabled?(feature) - retrieve(:features)[feature] || false + @features[feature] || false end def self.retrieve(symbol) @@ -227,6 +245,7 @@ module MSpec # :before before a single spec is run # :add while a describe block is adding examples to run later # :expectation before a 'should', 'should_receive', etc. + # :passed after an example block is run and passes, passed the block, run before :example action # :example after an example block is run, passed the block # :exception after an exception is rescued # :after after a single spec is run @@ -257,21 +276,17 @@ module MSpec end end - def self.randomize(flag=true) - @randomize = flag - end - def self.randomize? - @randomize == true - end - - def self.repeat=(times) - @repeat = times + @randomize end def self.repeat - (@repeat || 1).times do + if @repeat == 1 yield + else + @repeat.times do + yield + end end end @@ -287,17 +302,17 @@ module MSpec # Records that an expectation has been encountered in an example. def self.expectation - store :expectations, true + @expectations = true end # Returns true if an expectation has been encountered def self.expectation? - retrieve :expectations + @expectations end # Resets the flag that an expectation has been encountered in an example. def self.clear_expectations - store :expectations, false + @expectations = false end # Transforms a spec filename into a tags filename by applying each @@ -311,9 +326,9 @@ module MSpec # # See also +register_tags_patterns+. def self.tags_file - patterns = retrieve(:tags_patterns) || + patterns = @tags_patterns || [[%r(spec/), 'spec/tags/'], [/_spec.rb$/, '_tags.txt']] - patterns.inject(retrieve(:file).dup) do |file, pattern| + patterns.inject(@file.dup) do |file, pattern| file.gsub(*pattern) end end @@ -350,6 +365,7 @@ module MSpec # Writes each tag in +tags+ to the tag file. Overwrites the # tag file if it exists. def self.write_tags(tags) + return delete_tags if tags.empty? file = tags_file make_tag_dir(file) File.open(file, "w:utf-8") do |f| @@ -381,7 +397,7 @@ module MSpec desc = tag.escape(tag.description) file = tags_file if File.exist? file - lines = IO.readlines(file) + lines = File.readlines(file) File.open(file, "w:utf-8") do |f| lines.each do |line| line = line.chomp diff --git a/spec/mspec/lib/mspec/runner/object.rb b/spec/mspec/lib/mspec/runner/object.rb index 2ea8197165..58d98cc4df 100644 --- a/spec/mspec/lib/mspec/runner/object.rb +++ b/spec/mspec/lib/mspec/runner/object.rb @@ -1,18 +1,18 @@ class Object - private def before(at=:each, &block) + private def before(at = :each, &block) MSpec.current.before at, &block end - private def after(at=:each, &block) + private def after(at = :each, &block) MSpec.current.after at, &block end - private def describe(mod, msg=nil, options=nil, &block) - MSpec.describe mod, msg, &block + private def describe(description, options = nil, &block) + MSpec.describe description, options, &block end - private def it(msg, &block) - MSpec.current.it msg, &block + private def it(desc, &block) + MSpec.current.it desc, &block end private def it_should_behave_like(desc) diff --git a/spec/mspec/lib/mspec/runner/parallel.rb b/spec/mspec/lib/mspec/runner/parallel.rb new file mode 100644 index 0000000000..6a9ecd155d --- /dev/null +++ b/spec/mspec/lib/mspec/runner/parallel.rb @@ -0,0 +1,98 @@ +class ParallelRunner + def initialize(files, processes, formatter, argv) + @files = files + @processes = processes + @formatter = formatter + @argv = argv + @last_files = {} + @output_files = [] + @success = true + end + + def launch_children + @children = @processes.times.map { |i| + name = tmp "mspec-multi-#{i}" + @output_files << name + + env = { + "SPEC_TEMP_DIR" => "#{SPEC_TEMP_DIR}_#{i}", + "MSPEC_MULTI" => i.to_s + } + command = @argv + ["-fy", "-o", name] + $stderr.puts "$ #{command.join(' ')}" if $MSPEC_DEBUG + IO.popen([env, *command, close_others: false], "rb+") + } + end + + def handle(child, message) + case message + when '.' + @formatter.unload + send_new_file_or_quit(child) + else + if message == nil + msg = "A child mspec-run process died unexpectedly" + else + msg = "A child mspec-run process printed unexpected output on STDOUT" + while chunk = (child.read_nonblock(4096) rescue nil) + message += chunk + end + message.chomp!('.') + msg += ": #{message.inspect}" + end + + if last_file = @last_files[child] + msg += " while running #{last_file}" + end + + @success = false + quit(child) + abort "\n#{msg}" + end + end + + def quit(child) + begin + child.puts "QUIT" + rescue Errno::EPIPE + # The child process already died + end + _pid, status = Process.wait2(child.pid) + @success &&= status.success? + child.close + @children.delete(child) + end + + def send_new_file_or_quit(child) + if @files.empty? + quit(child) + else + file = @files.shift + @last_files[child] = file + child.puts file + end + end + + def run + MSpec.register_files @files + launch_children + + puts @children.map { |child| child.gets }.uniq + @formatter.start + begin + @children.each { |child| send_new_file_or_quit(child) } + + until @children.empty? + IO.select(@children)[0].each { |child| + handle(child, child.read(1)) + } + end + ensure + @children.dup.each { |child| quit(child) } + @formatter.aggregate_results(@output_files) + @formatter.finish + end + + @success + end +end diff --git a/spec/mspec/lib/mspec/runner/shared.rb b/spec/mspec/lib/mspec/runner/shared.rb index b606de473b..283711c1d7 100644 --- a/spec/mspec/lib/mspec/runner/shared.rb +++ b/spec/mspec/lib/mspec/runner/shared.rb @@ -1,10 +1,14 @@ require 'mspec/runner/mspec' -def it_behaves_like(desc, meth, obj=nil) - send :before, :all do +def it_behaves_like(desc, meth, obj = nil) + before :all do @method = meth @object = obj end + after :all do + @method = nil + @object = nil + end - send :it_should_behave_like, desc.to_s + it_should_behave_like desc.to_s end diff --git a/spec/mspec/lib/mspec/runner/tag.rb b/spec/mspec/lib/mspec/runner/tag.rb index e2275ad3a6..820df9159e 100644 --- a/spec/mspec/lib/mspec/runner/tag.rb +++ b/spec/mspec/lib/mspec/runner/tag.rb @@ -1,7 +1,7 @@ class SpecTag attr_accessor :tag, :comment, :description - def initialize(string=nil) + def initialize(string = nil) parse(string) if string 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..425dd4d11c --- /dev/null +++ b/spec/mspec/lib/mspec/utils/format.rb @@ -0,0 +1,24 @@ +# 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) + if String === obj and obj.include?("\n") + "\n#{obj.inspect.gsub('\n', "\n")}" + else + obj.pretty_inspect.chomp + end + rescue => e + "#<#{obj.class}>(#pretty_inspect raised #{e.inspect})" + end +end diff --git a/spec/mspec/lib/mspec/utils/name_map.rb b/spec/mspec/lib/mspec/utils/name_map.rb index c1de081af0..9b04112e2e 100644 --- a/spec/mspec/lib/mspec/utils/name_map.rb +++ b/spec/mspec/lib/mspec/utils/name_map.rb @@ -8,10 +8,9 @@ class NameMap '*' => 'multiply', '/' => 'divide', '%' => 'modulo', - '<<' => {'Bignum' => 'left_shift', - 'Fixnum' => 'left_shift', - 'IO' => 'output', - :default => 'append' }, + '<<' => {'Integer' => 'left_shift', + 'IO' => 'output', + :default => 'append' }, '>>' => 'right_shift', '<' => 'lt', '<=' => 'lte', @@ -25,33 +24,22 @@ class NameMap '[]=' => 'element_set', '**' => 'exponent', '!' => 'not', - '~' => {'Bignum' => 'complement', - 'Fixnum' => 'complement', - 'Regexp' => 'match', - 'String' => 'match' }, + '~' => {'Integer' => 'complement', + :default => 'match' }, '!=' => 'not_equal', '!~' => 'not_match', '=~' => 'match', - '&' => {'Bignum' => 'bit_and', - 'Fixnum' => 'bit_and', + '&' => {'Integer' => 'bit_and', 'Array' => 'intersection', - 'TrueClass' => 'and', - 'FalseClass' => 'and', - 'NilClass' => 'and', - 'Set' => 'intersection' }, - '|' => {'Bignum' => 'bit_or', - 'Fixnum' => 'bit_or', + 'Set' => 'intersection', + :default => 'and' }, + '|' => {'Integer' => 'bit_or', 'Array' => 'union', - 'TrueClass' => 'or', - 'FalseClass' => 'or', - 'NilClass' => 'or', - 'Set' => 'union' }, - '^' => {'Bignum' => 'bit_xor', - 'Fixnum' => 'bit_xor', - 'TrueClass' => 'xor', - 'FalseClass' => 'xor', - 'NilClass' => 'xor', - 'Set' => 'exclusion'}, + 'Set' => 'union', + :default => 'or' }, + '^' => {'Integer' => 'bit_xor', + 'Set' => 'exclusion', + :default => 'xor' }, } EXCLUDED = %w[ @@ -63,7 +51,11 @@ class NameMap SpecVersion ] - def initialize(filter=false) + ALWAYS_PRIVATE = %w[ + initialize initialize_copy initialize_clone initialize_dup respond_to_missing? + ].map(&:to_sym) + + def initialize(filter = false) @seen = {} @filter = filter end @@ -74,10 +66,17 @@ class NameMap end def class_or_module(c) - const = Object.const_get(c, false) + begin + const = Object.const_get(c, false) + rescue NameError, RuntimeError + # Either the constant doesn't exist or it is + # explicitly raising an error, like `SortedSet`. + return nil + end + return nil unless Module === const + filtered = @filter && EXCLUDED.include?(const.name) - return const if Module === const and !filtered - rescue NameError + return const unless filtered end def namespace(mod, const) @@ -85,7 +84,7 @@ class NameMap "#{mod}::#{const}" end - def map(hash, constants, mod=nil) + def map(hash, constants, mod = nil) @seen = {} unless mod constants.each do |const| @@ -98,7 +97,8 @@ class NameMap hash["#{name}."] = ms.sort unless ms.empty? ms = m.public_instance_methods(false) + - m.protected_instance_methods(false) + m.protected_instance_methods(false) + + (m.private_instance_methods(false) & ALWAYS_PRIVATE) ms.map! { |x| x.to_s } hash["#{name}#"] = ms.sort unless ms.empty? @@ -119,7 +119,12 @@ class NameMap def file_name(m, c) if MAP.key?(m) - name = MAP[m].is_a?(Hash) ? MAP[m][c.split('::').last] || MAP[m][:default] : MAP[m] + mapping = MAP[m] + if mapping.is_a?(Hash) + name = mapping[c.split('::').last] || mapping.fetch(:default) + else + name = mapping + end else name = m.gsub(/[?!=]/, '') end diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb index 9f8dd01dbf..adeafa1f81 100644 --- a/spec/mspec/lib/mspec/utils/options.rb +++ b/spec/mspec/lib/mspec/utils/options.rb @@ -32,9 +32,13 @@ class MSpecOptions # Raised if an unrecognized option is encountered. class ParseError < Exception; end + class << self + attr_accessor :latest + end + attr_accessor :config, :banner, :width, :options - def initialize(banner="", width=30, config=nil) + def initialize(banner = "", width = 30, config = nil) @banner = banner @config = config @width = width @@ -46,7 +50,7 @@ class MSpecOptions @extra << x } - yield self if block_given? + MSpecOptions.latest = self end # Registers an option. Acceptable formats for arguments are: @@ -94,7 +98,7 @@ class MSpecOptions @options.find { |o| o.match? opt } end - # Processes an option. Calles the #on_extra block (or default) for + # Processes an option. Calls the #on_extra block (or default) for # unrecognized options. For registered options, possibly fetches an # argument and invokes the option's block if it is not nil. def process(argv, entry, opt, arg) @@ -123,7 +127,7 @@ class MSpecOptions # Parses an array of command line entries, calling blocks for # registered options. - def parse(argv=ARGV) + def parse(argv = ARGV) argv = Array(argv).dup while entry = argv.shift @@ -200,6 +204,13 @@ class MSpecOptions "Load FILE containing configuration options", &block) end + def env + on("--env", "KEY=VALUE", "Set environment variable") do |env| + key, value = env.split('=', 2) + ENV[key] = value + end + end + def targets on("-t", "--target", "TARGET", "Implementation to run the specs, where TARGET is:") do |t| @@ -274,6 +285,8 @@ class MSpecOptions config[:formatter] = SpinnerFormatter when 't', 'method' config[:formatter] = MethodFormatter + when 'e', 'stats' + config[:formatter] = StatsPerFileFormatter when 'y', 'yaml' config[:formatter] = YamlFormatter when 'p', 'profile' @@ -281,7 +294,7 @@ class MSpecOptions when 'j', 'junit' config[:formatter] = JUnitFormatter else - abort "Unknown format: #{o}\n#{@parser}" unless File.exist?(o) + abort "Unknown format: #{o}" unless File.exist?(o) require File.expand_path(o) if Object.const_defined?(:CUSTOM_MSPEC_FORMATTER) config[:formatter] = CUSTOM_MSPEC_FORMATTER @@ -300,6 +313,7 @@ class MSpecOptions doc " m, summary SummaryFormatter" doc " a, *, spin SpinnerFormatter" doc " t, method MethodFormatter" + doc " e, stats StatsPerFileFormatter" doc " y, yaml YamlFormatter" doc " p, profile ProfileFormatter" doc " j, junit JUnitFormatter\n" @@ -308,6 +322,11 @@ class MSpecOptions "Write formatter output to FILE") do |f| config[:output] = f end + + on("--error-output", "FILE", + "Write error output of failing specs to FILE, or $stderr if value is 'stderr'.") do |f| + config[:error_output] = f + end end def filters @@ -377,14 +396,14 @@ class MSpecOptions def randomize on("-H", "--random", "Randomize the list of spec files") do - MSpec.randomize + MSpec.randomize = true end end def repeat on("-R", "--repeat", "NUMBER", "Repeatedly run an example NUMBER times") do |o| - MSpec.repeat = o.to_i + MSpec.repeat = Integer(o) end end @@ -392,11 +411,11 @@ class MSpecOptions on("-V", "--verbose", "Output the name of each file processed") do obj = Object.new def obj.start - @width = MSpec.retrieve(:files).inject(0) { |max, f| f.size > max ? f.size : max } + @width = MSpec.files_array.inject(0) { |max, f| f.size > max ? f.size : max } end def obj.load - file = MSpec.retrieve :file - STDERR.print "\n#{file.ljust(@width)}" + file = MSpec.file + STDERR.print "\n#{file.ljust(@width)}\n" end MSpec.register :start, obj MSpec.register :load, obj @@ -411,14 +430,26 @@ class MSpecOptions end MSpec.register :load, obj end + + on("--print-skips", "Print skips") do + config[:print_skips] = true + end end def interrupt - on("--int-spec", "Control-C interupts the current spec only") do + on("--int-spec", "Control-C interrupts the current spec only") do config[:abort] = false 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 @@ -453,15 +484,22 @@ class MSpecOptions def debug on("-d", "--debug", - "Set MSpec debugging flag for more verbose output") do + "Disable MSpec backtrace filtering") do $MSPEC_DEBUG = true end end + def launchable + on("--launchable-test-reports", "DIR", + "DIR The directory for reporting test results in Launchable JSON format") do |o| + require 'mspec/runner/formatters/launchable' + config[:launchable] = LaunchableFormatter.setDir(o) + end + end + def all - # Generated with: - # puts File.read(__FILE__).scan(/def (\w+).*\n\s*on\(/) configure {} + env targets formatters filters @@ -473,9 +511,11 @@ class MSpecOptions repeat verbose interrupt + timeout verify action_filters actions debug + launchable end end diff --git a/spec/mspec/lib/mspec/utils/script.rb b/spec/mspec/lib/mspec/utils/script.rb index 24cd069bb4..15fd23fabf 100644 --- a/spec/mspec/lib/mspec/utils/script.rb +++ b/spec/mspec/lib/mspec/utils/script.rb @@ -3,7 +3,6 @@ require 'mspec/guards/version' require 'mspec/utils/warnings' # MSpecScript provides a skeleton for all the MSpec runner scripts. - class MSpecScript # Returns the config object. Maintained at the class # level to easily enable simple config files. See the @@ -38,10 +37,19 @@ class MSpecScript config[key] end + class << self + attr_accessor :child_process + end + + # True if the current process is the one going to run the specs with `MSpec.process`. + # False for e.g. `mspec` which exec's to `mspec-run`. + # This is useful in .mspec config files. + def self.child_process? + MSpecScript.child_process + end + def initialize - ruby_version_is ""..."2.2" do - abort "MSpec needs Ruby 2.2 or more recent" - end + check_version! config[:formatter] = nil config[:includes] = [] @@ -125,14 +133,9 @@ class MSpecScript require 'mspec/runner/formatters/file' require 'mspec/runner/filters' - if config[:formatter].nil? - config[:formatter] = STDOUT.tty? ? SpinnerFormatter : @files.size < 50 ? DottedFormatter : FileFormatter - end - - if config[:formatter] - formatter = config[:formatter].new(config[:output]) + if formatter = config_formatter formatter.register - MSpec.store :formatter, formatter + MSpec.formatter = formatter end MatchFilter.new(:include, *config[:includes]).register unless config[:includes].empty? @@ -149,6 +152,23 @@ class MSpecScript custom_register end + # Makes a formatter specified by :formatter option. + def config_formatter + if config[:formatter].nil? + config[:formatter] = STDOUT.tty? ? SpinnerFormatter : @files.size < 50 ? DottedFormatter : FileFormatter + end + + if config[:formatter] + config[:formatter] = config[:formatter].new(config[:output]) + end + + if config[:launchable] + config[:formatter].extend config[:launchable] + end + + config[:formatter] + end + # Callback for enabling custom actions, etc. This version is a # no-op. Provide an implementation specific version in a config # file. Called by #register. @@ -189,7 +209,11 @@ class MSpecScript end patterns.each do |pattern| - expanded = File.expand_path(pattern) + begin + expanded = File.realpath(pattern) + rescue Errno::ENOENT, Errno::ENOTDIR + next + end if File.file?(expanded) && expanded.end_with?('.rb') return [expanded] elsif File.directory?(expanded) @@ -260,10 +284,11 @@ class MSpecScript # Instantiates an instance and calls the series of methods to # invoke the script. - def self.main + def self.main(child_process = true) + MSpecScript.child_process = child_process + script = new script.load_default - script.try_load '~/.mspecrc' script.options script.signals script.register @@ -271,4 +296,10 @@ class MSpecScript require 'mspec' script.run end + + private def check_version! + ruby_version_is ""..."2.6" do + warn "MSpec is supported for Ruby 2.6 and above only" + end + end end diff --git a/spec/mspec/lib/mspec/utils/version.rb b/spec/mspec/lib/mspec/utils/version.rb index 787a76b053..9c1c58b8df 100644 --- a/spec/mspec/lib/mspec/utils/version.rb +++ b/spec/mspec/lib/mspec/utils/version.rb @@ -42,7 +42,7 @@ class SpecVersion def <=>(other) if other.respond_to? :to_int - other = Integer other + other = Integer(other.to_int) else other = SpecVersion.new(String(other)).to_i end diff --git a/spec/mspec/lib/mspec/utils/warnings.rb b/spec/mspec/lib/mspec/utils/warnings.rb index 4d23474236..23efc696a5 100644 --- a/spec/mspec/lib/mspec/utils/warnings.rb +++ b/spec/mspec/lib/mspec/utils/warnings.rb @@ -1,61 +1,10 @@ require 'mspec/guards/version' -if RUBY_ENGINE == "ruby" and ruby_version_is("2.4") - ruby_version_is "2.4"..."2.5" do - # Kernel#warn does not delegate to Warning.warn in 2.4 - module Kernel - remove_method :warn - def warn(*messages) - return if $VERBOSE == nil or messages.empty? - msg = messages.join("\n") - msg += "\n" unless msg.end_with?("\n") - Warning.warn(msg) - end - private :warn - end - end - - def Warning.warn(message) - if Thread.current[:in_mspec_complain_matcher] - return $stderr.write(message) - end - - case message - # $VERBOSE = true warnings - 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 /method redefined/ - when /previous definition of/ - when /instance variable @.+ not initialized/ - when /statement not reached/ - when /shadowing outer local variable/ - when /setting Encoding.default_(in|ex)ternal/ - when /unknown (un)?pack directive/ - when /(un)?trust(ed\?)? is deprecated/ - when /\.exists\? is a deprecated name/ - when /Float .+ out of range/ - when /passing a block to String#(bytes|chars|codepoints|lines) is deprecated/ - when /core\/string\/modulo_spec\.rb:\d+: warning: too many arguments for format string/ - when /regexp\/shared\/new_ascii(_8bit)?\.rb:\d+: warning: Unknown escape .+ is ignored/ - - # $VERBOSE = false warnings - when /constant ::(Fixnum|Bignum) is deprecated/ - when /\/(argf|io|stringio)\/.+(ARGF|IO)#(lines|chars|bytes|codepoints) is deprecated/ - when /Thread\.exclusive is deprecated.+\n.+thread\/exclusive_spec\.rb/ - when /hash\/shared\/index\.rb:\d+: warning: Hash#index is deprecated; use Hash#key/ - when /env\/shared\/key\.rb:\d+: warning: ENV\.index is deprecated; use ENV\.key/ - when /exponent(_spec)?\.rb:\d+: warning: in a\*\*b, b may be too big/ - when /enumerator\/(new|initialize_spec)\.rb:\d+: warning: Enumerator\.new without a block is deprecated/ - else - $stderr.write message - end - end -else - $VERBOSE = nil unless ENV['OUTPUT_WARNINGS'] +# Always enable deprecation warnings when running MSpec, as ruby/spec tests for them, +# and like in most test frameworks, deprecation warnings should be enabled by default, +# so that deprecations are noticed before the breaking change. +# Disable experimental warnings, we want to test new experimental features in ruby/spec. +if Object.const_defined?(:Warning) and Warning.respond_to?(:[]=) + Warning[:deprecated] = true + Warning[:experimental] = false end diff --git a/spec/mspec/spec/commands/mkspec_spec.rb b/spec/mspec/spec/commands/mkspec_spec.rb index 14c363f286..32262723de 100644 --- a/spec/mspec/spec/commands/mkspec_spec.rb +++ b/spec/mspec/spec/commands/mkspec_spec.rb @@ -1,18 +1,18 @@ require 'spec_helper' require 'mspec/commands/mkspec' +require 'fileutils' - -describe "The -c, --constant CONSTANT option" do +RSpec.describe "The -c, --constant CONSTANT option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-c", "--constant", "CONSTANT", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-c", "--constant", "CONSTANT", an_instance_of(String)) @script.options [] end @@ -21,22 +21,22 @@ describe "The -c, --constant CONSTANT option" do ["-c", "--constant"].each do |opt| @config[:constants] = [] @script.options [opt, "Object"] - @config[:constants].should include("Object") + expect(@config[:constants]).to include("Object") end end end -describe "The -b, --base DIR option" do +RSpec.describe "The -b, --base DIR option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-b", "--base", "DIR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-b", "--base", "DIR", an_instance_of(String)) @script.options [] end @@ -45,22 +45,22 @@ describe "The -b, --base DIR option" do ["-b", "--base"].each do |opt| @config[:base] = nil @script.options [opt, "superspec"] - @config[:base].should == File.expand_path("superspec") + expect(@config[:base]).to eq(File.expand_path("superspec")) end end end -describe "The -r, --require LIBRARY option" do +RSpec.describe "The -r, --require LIBRARY option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-r", "--require", "LIBRARY", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-r", "--require", "LIBRARY", an_instance_of(String)) @script.options [] end @@ -69,22 +69,22 @@ describe "The -r, --require LIBRARY option" do ["-r", "--require"].each do |opt| @config[:requires] = [] @script.options [opt, "libspec"] - @config[:requires].should include("libspec") + expect(@config[:requires]).to include("libspec") end end end -describe "The -V, --version-guard VERSION option" do +RSpec.describe "The -V, --version-guard VERSION option" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new @config = @script.config end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-V", "--version-guard", "VERSION", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-V", "--version-guard", "VERSION", an_instance_of(String)) @script.options [] end @@ -93,150 +93,150 @@ describe "The -V, --version-guard VERSION option" do ["-r", "--require"].each do |opt| @config[:requires] = [] @script.options [opt, "libspec"] - @config[:requires].should include("libspec") + expect(@config[:requires]).to include("libspec") end end end -describe MkSpec, "#options" do +RSpec.describe MkSpec, "#options" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MkSpec.new end it "parses the command line options" do - @options.should_receive(:parse).with(["--this", "and", "--that"]) + expect(@options).to receive(:parse).with(["--this", "and", "--that"]) @script.options ["--this", "and", "--that"] end it "parses ARGV unless passed other options" do - @options.should_receive(:parse).with(ARGV) + expect(@options).to receive(:parse).with(ARGV) @script.options end it "prints help and exits if passed an unrecognized option" do - @options.should_receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) - @options.stub(:puts) - @options.stub(:exit) + expect(@options).to receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) + allow(@options).to receive(:puts) + allow(@options).to receive(:exit) @script.options ["--iunknown"] end end -describe MkSpec, "#create_directory" do +RSpec.describe MkSpec, "#create_directory" do before :each do @script = MkSpec.new @script.config[:base] = "spec" end it "prints a warning if a file with the directory name exists" do - File.should_receive(:exist?).and_return(true) - File.should_receive(:directory?).and_return(false) - FileUtils.should_not_receive(:mkdir_p) - @script.should_receive(:puts).with("spec/class already exists and is not a directory.") - @script.create_directory("Class").should == nil + expect(File).to receive(:exist?).and_return(true) + expect(File).to receive(:directory?).and_return(false) + expect(FileUtils).not_to receive(:mkdir_p) + expect(@script).to receive(:puts).with("spec/class already exists and is not a directory.") + expect(@script.create_directory("Class")).to eq(nil) end it "does nothing if the directory already exists" do - File.should_receive(:exist?).and_return(true) - File.should_receive(:directory?).and_return(true) - FileUtils.should_not_receive(:mkdir_p) - @script.create_directory("Class").should == "spec/class" + expect(File).to receive(:exist?).and_return(true) + expect(File).to receive(:directory?).and_return(true) + expect(FileUtils).not_to receive(:mkdir_p) + expect(@script.create_directory("Class")).to eq("spec/class") end it "creates the directory if it does not exist" do - File.should_receive(:exist?).and_return(false) - @script.should_receive(:mkdir_p).with("spec/class") - @script.create_directory("Class").should == "spec/class" + expect(File).to receive(:exist?).and_return(false) + expect(@script).to receive(:mkdir_p).with("spec/class") + expect(@script.create_directory("Class")).to eq("spec/class") end it "creates the directory for a namespaced module if it does not exist" do - File.should_receive(:exist?).and_return(false) - @script.should_receive(:mkdir_p).with("spec/struct/tms") - @script.create_directory("Struct::Tms").should == "spec/struct/tms" + expect(File).to receive(:exist?).and_return(false) + expect(@script).to receive(:mkdir_p).with("spec/struct/tms") + expect(@script.create_directory("Struct::Tms")).to eq("spec/struct/tms") end end -describe MkSpec, "#write_requires" do +RSpec.describe MkSpec, "#write_requires" do before :each do @script = MkSpec.new @script.config[:base] = "spec" @file = double("file") - File.stub(:open).and_yield(@file) + allow(File).to receive(:open).and_yield(@file) end it "writes the spec_helper require line" do - @file.should_receive(:puts).with("require File.expand_path('../../../../spec_helper', __FILE__)") + expect(@file).to receive(:puts).with("require_relative '../../../spec_helper'") @script.write_requires("spec/core/tcejbo", "spec/core/tcejbo/inspect_spec.rb") end it "writes require lines for each library specified on the command line" do - @file.stub(:puts) - @file.should_receive(:puts).with("require File.expand_path('../../../../spec_helper', __FILE__)") - @file.should_receive(:puts).with("require 'complex'") + allow(@file).to receive(:puts) + expect(@file).to receive(:puts).with("require_relative '../../../spec_helper'") + expect(@file).to receive(:puts).with("require 'complex'") @script.config[:requires] << 'complex' @script.write_requires("spec/core/tcejbo", "spec/core/tcejbo/inspect_spec.rb") end end -describe MkSpec, "#write_spec" do +RSpec.describe MkSpec, "#write_spec" do before :each do @file = IOStub.new - File.stub(:open).and_yield(@file) + allow(File).to receive(:open).and_yield(@file) @script = MkSpec.new - @script.stub(:puts) + allow(@script).to receive(:puts) @response = double("system command response") - @response.stub(:include?).and_return(false) - @script.stub(:`).and_return(@response) + allow(@response).to receive(:include?).and_return(false) + allow(@script).to receive(:`).and_return(@response) end it "checks if specs exist for the method if the spec file exists" do - name = Regexp.escape(@script.ruby) - @script.should_receive(:`).with( + name = Regexp.escape(RbConfig.ruby) + expect(@script).to receive(:`).with( %r"#{name} #{MSPEC_HOME}/bin/mspec-run --dry-run --unguarded -fs -e 'Object#inspect' spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "checks for the method name in the spec file output" do - @response.should_receive(:include?).with("Array#[]=") + expect(@response).to receive(:include?).with("Array#[]=") @script.write_spec("spec/core/yarra/element_set_spec.rb", "Array#[]=", true) end it "returns nil if the spec file exists and contains a spec for the method" do - @response.stub(:include?).and_return(true) - @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true).should == nil + allow(@response).to receive(:include?).and_return(true) + expect(@script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true)).to eq(nil) end it "does not print the spec file name if it exists and contains a spec for the method" do - @response.stub(:include?).and_return(true) - @script.should_not_receive(:puts) + allow(@response).to receive(:include?).and_return(true) + expect(@script).not_to receive(:puts) @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "prints the spec file name if a template spec is written" do - @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") + expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "writes a template spec to the file if the spec file does not exist" do - @file.should_receive(:puts).twice - @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") + expect(@file).to receive(:puts).twice + expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", false) end it "writes a template spec to the file if it exists but contains no spec for the method" do - @response.should_receive(:include?).and_return(false) - @file.should_receive(:puts).twice - @script.should_receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") + expect(@response).to receive(:include?).and_return(false) + expect(@file).to receive(:puts).twice + expect(@script).to receive(:puts).with("spec/core/tcejbo/inspect_spec.rb") @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) end it "writes a template spec" do @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) - @file.should == <<EOS + expect(@file).to eq <<EOS describe "Object#inspect" do it "needs to be reviewed for spec completeness" @@ -247,7 +247,7 @@ EOS it "writes a template spec with version guard" do @script.config[:version] = '""..."1.9"' @script.write_spec("spec/core/tcejbo/inspect_spec.rb", "Object#inspect", true) - @file.should == <<EOS + expect(@file).to eq <<EOS ruby_version_is ""..."1.9" do describe "Object#inspect" do @@ -259,105 +259,105 @@ EOS end end -describe MkSpec, "#create_file" do +RSpec.describe MkSpec, "#create_file" do before :each do @script = MkSpec.new - @script.stub(:write_requires) - @script.stub(:write_spec) + allow(@script).to receive(:write_requires) + allow(@script).to receive(:write_spec) - File.stub(:exist?).and_return(false) + allow(File).to receive(:exist?).and_return(false) end it "generates a file name based on the directory, class/module, and method" do - File.should_receive(:join).with("spec/tcejbo", "inspect_spec.rb" + expect(File).to receive(:join).with("spec/tcejbo", "inspect_spec.rb" ).and_return("spec/tcejbo/inspect_spec.rb") @script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect") end it "does not call #write_requires if the spec file already exists" do - File.should_receive(:exist?).and_return(true) - @script.should_not_receive(:write_requires) + expect(File).to receive(:exist?).and_return(true) + expect(@script).not_to receive(:write_requires) @script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect") end it "calls #write_requires if the spec file does not exist" do - File.should_receive(:exist?).and_return(false) - @script.should_receive(:write_requires).with( + expect(File).to receive(:exist?).and_return(false) + expect(@script).to receive(:write_requires).with( "spec/tcejbo", "spec/tcejbo/inspect_spec.rb") @script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect") end it "calls #write_spec with the file, method name" do - @script.should_receive(:write_spec).with( + expect(@script).to receive(:write_spec).with( "spec/tcejbo/inspect_spec.rb", "Object#inspect", false) @script.create_file("spec/tcejbo", "Object", "inspect", "Object#inspect") end end -describe MkSpec, "#run" do +RSpec.describe MkSpec, "#run" do before :each do @options = MSpecOptions.new - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @map = NameMap.new - NameMap.stub(:new).and_return(@map) + allow(NameMap).to receive(:new).and_return(@map) @script = MkSpec.new - @script.stub(:create_directory).and_return("spec/mkspec") - @script.stub(:create_file) + allow(@script).to receive(:create_directory).and_return("spec/mkspec") + allow(@script).to receive(:create_file) @script.config[:constants] = [MkSpec] end it "loads files in the requires list" do - @script.stub(:require) - @script.should_receive(:require).with("alib") - @script.should_receive(:require).with("blib") + allow(@script).to receive(:require) + expect(@script).to receive(:require).with("alib") + expect(@script).to receive(:require).with("blib") @script.config[:requires] = ["alib", "blib"] @script.run end it "creates a map of constants to methods" do - @map.should_receive(:map).with({}, @script.config[:constants]).and_return({}) + expect(@map).to receive(:map).with({}, @script.config[:constants]).and_return({}) @script.run end it "calls #create_directory for each class/module in the map" do - @script.should_receive(:create_directory).with("MkSpec").twice + expect(@script).to receive(:create_directory).with("MkSpec").twice @script.run end it "calls #create_file for each method on each class/module in the map" do - @map.should_receive(:map).with({}, @script.config[:constants] + expect(@map).to receive(:map).with({}, @script.config[:constants] ).and_return({"MkSpec#" => ["run"]}) - @script.should_receive(:create_file).with("spec/mkspec", "MkSpec", "run", "MkSpec#run") + expect(@script).to receive(:create_file).with("spec/mkspec", "MkSpec", "run", "MkSpec#run") @script.run end end -describe MkSpec, ".main" do +RSpec.describe MkSpec, ".main" do before :each do @script = double("MkSpec").as_null_object - MkSpec.stub(:new).and_return(@script) + allow(MkSpec).to receive(:new).and_return(@script) end it "sets MSPEC_RUNNER = '1' in the environment" do ENV["MSPEC_RUNNER"] = "0" MkSpec.main - ENV["MSPEC_RUNNER"].should == "1" + expect(ENV["MSPEC_RUNNER"]).to eq("1") end it "creates an instance of MSpecScript" do - MkSpec.should_receive(:new).and_return(@script) + expect(MkSpec).to receive(:new).and_return(@script) MkSpec.main end it "calls the #options method on the script" do - @script.should_receive(:options) + expect(@script).to receive(:options) MkSpec.main end it "calls the #run method on the script" do - @script.should_receive(:run) + expect(@script).to receive(:run) MkSpec.main end end diff --git a/spec/mspec/spec/commands/mspec_ci_spec.rb b/spec/mspec/spec/commands/mspec_ci_spec.rb index a90cbd8d0d..b8dc9d062f 100644 --- a/spec/mspec/spec/commands/mspec_ci_spec.rb +++ b/spec/mspec/spec/commands/mspec_ci_spec.rb @@ -3,148 +3,153 @@ require 'mspec/runner/mspec' require 'mspec/runner/filters/tag' require 'mspec/commands/mspec-ci' -describe MSpecCI, "#options" do +RSpec.describe MSpecCI, "#options" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecCI.new - @script.stub(:config).and_return(@config) - @script.stub(:files).and_return([]) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:files).and_return([]) end it "enables the chdir option" do - @options.should_receive(:chdir) + expect(@options).to receive(:chdir) @script.options [] end it "enables the prefix option" do - @options.should_receive(:prefix) + expect(@options).to receive(:prefix) @script.options [] end it "enables the config option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options [] end it "provides a custom action (block) to the config option" do - @script.should_receive(:load).with("cfg.mspec") + expect(@script).to receive(:load).with("cfg.mspec") @script.options ["-B", "cfg.mspec"] end it "enables the dry run option" do - @options.should_receive(:pretend) + expect(@options).to receive(:pretend) @script.options [] end it "enables the unguarded option" do - @options.should_receive(:unguarded) + expect(@options).to receive(:unguarded) @script.options [] end it "enables the interrupt single specs option" do - @options.should_receive(:interrupt) + expect(@options).to receive(:interrupt) @script.options [] end it "enables the formatter options" do - @options.should_receive(:formatters) + expect(@options).to receive(:formatters) @script.options [] end it "enables the verbose option" do - @options.should_receive(:verbose) + expect(@options).to receive(:verbose) @script.options [] end it "enables the action options" do - @options.should_receive(:actions) + expect(@options).to receive(:actions) @script.options [] end it "enables the action filter options" do - @options.should_receive(:action_filters) + expect(@options).to receive(:action_filters) @script.options [] end it "enables the version option" do - @options.should_receive(:version) + expect(@options).to receive(:version) @script.options [] end it "enables the help option" do - @options.should_receive(:help) + expect(@options).to receive(:help) @script.options [] end + it "enables the repeat option" do + expect(@options).to receive(:repeat) + @script.options @argv + end + it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options [] end end -describe MSpecCI, "#run" do +RSpec.describe MSpecCI, "#run" do before :each do - MSpec.stub(:process) + allow(MSpec).to receive(:process) @filter = double("TagFilter") - TagFilter.stub(:new).and_return(@filter) - @filter.stub(:register) + allow(TagFilter).to receive(:new).and_return(@filter) + allow(@filter).to receive(:register) @tags = ["fails", "critical", "unstable", "incomplete", "unsupported"] @config = { :ci_files => ["one", "two"] } @script = MSpecCI.new - @script.stub(:exit) - @script.stub(:config).and_return(@config) - @script.stub(:files).and_return(["one", "two"]) + allow(@script).to receive(:exit) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:files).and_return(["one", "two"]) @script.options [] end it "registers the tags patterns" do @config[:tags_patterns] = [/spec/, "tags"] - MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"]) + expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"]) @script.run end it "registers the files to process" do - MSpec.should_receive(:register_files).with(["one", "two"]) + expect(MSpec).to receive(:register_files).with(["one", "two"]) @script.run end it "registers a tag filter for 'fails', 'unstable', 'incomplete', 'critical', 'unsupported'" do filter = double("fails filter") - TagFilter.should_receive(:new).with(:exclude, *@tags).and_return(filter) - filter.should_receive(:register) + expect(TagFilter).to receive(:new).with(:exclude, *@tags).and_return(filter) + expect(filter).to receive(:register) @script.run end it "registers an additional exclude tag specified by :ci_xtags" do @config[:ci_xtags] = "windows" filter = double("fails filter") - TagFilter.should_receive(:new).with(:exclude, *(@tags + ["windows"])).and_return(filter) - filter.should_receive(:register) + expect(TagFilter).to receive(:new).with(:exclude, *(@tags + ["windows"])).and_return(filter) + expect(filter).to receive(:register) @script.run end it "registers additional exclude tags specified by a :ci_xtags array" do @config[:ci_xtags] = ["windows", "windoze"] filter = double("fails filter") - TagFilter.should_receive(:new).with(:exclude, + expect(TagFilter).to receive(:new).with(:exclude, *(@tags + ["windows", "windoze"])).and_return(filter) - filter.should_receive(:register) + expect(filter).to receive(:register) @script.run end it "processes the files" do - MSpec.should_receive(:process) + expect(MSpec).to receive(:process) @script.run end it "exits with the exit code registered with MSpec" do - MSpec.stub(:exit_code).and_return(7) - @script.should_receive(:exit).with(7) + allow(MSpec).to receive(:exit_code).and_return(7) + expect(@script).to receive(:exit).with(7) @script.run end end diff --git a/spec/mspec/spec/commands/mspec_run_spec.rb b/spec/mspec/spec/commands/mspec_run_spec.rb index fcb44ad5a9..f96be2b43e 100644 --- a/spec/mspec/spec/commands/mspec_run_spec.rb +++ b/spec/mspec/spec/commands/mspec_run_spec.rb @@ -5,130 +5,135 @@ require 'mspec/commands/mspec-run' one_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/one_spec.rb' two_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/two_spec.rb' -describe MSpecRun, ".new" do +RSpec.describe MSpecRun, ".new" do before :each do @script = MSpecRun.new end it "sets config[:files] to an empty list" do - @script.config[:files].should == [] + expect(@script.config[:files]).to eq([]) end end -describe MSpecRun, "#options" do +RSpec.describe MSpecRun, "#options" do before :each do @argv = [one_spec, two_spec] @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecRun.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "enables the filter options" do - @options.should_receive(:filters) + expect(@options).to receive(:filters) @script.options @argv end it "enables the chdir option" do - @options.should_receive(:chdir) + expect(@options).to receive(:chdir) @script.options @argv end it "enables the prefix option" do - @options.should_receive(:prefix) + expect(@options).to receive(:prefix) @script.options @argv end it "enables the configure option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options @argv end it "provides a custom action (block) to the config option" do - @script.should_receive(:load).with("cfg.mspec") + expect(@script).to receive(:load).with("cfg.mspec") @script.options ["-B", "cfg.mspec", one_spec] end it "enables the randomize option to runs specs in random order" do - @options.should_receive(:randomize) + expect(@options).to receive(:randomize) @script.options @argv end it "enables the dry run option" do - @options.should_receive(:pretend) + expect(@options).to receive(:pretend) @script.options @argv end it "enables the unguarded option" do - @options.should_receive(:unguarded) + expect(@options).to receive(:unguarded) @script.options @argv end it "enables the interrupt single specs option" do - @options.should_receive(:interrupt) + expect(@options).to receive(:interrupt) @script.options @argv end it "enables the formatter options" do - @options.should_receive(:formatters) + expect(@options).to receive(:formatters) @script.options @argv end it "enables the verbose option" do - @options.should_receive(:verbose) + expect(@options).to receive(:verbose) @script.options @argv end it "enables the verify options" do - @options.should_receive(:verify) + expect(@options).to receive(:verify) @script.options @argv end it "enables the action options" do - @options.should_receive(:actions) + expect(@options).to receive(:actions) @script.options @argv end it "enables the action filter options" do - @options.should_receive(:action_filters) + expect(@options).to receive(:action_filters) @script.options @argv end it "enables the version option" do - @options.should_receive(:version) + expect(@options).to receive(:version) @script.options @argv end it "enables the help option" do - @options.should_receive(:help) + expect(@options).to receive(:help) + @script.options @argv + end + + it "enables the repeat option" do + expect(@options).to receive(:repeat) @script.options @argv end 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) - @options.should_receive(:parse).and_return([]) - @script.should_receive(:abort).with("No files specified.") + expect(File).to receive(:directory?).with("./spec").and_return(false) + expect(@options).to receive(:parse).and_return([]) + expect(@script).to receive(:abort).with("No files specified.") @script.options end it "process 'spec/' if it is a directory and no files were specified" do - File.should_receive(:directory?).with("./spec").and_return(true) - @options.should_receive(:parse).and_return([]) - @script.should_receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"]) + expect(File).to receive(:directory?).with("./spec").and_return(true) + expect(@options).to receive(:parse).and_return([]) + expect(@script).to receive(:files).with(["spec/"]).and_return(["spec/a_spec.rb"]) @script.options end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options @argv end end -describe MSpecRun, "#run" do +RSpec.describe MSpecRun, "#run" do before :each do @script = MSpecRun.new - @script.stub(:exit) + allow(@script).to receive(:exit) @spec_dir = File.expand_path(File.dirname(__FILE__)+"/fixtures") @file_patterns = [ @spec_dir+"/level2", @@ -139,35 +144,35 @@ describe MSpecRun, "#run" do @spec_dir+"/one_spec.rb", @spec_dir+"/two_spec.rb"] @script.options @file_patterns - MSpec.stub :process + allow(MSpec).to receive :process end it "registers the tags patterns" do @script.config[:tags_patterns] = [/spec/, "tags"] - MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"]) + expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"]) @script.run end it "registers the files to process" do - MSpec.should_receive(:register_files).with(@files) + expect(MSpec).to receive(:register_files).with(@files) @script.run end it "uses config[:files] if no files are given on the command line" do @script.config[:files] = @file_patterns - MSpec.should_receive(:register_files).with(@files) + expect(MSpec).to receive(:register_files).with(@files) @script.options [] @script.run end it "processes the files" do - MSpec.should_receive(:process) + expect(MSpec).to receive(:process) @script.run end it "exits with the exit code registered with MSpec" do - MSpec.stub(:exit_code).and_return(7) - @script.should_receive(:exit).with(7) + allow(MSpec).to receive(:exit_code).and_return(7) + expect(@script).to receive(:exit).with(7) @script.run end end diff --git a/spec/mspec/spec/commands/mspec_spec.rb b/spec/mspec/spec/commands/mspec_spec.rb index b01af6b41b..d19bebb2d6 100644 --- a/spec/mspec/spec/commands/mspec_spec.rb +++ b/spec/mspec/spec/commands/mspec_spec.rb @@ -2,55 +2,55 @@ require 'spec_helper' require 'yaml' require 'mspec/commands/mspec' -describe MSpecMain, "#options" do +RSpec.describe MSpecMain, "#options" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) - @script.stub(:load) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:load) end it "enables the configure option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options end it "provides a custom action (block) to the config option" do @script.options ["-B", "config"] - @config[:options].should include("-B", "config") + expect(@config[:options]).to include("-B", "config") end it "loads the file specified by the config option" do - @script.should_receive(:load).with("config") + expect(@script).to receive(:load).with("config") @script.options ["-B", "config"] end it "enables the target options" do - @options.should_receive(:targets) + expect(@options).to receive(:targets) @script.options end it "sets config[:options] to all argv entries that are not registered options" do @options.on "-X", "--exclude", "ARG", "description" @script.options [".", "-G", "fail", "-X", "ARG", "--list", "unstable", "some/file.rb"] - @config[:options].should == [".", "-G", "fail", "--list", "unstable", "some/file.rb"] + expect(@config[:options]).to eq([".", "-G", "fail", "--list", "unstable", "some/file.rb"]) end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options end end -describe MSpecMain, "#run" do +RSpec.describe MSpecMain, "#run" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) - @script.stub(:exec) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:exec) @err = $stderr $stderr = IOStub.new end @@ -60,76 +60,49 @@ describe MSpecMain, "#run" do end it "uses exec to invoke the runner script" do - @script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) + expect(@script).to receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) @script.options [] @script.run end it "shows the command line on stderr" do - @script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) + expect(@script).to receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) @script.options [] @script.run - $stderr.to_s.should == "$ ruby #{Dir.pwd}/bin/mspec-run\n" + expect($stderr.to_s).to eq("$ ruby #{Dir.pwd}/bin/mspec-run\n") end it "adds config[:launch] to the exec options" do - @script.should_receive(:exec).with("ruby", + expect(@script).to receive(:exec).with("ruby", "-Xlaunch.option", "#{MSPEC_HOME}/bin/mspec-run", close_others: false) @config[:launch] << "-Xlaunch.option" @script.options [] @script.run - $stderr.to_s.should == "$ ruby -Xlaunch.option #{Dir.pwd}/bin/mspec-run\n" + expect($stderr.to_s).to eq("$ ruby -Xlaunch.option #{Dir.pwd}/bin/mspec-run\n") end it "calls #multi_exec if the command is 'ci' and the multi option is passed" do - @script.should_receive(:multi_exec).and_return do |argv| - argv.should == ["ruby", "#{MSPEC_HOME}/bin/mspec-ci"] + expect(@script).to receive(:multi_exec) do |argv| + expect(argv).to eq(["ruby", "#{MSPEC_HOME}/bin/mspec-ci"]) end @script.options ["ci", "-j"] - lambda do + expect do @script.run - end.should raise_error(SystemExit) + end.to raise_error(SystemExit) end end -describe "The --warnings option" do +RSpec.describe "The -j, --multi option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("--warnings", an_instance_of(String)) - @script.options - end - - it "sets flags to -w" do - @config[:flags] = [] - @script.options ["--warnings"] - @config[:flags].should include("-w") - end - - it "set OUTPUT_WARNINGS = '1' in the environment" do - ENV['OUTPUT_WARNINGS'] = '0' - @script.options ["--warnings"] - ENV['OUTPUT_WARNINGS'].should == '1' - end -end - -describe "The -j, --multi option" do - before :each do - @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) - @script = MSpecMain.new - @script.stub(:config).and_return(@config) - end - - it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-j", "--multi", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-j", "--multi", an_instance_of(String)) @script.options end @@ -137,22 +110,22 @@ describe "The -j, --multi option" do ["-j", "--multi"].each do |opt| @config[:multi] = nil @script.options [opt] - @config[:multi].should == true + expect(@config[:multi]).to eq(true) end end end -describe "The -h, --help option" do +RSpec.describe "The -h, --help option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-h", "--help", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-h", "--help", an_instance_of(String)) @script.options end @@ -160,30 +133,30 @@ describe "The -h, --help option" do ["-h", "--help"].each do |opt| @config[:options] = [] @script.options ["ci", opt] - @config[:options].sort.should == ["-h"] + expect(@config[:options].sort).to eq(["-h"]) end end it "prints help and exits" do - @script.should_receive(:puts).twice - @script.should_receive(:exit).twice + expect(@script).to receive(:puts).twice + expect(@script).to receive(:exit).twice ["-h", "--help"].each do |opt| @script.options [opt] end end end -describe "The -v, --version option" do +RSpec.describe "The -v, --version option" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecMain.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end it "is enabled by #options" do - @options.stub(:on) - @options.should_receive(:on).with("-v", "--version", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-v", "--version", an_instance_of(String)) @script.options end @@ -191,15 +164,15 @@ describe "The -v, --version option" do ["-v", "--version"].each do |opt| @config[:options] = [] @script.options ["ci", opt] - @config[:options].sort.should == ["-v"] + expect(@config[:options].sort).to eq(["-v"]) end end it "prints the version and exits if no subscript is invoked" do @config[:command] = nil - File.stub(:basename).and_return("mspec") - @script.should_receive(:puts).twice.with("mspec #{MSpec::VERSION}") - @script.should_receive(:exit).twice + allow(File).to receive(:basename).and_return("mspec") + expect(@script).to receive(:puts).twice.with("mspec #{MSpec::VERSION}") + expect(@script).to receive(:exit).twice ["-v", "--version"].each do |opt| @script.options [opt] end diff --git a/spec/mspec/spec/commands/mspec_tag_spec.rb b/spec/mspec/spec/commands/mspec_tag_spec.rb index cdb3ac1a60..1ab5f6ea58 100644 --- a/spec/mspec/spec/commands/mspec_tag_spec.rb +++ b/spec/mspec/spec/commands/mspec_tag_spec.rb @@ -8,13 +8,13 @@ require 'mspec/runner/actions/tagpurge' one_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/one_spec.rb' two_spec = File.expand_path(File.dirname(__FILE__)) + '/fixtures/two_spec.rb' -describe MSpecTag, ".new" do +RSpec.describe MSpecTag, ".new" do before :each do @script = MSpecTag.new end it "sets config[:ltags] to an empty list" do - @script.config[:ltags].should == [] + expect(@script.config[:ltags]).to eq([]) end it "sets config[:tagger] to :add" do @@ -30,16 +30,16 @@ describe MSpecTag, ".new" do end end -describe MSpecTag, "#options" do +RSpec.describe MSpecTag, "#options" do before :each do @stdout, $stdout = $stdout, IOStub.new @argv = [one_spec, two_spec] @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecTag.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end after :each do @@ -47,80 +47,80 @@ describe MSpecTag, "#options" do end it "enables the filter options" do - @options.should_receive(:filters) + expect(@options).to receive(:filters) @script.options @argv end it "enables the configure option" do - @options.should_receive(:configure) + expect(@options).to receive(:configure) @script.options @argv end it "provides a custom action (block) to the config option" do - @script.should_receive(:load).with("cfg.mspec") + expect(@script).to receive(:load).with("cfg.mspec") @script.options ["-B", "cfg.mspec", one_spec] end it "enables the dry run option" do - @options.should_receive(:pretend) + expect(@options).to receive(:pretend) @script.options @argv end it "enables the unguarded option" do - @options.should_receive(:unguarded) + expect(@options).to receive(:unguarded) @script.options @argv end it "enables the interrupt single specs option" do - @options.should_receive(:interrupt) + expect(@options).to receive(:interrupt) @script.options @argv end it "enables the formatter options" do - @options.should_receive(:formatters) + expect(@options).to receive(:formatters) @script.options @argv end it "enables the verbose option" do - @options.should_receive(:verbose) + expect(@options).to receive(:verbose) @script.options @argv end it "enables the version option" do - @options.should_receive(:version) + expect(@options).to receive(:version) @script.options @argv end it "enables the help option" do - @options.should_receive(:help) + expect(@options).to receive(:help) @script.options @argv end it "calls #custom_options" do - @script.should_receive(:custom_options).with(@options) + expect(@script).to receive(:custom_options).with(@options) @script.options @argv end it "exits if there are no files to process" do - @options.should_receive(:parse).and_return([]) - @script.should_receive(:exit) + expect(@options).to receive(:parse).and_return([]) + expect(@script).to receive(:exit) @script.options - $stdout.should include "No files specified" + expect($stdout.to_s).to include "No files specified" end end -describe MSpecTag, "options" do +RSpec.describe MSpecTag, "options" do before :each do @options, @config = new_option - MSpecOptions.stub(:new).and_return(@options) + allow(MSpecOptions).to receive(:new).and_return(@options) @script = MSpecTag.new - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end describe "-N, --add TAG" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-N", "--add", "TAG", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-N", "--add", "TAG", an_instance_of(String)) @script.options [one_spec] end @@ -129,16 +129,16 @@ describe MSpecTag, "options" do @config[:tagger] = nil @config[:tag] = nil @script.options [opt, "taggit", one_spec] - @config[:tagger].should == :add - @config[:tag].should == "taggit:" + expect(@config[:tagger]).to eq(:add) + expect(@config[:tag]).to eq("taggit:") end end end describe "-R, --del TAG" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-R", "--del", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-R", "--del", "TAG", an_instance_of(String)) @script.options [one_spec] end @@ -149,17 +149,17 @@ describe MSpecTag, "options" do @config[:tag] = nil @config[:outcome] = nil @script.options [opt, "taggit", one_spec] - @config[:tagger].should == :del - @config[:tag].should == "taggit:" - @config[:outcome].should == :pass + expect(@config[:tagger]).to eq(:del) + expect(@config[:tag]).to eq("taggit:") + expect(@config[:outcome]).to eq(:pass) end end end describe "-Q, --pass" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-Q", "--pass", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-Q", "--pass", an_instance_of(String)) @script.options [one_spec] end @@ -167,15 +167,15 @@ describe MSpecTag, "options" do ["-Q", "--pass"].each do |opt| @config[:outcome] = nil @script.options [opt, one_spec] - @config[:outcome].should == :pass + expect(@config[:outcome]).to eq(:pass) end end end describe "-F, --fail" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-F", "--fail", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-F", "--fail", an_instance_of(String)) @script.options [one_spec] end @@ -183,15 +183,15 @@ describe MSpecTag, "options" do ["-F", "--fail"].each do |opt| @config[:outcome] = nil @script.options [opt, one_spec] - @config[:outcome].should == :fail + expect(@config[:outcome]).to eq(:fail) end end end describe "-L, --all" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("-L", "--all", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-L", "--all", an_instance_of(String)) @script.options [one_spec] end @@ -199,100 +199,100 @@ describe MSpecTag, "options" do ["-L", "--all"].each do |opt| @config[:outcome] = nil @script.options [opt, one_spec] - @config[:outcome].should == :all + expect(@config[:outcome]).to eq(:all) end end end describe "--list TAG" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("--list", "TAG", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--list", "TAG", an_instance_of(String)) @script.options [one_spec] end it "sets the mode to :list" do @config[:tagger] = nil @script.options ["--list", "TAG", one_spec] - @config[:tagger].should == :list + expect(@config[:tagger]).to eq(:list) end it "sets ltags to include TAG" do @config[:tag] = nil @script.options ["--list", "TAG", one_spec] - @config[:ltags].should == ["TAG"] + expect(@config[:ltags]).to eq(["TAG"]) end end describe "--list-all" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("--list-all", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--list-all", an_instance_of(String)) @script.options [one_spec] end it "sets the mode to :list_all" do @config[:tagger] = nil @script.options ["--list-all", one_spec] - @config[:tagger].should == :list_all + expect(@config[:tagger]).to eq(:list_all) end end describe "--purge" do it "is enabled with #options" do - @options.stub(:on) - @options.should_receive(:on).with("--purge", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--purge", an_instance_of(String)) @script.options [one_spec] end it "sets the mode to :purge" do @config[:tagger] = nil @script.options ["--purge", one_spec] - @config[:tagger].should == :purge + expect(@config[:tagger]).to eq(:purge) end end end -describe MSpecTag, "#run" do +RSpec.describe MSpecTag, "#run" do before :each do - MSpec.stub(:process) + allow(MSpec).to receive(:process) options = double("MSpecOptions").as_null_object - options.stub(:parse).and_return(["one", "two"]) - MSpecOptions.stub(:new).and_return(options) + allow(options).to receive(:parse).and_return(["one", "two"]) + allow(MSpecOptions).to receive(:new).and_return(options) @config = { } @script = MSpecTag.new - @script.stub(:exit) - @script.stub(:config).and_return(@config) - @script.stub(:files).and_return(["one", "two"]) + allow(@script).to receive(:exit) + allow(@script).to receive(:config).and_return(@config) + allow(@script).to receive(:files).and_return(["one", "two"]) @script.options end it "registers the tags patterns" do @config[:tags_patterns] = [/spec/, "tags"] - MSpec.should_receive(:register_tags_patterns).with([/spec/, "tags"]) + expect(MSpec).to receive(:register_tags_patterns).with([/spec/, "tags"]) @script.run end it "registers the files to process" do - MSpec.should_receive(:register_files).with(["one", "two"]) + expect(MSpec).to receive(:register_files).with(["one", "two"]) @script.run end it "processes the files" do - MSpec.should_receive(:process) + expect(MSpec).to receive(:process) @script.run end it "exits with the exit code registered with MSpec" do - MSpec.stub(:exit_code).and_return(7) - @script.should_receive(:exit).with(7) + allow(MSpec).to receive(:exit_code).and_return(7) + expect(@script).to receive(:exit).with(7) @script.run end end -describe MSpecTag, "#register" do +RSpec.describe MSpecTag, "#register" do before :each do @script = MSpecTag.new @config = @script.config @@ -301,19 +301,19 @@ describe MSpecTag, "#register" do @config[:astrings] = [] @config[:ltags] = ["fails", "unstable"] - @script.stub(:files).and_return([]) + allow(@script).to receive(:files).and_return([]) @script.options "fake" @t = double("TagAction") - @t.stub(:register) + allow(@t).to receive(:register) @tl = double("TagListAction") - @tl.stub(:register) + allow(@tl).to receive(:register) end it "raises an ArgumentError if no recognized action is given" do @config[:tagger] = :totally_whack - lambda { @script.register }.should raise_error(ArgumentError) + expect { @script.register }.to raise_error(ArgumentError) end describe "when config[:tagger] is the default (:add)" do @@ -322,93 +322,93 @@ describe MSpecTag, "#register" do end it "creates a TagAction" do - TagAction.should_receive(:new).and_return(@t) + expect(TagAction).to receive(:new).and_return(@t) @script.register end it "creates a TagAction if config[:tagger] is :del" do @config[:tagger] = :del @config[:outcome] = :pass - TagAction.should_receive(:new).with(:del, :pass, "fake", nil, [], []).and_return(@t) + expect(TagAction).to receive(:new).with(:del, :pass, "fake", nil, [], []).and_return(@t) @script.register end it "calls #register on the TagAction instance" do - TagAction.should_receive(:new).and_return(@t) - @t.should_receive(:register) + expect(TagAction).to receive(:new).and_return(@t) + expect(@t).to receive(:register) @script.register end end describe "when config[:tagger] is :list" do before :each do - TagListAction.should_receive(:new).with(@config[:ltags]).and_return(@tl) + expect(TagListAction).to receive(:new).with(@config[:ltags]).and_return(@tl) @config[:tagger] = :list end it "creates a TagListAction" do - @tl.should_receive(:register) + expect(@tl).to receive(:register) @script.register end it "registers MSpec pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend) + expect(MSpec).to receive(:register_mode).with(:pretend) @script.register end it "sets config[:formatter] to false" do @script.register - @config[:formatter].should be_false + expect(@config[:formatter]).to be_falsey end end describe "when config[:tagger] is :list_all" do before :each do - TagListAction.should_receive(:new).with(nil).and_return(@tl) + expect(TagListAction).to receive(:new).with(nil).and_return(@tl) @config[:tagger] = :list_all end it "creates a TagListAction" do - @tl.should_receive(:register) + expect(@tl).to receive(:register) @script.register end it "registers MSpec pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend) + expect(MSpec).to receive(:register_mode).with(:pretend) @script.register end it "sets config[:formatter] to false" do @script.register - @config[:formatter].should be_false + expect(@config[:formatter]).to be_falsey end end describe "when config[:tagger] is :purge" do before :each do - TagPurgeAction.should_receive(:new).and_return(@tl) - MSpec.stub(:register_mode) + expect(TagPurgeAction).to receive(:new).and_return(@tl) + allow(MSpec).to receive(:register_mode) @config[:tagger] = :purge end it "creates a TagPurgeAction" do - @tl.should_receive(:register) + expect(@tl).to receive(:register) @script.register end it "registers MSpec in pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend) + expect(MSpec).to receive(:register_mode).with(:pretend) @script.register end it "registers MSpec in unguarded mode" do - MSpec.should_receive(:register_mode).with(:unguarded) + expect(MSpec).to receive(:register_mode).with(:unguarded) @script.register end it "sets config[:formatter] to false" do @script.register - @config[:formatter].should be_false + expect(@config[:formatter]).to be_falsey end end end diff --git a/spec/mspec/spec/expectations/expectations_spec.rb b/spec/mspec/spec/expectations/expectations_spec.rb index fea692f3e3..371829d4f9 100644 --- a/spec/mspec/spec/expectations/expectations_spec.rb +++ b/spec/mspec/spec/expectations/expectations_spec.rb @@ -1,29 +1,29 @@ require 'spec_helper' require 'mspec/expectations/expectations' -describe SpecExpectationNotMetError do +RSpec.describe SpecExpectationNotMetError do it "is a subclass of StandardError" do - SpecExpectationNotMetError.ancestors.should include(StandardError) + expect(SpecExpectationNotMetError.ancestors).to include(StandardError) end end -describe SpecExpectationNotFoundError do +RSpec.describe SpecExpectationNotFoundError do it "is a subclass of StandardError" do - SpecExpectationNotFoundError.ancestors.should include(StandardError) + expect(SpecExpectationNotFoundError.ancestors).to include(StandardError) end end -describe SpecExpectationNotFoundError, "#message" do +RSpec.describe SpecExpectationNotFoundError, "#message" do it "returns 'No behavior expectation was found in the example'" do m = SpecExpectationNotFoundError.new.message - m.should == "No behavior expectation was found in the example" + expect(m).to eq("No behavior expectation was found in the example") end end -describe SpecExpectation, "#fail_with" do +RSpec.describe SpecExpectation, "#fail_with" do it "raises an SpecExpectationNotMetError" do - lambda { + expect { SpecExpectation.fail_with "expected this", "to equal that" - }.should raise_error(SpecExpectationNotMetError, "expected this to equal that") + }.to raise_error(SpecExpectationNotMetError, "expected this to equal that") end end diff --git a/spec/mspec/spec/expectations/should_spec.rb b/spec/mspec/spec/expectations/should_spec.rb index 3258caf13c..472890979d 100644 --- a/spec/mspec/spec/expectations/should_spec.rb +++ b/spec/mspec/spec/expectations/should_spec.rb @@ -1,26 +1,26 @@ require 'spec_helper' require 'rbconfig' -describe "MSpec" do +RSpec.describe "MSpec" do before :all do path = RbConfig::CONFIG['bindir'] exe = RbConfig::CONFIG['ruby_install_name'] - file = File.dirname(__FILE__) + '/should.rb' + file = File.expand_path('../../fixtures/should.rb', __FILE__) @out = `#{path}/#{exe} #{file}` end describe "#should" do it "records failures" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 1) -MSpec expectation method #should causes a failue to be recorded FAILED -Expected 1 - to equal 2 +MSpec expectation method #should causes a failure to be recorded FAILED +Expected 1 == 2 +to be truthy but was false EOS end it "raises exceptions for examples with no expectations" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 2) MSpec expectation method #should registers that an expectation has been encountered FAILED No behavior expectation was found in the example @@ -30,16 +30,16 @@ EOS describe "#should_not" do it "records failures" do - @out.should include <<-EOS + expect(@out).to 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 it "raises exceptions for examples with no expectations" do - @out.should include <<-EOS + expect(@out).to include <<-EOS 4) MSpec expectation method #should_not registers that an expectation has been encountered FAILED No behavior expectation was found in the example @@ -48,14 +48,14 @@ EOS end it "prints status information" do - @out.should include ".FF..FF." + expect(@out).to include ".FF..FF." end it "prints out a summary" do - @out.should include "0 files, 8 examples, 6 expectations, 4 failures, 0 errors" + expect(@out).to include "0 files, 8 examples, 6 expectations, 4 failures, 0 errors" end it "records expectations" do - @out.should include "I was called 6 times" + expect(@out).to include "I was called 6 times" end end diff --git a/spec/mspec/spec/fixtures/chatty_spec.rb b/spec/mspec/spec/fixtures/chatty_spec.rb new file mode 100644 index 0000000000..2d110d8ce4 --- /dev/null +++ b/spec/mspec/spec/fixtures/chatty_spec.rb @@ -0,0 +1,8 @@ +unless defined?(RSpec) + describe "Chatty#spec" do + it "prints too much" do + STDOUT.puts "Hello\nIt's me!" + 1.should == 1 + end + end +end diff --git a/spec/mspec/spec/fixtures/config.mspec b/spec/mspec/spec/fixtures/config.mspec index 4a069e2eb0..01654c5094 100644 --- a/spec/mspec/spec/fixtures/config.mspec +++ b/spec/mspec/spec/fixtures/config.mspec @@ -1,8 +1,6 @@ class MSpecScript set :target, 'ruby' - set :backtrace_filter, /lib\/mspec\// - set :tags_patterns, [ [%r(spec/fixtures/), 'spec/fixtures/tags/'], [/_spec.rb$/, '_tags.txt'] diff --git a/spec/mspec/spec/fixtures/die_spec.rb b/spec/mspec/spec/fixtures/die_spec.rb new file mode 100644 index 0000000000..0f66793274 --- /dev/null +++ b/spec/mspec/spec/fixtures/die_spec.rb @@ -0,0 +1,7 @@ +unless defined?(RSpec) + describe "Deadly#spec" do + it "dies" do + abort "DEAD" + end + end +end diff --git a/spec/mspec/spec/fixtures/my_ruby b/spec/mspec/spec/fixtures/my_ruby index 4d552f27fb..eeda3eeeec 100755 --- a/spec/mspec/spec/fixtures/my_ruby +++ b/spec/mspec/spec/fixtures/my_ruby @@ -1,4 +1,4 @@ #!/usr/bin/env bash echo $RUBY_EXE -ruby "$@" +exec ruby "$@" diff --git a/spec/mspec/spec/expectations/should.rb b/spec/mspec/spec/fixtures/should.rb index 24b1cf2bf8..f494775c5f 100644 --- a/spec/mspec/spec/expectations/should.rb +++ b/spec/mspec/spec/fixtures/should.rb @@ -8,6 +8,8 @@ require 'mspec/utils/script' # specs but is run by MSpec. This avoids conflicting with # RSpec's #should and #should_not methods. +raise "RSpec should not be loaded" if defined?(RSpec) + class ShouldSpecsMonitor def initialize @called = 0 @@ -41,7 +43,7 @@ describe "MSpec expectation method #should" do :sym.should be_kind_of(Symbol) end - it "causes a failue to be recorded" do + it "causes a failure to be recorded" do 1.should == 2 end diff --git a/spec/mspec/spec/guards/block_device_spec.rb b/spec/mspec/spec/guards/block_device_spec.rb index 3b437b6d74..dd420d4a81 100644 --- a/spec/mspec/spec/guards/block_device_spec.rb +++ b/spec/mspec/spec/guards/block_device_spec.rb @@ -1,46 +1,46 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#with_block_device" do +RSpec.describe Object, "#with_block_device" do before :each do ScratchPad.clear @guard = BlockDeviceGuard.new - BlockDeviceGuard.stub(:new).and_return(@guard) + allow(BlockDeviceGuard).to receive(:new).and_return(@guard) end platform_is_not :freebsd, :windows do it "yields if block device is available" do - @guard.should_receive(:`).and_return("block devices") + expect(@guard).to receive(:`).and_return("block devices") with_block_device { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if block device is not available" do - @guard.should_receive(:`).and_return(nil) + expect(@guard).to receive(:`).and_return(nil) with_block_device { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end platform_is :freebsd, :windows do it "does not yield, since platform does not support block devices" do - @guard.should_not_receive(:`) + expect(@guard).not_to receive(:`) with_block_device { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end it "sets the name of the guard to :with_block_device" do with_block_device { } - @guard.name.should == :with_block_device + expect(@guard.name).to eq(:with_block_device) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do with_block_device { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/spec/mspec/spec/guards/bug_spec.rb b/spec/mspec/spec/guards/bug_spec.rb index c8529a49f7..72a3405dbc 100644 --- a/spec/mspec/spec/guards/bug_spec.rb +++ b/spec/mspec/spec/guards/bug_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require 'mspec/guards' -describe BugGuard, "#match? when #implementation? is 'ruby'" do +RSpec.describe BugGuard, "#match? when #implementation? is 'ruby'" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -23,47 +23,47 @@ describe BugGuard, "#match? when #implementation? is 'ruby'" do end it "returns false when version argument is less than RUBY_VERSION" do - BugGuard.new("#1", "1.8.5").match?.should == false + expect(BugGuard.new("#1", "1.8.5").match?).to eq(false) end it "returns true when version argument is equal to RUBY_VERSION" do - BugGuard.new("#1", "1.8.6").match?.should == true + expect(BugGuard.new("#1", "1.8.6").match?).to eq(true) end it "returns true when version argument is greater than RUBY_VERSION" do - BugGuard.new("#1", "1.8.7").match?.should == true + expect(BugGuard.new("#1", "1.8.7").match?).to eq(true) end it "returns true when version argument implicitly includes RUBY_VERSION" do - BugGuard.new("#1", "1.8").match?.should == true - BugGuard.new("#1", "1.8.6").match?.should == true + expect(BugGuard.new("#1", "1.8").match?).to eq(true) + expect(BugGuard.new("#1", "1.8.6").match?).to eq(true) end it "returns true when the argument range includes RUBY_VERSION" do - BugGuard.new("#1", '1.8.5'..'1.8.7').match?.should == true - BugGuard.new("#1", '1.8'..'1.9').match?.should == true - BugGuard.new("#1", '1.8'...'1.9').match?.should == true - BugGuard.new("#1", '1.8'..'1.8.6').match?.should == true - BugGuard.new("#1", '1.8.5'..'1.8.6').match?.should == true - BugGuard.new("#1", ''...'1.8.7').match?.should == true + expect(BugGuard.new("#1", '1.8.5'..'1.8.7').match?).to eq(true) + expect(BugGuard.new("#1", '1.8'..'1.9').match?).to eq(true) + expect(BugGuard.new("#1", '1.8'...'1.9').match?).to eq(true) + expect(BugGuard.new("#1", '1.8'..'1.8.6').match?).to eq(true) + expect(BugGuard.new("#1", '1.8.5'..'1.8.6').match?).to eq(true) + expect(BugGuard.new("#1", ''...'1.8.7').match?).to eq(true) end it "returns false when the argument range does not include RUBY_VERSION" do - BugGuard.new("#1", '1.8.7'..'1.8.9').match?.should == false - BugGuard.new("#1", '1.8.4'..'1.8.5').match?.should == false - BugGuard.new("#1", '1.8.4'...'1.8.6').match?.should == false - BugGuard.new("#1", '1.8.5'...'1.8.6').match?.should == false - BugGuard.new("#1", ''...'1.8.6').match?.should == false + expect(BugGuard.new("#1", '1.8.7'..'1.8.9').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.4'..'1.8.5').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.4'...'1.8.6').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.5'...'1.8.6').match?).to eq(false) + expect(BugGuard.new("#1", ''...'1.8.6').match?).to eq(false) end it "returns false when MSpec.mode?(:no_ruby_bug) is true" do - MSpec.should_receive(:mode?).with(:no_ruby_bug).twice.and_return(:true) - BugGuard.new("#1", "1.8.5").match?.should == false - BugGuard.new("#1", "1.8").match?.should == false + expect(MSpec).to receive(:mode?).with(:no_ruby_bug).twice.and_return(:true) + expect(BugGuard.new("#1", "1.8.5").match?).to eq(false) + expect(BugGuard.new("#1", "1.8").match?).to eq(false) end end -describe BugGuard, "#match? when #implementation? is not 'ruby'" do +RSpec.describe BugGuard, "#match? when #implementation? is not 'ruby'" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -88,64 +88,64 @@ describe BugGuard, "#match? when #implementation? is not 'ruby'" do end it "returns false when version argument is less than RUBY_VERSION" do - BugGuard.new("#1", "1.8").match?.should == false - BugGuard.new("#1", "1.8.6").match?.should == false + expect(BugGuard.new("#1", "1.8").match?).to eq(false) + expect(BugGuard.new("#1", "1.8.6").match?).to eq(false) end it "returns false when version argument is equal to RUBY_VERSION" do - BugGuard.new("#1", "1.8.6").match?.should == false + expect(BugGuard.new("#1", "1.8.6").match?).to eq(false) end it "returns false when version argument is greater than RUBY_VERSION" do - BugGuard.new("#1", "1.8.7").match?.should == false + expect(BugGuard.new("#1", "1.8.7").match?).to eq(false) end it "returns false no matter if the argument range includes RUBY_VERSION" do - BugGuard.new("#1", '1.8'...'1.9').match?.should == false - BugGuard.new("#1", '1.8.5'...'1.8.7').match?.should == false - BugGuard.new("#1", '1.8.4'...'1.8.6').match?.should == false + expect(BugGuard.new("#1", '1.8'...'1.9').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.5'...'1.8.7').match?).to eq(false) + expect(BugGuard.new("#1", '1.8.4'...'1.8.6').match?).to eq(false) end it "returns false when MSpec.mode?(:no_ruby_bug) is true" do - MSpec.stub(:mode?).and_return(:true) - BugGuard.new("#1", "1.8.6").match?.should == false + allow(MSpec).to receive(:mode?).and_return(:true) + expect(BugGuard.new("#1", "1.8.6").match?).to eq(false) end end -describe Object, "#ruby_bug" do +RSpec.describe Object, "#ruby_bug" do before :each do hide_deprecation_warnings @guard = BugGuard.new "#1234", "x.x.x" - BugGuard.stub(:new).and_return(@guard) + allow(BugGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields when #match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) ruby_bug("#1234", "1.8.6") { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when #match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) ruby_bug("#1234", "1.8.6") { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "requires a bug tracker number and a version number" do - lambda { ruby_bug { } }.should raise_error(ArgumentError) - lambda { ruby_bug("#1234") { } }.should raise_error(ArgumentError) + expect { ruby_bug { } }.to raise_error(ArgumentError) + expect { ruby_bug("#1234") { } }.to raise_error(ArgumentError) end it "sets the name of the guard to :ruby_bug" do ruby_bug("#1234", "1.8.6") { } - @guard.name.should == :ruby_bug + expect(@guard.name).to eq(:ruby_bug) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:unregister) + expect do ruby_bug("", "") { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/spec/mspec/spec/guards/conflict_spec.rb b/spec/mspec/spec/guards/conflict_spec.rb index e06a2809ee..7dbe83153d 100644 --- a/spec/mspec/spec/guards/conflict_spec.rb +++ b/spec/mspec/spec/guards/conflict_spec.rb @@ -1,51 +1,53 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#conflicts_with" do +RSpec.describe Object, "#conflicts_with" do before :each do + hide_deprecation_warnings ScratchPad.clear end it "does not yield if Object.constants includes any of the arguments" do - Object.stub(:constants).and_return(["SomeClass", "OtherClass"]) + allow(Object).to receive(:constants).and_return(["SomeClass", "OtherClass"]) conflicts_with(:SomeClass, :AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "does not yield if Object.constants (as Symbols) includes any of the arguments" do - Object.stub(:constants).and_return([:SomeClass, :OtherClass]) + allow(Object).to receive(:constants).and_return([:SomeClass, :OtherClass]) conflicts_with(:SomeClass, :AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields if Object.constants does not include any of the arguments" do - Object.stub(:constants).and_return(["SomeClass", "OtherClass"]) + allow(Object).to receive(:constants).and_return(["SomeClass", "OtherClass"]) conflicts_with(:AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "yields if Object.constants (as Symbols) does not include any of the arguments" do - Object.stub(:constants).and_return([:SomeClass, :OtherClass]) + allow(Object).to receive(:constants).and_return([:SomeClass, :OtherClass]) conflicts_with(:AClass, :BClass) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end end -describe Object, "#conflicts_with" do +RSpec.describe Object, "#conflicts_with" do before :each do + hide_deprecation_warnings @guard = ConflictsGuard.new - ConflictsGuard.stub(:new).and_return(@guard) + allow(ConflictsGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :conflicts_with" do conflicts_with(:AClass, :BClass) { } - @guard.name.should == :conflicts_with + expect(@guard.name).to eq(:conflicts_with) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:unregister) + expect do conflicts_with(:AClass, :BClass) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/spec/mspec/spec/guards/endian_spec.rb b/spec/mspec/spec/guards/endian_spec.rb index 5b40c203ab..943b558ed3 100644 --- a/spec/mspec/spec/guards/endian_spec.rb +++ b/spec/mspec/spec/guards/endian_spec.rb @@ -1,55 +1,55 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#big_endian" do +RSpec.describe Object, "#big_endian" do before :each do @guard = BigEndianGuard.new - BigEndianGuard.stub(:new).and_return(@guard) + allow(BigEndianGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields on big-endian platforms" do - @guard.stub(:pattern).and_return([?\001]) + allow(@guard).to receive(:pattern).and_return([?\001]) big_endian { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield on little-endian platforms" do - @guard.stub(:pattern).and_return([?\000]) + allow(@guard).to receive(:pattern).and_return([?\000]) big_endian { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "sets the name of the guard to :big_endian" do big_endian { } - @guard.name.should == :big_endian + expect(@guard.name).to eq(:big_endian) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.stub(:pattern).and_return([?\001]) - @guard.should_receive(:unregister) - lambda do + allow(@guard).to receive(:pattern).and_return([?\001]) + expect(@guard).to receive(:unregister) + expect do big_endian { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#little_endian" do +RSpec.describe Object, "#little_endian" do before :each do @guard = BigEndianGuard.new - BigEndianGuard.stub(:new).and_return(@guard) + allow(BigEndianGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields on little-endian platforms" do - @guard.stub(:pattern).and_return([?\000]) + allow(@guard).to receive(:pattern).and_return([?\000]) little_endian { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield on big-endian platforms" do - @guard.stub(:pattern).and_return([?\001]) + allow(@guard).to receive(:pattern).and_return([?\001]) little_endian { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end diff --git a/spec/mspec/spec/guards/feature_spec.rb b/spec/mspec/spec/guards/feature_spec.rb index d14e5f8e67..fcb8997591 100644 --- a/spec/mspec/spec/guards/feature_spec.rb +++ b/spec/mspec/spec/guards/feature_spec.rb @@ -1,80 +1,120 @@ require 'spec_helper' require 'mspec/guards' -describe FeatureGuard, ".enabled?" do +RSpec.describe FeatureGuard, ".enabled?" do it "returns true if the feature is enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true) - FeatureGuard.enabled?(:encoding).should be_true + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true) + expect(FeatureGuard.enabled?(:encoding)).to be_truthy end it "returns false if the feature is not enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false) - FeatureGuard.enabled?(:encoding).should be_false + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false) + expect(FeatureGuard.enabled?(:encoding)).to be_falsey end it "returns true if all the features are enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(true) - FeatureGuard.enabled?(:one, :two).should be_true + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(true) + expect(FeatureGuard.enabled?(:one, :two)).to be_truthy end it "returns false if any of the features are not enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(false) - FeatureGuard.enabled?(:one, :two).should be_false + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(false) + expect(FeatureGuard.enabled?(:one, :two)).to be_falsey end end -describe Object, "#with_feature" do +RSpec.describe Object, "#with_feature" do before :each do ScratchPad.clear @guard = FeatureGuard.new :encoding - FeatureGuard.stub(:new).and_return(@guard) + allow(FeatureGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :with_feature" do with_feature(:encoding) { } - @guard.name.should == :with_feature + expect(@guard.name).to eq(:with_feature) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do with_feature { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#with_feature" do +RSpec.describe Object, "#with_feature" do before :each do ScratchPad.clear end it "yields if the feature is enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true) with_feature(:encoding) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "yields if all the features are enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(true) with_feature(:one, :two) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if the feature is not enabled" do - MSpec.should_receive(:feature_enabled?).with(:encoding).and_return(false) + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false) with_feature(:encoding) { ScratchPad.record :yield } - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end it "does not yield if any of the features are not enabled" do - MSpec.should_receive(:feature_enabled?).with(:one).and_return(true) - MSpec.should_receive(:feature_enabled?).with(:two).and_return(false) + expect(MSpec).to receive(:feature_enabled?).with(:one).and_return(true) + expect(MSpec).to receive(:feature_enabled?).with(:two).and_return(false) with_feature(:one, :two) { ScratchPad.record :yield } - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil + end +end + +RSpec.describe Object, "#without_feature" do + before :each do + ScratchPad.clear + + @guard = FeatureGuard.new :encoding + allow(FeatureGuard).to receive(:new).and_return(@guard) + end + + it "sets the name of the guard to :without_feature" do + without_feature(:encoding) { } + expect(@guard.name).to eq(:without_feature) + end + + it "calls #unregister even when an exception is raised in the guard block" do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do + without_feature { raise Exception } + end.to raise_error(Exception) + end +end + +RSpec.describe Object, "#without_feature" do + before :each do + ScratchPad.clear + end + + it "does not yield if the feature is enabled" do + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(true) + without_feature(:encoding) { ScratchPad.record :yield } + expect(ScratchPad.recorded).to be_nil + end + + it "yields if the feature is disabled" do + expect(MSpec).to receive(:feature_enabled?).with(:encoding).and_return(false) + without_feature(:encoding) { ScratchPad.record :yield } + expect(ScratchPad.recorded).to eq(:yield) end end diff --git a/spec/mspec/spec/guards/guard_spec.rb b/spec/mspec/spec/guards/guard_spec.rb index 5c3dae4b3f..e29d235747 100644 --- a/spec/mspec/spec/guards/guard_spec.rb +++ b/spec/mspec/spec/guards/guard_spec.rb @@ -2,41 +2,41 @@ require 'spec_helper' require 'mspec/guards' require 'rbconfig' -describe SpecGuard, ".ruby_version" do +RSpec.describe SpecGuard, ".ruby_version" do before :each do stub_const "RUBY_VERSION", "8.2.3" end it "returns the full version for :full" do - SpecGuard.ruby_version(:full).should == "8.2.3" + expect(SpecGuard.ruby_version(:full)).to eq("8.2.3") end it "returns major.minor.tiny for :tiny" do - SpecGuard.ruby_version(:tiny).should == "8.2.3" + expect(SpecGuard.ruby_version(:tiny)).to eq("8.2.3") end it "returns major.minor.tiny for :teeny" do - SpecGuard.ruby_version(:tiny).should == "8.2.3" + expect(SpecGuard.ruby_version(:tiny)).to eq("8.2.3") end it "returns major.minor for :minor" do - SpecGuard.ruby_version(:minor).should == "8.2" + expect(SpecGuard.ruby_version(:minor)).to eq("8.2") end it "defaults to :minor" do - SpecGuard.ruby_version.should == "8.2" + expect(SpecGuard.ruby_version).to eq("8.2") end it "returns major for :major" do - SpecGuard.ruby_version(:major).should == "8" + expect(SpecGuard.ruby_version(:major)).to eq("8") end end -describe SpecGuard, "#yield?" do +RSpec.describe SpecGuard, "#yield?" do before :each do MSpec.clear_modes @guard = SpecGuard.new - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) end after :each do @@ -47,77 +47,77 @@ describe SpecGuard, "#yield?" do it "returns true if MSpec.mode?(:unguarded) is true" do MSpec.register_mode :unguarded - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns true if MSpec.mode?(:verify) is true" do MSpec.register_mode :verify - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns true if MSpec.mode?(:verify) is true regardless of invert being true" do MSpec.register_mode :verify - @guard.yield?(true).should == true + expect(@guard.yield?(true)).to eq(true) end it "returns true if MSpec.mode?(:report) is true" do MSpec.register_mode :report - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns true if MSpec.mode?(:report) is true regardless of invert being true" do MSpec.register_mode :report - @guard.yield?(true).should == true + expect(@guard.yield?(true)).to eq(true) end it "returns true if MSpec.mode?(:report_on) is true and SpecGuards.guards contains the named guard" do MSpec.register_mode :report_on SpecGuard.guards << :guard_name - @guard.yield?.should == false + expect(@guard.yield?).to eq(false) @guard.name = :guard_name - @guard.yield?.should == true + expect(@guard.yield?).to eq(true) end it "returns #match? if neither report nor verify mode are true" do - @guard.stub(:match?).and_return(false) - @guard.yield?.should == false - @guard.stub(:match?).and_return(true) - @guard.yield?.should == true + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.yield?).to eq(false) + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.yield?).to eq(true) end it "returns #match? if invert is true and neither report nor verify mode are true" do - @guard.stub(:match?).and_return(false) - @guard.yield?(true).should == true - @guard.stub(:match?).and_return(true) - @guard.yield?(true).should == false + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.yield?(true)).to eq(true) + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.yield?(true)).to eq(false) end end -describe SpecGuard, "#match?" do +RSpec.describe SpecGuard, "#match?" do before :each do @guard = SpecGuard.new end it "must be implemented in subclasses" do - lambda { + expect { @guard.match? - }.should raise_error("must be implemented by the subclass") + }.to raise_error("must be implemented by the subclass") end end -describe SpecGuard, "#unregister" do +RSpec.describe SpecGuard, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) @guard = SpecGuard.new end it "unregisters from MSpec :add actions" do - MSpec.should_receive(:unregister).with(:add, @guard) + expect(MSpec).to receive(:unregister).with(:add, @guard) @guard.unregister end end -describe SpecGuard, "#record" do +RSpec.describe SpecGuard, "#record" do after :each do SpecGuard.clear end @@ -126,28 +126,28 @@ describe SpecGuard, "#record" do guard = SpecGuard.new "a", "1.8"..."1.9" guard.name = :named_guard guard.record "SomeClass#action returns true" - SpecGuard.report.should == { + expect(SpecGuard.report).to eq({ 'named_guard a, 1.8...1.9' => ["SomeClass#action returns true"] - } + }) end end -describe SpecGuard, ".guards" do +RSpec.describe SpecGuard, ".guards" do it "returns an Array" do - SpecGuard.guards.should be_kind_of(Array) + expect(SpecGuard.guards).to be_kind_of(Array) end end -describe SpecGuard, ".clear_guards" do +RSpec.describe SpecGuard, ".clear_guards" do it "resets the array to empty" do SpecGuard.guards << :guard - SpecGuard.guards.should == [:guard] + expect(SpecGuard.guards).to eq([:guard]) SpecGuard.clear_guards - SpecGuard.guards.should == [] + expect(SpecGuard.guards).to eq([]) end end -describe SpecGuard, ".finish" do +RSpec.describe SpecGuard, ".finish" do before :each do $stdout = @out = IOStub.new end @@ -163,88 +163,88 @@ describe SpecGuard, ".finish" do guard.record "SomeClass#action returns true" guard.record "SomeClass#reverse returns false" SpecGuard.finish - $stdout.should == %[ + expect($stdout).to eq(%[ 2 specs omitted by guard: named_guard a, 1.8...1.9: SomeClass#action returns true SomeClass#reverse returns false -] +]) end end -describe SpecGuard, ".run_if" do +RSpec.describe SpecGuard, ".run_if" do before :each do @guard = SpecGuard.new ScratchPad.clear end it "yields if match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) @guard.run_if(:name) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) @guard.run_if(:name) { fail } end it "returns the result of the block if match? is true" do - @guard.stub(:match?).and_return(true) - @guard.run_if(:name) { 42 }.should == 42 + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_if(:name) { 42 }).to eq(42) end it "returns nil if given a block and match? is false" do - @guard.stub(:match?).and_return(false) - @guard.run_if(:name) { 42 }.should == nil + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_if(:name) { 42 }).to eq(nil) end it "returns what #match? returns when no block is given" do - @guard.stub(:match?).and_return(true) - @guard.run_if(:name).should == true - @guard.stub(:match?).and_return(false) - @guard.run_if(:name).should == false + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_if(:name)).to eq(true) + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_if(:name)).to eq(false) end end -describe SpecGuard, ".run_unless" do +RSpec.describe SpecGuard, ".run_unless" do before :each do @guard = SpecGuard.new ScratchPad.clear end it "yields if match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) @guard.run_unless(:name) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield if match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) @guard.run_unless(:name) { fail } end it "returns the result of the block if match? is false" do - @guard.stub(:match?).and_return(false) - @guard.run_unless(:name) { 42 }.should == 42 + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_unless(:name) { 42 }).to eq(42) end it "returns nil if given a block and match? is true" do - @guard.stub(:match?).and_return(true) - @guard.run_unless(:name) { 42 }.should == nil + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_unless(:name) { 42 }).to eq(nil) end it "returns the opposite of what #match? returns when no block is given" do - @guard.stub(:match?).and_return(true) - @guard.run_unless(:name).should == false - @guard.stub(:match?).and_return(false) - @guard.run_unless(:name).should == true + allow(@guard).to receive(:match?).and_return(true) + expect(@guard.run_unless(:name)).to eq(false) + allow(@guard).to receive(:match?).and_return(false) + expect(@guard.run_unless(:name)).to eq(true) end end -describe Object, "#guard" do +RSpec.describe Object, "#guard" do before :each do ScratchPad.clear end @@ -254,32 +254,32 @@ describe Object, "#guard" do end it "allows to combine guards" do - guard1 = VersionGuard.new 'x.x.x' - VersionGuard.stub(:new).and_return(guard1) + guard1 = VersionGuard.new '1.2.3', 'x.x.x' + allow(VersionGuard).to receive(:new).and_return(guard1) guard2 = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(guard2) + allow(PlatformGuard).to receive(:new).and_return(guard2) - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(true) guard -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield end - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(true) guard -> { ruby_version_is "2.4" and platform_is :linux } do fail end - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(false) guard -> { ruby_version_is "2.4" and platform_is :linux } do fail end - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(false) guard -> { ruby_version_is "2.4" and platform_is :linux } do fail end @@ -289,7 +289,7 @@ describe Object, "#guard" do guard -> { true } do ScratchPad.record :yield end - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when the Proc returns false" do @@ -304,12 +304,12 @@ describe Object, "#guard" do guard -> { false } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) guard -> { true } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) end it "yields if MSpec.mode?(:verify) is true" do @@ -318,12 +318,12 @@ describe Object, "#guard" do guard -> { false } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) guard -> { true } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) end it "yields if MSpec.mode?(:report) is true" do @@ -332,72 +332,72 @@ describe Object, "#guard" do guard -> { false } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) guard -> { true } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) end it "raises an error if no Proc is given" do - -> { guard :foo }.should raise_error(RuntimeError) + expect { guard :foo }.to raise_error(RuntimeError) end it "requires a block" do - -> { + expect { guard(-> { true }) - }.should raise_error(LocalJumpError) - -> { + }.to raise_error(LocalJumpError) + expect { guard(-> { false }) - }.should raise_error(LocalJumpError) + }.to raise_error(LocalJumpError) end end -describe Object, "#guard_not" do +RSpec.describe Object, "#guard_not" do before :each do ScratchPad.clear end it "allows to combine guards" do - guard1 = VersionGuard.new 'x.x.x' - VersionGuard.stub(:new).and_return(guard1) + guard1 = VersionGuard.new '1.2.3', 'x.x.x' + allow(VersionGuard).to receive(:new).and_return(guard1) guard2 = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(guard2) + allow(PlatformGuard).to receive(:new).and_return(guard2) - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(true) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do fail end - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(true) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(true) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield1 end - ScratchPad.recorded.should == :yield1 + expect(ScratchPad.recorded).to eq(:yield1) - guard1.stub(:match?).and_return(true) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(true) + allow(guard2).to receive(:match?).and_return(false) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield2 end - ScratchPad.recorded.should == :yield2 + expect(ScratchPad.recorded).to eq(:yield2) - guard1.stub(:match?).and_return(false) - guard2.stub(:match?).and_return(false) + allow(guard1).to receive(:match?).and_return(false) + allow(guard2).to receive(:match?).and_return(false) guard_not -> { ruby_version_is "2.4" and platform_is :linux } do ScratchPad.record :yield3 end - ScratchPad.recorded.should == :yield3 + expect(ScratchPad.recorded).to eq(:yield3) end it "yields when the Proc returns false" do guard_not -> { false } do ScratchPad.record :yield end - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when the Proc returns true" do @@ -407,15 +407,15 @@ describe Object, "#guard_not" do end it "raises an error if no Proc is given" do - -> { guard_not :foo }.should raise_error(RuntimeError) + expect { guard_not :foo }.to raise_error(RuntimeError) end it "requires a block" do - -> { + expect { guard_not(-> { true }) - }.should raise_error(LocalJumpError) - -> { + }.to raise_error(LocalJumpError) + expect { guard_not(-> { false }) - }.should raise_error(LocalJumpError) + }.to raise_error(LocalJumpError) end end diff --git a/spec/mspec/spec/guards/platform_spec.rb b/spec/mspec/spec/guards/platform_spec.rb index 749963d3db..bd37432800 100644 --- a/spec/mspec/spec/guards/platform_spec.rb +++ b/spec/mspec/spec/guards/platform_spec.rb @@ -1,243 +1,252 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#platform_is" do +RSpec.describe Object, "#platform_is" do before :each do @guard = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(@guard) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "does not yield when #os? returns false" do - PlatformGuard.stub(:os?).and_return(false) + allow(PlatformGuard).to receive(:os?).and_return(false) platform_is(:ruby) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when #os? returns true" do - PlatformGuard.stub(:os?).and_return(true) + allow(PlatformGuard).to receive(:os?).and_return(true) platform_is(:solarce) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "returns what #os? returns when no block is given" do - PlatformGuard.stub(:os?).and_return(true) - platform_is(:solarce).should == true - PlatformGuard.stub(:os?).and_return(false) - platform_is(:solarce).should == false + allow(PlatformGuard).to receive(:os?).and_return(true) + expect(platform_is(:solarce)).to eq(true) + allow(PlatformGuard).to receive(:os?).and_return(false) + expect(platform_is(:solarce)).to eq(false) end it "sets the name of the guard to :platform_is" do platform_is(:solarce) { } - @guard.name.should == :platform_is + expect(@guard.name).to eq(:platform_is) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do platform_is(:solarce) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#platform_is_not" do +RSpec.describe Object, "#platform_is_not" do before :each do @guard = PlatformGuard.new :dummy - PlatformGuard.stub(:new).and_return(@guard) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "does not yield when #os? returns true" do - PlatformGuard.stub(:os?).and_return(true) + allow(PlatformGuard).to receive(:os?).and_return(true) platform_is_not(:ruby) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when #os? returns false" do - PlatformGuard.stub(:os?).and_return(false) + allow(PlatformGuard).to receive(:os?).and_return(false) platform_is_not(:solarce) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "returns the opposite of what #os? returns when no block is given" do - PlatformGuard.stub(:os?).and_return(true) - platform_is_not(:solarce).should == false - PlatformGuard.stub(:os?).and_return(false) - platform_is_not(:solarce).should == true + allow(PlatformGuard).to receive(:os?).and_return(true) + expect(platform_is_not(:solarce)).to eq(false) + allow(PlatformGuard).to receive(:os?).and_return(false) + expect(platform_is_not(:solarce)).to eq(true) end it "sets the name of the guard to :platform_is_not" do platform_is_not(:solarce) { } - @guard.name.should == :platform_is_not + expect(@guard.name).to eq(:platform_is_not) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do platform_is_not(:solarce) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end -describe Object, "#platform_is :wordsize => SIZE_SPEC" do +RSpec.describe Object, "#platform_is :c_long_size => SIZE_SPEC" do before :each do - @guard = PlatformGuard.new :darwin, :wordsize => 32 - PlatformGuard.stub(:os?).and_return(true) - PlatformGuard.stub(:new).and_return(@guard) + @guard = PlatformGuard.new :darwin, :c_long_size => 32 + allow(PlatformGuard).to receive(:os?).and_return(true) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end - it "yields when #wordsize? returns true" do - PlatformGuard.stub(:wordsize?).and_return(true) - platform_is(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + it "yields when #c_long_size? returns true" do + allow(PlatformGuard).to receive(:c_long_size?).and_return(true) + platform_is(:c_long_size => 32) { ScratchPad.record :yield } + expect(ScratchPad.recorded).to eq(:yield) end - it "doesn not yield when #wordsize? returns false" do - PlatformGuard.stub(:wordsize?).and_return(false) - platform_is(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + it "doesn not yield when #c_long_size? returns false" do + allow(PlatformGuard).to receive(:c_long_size?).and_return(false) + platform_is(:c_long_size => 32) { ScratchPad.record :yield } + expect(ScratchPad.recorded).not_to eq(:yield) end end -describe Object, "#platform_is_not :wordsize => SIZE_SPEC" do +RSpec.describe Object, "#platform_is_not :c_long_size => SIZE_SPEC" do before :each do - @guard = PlatformGuard.new :darwin, :wordsize => 32 - PlatformGuard.stub(:os?).and_return(true) - PlatformGuard.stub(:new).and_return(@guard) + @guard = PlatformGuard.new :darwin, :c_long_size => 32 + allow(PlatformGuard).to receive(:os?).and_return(true) + allow(PlatformGuard).to receive(:new).and_return(@guard) ScratchPad.clear end - it "yields when #wordsize? returns false" do - PlatformGuard.stub(:wordsize?).and_return(false) - platform_is_not(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + it "yields when #c_long_size? returns false" do + allow(PlatformGuard).to receive(:c_long_size?).and_return(false) + platform_is_not(:c_long_size => 32) { ScratchPad.record :yield } + expect(ScratchPad.recorded).to eq(:yield) end - it "doesn not yield when #wordsize? returns true" do - PlatformGuard.stub(:wordsize?).and_return(true) - platform_is_not(:wordsize => 32) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + it "doesn not yield when #c_long_size? returns true" do + allow(PlatformGuard).to receive(:c_long_size?).and_return(true) + platform_is_not(:c_long_size => 32) { ScratchPad.record :yield } + expect(ScratchPad.recorded).not_to eq(:yield) end end -describe PlatformGuard, ".implementation?" do +RSpec.describe PlatformGuard, ".implementation?" do it "returns true if passed :ruby and RUBY_ENGINE == 'ruby'" do stub_const 'RUBY_ENGINE', 'ruby' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) end it "returns true if passed :rubinius and RUBY_ENGINE == 'rbx'" do stub_const 'RUBY_ENGINE', 'rbx' - PlatformGuard.implementation?(:rubinius).should == true + expect(PlatformGuard.implementation?(:rubinius)).to eq(true) end it "returns true if passed :jruby and RUBY_ENGINE == 'jruby'" do stub_const 'RUBY_ENGINE', 'jruby' - PlatformGuard.implementation?(:jruby).should == true + expect(PlatformGuard.implementation?(:jruby)).to eq(true) end it "returns true if passed :ironruby and RUBY_ENGINE == 'ironruby'" do stub_const 'RUBY_ENGINE', 'ironruby' - PlatformGuard.implementation?(:ironruby).should == true + expect(PlatformGuard.implementation?(:ironruby)).to eq(true) end it "returns true if passed :maglev and RUBY_ENGINE == 'maglev'" do stub_const 'RUBY_ENGINE', 'maglev' - PlatformGuard.implementation?(:maglev).should == true + expect(PlatformGuard.implementation?(:maglev)).to eq(true) end it "returns true if passed :topaz and RUBY_ENGINE == 'topaz'" do stub_const 'RUBY_ENGINE', 'topaz' - PlatformGuard.implementation?(:topaz).should == true + expect(PlatformGuard.implementation?(:topaz)).to eq(true) end it "returns true if passed :ruby and RUBY_ENGINE matches /^ruby/" do stub_const 'RUBY_ENGINE', 'ruby' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) stub_const 'RUBY_ENGINE', 'ruby1.8' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) stub_const 'RUBY_ENGINE', 'ruby1.9' - PlatformGuard.implementation?(:ruby).should == true + expect(PlatformGuard.implementation?(:ruby)).to eq(true) end - it "raises an error when passed an unrecognized name" do - stub_const 'RUBY_ENGINE', 'ruby' - lambda { - PlatformGuard.implementation?(:python) - }.should raise_error(/unknown implementation/) + it "works for an unrecognized name" do + stub_const 'RUBY_ENGINE', 'myrubyimplementation' + expect(PlatformGuard.implementation?(:myrubyimplementation)).to eq(true) + expect(PlatformGuard.implementation?(:other)).to eq(false) end end -describe PlatformGuard, ".standard?" do +RSpec.describe PlatformGuard, ".standard?" do it "returns true if implementation? returns true" do - PlatformGuard.should_receive(:implementation?).with(:ruby).and_return(true) - PlatformGuard.standard?.should be_true + expect(PlatformGuard).to receive(:implementation?).with(:ruby).and_return(true) + expect(PlatformGuard.standard?).to be_truthy end it "returns false if implementation? returns false" do - PlatformGuard.should_receive(:implementation?).with(:ruby).and_return(false) - PlatformGuard.standard?.should be_false + expect(PlatformGuard).to receive(:implementation?).with(:ruby).and_return(false) + expect(PlatformGuard.standard?).to be_falsey end end -describe PlatformGuard, ".wordsize?" do +RSpec.describe PlatformGuard, ".c_long_size?" do it "returns true when arg is 32 and 1.size is 4" do - PlatformGuard.wordsize?(32).should == (1.size == 4) + expect(PlatformGuard.c_long_size?(32)).to eq(1.size == 4) end it "returns true when arg is 64 and 1.size is 8" do - PlatformGuard.wordsize?(64).should == (1.size == 8) + expect(PlatformGuard.c_long_size?(64)).to eq(1.size == 8) end end -describe PlatformGuard, ".os?" do +RSpec.describe PlatformGuard, ".os?" do before :each do - stub_const 'PlatformGuard::HOST_OS', 'solarce' + stub_const 'PlatformGuard::PLATFORM', 'solarce' end it "returns false when arg does not match the platform" do - PlatformGuard.os?(:ruby).should == false + expect(PlatformGuard.os?(:ruby)).to eq(false) end it "returns false when no arg matches the platform" do - PlatformGuard.os?(:ruby, :jruby, :rubinius, :maglev).should == false + expect(PlatformGuard.os?(:ruby, :jruby, :rubinius, :maglev)).to eq(false) end it "returns true when arg matches the platform" do - PlatformGuard.os?(:solarce).should == true + expect(PlatformGuard.os?(:solarce)).to eq(true) end it "returns true when any arg matches the platform" do - PlatformGuard.os?(:ruby, :jruby, :solarce, :rubinius, :maglev).should == true + expect(PlatformGuard.os?(:ruby, :jruby, :solarce, :rubinius, :maglev)).to eq(true) end it "returns true when arg is :windows and the platform contains 'mswin'" do - stub_const 'PlatformGuard::HOST_OS', 'mswin32' - PlatformGuard.os?(:windows).should == true + stub_const 'PlatformGuard::PLATFORM', 'mswin32' + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns true when arg is :windows and the platform contains 'mingw'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32' - PlatformGuard.os?(:windows).should == true + stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mswin32' - PlatformGuard.os?(:linux).should == false + stub_const 'PlatformGuard::PLATFORM', 'i386-mswin32' + expect(PlatformGuard.os?(:linux)).to eq(false) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32' - PlatformGuard.os?(:linux).should == false + stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' + expect(PlatformGuard.os?(:linux)).to eq(false) + end +end + +RSpec.describe PlatformGuard, ".os?" do + it "returns true if called with the current OS or architecture" do + os = RbConfig::CONFIG["host_os"].sub("-gnu", "") + arch = RbConfig::CONFIG["host_arch"] + expect(PlatformGuard.os?(os)).to eq(true) + expect(PlatformGuard.os?(arch)).to eq(true) + expect(PlatformGuard.os?("#{arch}-#{os}")).to eq(true) end end -describe PlatformGuard, ".os? on JRuby" do +RSpec.describe PlatformGuard, ".os? on JRuby" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -257,72 +266,72 @@ describe PlatformGuard, ".os? on JRuby" do end it "raises an error when testing for a :java platform" do - lambda { + expect { PlatformGuard.os?(:java) - }.should raise_error(":java is not a valid OS") + }.to raise_error(":java is not a valid OS") end it "returns true when arg is :windows and RUBY_PLATFORM contains 'java' and os?(:windows) is true" do - stub_const 'PlatformGuard::HOST_OS', 'mswin32' - PlatformGuard.os?(:windows).should == true + stub_const 'PlatformGuard::PLATFORM', 'mswin32' + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns true when RUBY_PLATFORM contains 'java' and os?(argument) is true" do - stub_const 'PlatformGuard::HOST_OS', 'amiga' - PlatformGuard.os?(:amiga).should == true + stub_const 'PlatformGuard::PLATFORM', 'amiga' + expect(PlatformGuard.os?(:amiga)).to eq(true) end end -describe PlatformGuard, ".os?" do +RSpec.describe PlatformGuard, ".os?" do before :each do - stub_const 'PlatformGuard::HOST_OS', 'unreal' + stub_const 'PlatformGuard::PLATFORM', 'unreal' end it "returns true if argument matches RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:unreal).should == true + expect(PlatformGuard.os?(:unreal)).to eq(true) end it "returns true if any argument matches RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:bsd, :unreal, :amiga).should == true + expect(PlatformGuard.os?(:bsd, :unreal, :amiga)).to eq(true) end it "returns false if no argument matches RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:bsd, :netbsd, :amiga, :msdos).should == false + expect(PlatformGuard.os?(:bsd, :netbsd, :amiga, :msdos)).to eq(false) end it "returns false if argument does not match RbConfig::CONFIG['host_os']" do - PlatformGuard.os?(:amiga).should == false + expect(PlatformGuard.os?(:amiga)).to eq(false) end it "returns true when arg is :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mswin32' - PlatformGuard.os?(:windows).should == true + stub_const 'PlatformGuard::PLATFORM', 'i386-mswin32' + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns true when arg is :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32' - PlatformGuard.os?(:windows).should == true + stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' + expect(PlatformGuard.os?(:windows)).to eq(true) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mswin'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32' - PlatformGuard.os?(:linux).should == false + stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' + expect(PlatformGuard.os?(:linux)).to eq(false) end it "returns false when arg is not :windows and RbConfig::CONFIG['host_os'] contains 'mingw'" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32' - PlatformGuard.os?(:linux).should == false + stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' + expect(PlatformGuard.os?(:linux)).to eq(false) end end -describe PlatformGuard, ".windows?" do +RSpec.describe PlatformGuard, ".windows?" do it "returns true on windows" do - stub_const 'PlatformGuard::HOST_OS', 'i386-mingw32' - PlatformGuard.windows?.should == true + stub_const 'PlatformGuard::PLATFORM', 'i386-mingw32' + expect(PlatformGuard.windows?).to eq(true) end it "returns false on non-windows" do - stub_const 'PlatformGuard::HOST_OS', 'i586-linux' - PlatformGuard.windows?.should == false + stub_const 'PlatformGuard::PLATFORM', 'i586-linux' + expect(PlatformGuard.windows?).to eq(false) end end diff --git a/spec/mspec/spec/guards/quarantine_spec.rb b/spec/mspec/spec/guards/quarantine_spec.rb index e5c7da7939..eb5ff1da27 100644 --- a/spec/mspec/spec/guards/quarantine_spec.rb +++ b/spec/mspec/spec/guards/quarantine_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' require 'mspec/guards' -describe QuarantineGuard, "#match?" do +RSpec.describe QuarantineGuard, "#match?" do it "returns true" do - QuarantineGuard.new.match?.should == true + expect(QuarantineGuard.new.match?).to eq(true) end end -describe Object, "#quarantine!" do +RSpec.describe Object, "#quarantine!" do before :each do ScratchPad.clear @guard = QuarantineGuard.new - QuarantineGuard.stub(:new).and_return(@guard) + allow(QuarantineGuard).to receive(:new).and_return(@guard) end it "does not yield" do quarantine! { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "sets the name of the guard to :quarantine!" do quarantine! { } - @guard.name.should == :quarantine! + expect(@guard.name).to eq(:quarantine!) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do quarantine! { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/spec/mspec/spec/guards/superuser_spec.rb b/spec/mspec/spec/guards/superuser_spec.rb index f8815057e1..aba2cc2bb0 100644 --- a/spec/mspec/spec/guards/superuser_spec.rb +++ b/spec/mspec/spec/guards/superuser_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#as_superuser" do +RSpec.describe Object, "#as_superuser" do before :each do @guard = SuperUserGuard.new - SuperUserGuard.stub(:new).and_return(@guard) + allow(SuperUserGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "does not yield when Process.euid is not 0" do - Process.stub(:euid).and_return(501) + allow(Process).to receive(:euid).and_return(501) as_superuser { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when Process.euid is 0" do - Process.stub(:euid).and_return(0) + allow(Process).to receive(:euid).and_return(0) as_superuser { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "sets the name of the guard to :as_superuser" do as_superuser { } - @guard.name.should == :as_superuser + expect(@guard.name).to eq(:as_superuser) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do as_superuser { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/spec/mspec/spec/guards/support_spec.rb b/spec/mspec/spec/guards/support_spec.rb index 38414abebd..a61d003d6c 100644 --- a/spec/mspec/spec/guards/support_spec.rb +++ b/spec/mspec/spec/guards/support_spec.rb @@ -1,54 +1,54 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#not_supported_on" do +RSpec.describe Object, "#not_supported_on" do before :each do ScratchPad.clear end it "raises an Exception when passed :ruby" do stub_const "RUBY_ENGINE", "jruby" - lambda { + expect { not_supported_on(:ruby) { ScratchPad.record :yield } - }.should raise_error(Exception) - ScratchPad.recorded.should_not == :yield + }.to raise_error(Exception) + expect(ScratchPad.recorded).not_to eq(:yield) end it "does not yield when #implementation? returns true" do stub_const "RUBY_ENGINE", "jruby" not_supported_on(:jruby) { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "yields when #standard? returns true" do stub_const "RUBY_ENGINE", "ruby" not_supported_on(:rubinius) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "yields when #implementation? returns false" do stub_const "RUBY_ENGINE", "jruby" not_supported_on(:rubinius) { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end end -describe Object, "#not_supported_on" do +RSpec.describe Object, "#not_supported_on" do before :each do @guard = SupportedGuard.new - SupportedGuard.stub(:new).and_return(@guard) + allow(SupportedGuard).to receive(:new).and_return(@guard) end it "sets the name of the guard to :not_supported_on" do not_supported_on(:rubinius) { } - @guard.name.should == :not_supported_on + expect(@guard.name).to eq(:not_supported_on) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(false) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(false) + expect(@guard).to receive(:unregister) + expect do not_supported_on(:rubinius) { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) end end diff --git a/spec/mspec/spec/guards/user_spec.rb b/spec/mspec/spec/guards/user_spec.rb index 2de4db7390..2526504656 100644 --- a/spec/mspec/spec/guards/user_spec.rb +++ b/spec/mspec/spec/guards/user_spec.rb @@ -1,20 +1,20 @@ require 'spec_helper' require 'mspec/guards' -describe Object, "#as_user" do +RSpec.describe Object, "#as_user" do before :each do ScratchPad.clear end it "yields when the Process.euid is not 0" do - Process.stub(:euid).and_return(501) + allow(Process).to receive(:euid).and_return(501) as_user { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when the Process.euid is 0" do - Process.stub(:euid).and_return(0) + allow(Process).to receive(:euid).and_return(0) as_user { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end end diff --git a/spec/mspec/spec/guards/version_spec.rb b/spec/mspec/spec/guards/version_spec.rb index 07eb451ec9..5a5f4ddc3b 100644 --- a/spec/mspec/spec/guards/version_spec.rb +++ b/spec/mspec/spec/guards/version_spec.rb @@ -11,80 +11,102 @@ require 'mspec/guards' # is as typically understood: a..b means v >= a and v <= b; # a...b means v >= a and v < b. -describe VersionGuard, "#match?" do +RSpec.describe VersionGuard, "#match?" do before :each do hide_deprecation_warnings - stub_const "VersionGuard::FULL_RUBY_VERSION", SpecVersion.new('1.8.6') + @current = '1.8.6' end it "returns true when the argument is equal to RUBY_VERSION" do - VersionGuard.new('1.8.6').match?.should == true + expect(VersionGuard.new(@current, '1.8.6').match?).to eq(true) end it "returns true when the argument is less than RUBY_VERSION" do - VersionGuard.new('1.8').match?.should == true - VersionGuard.new('1.8.5').match?.should == true + expect(VersionGuard.new(@current, '1.8').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8.5').match?).to eq(true) end it "returns false when the argument is greater than RUBY_VERSION" do - VersionGuard.new('1.8.7').match?.should == false - VersionGuard.new('1.9.2').match?.should == false + expect(VersionGuard.new(@current, '1.8.7').match?).to eq(false) + expect(VersionGuard.new(@current, '1.9.2').match?).to eq(false) end it "returns true when the argument range includes RUBY_VERSION" do - VersionGuard.new('1.8.5'..'1.8.7').match?.should == true - VersionGuard.new('1.8'..'1.9').match?.should == true - VersionGuard.new('1.8'...'1.9').match?.should == true - VersionGuard.new('1.8'..'1.8.6').match?.should == true - VersionGuard.new('1.8.5'..'1.8.6').match?.should == true - VersionGuard.new(''...'1.8.7').match?.should == true + expect(VersionGuard.new(@current, '1.8.5'..'1.8.7').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8'..'1.9').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8'...'1.9').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8'..'1.8.6').match?).to eq(true) + expect(VersionGuard.new(@current, '1.8.5'..'1.8.6').match?).to eq(true) + expect(VersionGuard.new(@current, ''...'1.8.7').match?).to eq(true) end it "returns false when the argument range does not include RUBY_VERSION" do - VersionGuard.new('1.8.7'..'1.8.9').match?.should == false - VersionGuard.new('1.8.4'..'1.8.5').match?.should == false - VersionGuard.new('1.8.4'...'1.8.6').match?.should == false - VersionGuard.new('1.8.5'...'1.8.6').match?.should == false - VersionGuard.new(''...'1.8.6').match?.should == false + expect(VersionGuard.new(@current, '1.8.7'..'1.8.9').match?).to eq(false) + expect(VersionGuard.new(@current, '1.8.4'..'1.8.5').match?).to eq(false) + expect(VersionGuard.new(@current, '1.8.4'...'1.8.6').match?).to eq(false) + expect(VersionGuard.new(@current, '1.8.5'...'1.8.6').match?).to eq(false) + expect(VersionGuard.new(@current, ''...'1.8.6').match?).to eq(false) end end -describe Object, "#ruby_version_is" do +RSpec.describe Object, "#ruby_version_is" do before :each do - @guard = VersionGuard.new 'x.x.x' - VersionGuard.stub(:new).and_return(@guard) + @guard = VersionGuard.new '1.2.3', 'x.x.x' + allow(VersionGuard).to receive(:new).and_return(@guard) ScratchPad.clear end it "yields when #match? returns true" do - @guard.stub(:match?).and_return(true) + allow(@guard).to receive(:match?).and_return(true) ruby_version_is('x.x.x') { ScratchPad.record :yield } - ScratchPad.recorded.should == :yield + expect(ScratchPad.recorded).to eq(:yield) end it "does not yield when #match? returns false" do - @guard.stub(:match?).and_return(false) + allow(@guard).to receive(:match?).and_return(false) ruby_version_is('x.x.x') { ScratchPad.record :yield } - ScratchPad.recorded.should_not == :yield + expect(ScratchPad.recorded).not_to eq(:yield) end it "returns what #match? returns when no block is given" do - @guard.stub(:match?).and_return(true) - ruby_version_is('x.x.x').should == true - @guard.stub(:match?).and_return(false) - ruby_version_is('x.x.x').should == false + allow(@guard).to receive(:match?).and_return(true) + expect(ruby_version_is('x.x.x')).to eq(true) + allow(@guard).to receive(:match?).and_return(false) + expect(ruby_version_is('x.x.x')).to eq(false) end it "sets the name of the guard to :ruby_version_is" do ruby_version_is("") { } - @guard.name.should == :ruby_version_is + expect(@guard.name).to eq(:ruby_version_is) end it "calls #unregister even when an exception is raised in the guard block" do - @guard.should_receive(:match?).and_return(true) - @guard.should_receive(:unregister) - lambda do + expect(@guard).to receive(:match?).and_return(true) + expect(@guard).to receive(:unregister) + expect do ruby_version_is("") { raise Exception } - end.should raise_error(Exception) + end.to raise_error(Exception) + end +end + +RSpec.describe Object, "#version_is" do + before :each do + hide_deprecation_warnings + end + + it "returns the expected values" do + expect(version_is('1.2.3', '1.2.2')).to eq(true) + expect(version_is('1.2.3', '1.2.3')).to eq(true) + expect(version_is('1.2.3', '1.2.4')).to eq(false) + + expect(version_is('1.2.3', '1')).to eq(true) + expect(version_is('1.2.3', '1.0')).to eq(true) + expect(version_is('1.2.3', '2')).to eq(false) + expect(version_is('1.2.3', '2.0')).to eq(false) + + expect(version_is('1.2.3', '1.2.2'..'1.2.4')).to eq(true) + expect(version_is('1.2.3', '1.2.2'..'1.2.3')).to eq(true) + expect(version_is('1.2.3', '1.2.2'...'1.2.3')).to eq(false) + expect(version_is('1.2.3', '1.2.3'..'1.2.4')).to eq(true) end end diff --git a/spec/mspec/spec/helpers/argf_spec.rb b/spec/mspec/spec/helpers/argf_spec.rb index cf5eb0fe88..1412d71f84 100644 --- a/spec/mspec/spec/helpers/argf_spec.rb +++ b/spec/mspec/spec/helpers/argf_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#argf" do +RSpec.describe Object, "#argf" do before :each do @saved_argv = ARGV.dup @argv = [__FILE__] @@ -10,28 +10,28 @@ describe Object, "#argf" do it "sets @argf to an instance of ARGF.class with the given argv" do argf @argv do - @argf.should be_an_instance_of ARGF.class - @argf.filename.should == @argv.first + expect(@argf).to be_an_instance_of ARGF.class + expect(@argf.filename).to eq(@argv.first) end - @argf.should be_nil + expect(@argf).to be_nil end it "does not alter ARGV nor ARGF" do argf @argv do end - ARGV.should == @saved_argv - ARGF.argv.should == @saved_argv + expect(ARGV).to eq(@saved_argv) + expect(ARGF.argv).to eq(@saved_argv) end it "does not close STDIN" do argf ['-'] do end - STDIN.should_not be_closed + expect(STDIN).not_to be_closed end it "disallows nested calls" do argf @argv do - lambda { argf @argv }.should raise_error + expect { argf @argv }.to raise_error end end end diff --git a/spec/mspec/spec/helpers/argv_spec.rb b/spec/mspec/spec/helpers/argv_spec.rb index c3b21c7639..1db7e38650 100644 --- a/spec/mspec/spec/helpers/argv_spec.rb +++ b/spec/mspec/spec/helpers/argv_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#argv" do +RSpec.describe Object, "#argv" do before :each do ScratchPad.clear @@ -12,16 +12,16 @@ describe Object, "#argv" do it "replaces and restores the value of ARGV" do argv @argv - ARGV.should == @argv + expect(ARGV).to eq(@argv) argv :restore - ARGV.should == @saved_argv + expect(ARGV).to eq(@saved_argv) end it "yields to the block after setting ARGV" do argv @argv do ScratchPad.record ARGV.dup end - ScratchPad.recorded.should == @argv - ARGV.should == @saved_argv + expect(ScratchPad.recorded).to eq(@argv) + expect(ARGV).to eq(@saved_argv) end end diff --git a/spec/mspec/spec/helpers/datetime_spec.rb b/spec/mspec/spec/helpers/datetime_spec.rb index 8696c0c9c7..af4f557376 100644 --- a/spec/mspec/spec/helpers/datetime_spec.rb +++ b/spec/mspec/spec/helpers/datetime_spec.rb @@ -2,43 +2,43 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#new_datetime" do +RSpec.describe Object, "#new_datetime" do it "returns a default DateTime instance" do - new_datetime.should == DateTime.new + expect(new_datetime).to eq(DateTime.new) end it "returns a DateTime instance with the specified year value" do d = new_datetime :year => 1970 - d.year.should == 1970 + expect(d.year).to eq(1970) end it "returns a DateTime instance with the specified month value" do d = new_datetime :month => 11 - d.mon.should == 11 + expect(d.mon).to eq(11) end it "returns a DateTime instance with the specified day value" do d = new_datetime :day => 23 - d.day.should == 23 + expect(d.day).to eq(23) end it "returns a DateTime instance with the specified hour value" do d = new_datetime :hour => 10 - d.hour.should == 10 + expect(d.hour).to eq(10) end it "returns a DateTime instance with the specified minute value" do d = new_datetime :minute => 10 - d.min.should == 10 + expect(d.min).to eq(10) end it "returns a DateTime instance with the specified second value" do d = new_datetime :second => 2 - d.sec.should == 2 + expect(d.sec).to eq(2) end it "returns a DateTime instance with the specified offset value" do d = new_datetime :offset => Rational(3,24) - d.offset.should == Rational(3,24) + expect(d.offset).to eq(Rational(3,24)) end end diff --git a/spec/mspec/spec/helpers/fixture_spec.rb b/spec/mspec/spec/helpers/fixture_spec.rb index 4dbdd092f1..d8e2ae7be4 100644 --- a/spec/mspec/spec/helpers/fixture_spec.rb +++ b/spec/mspec/spec/helpers/fixture_spec.rb @@ -2,24 +2,24 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#fixture" do +RSpec.describe Object, "#fixture" do before :each do @dir = File.realpath("..", __FILE__) end it "returns the expanded path to a fixture file" do name = fixture(__FILE__, "subdir", "file.txt") - name.should == "#{@dir}/fixtures/subdir/file.txt" + expect(name).to eq("#{@dir}/fixtures/subdir/file.txt") end it "omits '/shared' if it is the suffix of the directory string" do name = fixture("#{@dir}/shared/file.rb", "subdir", "file.txt") - name.should == "#{@dir}/fixtures/subdir/file.txt" + expect(name).to eq("#{@dir}/fixtures/subdir/file.txt") end it "does not append '/fixtures' if it is the suffix of the directory string" do commands_dir = "#{File.dirname(@dir)}/commands" name = fixture("#{commands_dir}/fixtures/file.rb", "subdir", "file.txt") - name.should == "#{commands_dir}/fixtures/subdir/file.txt" + expect(name).to eq("#{commands_dir}/fixtures/subdir/file.txt") end end diff --git a/spec/mspec/spec/helpers/flunk_spec.rb b/spec/mspec/spec/helpers/flunk_spec.rb index 7b1216d3f7..b6a1f21c12 100644 --- a/spec/mspec/spec/helpers/flunk_spec.rb +++ b/spec/mspec/spec/helpers/flunk_spec.rb @@ -4,17 +4,17 @@ require 'mspec/runner/mspec' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#flunk" do +RSpec.describe Object, "#flunk" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end it "raises an SpecExpectationNotMetError unconditionally" do - lambda { flunk }.should raise_error(SpecExpectationNotMetError) + expect { flunk }.to raise_error(SpecExpectationNotMetError) end it "accepts on argument for an optional message" do - lambda {flunk "test"}.should raise_error(SpecExpectationNotMetError) + expect {flunk "test"}.to raise_error(SpecExpectationNotMetError) end end diff --git a/spec/mspec/spec/helpers/fs_spec.rb b/spec/mspec/spec/helpers/fs_spec.rb index e40c6c5607..15bb43903a 100644 --- a/spec/mspec/spec/helpers/fs_spec.rb +++ b/spec/mspec/spec/helpers/fs_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#cp" do +RSpec.describe Object, "#cp" do before :each do @source = tmp("source.txt") @copy = tmp("copied.txt") @@ -19,12 +19,12 @@ describe Object, "#cp" do it "copies a file" do cp @source, @copy data = IO.read(@copy) - data.should == @contents - data.should == IO.read(@source) + expect(data).to eq(@contents) + expect(data).to eq(IO.read(@source)) end end -describe Object, "#touch" do +RSpec.describe Object, "#touch" do before :all do @name = tmp("touched.txt") end @@ -35,29 +35,29 @@ describe Object, "#touch" do it "creates a file" do touch @name - File.exist?(@name).should be_true + expect(File.exist?(@name)).to be_truthy end it "accepts an optional mode argument" do touch @name, "wb" - File.exist?(@name).should be_true + expect(File.exist?(@name)).to be_truthy end it "overwrites an existing file" do File.open(@name, "w") { |f| f.puts "used" } - File.size(@name).should > 0 + expect(File.size(@name)).to be > 0 touch @name - File.size(@name).should == 0 + expect(File.size(@name)).to eq(0) end it "yields the open file if passed a block" do touch(@name) { |f| f.write "touching" } - IO.read(@name).should == "touching" + expect(IO.read(@name)).to eq("touching") end end -describe Object, "#touch" do +RSpec.describe Object, "#touch" do before :all do @name = tmp("subdir/touched.txt") end @@ -68,11 +68,11 @@ describe Object, "#touch" do it "creates all the directories in the path to the file" do touch @name - File.exist?(@name).should be_true + expect(File.exist?(@name)).to be_truthy end end -describe Object, "#mkdir_p" do +RSpec.describe Object, "#mkdir_p" do before :all do @dir1 = tmp("/nested") @dir2 = @dir1 + "/directory" @@ -86,17 +86,17 @@ describe Object, "#mkdir_p" do it "creates all the directories in a path" do mkdir_p @dir2 - File.directory?(@dir2).should be_true + expect(File.directory?(@dir2)).to be_truthy end it "raises an ArgumentError if a path component is a file" do File.open(@dir1, "w") { |f| } - lambda { mkdir_p @dir2 }.should raise_error(ArgumentError) + expect { mkdir_p @dir2 }.to raise_error(ArgumentError) end it "works if multiple processes try to create the same directory concurrently" do original = File.method(:directory?) - File.should_receive(:directory?).at_least(:once) { |dir| + expect(File).to receive(:directory?).at_least(:once) { |dir| ret = original.call(dir) if !ret and dir == @dir1 Dir.mkdir(dir) # Simulate race @@ -104,11 +104,11 @@ describe Object, "#mkdir_p" do ret } mkdir_p @dir1 - original.call(@dir1).should be_true + expect(original.call(@dir1)).to be_truthy end end -describe Object, "#rm_r" do +RSpec.describe Object, "#rm_r" do before :all do @topdir = tmp("rm_r_tree") @topfile = @topdir + "/file.txt" @@ -137,59 +137,59 @@ describe Object, "#rm_r" do end it "raises an ArgumentError if the path is not prefixed by MSPEC_RM_PREFIX" do - lambda { rm_r "some_file.txt" }.should raise_error(ArgumentError) + expect { rm_r "some_file.txt" }.to raise_error(ArgumentError) end it "removes a single file" do rm_r @subfile - File.exist?(@subfile).should be_false + expect(File.exist?(@subfile)).to be_falsey end it "removes multiple files" do rm_r @topfile, @subfile - File.exist?(@topfile).should be_false - File.exist?(@subfile).should be_false + expect(File.exist?(@topfile)).to be_falsey + expect(File.exist?(@subfile)).to be_falsey end platform_is_not :windows do it "removes a symlink to a file" do File.symlink @topfile, @link rm_r @link - File.exist?(@link).should be_false + expect(File.exist?(@link)).to be_falsey end it "removes a symlink to a directory" do File.symlink @subdir1, @link rm_r @link - lambda do + expect do File.lstat(@link) - end.should raise_error(Errno::ENOENT) - File.exist?(@subdir1).should be_true + end.to raise_error(Errno::ENOENT) + expect(File.exist?(@subdir1)).to be_truthy end it "removes a dangling symlink" do File.symlink "non_existent_file", @link rm_r @link - lambda do + expect do File.lstat(@link) - end.should raise_error(Errno::ENOENT) + end.to raise_error(Errno::ENOENT) end it "removes a socket" do require 'socket' UNIXServer.new(@socket).close rm_r @socket - File.exist?(@socket).should be_false + expect(File.exist?(@socket)).to be_falsey end end it "removes a single directory" do rm_r @subdir2 - File.directory?(@subdir2).should be_false + expect(File.directory?(@subdir2)).to be_falsey end it "recursively removes a directory tree" do rm_r @topdir - File.directory?(@topdir).should be_false + expect(File.directory?(@topdir)).to be_falsey end end diff --git a/spec/mspec/spec/helpers/io_spec.rb b/spec/mspec/spec/helpers/io_spec.rb index 3219f59947..14c1a2d6b5 100644 --- a/spec/mspec/spec/helpers/io_spec.rb +++ b/spec/mspec/spec/helpers/io_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe IOStub do +RSpec.describe IOStub do before :each do @out = IOStub.new @sep = $\ @@ -14,42 +14,42 @@ describe IOStub do it "provides a write method" do @out.write "this" - @out.should == "this" + expect(@out).to eq("this") end it "concatenates the arguments sent to write" do @out.write "flim ", "flam" - @out.should == "flim flam" + expect(@out).to eq("flim flam") end it "provides a print method that appends the default separator" do $\ = " [newline] " @out.print "hello" @out.print "world" - @out.should == "hello [newline] world [newline] " + expect(@out).to eq("hello [newline] world [newline] ") end it "provides a puts method that appends the default separator" do @out.puts "hello", 1, 2, 3 - @out.should == "hello\n1\n2\n3\n" + expect(@out).to eq("hello\n1\n2\n3\n") end it "provides a puts method that appends separator if argument not given" do @out.puts - @out.should == "\n" + expect(@out).to eq("\n") end it "provides a printf method" do @out.printf "%-10s, %03d, %2.1f", "test", 42, 4.2 - @out.should == "test , 042, 4.2" + expect(@out).to eq("test , 042, 4.2") end it "provides a flush method that does nothing and returns self" do - @out.flush.should == @out + expect(@out.flush).to eq(@out) end end -describe Object, "#new_fd" do +RSpec.describe Object, "#new_fd" do before :each do @name = tmp("io_specs") @io = nil @@ -60,36 +60,36 @@ describe Object, "#new_fd" do rm_r @name end - it "returns a Integer that can be used to create an IO instance" do + it "returns an Integer that can be used to create an IO instance" do fd = new_fd @name - fd.should be_kind_of(Integer) + expect(fd).to be_kind_of(Integer) - @io = IO.new fd, fmode('w:utf-8') + @io = IO.new fd, 'w:utf-8' @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end it "accepts an options Hash" do - FeatureGuard.stub(:enabled?).and_return(true) + allow(FeatureGuard).to receive(:enabled?).and_return(true) fd = new_fd @name, { :mode => 'w:utf-8' } - fd.should be_kind_of(Integer) + expect(fd).to be_kind_of(Integer) - @io = IO.new fd, fmode('w:utf-8') + @io = IO.new fd, 'w:utf-8' @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end it "raises an ArgumentError if the options Hash does not include :mode" do - FeatureGuard.stub(:enabled?).and_return(true) - lambda { new_fd @name, { :encoding => "utf-8" } }.should raise_error(ArgumentError) + allow(FeatureGuard).to receive(:enabled?).and_return(true) + expect { new_fd @name, { :encoding => "utf-8" } }.to raise_error(ArgumentError) end end -describe Object, "#new_io" do +RSpec.describe Object, "#new_io" do before :each do @name = tmp("io_specs.txt") end @@ -99,16 +99,16 @@ describe Object, "#new_io" do rm_r @name end - it "returns an IO instance" do + it "returns a File instance" do @io = new_io @name - @io.should be_an_instance_of(IO) + expect(@io).to be_an_instance_of(File) end it "opens the IO for reading if passed 'r'" do touch(@name) { |f| f.print "io data" } @io = new_io @name, "r" - @io.read.should == "io data" - lambda { @io.puts "more data" }.should raise_error(IOError) + expect(@io.read).to eq("io data") + expect { @io.puts "more data" }.to raise_error(IOError) end it "opens the IO for writing if passed 'w'" do @@ -116,14 +116,14 @@ describe Object, "#new_io" do @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" + expect(IO.read(@name)).to eq("io data") end it "opens the IO for reading if passed { :mode => 'r' }" do touch(@name) { |f| f.print "io data" } @io = new_io @name, { :mode => "r" } - @io.read.should == "io data" - lambda { @io.puts "more data" }.should raise_error(IOError) + expect(@io.read).to eq("io data") + expect { @io.puts "more data" }.to raise_error(IOError) end it "opens the IO for writing if passed { :mode => 'w' }" do @@ -131,44 +131,6 @@ describe Object, "#new_io" do @io.sync = true @io.print "io data" - IO.read(@name).should == "io data" - end -end - -describe Object, "#fmode" do - it "returns the argument unmodified if :encoding feature is enabled" do - FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(true) - fmode("rb:binary:utf-8").should == "rb:binary:utf-8" - end - - it "returns only the file access mode if :encoding feature is not enabled" do - FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(false) - fmode("rb:binary:utf-8").should == "rb" - end -end - -describe Object, "#options_or_mode" do - describe "if passed a Hash" do - it "returns a mode string if :encoding feature is not enabled" do - FeatureGuard.should_receive(:enabled?).with(:encoding).twice.and_return(false) - options_or_mode(:mode => "rb:binary").should == "rb" - end - - it "returns a Hash if :encoding feature is enabled" do - FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(true) - options_or_mode(:mode => "rb:utf-8").should == { :mode => "rb:utf-8" } - end - end - - describe "if passed a String" do - it "returns only the file access mode if :encoding feature is not enabled" do - FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(false) - options_or_mode("rb:binary:utf-8").should == "rb" - end - - it "returns the argument unmodified if :encoding feature is enabled" do - FeatureGuard.should_receive(:enabled?).with(:encoding).and_return(true) - options_or_mode("rb:binary:utf-8").should == "rb:binary:utf-8" - end + expect(IO.read(@name)).to eq("io data") end end diff --git a/spec/mspec/spec/helpers/mock_to_path_spec.rb b/spec/mspec/spec/helpers/mock_to_path_spec.rb index 464e7e5440..c2ce985190 100644 --- a/spec/mspec/spec/helpers/mock_to_path_spec.rb +++ b/spec/mspec/spec/helpers/mock_to_path_spec.rb @@ -1,17 +1,23 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' +require 'mspec/mocks' + +RSpec.describe Object, "#mock_to_path" do + before :each do + state = double("run state").as_null_object + expect(MSpec).to receive(:current).and_return(state) + end -describe Object, "#mock_to_path" do it "returns an object that responds to #to_path" do obj = mock_to_path("foo") - obj.should be_a(MockObject) - obj.should respond_to(:to_path) + expect(obj).to be_a(MockObject) + expect(obj).to respond_to(:to_path) obj.to_path end it "returns the provided path when #to_path is called" do obj = mock_to_path("/tmp/foo") - obj.to_path.should == "/tmp/foo" + expect(obj.to_path).to eq("/tmp/foo") end end diff --git a/spec/mspec/spec/helpers/numeric_spec.rb b/spec/mspec/spec/helpers/numeric_spec.rb index 2ea56e5961..64495b7276 100644 --- a/spec/mspec/spec/helpers/numeric_spec.rb +++ b/spec/mspec/spec/helpers/numeric_spec.rb @@ -2,24 +2,30 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#bignum_value" do +RSpec.describe Object, "#bignum_value" do it "returns a value that is an instance of Bignum on any platform" do - bignum_value.should == 0x8000_0000_0000_0000 + expect(bignum_value).to be > fixnum_max end it "returns the default value incremented by the argument" do - bignum_value(42).should == 0x8000_0000_0000_002a + expect(bignum_value(42)).to eq(bignum_value + 42) end end -describe Object, "#nan_value" do +RSpec.describe Object, "-bignum_value" do + it "returns a value that is an instance of Bignum on any platform" do + expect(-bignum_value).to be < fixnum_min + end +end + +RSpec.describe Object, "#nan_value" do it "returns NaN" do - nan_value.nan?.should be_true + expect(nan_value.nan?).to be_truthy end end -describe Object, "#infinity_value" do +RSpec.describe Object, "#infinity_value" do it "returns Infinity" do - infinity_value.infinite?.should == 1 + expect(infinity_value.infinite?).to eq(1) end end diff --git a/spec/mspec/spec/helpers/ruby_exe_spec.rb b/spec/mspec/spec/helpers/ruby_exe_spec.rb index 8036043578..56bade1ba9 100644 --- a/spec/mspec/spec/helpers/ruby_exe_spec.rb +++ b/spec/mspec/spec/helpers/ruby_exe_spec.rb @@ -10,7 +10,7 @@ class RubyExeSpecs public :ruby_exe end -describe "#ruby_exe_options" do +RSpec.describe "#ruby_exe_options" do before :each do @ruby_exe_env = ENV['RUBY_EXE'] @script = RubyExeSpecs.new @@ -22,89 +22,89 @@ describe "#ruby_exe_options" do it "returns ENV['RUBY_EXE'] when passed :env" do ENV['RUBY_EXE'] = "kowabunga" - @script.ruby_exe_options(:env).should == "kowabunga" + expect(@script.ruby_exe_options(:env)).to eq("kowabunga") end it "returns 'bin/jruby' when passed :engine and RUBY_ENGINE is 'jruby'" do stub_const "RUBY_ENGINE", 'jruby' - @script.ruby_exe_options(:engine).should == 'bin/jruby' + expect(@script.ruby_exe_options(:engine)).to eq('bin/jruby') end it "returns 'bin/rbx' when passed :engine, RUBY_ENGINE is 'rbx'" do stub_const "RUBY_ENGINE", 'rbx' - @script.ruby_exe_options(:engine).should == 'bin/rbx' + expect(@script.ruby_exe_options(:engine)).to eq('bin/rbx') end it "returns 'ir' when passed :engine and RUBY_ENGINE is 'ironruby'" do stub_const "RUBY_ENGINE", 'ironruby' - @script.ruby_exe_options(:engine).should == 'ir' + expect(@script.ruby_exe_options(:engine)).to eq('ir') end it "returns 'maglev-ruby' when passed :engine and RUBY_ENGINE is 'maglev'" do stub_const "RUBY_ENGINE", 'maglev' - @script.ruby_exe_options(:engine).should == 'maglev-ruby' + expect(@script.ruby_exe_options(:engine)).to eq('maglev-ruby') end it "returns 'topaz' when passed :engine and RUBY_ENGINE is 'topaz'" do stub_const "RUBY_ENGINE", 'topaz' - @script.ruby_exe_options(:engine).should == 'topaz' + expect(@script.ruby_exe_options(:engine)).to eq('topaz') end it "returns RUBY_ENGINE + $(EXEEXT) when passed :name" do bin = RUBY_ENGINE + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '') name = File.join ".", bin - @script.ruby_exe_options(:name).should == name + expect(@script.ruby_exe_options(:name)).to eq(name) end it "returns $(bindir)/$(RUBY_INSTALL_NAME) + $(EXEEXT) when passed :install_name" do bin = RbConfig::CONFIG['RUBY_INSTALL_NAME'] + (RbConfig::CONFIG['EXEEXT'] || RbConfig::CONFIG['exeext'] || '') name = File.join RbConfig::CONFIG['bindir'], bin - @script.ruby_exe_options(:install_name).should == name + expect(@script.ruby_exe_options(:install_name)).to eq(name) end end -describe "#resolve_ruby_exe" do +RSpec.describe "#resolve_ruby_exe" do before :each do @name = "ruby_spec_exe" @script = RubyExeSpecs.new end it "returns the value returned by #ruby_exe_options if it exists and is executable" do - @script.should_receive(:ruby_exe_options).and_return(@name) - File.should_receive(:file?).with(@name).and_return(true) - File.should_receive(:executable?).with(@name).and_return(true) - File.should_receive(:expand_path).with(@name).and_return(@name) - @script.resolve_ruby_exe.should == @name + expect(@script).to receive(:ruby_exe_options).and_return(@name) + expect(File).to receive(:file?).with(@name).and_return(true) + expect(File).to receive(:executable?).with(@name).and_return(true) + expect(File).to receive(:expand_path).with(@name).and_return(@name) + expect(@script.resolve_ruby_exe).to eq(@name) end it "expands the path portion of the result of #ruby_exe_options" do - @script.should_receive(:ruby_exe_options).and_return("#{@name}") - File.should_receive(:file?).with(@name).and_return(true) - File.should_receive(:executable?).with(@name).and_return(true) - File.should_receive(:expand_path).with(@name).and_return("/usr/bin/#{@name}") - @script.resolve_ruby_exe.should == "/usr/bin/#{@name}" + expect(@script).to receive(:ruby_exe_options).and_return("#{@name}") + expect(File).to receive(:file?).with(@name).and_return(true) + expect(File).to receive(:executable?).with(@name).and_return(true) + expect(File).to receive(:expand_path).with(@name).and_return("/usr/bin/#{@name}") + expect(@script.resolve_ruby_exe).to eq("/usr/bin/#{@name}") end it "adds the flags after the executable" do @name = 'bin/rbx' - @script.should_receive(:ruby_exe_options).and_return(@name) - File.should_receive(:file?).with(@name).and_return(true) - File.should_receive(:executable?).with(@name).and_return(true) - File.should_receive(:expand_path).with(@name).and_return(@name) + expect(@script).to receive(:ruby_exe_options).and_return(@name) + expect(File).to receive(:file?).with(@name).and_return(true) + expect(File).to receive(:executable?).with(@name).and_return(true) + expect(File).to receive(:expand_path).with(@name).and_return(@name) - ENV.should_receive(:[]).with("RUBY_FLAGS").and_return('-X19') - @script.resolve_ruby_exe.should == 'bin/rbx -X19' + expect(ENV).to receive(:[]).with("RUBY_FLAGS").and_return('-X19') + expect(@script.resolve_ruby_exe).to eq('bin/rbx -X19') end it "raises an exception if no exe is found" do - File.should_receive(:file?).at_least(:once).and_return(false) - lambda { + expect(File).to receive(:file?).at_least(:once).and_return(false) + expect { @script.resolve_ruby_exe - }.should raise_error(Exception) + }.to raise_error(Exception) end end -describe Object, "#ruby_cmd" do +RSpec.describe Object, "#ruby_cmd" do before :each do stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q' @@ -115,83 +115,142 @@ describe Object, "#ruby_cmd" do end it "returns a command that runs the given file if it is a file that exists" do - File.should_receive(:exist?).with(@file).and_return(true) - @script.ruby_cmd(@file).should == "ruby_spec_exe -w -Q some/ruby/file.rb" + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(@script.ruby_cmd(@file)).to eq("ruby_spec_exe -w -Q some/ruby/file.rb") end it "includes the given options and arguments with a file" do - File.should_receive(:exist?).with(@file).and_return(true) - @script.ruby_cmd(@file, :options => "-w -Cdir", :args => "< file.txt").should == + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(@script.ruby_cmd(@file, :options => "-w -Cdir", :args => "< file.txt")).to eq( "ruby_spec_exe -w -Q -w -Cdir some/ruby/file.rb < file.txt" + ) end it "includes the given options and arguments with -e" do - File.should_receive(:exist?).with(@code).and_return(false) - @script.ruby_cmd(@code, :options => "-W0 -Cdir", :args => "< file.txt").should == + expect(File).to receive(:exist?).with(@code).and_return(false) + expect(@script.ruby_cmd(@code, :options => "-W0 -Cdir", :args => "< file.txt")).to eq( %(ruby_spec_exe -w -Q -W0 -Cdir -e "some \\"real\\" 'ruby' code" < file.txt) + ) end it "returns a command with options and arguments but without code or file" do - @script.ruby_cmd(nil, :options => "-c", :args => "> file.txt").should == + expect(@script.ruby_cmd(nil, :options => "-c", :args => "> file.txt")).to eq( "ruby_spec_exe -w -Q -c > file.txt" + ) end end -describe Object, "#ruby_exe" do +RSpec.describe Object, "#ruby_exe" do before :each do stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q' @script = RubyExeSpecs.new - @script.stub(:`) + allow(IO).to receive(:popen).and_return('OUTPUT') + + status_successful = double(Process::Status, exited?: true, exitstatus: 0) + allow(Process).to receive(:last_status).and_return(status_successful) + end + + it "returns command STDOUT when given command" do + code = "code" + options = {} + output = "output" + expect(IO).to receive(:popen).and_return(output) + + expect(@script.ruby_exe(code, options)).to eq output end it "returns an Array containing the interpreter executable and flags when given no arguments" do - @script.ruby_exe.should == ['ruby_spec_exe', '-w', '-Q'] + expect(@script.ruby_exe).to eq(['ruby_spec_exe', '-w', '-Q']) end it "executes (using `) the result of calling #ruby_cmd with the given arguments" do code = "code" options = {} - @script.should_receive(:ruby_cmd).and_return("ruby_cmd") - @script.should_receive(:`).with("ruby_cmd") + expect(@script).to receive(:ruby_cmd).and_return("ruby_cmd") + expect(IO).to receive(:popen).with("ruby_cmd") @script.ruby_exe(code, options) end + it "raises exception when command exit status is not successful" do + code = "code" + options = {} + + status_failed = double(Process::Status, exited?: true, exitstatus: 4) + allow(Process).to receive(:last_status).and_return(status_failed) + + expect { + @script.ruby_exe(code, options) + }.to raise_error(%r{Expected exit status is 0 but actual is 4 for command ruby_exe\(.+\)}) + end + + it "shows in the exception message if a signal killed the process" do + code = "code" + options = {} + + status_failed = double(Process::Status, exited?: false, signaled?: true, termsig: Signal.list.fetch('TERM')) + allow(Process).to receive(:last_status).and_return(status_failed) + + expect { + @script.ruby_exe(code, options) + }.to raise_error(%r{Expected exit status is 0 but actual is :SIGTERM for command ruby_exe\(.+\)}) + end + describe "with :dir option" do it "is deprecated" do - lambda { + expect { @script.ruby_exe nil, :dir => "tmp" - }.should raise_error(/no longer supported, use Dir\.chdir/) + }.to raise_error(/no longer supported, use Dir\.chdir/) end end describe "with :env option" do it "preserves the values of existing ENV keys" do ENV["ABC"] = "123" - ENV.stub(:[]) - ENV.should_receive(:[]).with("ABC") + allow(ENV).to receive(:[]) + expect(ENV).to receive(:[]).with("ABC") @script.ruby_exe nil, :env => { :ABC => "xyz" } end it "adds the :env entries to ENV" do - ENV.should_receive(:[]=).with("ABC", "xyz") + expect(ENV).to receive(:[]=).with("ABC", "xyz") @script.ruby_exe nil, :env => { :ABC => "xyz" } end it "deletes the :env entries in ENV when an exception is raised" do - ENV.should_receive(:delete).with("XYZ") + expect(ENV).to receive(:delete).with("XYZ") @script.ruby_exe nil, :env => { :XYZ => "xyz" } end it "resets the values of existing ENV keys when an exception is raised" do ENV["ABC"] = "123" - ENV.should_receive(:[]=).with("ABC", "xyz") - ENV.should_receive(:[]=).with("ABC", "123") + expect(ENV).to receive(:[]=).with("ABC", "xyz") + expect(ENV).to receive(:[]=).with("ABC", "123") - @script.should_receive(:`).and_raise(Exception) - lambda do + expect(IO).to receive(:popen).and_raise(Exception) + expect do @script.ruby_exe nil, :env => { :ABC => "xyz" } - end.should raise_error(Exception) + end.to raise_error(Exception) + end + end + + describe "with :exit_status option" do + before do + status_failed = double(Process::Status, exited?: true, exitstatus: 4) + allow(Process).to receive(:last_status).and_return(status_failed) + end + + it "raises exception when command ends with not expected status" do + expect { + @script.ruby_exe("path", exit_status: 1) + }.to raise_error(%r{Expected exit status is 1 but actual is 4 for command ruby_exe\(.+\)}) + end + + it "does not raise exception when command ends with expected status" do + output = "output" + expect(IO).to receive(:popen).and_return(output) + + expect(@script.ruby_exe("path", exit_status: 4)).to eq output end end end diff --git a/spec/mspec/spec/helpers/scratch_spec.rb b/spec/mspec/spec/helpers/scratch_spec.rb index 6a9eb2cf73..9dbef94aa3 100644 --- a/spec/mspec/spec/helpers/scratch_spec.rb +++ b/spec/mspec/spec/helpers/scratch_spec.rb @@ -2,23 +2,23 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe ScratchPad do +RSpec.describe ScratchPad do it "records an object and returns a previously recorded object" do ScratchPad.record :this - ScratchPad.recorded.should == :this + expect(ScratchPad.recorded).to eq(:this) end it "clears the recorded object" do ScratchPad.record :that - ScratchPad.recorded.should == :that + expect(ScratchPad.recorded).to eq(:that) ScratchPad.clear - ScratchPad.recorded.should == nil + expect(ScratchPad.recorded).to eq(nil) end it "provides a convenience shortcut to append to a previously recorded object" do ScratchPad.record [] ScratchPad << :new ScratchPad << :another - ScratchPad.recorded.should == [:new, :another] + expect(ScratchPad.recorded).to eq([:new, :another]) end end diff --git a/spec/mspec/spec/helpers/suppress_warning_spec.rb b/spec/mspec/spec/helpers/suppress_warning_spec.rb index d16361fa55..4cae189bd3 100644 --- a/spec/mspec/spec/helpers/suppress_warning_spec.rb +++ b/spec/mspec/spec/helpers/suppress_warning_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#suppress_warning" do +RSpec.describe Object, "#suppress_warning" do it "hides warnings" do suppress_warning do warn "should not be shown" @@ -14,6 +14,6 @@ describe Object, "#suppress_warning" do suppress_warning do a = 1 end - a.should == 1 + expect(a).to eq(1) end end diff --git a/spec/mspec/spec/helpers/tmp_spec.rb b/spec/mspec/spec/helpers/tmp_spec.rb index afadc7f51c..c41dcd57b3 100644 --- a/spec/mspec/spec/helpers/tmp_spec.rb +++ b/spec/mspec/spec/helpers/tmp_spec.rb @@ -2,26 +2,26 @@ require 'spec_helper' require 'mspec/guards' require 'mspec/helpers' -describe Object, "#tmp" do +RSpec.describe Object, "#tmp" do before :all do - @dir = "#{File.expand_path(Dir.pwd)}/rubyspec_temp" + @dir = SPEC_TEMP_DIR end it "returns a name relative to the current working directory" do - tmp("test.txt").should == "#{@dir}/#{SPEC_TEMP_UNIQUIFIER}-test.txt" + expect(tmp("test.txt")).to eq("#{@dir}/#{SPEC_TEMP_UNIQUIFIER}-test.txt") end it "returns a 'unique' name on repeated calls" do a = tmp("text.txt") b = tmp("text.txt") - a.should_not == b + expect(a).not_to eq(b) end it "does not 'uniquify' the name if requested not to" do - tmp("test.txt", false).should == "#{@dir}/test.txt" + expect(tmp("test.txt", false)).to eq("#{@dir}/test.txt") end it "returns the name of the temporary directory when passed an empty string" do - tmp("").should == "#{@dir}/" + expect(tmp("")).to eq("#{@dir}/") end end diff --git a/spec/mspec/spec/integration/interpreter_spec.rb b/spec/mspec/spec/integration/interpreter_spec.rb index b6fa6859d1..dbf3987a08 100644 --- a/spec/mspec/spec/integration/interpreter_spec.rb +++ b/spec/mspec/spec/integration/interpreter_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "The interpreter passed with -t" do +RSpec.describe "The interpreter passed with -t" do it "is used in subprocess" do fixtures = "spec/fixtures" interpreter = "#{fixtures}/my_ruby" @@ -8,11 +8,11 @@ describe "The interpreter passed with -t" do out = out.lines.map(&:chomp).reject { |line| line == 'RUBY_DESCRIPTION' }.take(3) - out.should == [ + expect(out).to eq([ interpreter, interpreter, "CWD/#{interpreter}" - ] - ret.success?.should == true + ]) + expect(ret.success?).to eq(true) end end diff --git a/spec/mspec/spec/integration/object_methods_spec.rb b/spec/mspec/spec/integration/object_methods_spec.rb index 3be704beb6..697fbd10fa 100644 --- a/spec/mspec/spec/integration/object_methods_spec.rb +++ b/spec/mspec/spec/integration/object_methods_spec.rb @@ -9,10 +9,10 @@ Finished in D.DDDDDD seconds 1 file, 1 example, 1 expectation, 0 failures, 0 errors, 0 tagged EOS -describe "MSpec" do +RSpec.describe "MSpec" do it "does not define public methods on Object" do out, ret = run_mspec("run", "spec/fixtures/object_methods_spec.rb") - out.should == expected_output - ret.success?.should == true + expect(out).to eq(expected_output) + expect(ret.success?).to eq(true) end end diff --git a/spec/mspec/spec/integration/run_spec.rb b/spec/mspec/spec/integration/run_spec.rb index 93d2ef8b68..ea0735e9b2 100644 --- a/spec/mspec/spec/integration/run_spec.rb +++ b/spec/mspec/spec/integration/run_spec.rb @@ -1,52 +1,72 @@ require 'spec_helper' -describe "Running mspec" do +RSpec.describe "Running mspec" do + q = BACKTRACE_QUOTE a_spec_output = <<EOS 1) Foo#bar errors FAILED -Expected 1 - to equal 2 - -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/bin/mspec-run:7:in `<main>' +Expected 1 == 2 +to be truthy but was false +CWD/spec/fixtures/a_spec.rb:8:in #{q}block (2 levels) in <top (required)>' +CWD/spec/fixtures/a_spec.rb:2:in #{q}<top (required)>' 2) Foo#bar fails ERROR RuntimeError: failure -CWD/spec/fixtures/a_spec.rb:12:in `block (2 levels) in <top (required)>' -CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>' -CWD/bin/mspec-run:7:in `<main>' +CWD/spec/fixtures/a_spec.rb:12:in #{q}block (2 levels) in <top (required)>' +CWD/spec/fixtures/a_spec.rb:2:in #{q}<top (required)>' Finished in D.DDDDDD seconds EOS a_stats = "1 file, 3 examples, 2 expectations, 1 failure, 1 error, 0 tagged\n" ab_stats = "2 files, 4 examples, 3 expectations, 1 failure, 1 error, 0 tagged\n" + fixtures = "spec/fixtures" it "runs the specs" do - fixtures = "spec/fixtures" out, ret = run_mspec("run", "#{fixtures}/a_spec.rb") - out.should == "RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}") + expect(ret.success?).to eq(false) end it "directly with mspec-run runs the specs" do - fixtures = "spec/fixtures" out, ret = run_mspec("-run", "#{fixtures}/a_spec.rb") - out.should == "RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n.FE\n#{a_spec_output}\n#{a_stats}") + expect(ret.success?).to eq(false) end - it "runs the specs in parallel with -j" do - fixtures = "spec/fixtures" + it "runs the specs in parallel with -j using the dotted formatter" do out, ret = run_mspec("run", "-j #{fixtures}/a_spec.rb #{fixtures}/b_spec.rb") + expect(out).to eq("RUBY_DESCRIPTION\n...\n#{a_spec_output}\n#{ab_stats}") + expect(ret.success?).to eq(false) + end + + it "runs the specs in parallel with -j -fa" do + out, ret = run_mspec("run", "-j -fa #{fixtures}/a_spec.rb #{fixtures}/b_spec.rb") progress_bar = "\r[/ | 0% | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " + "\r[- | ==================50% | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " + "\r[\\ | ==================100%================== | 00:00:00] \e[0;32m 0F \e[0;32m 0E\e[0m " - out.should == "RUBY_DESCRIPTION\n#{progress_bar}\n#{a_spec_output}\n#{ab_stats}" - ret.success?.should == false + expect(out).to eq("RUBY_DESCRIPTION\n#{progress_bar}\n#{a_spec_output}\n#{ab_stats}") + expect(ret.success?).to eq(false) + end + + it "gives a useful error message when a subprocess dies in parallel mode" do + out, ret = run_mspec("run", "-j #{fixtures}/b_spec.rb #{fixtures}/die_spec.rb") + lines = out.lines + expect(lines).to include "A child mspec-run process died unexpectedly while running CWD/spec/fixtures/die_spec.rb\n" + expect(lines).to include "Finished in D.DDDDDD seconds\n" + expect(lines.last).to match(/^\d files?, \d examples?, \d expectations?, 0 failures, 0 errors, 0 tagged$/) + expect(ret.success?).to eq(false) + end + + it "gives a useful error message when a subprocess prints unexpected output on STDOUT in parallel mode" do + out, ret = run_mspec("run", "-j #{fixtures}/b_spec.rb #{fixtures}/chatty_spec.rb") + lines = out.lines + expect(lines).to include "A child mspec-run process printed unexpected output on STDOUT: #{'"Hello\nIt\'s me!\n"'} while running CWD/spec/fixtures/chatty_spec.rb\n" + expect(lines).to include "Finished in D.DDDDDD seconds\n" + expect(lines.last).to eq("2 files, 2 examples, 2 expectations, 0 failures, 0 errors, 0 tagged\n") + expect(ret.success?).to eq(false) end end diff --git a/spec/mspec/spec/integration/tag_spec.rb b/spec/mspec/spec/integration/tag_spec.rb index d980769043..ae08e9d45f 100644 --- a/spec/mspec/spec/integration/tag_spec.rb +++ b/spec/mspec/spec/integration/tag_spec.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require 'spec_helper' -describe "Running mspec tag" do +RSpec.describe "Running mspec tag" do before :all do FileUtils.rm_rf 'spec/fixtures/tags' end @@ -13,7 +13,8 @@ describe "Running mspec tag" do it "tags the failing specs" do fixtures = "spec/fixtures" out, ret = run_mspec("tag", "--add fails --fail #{fixtures}/tagging_spec.rb") - out.should == <<EOS + q = BACKTRACE_QUOTE + expect(out).to eq <<EOS RUBY_DESCRIPTION .FF TagAction: specs tagged with 'fails': @@ -24,33 +25,29 @@ Tag#me érròrs in unicode 1) Tag#me errors FAILED -Expected 1 - to equal 2 - -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/bin/mspec-tag:7:in `<main>' +Expected 1 == 2 +to be truthy but was false +CWD/spec/fixtures/tagging_spec.rb:9:in #{q}block (2 levels) in <top (required)>' +CWD/spec/fixtures/tagging_spec.rb:3:in #{q}<top (required)>' 2) Tag#me érròrs in unicode FAILED -Expected 1 - to equal 2 - -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/bin/mspec-tag:7:in `<main>' +Expected 1 == 2 +to be truthy but was false +CWD/spec/fixtures/tagging_spec.rb:13:in #{q}block (2 levels) in <top (required)>' +CWD/spec/fixtures/tagging_spec.rb:3:in #{q}<top (required)>' Finished in D.DDDDDD seconds 1 file, 3 examples, 3 expectations, 2 failures, 0 errors, 0 tagged EOS - ret.success?.should == false + expect(ret.success?).to eq(false) end it "does not run already tagged specs" do fixtures = "spec/fixtures" out, ret = run_mspec("run", "--excl-tag fails #{fixtures}/tagging_spec.rb") - out.should == <<EOS + expect(out).to eq <<EOS RUBY_DESCRIPTION . @@ -58,6 +55,6 @@ Finished in D.DDDDDD seconds 1 file, 3 examples, 1 expectation, 0 failures, 0 errors, 2 tagged EOS - ret.success?.should == true + expect(ret.success?).to eq(true) end end diff --git a/spec/mspec/spec/matchers/base_spec.rb b/spec/mspec/spec/matchers/base_spec.rb index cc13c29d1d..6b5a3fbd72 100644 --- a/spec/mspec/spec/matchers/base_spec.rb +++ b/spec/mspec/spec/matchers/base_spec.rb @@ -3,223 +3,226 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' require 'time' -describe SpecPositiveOperatorMatcher, "== operator" do - it "raises an SpecExpectationNotMetError when expected == actual returns false" do - lambda { - SpecPositiveOperatorMatcher.new(1) == 2 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecPositiveOperatorMatcher, "== operator" do 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 + expect { + SpecPositiveOperatorMatcher.new(1) == 2 + }.to raise_error(SpecExpectationNotMetError, "Expected 1 == 2\nto be truthy but was false") 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 - lambda { - SpecPositiveOperatorMatcher.new('real') =~ /fake/ - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecPositiveOperatorMatcher, "=~ operator" do 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/ + expect { + SpecPositiveOperatorMatcher.new('real') =~ /fake/ + }.to raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /fake/\nto be truthy but was nil") 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 - lambda { - SpecPositiveOperatorMatcher.new(4) > 5 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecPositiveOperatorMatcher, "> operator" do 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 + expect { + SpecPositiveOperatorMatcher.new(4) > 5 + }.to raise_error(SpecExpectationNotMetError, "Expected 4 > 5\nto be truthy but was false") 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 - lambda { - SpecPositiveOperatorMatcher.new(4) >= 5 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecPositiveOperatorMatcher, ">= operator" do 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 + expect { + SpecPositiveOperatorMatcher.new(4) >= 5 + }.to raise_error(SpecExpectationNotMetError, "Expected 4 >= 5\nto be truthy but was false") 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 - lambda { - SpecPositiveOperatorMatcher.new(5) < 4 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecPositiveOperatorMatcher, "< operator" do 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 + expect { + SpecPositiveOperatorMatcher.new(5) < 4 + }.to raise_error(SpecExpectationNotMetError, "Expected 5 < 4\nto be truthy but was false") 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 - lambda { - SpecPositiveOperatorMatcher.new(5) <= 4 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecPositiveOperatorMatcher, "<= operator" do 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 + expect { + SpecPositiveOperatorMatcher.new(5) <= 4 + }.to raise_error(SpecExpectationNotMetError, "Expected 5 <= 4\nto be truthy but was false") 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 SpecNegativeOperatorMatcher, "== operator" do - it "raises an SpecExpectationNotMetError when expected == actual returns true" do - lambda { - SpecNegativeOperatorMatcher.new(1) == 1 - }.should raise_error(SpecExpectationNotMetError) +RSpec.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 + expect { + SpecPositiveOperatorMatcher.new(2).eql?(3) + }.to raise_error(SpecExpectationNotMetError, "Expected 2.eql? 3\nto be truthy but was false") + expect { + SpecPositiveOperatorMatcher.new(2).equal?(3) + }.to raise_error(SpecExpectationNotMetError, "Expected 2.equal? 3\nto be truthy but was false") + expect { + SpecPositiveOperatorMatcher.new([1, 2, 3]).include?(4) + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 4\nto be truthy but was false") + expect { + SpecPositiveOperatorMatcher.new("abc").start_with?("de") + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"de\"\nto be truthy but was false") + expect { + SpecPositiveOperatorMatcher.new("abc").start_with?("d", "e") + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"e\"\nto be truthy but was false") + expect { + SpecPositiveOperatorMatcher.new(2).odd? + }.to raise_error(SpecExpectationNotMetError, "Expected 2.odd?\nto be truthy but was false") + expect { + SpecPositiveOperatorMatcher.new([1, 3]).any? { |e| e.even? } + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 3].any? { ... }\nto be truthy but was false") end +end + +RSpec.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 + expect { + SpecNegativeOperatorMatcher.new(2).eql?(2) + }.to raise_error(SpecExpectationNotMetError, "Expected 2.eql? 2\nto be falsy but was true") + expect { + SpecNegativeOperatorMatcher.new(2).equal?(2) + }.to raise_error(SpecExpectationNotMetError, "Expected 2.equal? 2\nto be falsy but was true") + expect { + SpecNegativeOperatorMatcher.new([1, 2, 3]).include?(2) + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2, 3].include? 2\nto be falsy but was true") + expect { + SpecNegativeOperatorMatcher.new("abc").start_with?("ab") + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"ab\"\nto be falsy but was true") + expect { + SpecNegativeOperatorMatcher.new("abc").start_with?("d", "a") + }.to raise_error(SpecExpectationNotMetError, "Expected \"abc\".start_with? \"d\", \"a\"\nto be falsy but was true") + expect { + SpecNegativeOperatorMatcher.new(3).odd? + }.to raise_error(SpecExpectationNotMetError, "Expected 3.odd?\nto be falsy but was true") + expect { + SpecNegativeOperatorMatcher.new([1, 2]).any? { |e| e.even? } + }.to raise_error(SpecExpectationNotMetError, "Expected [1, 2].any? { ... }\nto be falsy but was true") + end +end +RSpec.describe SpecNegativeOperatorMatcher, "== operator" do 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 + expect { + SpecNegativeOperatorMatcher.new(1) == 1 + }.to raise_error(SpecExpectationNotMetError, "Expected 1 == 1\nto be falsy but was true") 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 - lambda { - SpecNegativeOperatorMatcher.new('real') =~ /real/ - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecNegativeOperatorMatcher, "=~ operator" do 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/ + expect { + SpecNegativeOperatorMatcher.new('real') =~ /real/ + }.to raise_error(SpecExpectationNotMetError, "Expected \"real\" =~ /real/\nto be falsy but was 0") 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 - lambda { - SpecNegativeOperatorMatcher.new(4) < 5 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecNegativeOperatorMatcher, "< operator" do 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 + expect { + SpecNegativeOperatorMatcher.new(4) < 5 + }.to raise_error(SpecExpectationNotMetError, "Expected 4 < 5\nto be falsy but was true") 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 - lambda { +RSpec.describe SpecNegativeOperatorMatcher, "<= operator" do + it "provides a failure message that 'Expected x not to be less than or equal to y'" do + expect { SpecNegativeOperatorMatcher.new(4) <= 5 - }.should raise_error(SpecExpectationNotMetError) - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 4 <= 5\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new(5) <= 5 - }.should raise_error(SpecExpectationNotMetError) - 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 + }.to raise_error(SpecExpectationNotMetError, "Expected 5 <= 5\nto be falsy but was true") 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 - lambda { - SpecNegativeOperatorMatcher.new(5) > 4 - }.should raise_error(SpecExpectationNotMetError) - end - +RSpec.describe SpecNegativeOperatorMatcher, "> operator" do 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 + expect { + SpecNegativeOperatorMatcher.new(5) > 4 + }.to raise_error(SpecExpectationNotMetError, "Expected 5 > 4\nto be falsy but was true") 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 - lambda { +RSpec.describe SpecNegativeOperatorMatcher, ">= operator" do + it "provides a failure message that 'Expected x not to be greater than or equal to y'" do + expect { SpecNegativeOperatorMatcher.new(5) >= 4 - }.should raise_error(SpecExpectationNotMetError) - lambda { + }.to raise_error(SpecExpectationNotMetError, "Expected 5 >= 4\nto be falsy but was true") + expect { SpecNegativeOperatorMatcher.new(5) >= 5 - }.should raise_error(SpecExpectationNotMetError) - 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 + }.to raise_error(SpecExpectationNotMetError, "Expected 5 >= 5\nto be falsy but was true") 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/be_an_instance_of_spec.rb b/spec/mspec/spec/matchers/be_an_instance_of_spec.rb index 7f2126df7d..7c74249d24 100644 --- a/spec/mspec/spec/matchers/be_an_instance_of_spec.rb +++ b/spec/mspec/spec/matchers/be_an_instance_of_spec.rb @@ -13,38 +13,38 @@ module BeAnInOfSpecs end end -describe BeAnInstanceOfMatcher do +RSpec.describe BeAnInstanceOfMatcher do it "matches when actual is an instance_of? expected" do a = BeAnInOfSpecs::A.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(a).should be_true + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(a)).to be_truthy b = BeAnInOfSpecs::B.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(b).should be_true + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(b)).to be_truthy end it "does not match when actual is not an instance_of? expected" do a = BeAnInOfSpecs::A.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(a).should be_false + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(a)).to be_falsey b = BeAnInOfSpecs::B.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(b).should be_false + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(b)).to be_falsey c = BeAnInOfSpecs::C.new - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(c).should be_false - BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(c).should be_false + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::A).matches?(c)).to be_falsey + expect(BeAnInstanceOfMatcher.new(BeAnInOfSpecs::B).matches?(c)).to be_falsey end it "provides a useful failure message" do matcher = BeAnInstanceOfMatcher.new(Numeric) matcher.matches?("string") - matcher.failure_message.should == [ - "Expected \"string\" (String)", "to be an instance of Numeric"] + expect(matcher.failure_message).to eq([ + "Expected \"string\" (String)", "to be an instance of Numeric"]) end it "provides a useful negative failure message" do matcher = BeAnInstanceOfMatcher.new(Numeric) matcher.matches?(4.0) - matcher.negative_failure_message.should == [ - "Expected 4.0 (Float)", "not to be an instance of Numeric"] + expect(matcher.negative_failure_message).to eq([ + "Expected 4.0 (Float)", "not to be an instance of Numeric"]) end end diff --git a/spec/mspec/spec/matchers/be_ancestor_of_spec.rb b/spec/mspec/spec/matchers/be_ancestor_of_spec.rb index c6bd1a26c7..abc05e0f7a 100644 --- a/spec/mspec/spec/matchers/be_ancestor_of_spec.rb +++ b/spec/mspec/spec/matchers/be_ancestor_of_spec.rb @@ -5,24 +5,24 @@ require 'mspec/matchers' class Parent; end class Child < Parent; end -describe BeAncestorOfMatcher do +RSpec.describe BeAncestorOfMatcher do it "matches when actual is an ancestor of expected" do - BeAncestorOfMatcher.new(Child).matches?(Parent).should == true + expect(BeAncestorOfMatcher.new(Child).matches?(Parent)).to eq(true) end it "does not match when actual is not an ancestor of expected" do - BeAncestorOfMatcher.new(Parent).matches?(Child).should == false + expect(BeAncestorOfMatcher.new(Parent).matches?(Child)).to eq(false) end it "provides a useful failure message" do matcher = BeAncestorOfMatcher.new(Parent) matcher.matches?(Child) - matcher.failure_message.should == ["Expected Child", "to be an ancestor of Parent"] + expect(matcher.failure_message).to eq(["Expected Child", "to be an ancestor of Parent"]) end it "provides a useful negative failure message" do matcher = BeAncestorOfMatcher.new(Child) matcher.matches?(Parent) - matcher.negative_failure_message.should == ["Expected Parent", "not to be an ancestor of Child"] + expect(matcher.negative_failure_message).to eq(["Expected Parent", "not to be an ancestor of Child"]) end end diff --git a/spec/mspec/spec/matchers/be_close_spec.rb b/spec/mspec/spec/matchers/be_close_spec.rb index 3ced61dc7a..dfd4f4ddbb 100644 --- a/spec/mspec/spec/matchers/be_close_spec.rb +++ b/spec/mspec/spec/matchers/be_close_spec.rb @@ -3,44 +3,46 @@ require 'mspec/expectations/expectations' require 'mspec/matchers' # Adapted from RSpec 1.0.8 -describe BeCloseMatcher do +RSpec.describe BeCloseMatcher do it "matches when actual == expected" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.0).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.0)).to eq(true) end it "matches when actual < (expected + tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.49).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.49)).to eq(true) end it "matches when actual > (expected - tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(4.51).should == true + expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.51)).to eq(true) end - it "does not match when actual == (expected + tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.5).should == false + it "matches when actual == (expected + tolerance)" do + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.5)).to eq(true) + expect(BeCloseMatcher.new(3, 2).matches?(5)).to eq(true) end - it "does not match when actual == (expected - tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(4.5).should == false + it "matches when actual == (expected - tolerance)" do + expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.5)).to eq(true) + expect(BeCloseMatcher.new(3, 2).matches?(1)).to eq(true) end it "does not match when actual < (expected - tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(4.49).should == false + expect(BeCloseMatcher.new(5.0, 0.5).matches?(4.49)).to eq(false) end it "does not match when actual > (expected + tolerance)" do - BeCloseMatcher.new(5.0, 0.5).matches?(5.51).should == false + expect(BeCloseMatcher.new(5.0, 0.5).matches?(5.51)).to eq(false) end it "provides a useful failure message" do matcher = BeCloseMatcher.new(5.0, 0.5) - matcher.matches?(5.5) - matcher.failure_message.should == ["Expected 5.0", "to be within +/- 0.5 of 5.5"] + matcher.matches?(6.5) + expect(matcher.failure_message).to eq(["Expected 6.5", "to be within 5.0 +/- 0.5"]) end it "provides a useful negative failure message" do matcher = BeCloseMatcher.new(5.0, 0.5) - matcher.matches?(5.0) - matcher.negative_failure_message.should == ["Expected 5.0", "not to be within +/- 0.5 of 5.0"] + matcher.matches?(4.9) + expect(matcher.negative_failure_message).to eq(["Expected 4.9", "not to be within 5.0 +/- 0.5"]) end end diff --git a/spec/mspec/spec/matchers/be_computed_by_spec.rb b/spec/mspec/spec/matchers/be_computed_by_spec.rb index 9833e211a4..f73861a576 100644 --- a/spec/mspec/spec/matchers/be_computed_by_spec.rb +++ b/spec/mspec/spec/matchers/be_computed_by_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' require 'mspec/matchers' -describe BeComputedByMatcher do +RSpec.describe BeComputedByMatcher do it "matches when all entries in the Array compute" do array = [ [65, "A"], [90, "Z"] ] - BeComputedByMatcher.new(:chr).matches?(array).should be_true + expect(BeComputedByMatcher.new(:chr).matches?(array)).to be_truthy end it "matches when all entries in the Array with arguments compute" do array = [ [1, 2, 3], [2, 4, 6] ] - BeComputedByMatcher.new(:+).matches?(array).should be_true + expect(BeComputedByMatcher.new(:+).matches?(array)).to be_truthy end it "does not match when any entry in the Array does not compute" do array = [ [65, "A" ], [91, "Z" ] ] - BeComputedByMatcher.new(:chr).matches?(array).should be_false + expect(BeComputedByMatcher.new(:chr).matches?(array)).to be_falsey end it "accepts an argument list to apply to each method call" do array = [ [65, "1000001" ], [90, "1011010" ] ] - BeComputedByMatcher.new(:to_s, 2).matches?(array).should be_true + expect(BeComputedByMatcher.new(:to_s, 2).matches?(array)).to be_truthy end it "does not match when any entry in the Array with arguments does not compute" do array = [ [1, 2, 3], [2, 4, 7] ] - BeComputedByMatcher.new(:+).matches?(array).should be_false + expect(BeComputedByMatcher.new(:+).matches?(array)).to be_falsey end it "provides a useful failure message" do @@ -37,6 +37,6 @@ describe BeComputedByMatcher do [91, "Z" ] ] matcher = BeComputedByMatcher.new(:chr) matcher.matches?(array) - matcher.failure_message.should == ["Expected \"Z\"", "to be computed by 91.chr (computed \"[\" instead)"] + expect(matcher.failure_message).to eq(["Expected \"Z\"", "to be computed by 91.chr (computed \"[\" instead)"]) end end diff --git a/spec/mspec/spec/matchers/be_empty_spec.rb b/spec/mspec/spec/matchers/be_empty_spec.rb index cb8663f5ee..30678fe85f 100644 --- a/spec/mspec/spec/matchers/be_empty_spec.rb +++ b/spec/mspec/spec/matchers/be_empty_spec.rb @@ -2,25 +2,25 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeEmptyMatcher do +RSpec.describe BeEmptyMatcher do it "matches when actual is empty" do - BeEmptyMatcher.new.matches?("").should == true + expect(BeEmptyMatcher.new.matches?("")).to eq(true) end it "does not match when actual is not empty" do - BeEmptyMatcher.new.matches?([10]).should == false + expect(BeEmptyMatcher.new.matches?([10])).to eq(false) end it "provides a useful failure message" do matcher = BeEmptyMatcher.new matcher.matches?("not empty string") - matcher.failure_message.should == ["Expected \"not empty string\"", "to be empty"] + expect(matcher.failure_message).to eq(["Expected \"not empty string\"", "to be empty"]) end it "provides a useful negative failure message" do matcher = BeEmptyMatcher.new matcher.matches?("") - matcher.negative_failure_message.should == ["Expected \"\"", "not to be empty"] + expect(matcher.negative_failure_message).to eq(["Expected \"\"", "not to be empty"]) end end diff --git a/spec/mspec/spec/matchers/be_false_spec.rb b/spec/mspec/spec/matchers/be_false_spec.rb index 31afd24ebc..46d7253220 100644 --- a/spec/mspec/spec/matchers/be_false_spec.rb +++ b/spec/mspec/spec/matchers/be_false_spec.rb @@ -2,27 +2,27 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeFalseMatcher do +RSpec.describe BeFalseMatcher do it "matches when actual is false" do - BeFalseMatcher.new.matches?(false).should == true + expect(BeFalseMatcher.new.matches?(false)).to eq(true) end it "does not match when actual is not false" do - BeFalseMatcher.new.matches?("").should == false - BeFalseMatcher.new.matches?(true).should == false - BeFalseMatcher.new.matches?(nil).should == false - BeFalseMatcher.new.matches?(0).should == false + expect(BeFalseMatcher.new.matches?("")).to eq(false) + expect(BeFalseMatcher.new.matches?(true)).to eq(false) + expect(BeFalseMatcher.new.matches?(nil)).to eq(false) + expect(BeFalseMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeFalseMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be false"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be false"]) end it "provides a useful negative failure message" do matcher = BeFalseMatcher.new matcher.matches?(false) - matcher.negative_failure_message.should == ["Expected false", "not to be false"] + expect(matcher.negative_failure_message).to eq(["Expected false", "not to be false"]) end end diff --git a/spec/mspec/spec/matchers/be_kind_of_spec.rb b/spec/mspec/spec/matchers/be_kind_of_spec.rb index 7c4a59f7b9..1e19058411 100644 --- a/spec/mspec/spec/matchers/be_kind_of_spec.rb +++ b/spec/mspec/spec/matchers/be_kind_of_spec.rb @@ -2,30 +2,30 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeKindOfMatcher do +RSpec.describe BeKindOfMatcher do it "matches when actual is a kind_of? expected" do - BeKindOfMatcher.new(Numeric).matches?(1).should == true - BeKindOfMatcher.new(Integer).matches?(2).should == true - BeKindOfMatcher.new(Regexp).matches?(/m/).should == true + expect(BeKindOfMatcher.new(Numeric).matches?(1)).to eq(true) + expect(BeKindOfMatcher.new(Integer).matches?(2)).to eq(true) + expect(BeKindOfMatcher.new(Regexp).matches?(/m/)).to eq(true) end it "does not match when actual is not a kind_of? expected" do - BeKindOfMatcher.new(Integer).matches?(1.5).should == false - BeKindOfMatcher.new(String).matches?(:a).should == false - BeKindOfMatcher.new(Hash).matches?([]).should == false + expect(BeKindOfMatcher.new(Integer).matches?(1.5)).to eq(false) + expect(BeKindOfMatcher.new(String).matches?(:a)).to eq(false) + expect(BeKindOfMatcher.new(Hash).matches?([])).to eq(false) end it "provides a useful failure message" do matcher = BeKindOfMatcher.new(Numeric) matcher.matches?('string') - matcher.failure_message.should == [ - "Expected \"string\" (String)", "to be kind of Numeric"] + expect(matcher.failure_message).to eq([ + "Expected \"string\" (String)", "to be kind of Numeric"]) end it "provides a useful negative failure message" do matcher = BeKindOfMatcher.new(Numeric) matcher.matches?(4.0) - matcher.negative_failure_message.should == [ - "Expected 4.0 (Float)", "not to be kind of Numeric"] + expect(matcher.negative_failure_message).to eq([ + "Expected 4.0 (Float)", "not to be kind of Numeric"]) end end diff --git a/spec/mspec/spec/matchers/be_nan_spec.rb b/spec/mspec/spec/matchers/be_nan_spec.rb index 2062763a92..baa7447943 100644 --- a/spec/mspec/spec/matchers/be_nan_spec.rb +++ b/spec/mspec/spec/matchers/be_nan_spec.rb @@ -4,25 +4,25 @@ require 'mspec/guards' require 'mspec/helpers' require 'mspec/matchers' -describe BeNaNMatcher do +RSpec.describe BeNaNMatcher do it "matches when actual is NaN" do - BeNaNMatcher.new.matches?(nan_value).should == true + expect(BeNaNMatcher.new.matches?(nan_value)).to eq(true) end it "does not match when actual is not NaN" do - BeNaNMatcher.new.matches?(1.0).should == false - BeNaNMatcher.new.matches?(0).should == false + expect(BeNaNMatcher.new.matches?(1.0)).to eq(false) + expect(BeNaNMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeNaNMatcher.new matcher.matches?(0) - matcher.failure_message.should == ["Expected 0", "to be NaN"] + expect(matcher.failure_message).to eq(["Expected 0", "to be NaN"]) end it "provides a useful negative failure message" do matcher = BeNaNMatcher.new matcher.matches?(nan_value) - matcher.negative_failure_message.should == ["Expected NaN", "not to be NaN"] + expect(matcher.negative_failure_message).to eq(["Expected NaN", "not to be NaN"]) end end diff --git a/spec/mspec/spec/matchers/be_nil_spec.rb b/spec/mspec/spec/matchers/be_nil_spec.rb index 6551feb5de..e2768acf83 100644 --- a/spec/mspec/spec/matchers/be_nil_spec.rb +++ b/spec/mspec/spec/matchers/be_nil_spec.rb @@ -2,26 +2,26 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeNilMatcher do +RSpec.describe BeNilMatcher do it "matches when actual is nil" do - BeNilMatcher.new.matches?(nil).should == true + expect(BeNilMatcher.new.matches?(nil)).to eq(true) end it "does not match when actual is not nil" do - BeNilMatcher.new.matches?("").should == false - BeNilMatcher.new.matches?(false).should == false - BeNilMatcher.new.matches?(0).should == false + expect(BeNilMatcher.new.matches?("")).to eq(false) + expect(BeNilMatcher.new.matches?(false)).to eq(false) + expect(BeNilMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeNilMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be nil"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be nil"]) end it "provides a useful negative failure message" do matcher = BeNilMatcher.new matcher.matches?(nil) - matcher.negative_failure_message.should == ["Expected nil", "not to be nil"] + expect(matcher.negative_failure_message).to eq(["Expected nil", "not to be nil"]) end end diff --git a/spec/mspec/spec/matchers/be_true_or_false_spec.rb b/spec/mspec/spec/matchers/be_true_or_false_spec.rb index 3edffcb1b1..e4b456eafc 100644 --- a/spec/mspec/spec/matchers/be_true_or_false_spec.rb +++ b/spec/mspec/spec/matchers/be_true_or_false_spec.rb @@ -2,18 +2,18 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeTrueOrFalseMatcher do +RSpec.describe BeTrueOrFalseMatcher do it "matches when actual is true" do - BeTrueOrFalseMatcher.new.matches?(true).should == true + expect(BeTrueOrFalseMatcher.new.matches?(true)).to eq(true) end it "matches when actual is false" do - BeTrueOrFalseMatcher.new.matches?(false).should == true + expect(BeTrueOrFalseMatcher.new.matches?(false)).to eq(true) end it "provides a useful failure message" do matcher = BeTrueOrFalseMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be true or false"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be true or false"]) end end diff --git a/spec/mspec/spec/matchers/be_true_spec.rb b/spec/mspec/spec/matchers/be_true_spec.rb index 90c89b3911..39ef05a0f8 100644 --- a/spec/mspec/spec/matchers/be_true_spec.rb +++ b/spec/mspec/spec/matchers/be_true_spec.rb @@ -2,27 +2,27 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BeTrueMatcher do +RSpec.describe BeTrueMatcher do it "matches when actual is true" do - BeTrueMatcher.new.matches?(true).should == true + expect(BeTrueMatcher.new.matches?(true)).to eq(true) end it "does not match when actual is not true" do - BeTrueMatcher.new.matches?("").should == false - BeTrueMatcher.new.matches?(false).should == false - BeTrueMatcher.new.matches?(nil).should == false - BeTrueMatcher.new.matches?(0).should == false + expect(BeTrueMatcher.new.matches?("")).to eq(false) + expect(BeTrueMatcher.new.matches?(false)).to eq(false) + expect(BeTrueMatcher.new.matches?(nil)).to eq(false) + expect(BeTrueMatcher.new.matches?(0)).to eq(false) end it "provides a useful failure message" do matcher = BeTrueMatcher.new matcher.matches?("some string") - matcher.failure_message.should == ["Expected \"some string\"", "to be true"] + expect(matcher.failure_message).to eq(["Expected \"some string\"", "to be true"]) end it "provides a useful negative failure message" do matcher = BeTrueMatcher.new matcher.matches?(true) - matcher.negative_failure_message.should == ["Expected true", "not to be true"] + expect(matcher.negative_failure_message).to eq(["Expected true", "not to be true"]) end end diff --git a/spec/mspec/spec/matchers/block_caller_spec.rb b/spec/mspec/spec/matchers/block_caller_spec.rb index d6793b9779..5d7085fa63 100644 --- a/spec/mspec/spec/matchers/block_caller_spec.rb +++ b/spec/mspec/spec/matchers/block_caller_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe BlockingMatcher do +RSpec.describe BlockingMatcher do it 'matches when a Proc blocks the caller' do - BlockingMatcher.new.matches?(proc { sleep }).should == true + expect(BlockingMatcher.new.matches?(proc { sleep })).to eq(true) end it 'does not match when a Proc does not block the caller' do - BlockingMatcher.new.matches?(proc { 1 }).should == false + expect(BlockingMatcher.new.matches?(proc { 1 })).to eq(false) end end diff --git a/spec/mspec/spec/matchers/complain_spec.rb b/spec/mspec/spec/matchers/complain_spec.rb index 709b57be6c..399ef3105b 100644 --- a/spec/mspec/spec/matchers/complain_spec.rb +++ b/spec/mspec/spec/matchers/complain_spec.rb @@ -2,51 +2,101 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe ComplainMatcher do +RSpec.describe ComplainMatcher do it "matches when executing the proc results in output to $stderr" do proc = lambda { warn "I'm gonna tell yo mama" } - ComplainMatcher.new(nil).matches?(proc).should == true + expect(ComplainMatcher.new(nil).matches?(proc)).to eq(true) end - it "maches when executing the proc results in the expected output to $stderr" do + it "matches when executing the proc results in the expected output to $stderr" do proc = lambda { warn "Que haces?" } - ComplainMatcher.new("Que haces?\n").matches?(proc).should == true - ComplainMatcher.new("Que pasa?\n").matches?(proc).should == false - ComplainMatcher.new(/Que/).matches?(proc).should == true - ComplainMatcher.new(/Quoi/).matches?(proc).should == false + expect(ComplainMatcher.new("Que haces?\n").matches?(proc)).to eq(true) + expect(ComplainMatcher.new("Que pasa?\n").matches?(proc)).to eq(false) + expect(ComplainMatcher.new(/Que/).matches?(proc)).to eq(true) + expect(ComplainMatcher.new(/Quoi/).matches?(proc)).to eq(false) end it "does not match when there is no output to $stderr" do - ComplainMatcher.new(nil).matches?(lambda {}).should == false + expect(ComplainMatcher.new(nil).matches?(lambda {})).to eq(false) end it "provides a useful failure message" do matcher = ComplainMatcher.new(nil) matcher.matches?(lambda { }) - matcher.failure_message.should == ["Expected a warning", "but received none"] + expect(matcher.failure_message).to eq(["Expected a warning", "but received none"]) matcher = ComplainMatcher.new("listen here") matcher.matches?(lambda { warn "look out" }) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected warning: \"listen here\"", "but got: \"look out\""] + ) matcher = ComplainMatcher.new(/talk/) matcher.matches?(lambda { warn "listen up" }) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected warning to match: /talk/", "but got: \"listen up\""] + ) end it "provides a useful negative failure message" do proc = lambda { warn "ouch" } matcher = ComplainMatcher.new(nil) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Unexpected warning: ", "\"ouch\""] + ) matcher = ComplainMatcher.new("ouchy") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected warning: \"ouchy\"", "but got: \"ouch\""] + ) matcher = ComplainMatcher.new(/ou/) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected warning not to match: /ou/", "but got: \"ouch\""] + ) + end + + context "`verbose` option specified" do + before do + $VERBOSE, @verbose = nil, $VERBOSE + end + + after do + $VERBOSE = @verbose + end + + it "sets $VERBOSE with specified second optional parameter" do + verbose = nil + proc = lambda { verbose = $VERBOSE } + + ComplainMatcher.new(nil, verbose: true).matches?(proc) + expect(verbose).to eq(true) + + ComplainMatcher.new(nil, verbose: false).matches?(proc) + expect(verbose).to eq(false) + end + + it "sets $VERBOSE with false by default" do + verbose = nil + proc = lambda { verbose = $VERBOSE } + + ComplainMatcher.new(nil).matches?(proc) + expect(verbose).to eq(false) + end + + it "does not have side effect" do + proc = lambda { safe_value = $VERBOSE } + + expect do + ComplainMatcher.new(nil, verbose: true).matches?(proc) + end.not_to change { $VERBOSE } + end + + it "accepts a verbose level as single argument" do + verbose = nil + proc = lambda { verbose = $VERBOSE } + + ComplainMatcher.new(verbose: true).matches?(proc) + expect(verbose).to eq(true) + end end end diff --git a/spec/mspec/spec/matchers/eql_spec.rb b/spec/mspec/spec/matchers/eql_spec.rb index 711ebdb679..66307d2a9d 100644 --- a/spec/mspec/spec/matchers/eql_spec.rb +++ b/spec/mspec/spec/matchers/eql_spec.rb @@ -2,32 +2,32 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe EqlMatcher do +RSpec.describe EqlMatcher do it "matches when actual is eql? to expected" do - EqlMatcher.new(1).matches?(1).should == true - EqlMatcher.new(1.5).matches?(1.5).should == true - EqlMatcher.new("red").matches?("red").should == true - EqlMatcher.new(:blue).matches?(:blue).should == true - EqlMatcher.new(Object).matches?(Object).should == true + expect(EqlMatcher.new(1).matches?(1)).to eq(true) + expect(EqlMatcher.new(1.5).matches?(1.5)).to eq(true) + expect(EqlMatcher.new("red").matches?("red")).to eq(true) + expect(EqlMatcher.new(:blue).matches?(:blue)).to eq(true) + expect(EqlMatcher.new(Object).matches?(Object)).to eq(true) o = Object.new - EqlMatcher.new(o).matches?(o).should == true + expect(EqlMatcher.new(o).matches?(o)).to eq(true) end it "does not match when actual is not eql? to expected" do - EqlMatcher.new(1).matches?(1.0).should == false - EqlMatcher.new(Hash).matches?(Object).should == false + expect(EqlMatcher.new(1).matches?(1.0)).to eq(false) + expect(EqlMatcher.new(Hash).matches?(Object)).to eq(false) end 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"] + expect(matcher.failure_message).to eq(["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"] + expect(matcher.negative_failure_message).to eq(["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..3a5ae4ede2 100644 --- a/spec/mspec/spec/matchers/equal_element_spec.rb +++ b/spec/mspec/spec/matchers/equal_element_spec.rb @@ -2,74 +2,74 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe EqualElementMatcher do +RSpec.describe EqualElementMatcher do it "matches if it finds an element with the passed name, no matter what attributes/content" do - EqualElementMatcher.new("A").matches?('<A></A>').should be_true - EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>').should be_true - EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>').should be_true + expect(EqualElementMatcher.new("A").matches?('<A></A>')).to be_truthy + expect(EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>')).to be_truthy + expect(EqualElementMatcher.new("A").matches?('<A HREF="http://example.com"></A>')).to be_truthy - EqualElementMatcher.new("BASE").matches?('<BASE></A>').should be_false - EqualElementMatcher.new("BASE").matches?('<A></BASE>').should be_false - EqualElementMatcher.new("BASE").matches?('<A></A>').should be_false - EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>').should be_false - EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>').should be_false + expect(EqualElementMatcher.new("BASE").matches?('<BASE></A>')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('<A></BASE>')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('<A></A>')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>')).to be_falsey + expect(EqualElementMatcher.new("BASE").matches?('<A HREF="http://example.com"></A>')).to be_falsey end it "matches if it finds an element with the passed name and the passed attributes" do - EqualElementMatcher.new("A", {}).matches?('<A></A>').should be_true - EqualElementMatcher.new("A", nil).matches?('<A HREF="http://example.com"></A>').should be_true - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com"></A>').should be_true + expect(EqualElementMatcher.new("A", {}).matches?('<A></A>')).to be_truthy + expect(EqualElementMatcher.new("A", nil).matches?('<A HREF="http://example.com"></A>')).to be_truthy + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com"></A>')).to be_truthy - EqualElementMatcher.new("A", {}).matches?('<A HREF="http://example.com"></A>').should be_false - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A></A>').should be_false - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://test.com"></A>').should be_false - EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com" HREF="http://example.com"></A>').should be_false + expect(EqualElementMatcher.new("A", {}).matches?('<A HREF="http://example.com"></A>')).to be_falsey + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A></A>')).to be_falsey + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://test.com"></A>')).to be_falsey + expect(EqualElementMatcher.new("A", "HREF" => "http://example.com").matches?('<A HREF="http://example.com" HREF="http://example.com"></A>')).to be_falsey end it "matches if it finds an element with the passed name, the passed attributes and the passed content" do - EqualElementMatcher.new("A", {}, "").matches?('<A></A>').should be_true - EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Example</A>').should be_true + expect(EqualElementMatcher.new("A", {}, "").matches?('<A></A>')).to be_truthy + expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Example</A>')).to be_truthy - EqualElementMatcher.new("A", {}, "Test").matches?('<A></A>').should be_false - EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com"></A>').should be_false - EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Test</A>').should be_false + expect(EqualElementMatcher.new("A", {}, "Test").matches?('<A></A>')).to be_falsey + expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com"></A>')).to be_falsey + expect(EqualElementMatcher.new("A", {"HREF" => "http://example.com"}, "Example").matches?('<A HREF="http://example.com">Test</A>')).to be_falsey end it "can match unclosed elements" do - EqualElementMatcher.new("BASE", nil, nil, :not_closed => true).matches?('<BASE>').should be_true - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">').should be_true - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Example", :not_closed => true).matches?('<BASE HREF="http://example.com">Example').should be_true + expect(EqualElementMatcher.new("BASE", nil, nil, :not_closed => true).matches?('<BASE>')).to be_truthy + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">')).to be_truthy + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Example", :not_closed => true).matches?('<BASE HREF="http://example.com">Example')).to be_truthy - EqualElementMatcher.new("BASE", {}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">').should be_false - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "", :not_closed => true).matches?('<BASE HREF="http://example.com">Example').should be_false - EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Test", :not_closed => true).matches?('<BASE HREF="http://example.com">Example').should be_false + expect(EqualElementMatcher.new("BASE", {}, nil, :not_closed => true).matches?('<BASE HREF="http://example.com">')).to be_falsey + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "", :not_closed => true).matches?('<BASE HREF="http://example.com">Example')).to be_falsey + expect(EqualElementMatcher.new("BASE", {"HREF" => "http://example.com"}, "Test", :not_closed => true).matches?('<BASE HREF="http://example.com">Example')).to be_falsey end it "provides a useful failure message" do equal_element = EqualElementMatcher.new("A", {}, "Test") - 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}] + expect(equal_element.matches?('<A></A>')).to be_falsey + expect(equal_element.failure_message).to eq([%{Expected "<A></A>"}, %{to be a 'A' element with no attributes and "Test" as content}]) equal_element = EqualElementMatcher.new("A", {}, "") - 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}] + expect(equal_element.matches?('<A>Test</A>')).to be_falsey + expect(equal_element.failure_message).to eq([%{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.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}] + expect(equal_element.matches?('<A>Test</A>')).to be_falsey + expect(equal_element.failure_message).to eq([%{Expected "<A>Test</A>"}, %{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?('<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}] + expect(equal_element.matches?('<A></A>')).to be_falsey + expect(equal_element.negative_failure_message).to eq([%{Expected "<A></A>"}, %{not to be a 'A' element with no attributes and "Test" as content}]) equal_element = EqualElementMatcher.new("A", {}, "") - 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}] + expect(equal_element.matches?('<A>Test</A>')).to be_falsey + expect(equal_element.negative_failure_message).to eq([%{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.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}] + expect(equal_element.matches?('<A>Test</A>')).to be_falsey + expect(equal_element.negative_failure_message).to eq([%{Expected "<A>Test</A>"}, %{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..2df1de54b4 100644 --- a/spec/mspec/spec/matchers/equal_spec.rb +++ b/spec/mspec/spec/matchers/equal_spec.rb @@ -2,31 +2,31 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe EqualMatcher do +RSpec.describe EqualMatcher do it "matches when actual is equal? to expected" do - EqualMatcher.new(1).matches?(1).should == true - EqualMatcher.new(:blue).matches?(:blue).should == true - EqualMatcher.new(Object).matches?(Object).should == true + expect(EqualMatcher.new(1).matches?(1)).to eq(true) + expect(EqualMatcher.new(:blue).matches?(:blue)).to eq(true) + expect(EqualMatcher.new(Object).matches?(Object)).to eq(true) o = Object.new - EqualMatcher.new(o).matches?(o).should == true + expect(EqualMatcher.new(o).matches?(o)).to eq(true) end it "does not match when actual is not a equal? to expected" do - EqualMatcher.new(1).matches?(1.0).should == false - EqualMatcher.new("blue").matches?("blue").should == false - EqualMatcher.new(Hash).matches?(Object).should == false + expect(EqualMatcher.new(1).matches?(1.0)).to eq(false) + expect(EqualMatcher.new("blue").matches?("blue")).to eq(false) + expect(EqualMatcher.new(Hash).matches?(Object)).to eq(false) end 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"] + expect(matcher.failure_message).to eq(["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"] + expect(matcher.negative_failure_message).to eq(["Expected 1", "not to be identical to 1"]) end end diff --git a/spec/mspec/spec/matchers/have_class_variable_spec.rb b/spec/mspec/spec/matchers/have_class_variable_spec.rb index 01ba9d0f57..d6fcf9d4e2 100644 --- a/spec/mspec/spec/matchers/have_class_variable_spec.rb +++ b/spec/mspec/spec/matchers/have_class_variable_spec.rb @@ -8,42 +8,42 @@ class IVarModMock end end -describe HaveClassVariableMatcher, "on RUBY_VERSION >= 1.9" do +RSpec.describe HaveClassVariableMatcher, "on RUBY_VERSION >= 1.9" do it "matches when mod has the class variable, given as string" do matcher = HaveClassVariableMatcher.new('@foo') - matcher.matches?(IVarModMock).should be_true + expect(matcher.matches?(IVarModMock)).to be_truthy end it "matches when mod has the class variable, given as symbol" do matcher = HaveClassVariableMatcher.new(:@foo) - matcher.matches?(IVarModMock).should be_true + expect(matcher.matches?(IVarModMock)).to be_truthy end it "does not match when mod hasn't got the class variable, given as string" do matcher = HaveClassVariableMatcher.new('@bar') - matcher.matches?(IVarModMock).should be_false + expect(matcher.matches?(IVarModMock)).to be_falsey end it "does not match when mod hasn't got the class variable, given as symbol" do matcher = HaveClassVariableMatcher.new(:@bar) - matcher.matches?(IVarModMock).should be_false + expect(matcher.matches?(IVarModMock)).to be_falsey end it "provides a failure message for #should" do matcher = HaveClassVariableMatcher.new(:@bar) matcher.matches?(IVarModMock) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected IVarModMock to have class variable '@bar'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveClassVariableMatcher.new(:@bar) matcher.matches?(IVarModMock) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected IVarModMock NOT to have class variable '@bar'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_constant_spec.rb b/spec/mspec/spec/matchers/have_constant_spec.rb index 20c5f161d4..0bf44dbe2b 100644 --- a/spec/mspec/spec/matchers/have_constant_spec.rb +++ b/spec/mspec/spec/matchers/have_constant_spec.rb @@ -6,32 +6,32 @@ class HCMSpecs X = :x end -describe HaveConstantMatcher do +RSpec.describe HaveConstantMatcher do it "matches when mod has the constant" do matcher = HaveConstantMatcher.new :X - matcher.matches?(HCMSpecs).should be_true + expect(matcher.matches?(HCMSpecs)).to be_truthy end it "does not match when mod does not have the constant" do matcher = HaveConstantMatcher.new :A - matcher.matches?(HCMSpecs).should be_false + expect(matcher.matches?(HCMSpecs)).to be_falsey end it "provides a failure message for #should" do matcher = HaveConstantMatcher.new :A matcher.matches?(HCMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HCMSpecs to have constant 'A'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveConstantMatcher.new :X matcher.matches?(HCMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HCMSpecs NOT to have constant 'X'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_instance_method_spec.rb b/spec/mspec/spec/matchers/have_instance_method_spec.rb index 738f5f875d..7c2e50dba6 100644 --- a/spec/mspec/spec/matchers/have_instance_method_spec.rb +++ b/spec/mspec/spec/matchers/have_instance_method_spec.rb @@ -12,42 +12,42 @@ class HIMMSpecs end end -describe HaveInstanceMethodMatcher do +RSpec.describe HaveInstanceMethodMatcher do it "inherits from MethodMatcher" do - HaveInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the instance method" do matcher = HaveInstanceMethodMatcher.new :instance_method - matcher.matches?(HIMMSpecs).should be_true - matcher.matches?(HIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HIMMSpecs)).to be_truthy + expect(matcher.matches?(HIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the instance method" do matcher = HaveInstanceMethodMatcher.new :another_method - matcher.matches?(HIMMSpecs).should be_false + expect(matcher.matches?(HIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HaveInstanceMethodMatcher.new :instance_method, false - matcher.matches?(HIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HaveInstanceMethodMatcher.new :some_method matcher.matches?(HIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HIMMSpecs to have instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveInstanceMethodMatcher.new :some_method matcher.matches?(HIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HIMMSpecs NOT to have instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_instance_variable_spec.rb b/spec/mspec/spec/matchers/have_instance_variable_spec.rb index 4122c6551b..12e2470f14 100644 --- a/spec/mspec/spec/matchers/have_instance_variable_spec.rb +++ b/spec/mspec/spec/matchers/have_instance_variable_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe HaveInstanceVariableMatcher do +RSpec.describe HaveInstanceVariableMatcher do before :each do @object = Object.new def @object.instance_variables @@ -12,39 +12,39 @@ describe HaveInstanceVariableMatcher do it "matches when object has the instance variable, given as string" do matcher = HaveInstanceVariableMatcher.new('@foo') - matcher.matches?(@object).should be_true + expect(matcher.matches?(@object)).to be_truthy end it "matches when object has the instance variable, given as symbol" do matcher = HaveInstanceVariableMatcher.new(:@foo) - matcher.matches?(@object).should be_true + expect(matcher.matches?(@object)).to be_truthy end it "does not match when object hasn't got the instance variable, given as string" do matcher = HaveInstanceVariableMatcher.new('@bar') - matcher.matches?(@object).should be_false + expect(matcher.matches?(@object)).to be_falsey end it "does not match when object hasn't got the instance variable, given as symbol" do matcher = HaveInstanceVariableMatcher.new(:@bar) - matcher.matches?(@object).should be_false + expect(matcher.matches?(@object)).to be_falsey end it "provides a failure message for #should" do matcher = HaveInstanceVariableMatcher.new(:@bar) matcher.matches?(@object) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected #{@object.inspect} to have instance variable '@bar'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveInstanceVariableMatcher.new(:@bar) matcher.matches?(@object) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected #{@object.inspect} NOT to have instance variable '@bar'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_method_spec.rb b/spec/mspec/spec/matchers/have_method_spec.rb index 41bd485119..4fc0bf5e45 100644 --- a/spec/mspec/spec/matchers/have_method_spec.rb +++ b/spec/mspec/spec/matchers/have_method_spec.rb @@ -12,44 +12,44 @@ class HMMSpecs end end -describe HaveMethodMatcher do +RSpec.describe HaveMethodMatcher do it "inherits from MethodMatcher" do - HaveMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the method" do matcher = HaveMethodMatcher.new :instance_method - matcher.matches?(HMMSpecs).should be_true - matcher.matches?(HMMSpecs.new).should be_true - matcher.matches?(HMMSpecs::Subclass).should be_true - matcher.matches?(HMMSpecs::Subclass.new).should be_true + expect(matcher.matches?(HMMSpecs)).to be_truthy + expect(matcher.matches?(HMMSpecs.new)).to be_truthy + expect(matcher.matches?(HMMSpecs::Subclass)).to be_truthy + expect(matcher.matches?(HMMSpecs::Subclass.new)).to be_truthy end it "does not match when mod does not have the method" do matcher = HaveMethodMatcher.new :another_method - matcher.matches?(HMMSpecs).should be_false + expect(matcher.matches?(HMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HaveMethodMatcher.new :instance_method, false - matcher.matches?(HMMSpecs::Subclass).should be_false + expect(matcher.matches?(HMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HaveMethodMatcher.new :some_method matcher.matches?(HMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HMMSpecs to have method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveMethodMatcher.new :some_method matcher.matches?(HMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HMMSpecs NOT to have method 'some_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_private_instance_method_spec.rb b/spec/mspec/spec/matchers/have_private_instance_method_spec.rb index 827c6b6034..0e65c264d9 100644 --- a/spec/mspec/spec/matchers/have_private_instance_method_spec.rb +++ b/spec/mspec/spec/matchers/have_private_instance_method_spec.rb @@ -16,42 +16,42 @@ class HPIMMSpecs end end -describe HavePrivateInstanceMethodMatcher do +RSpec.describe HavePrivateInstanceMethodMatcher do it "inherits from MethodMatcher" do - HavePrivateInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HavePrivateInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the private instance method" do matcher = HavePrivateInstanceMethodMatcher.new :private_method - matcher.matches?(HPIMMSpecs).should be_true - matcher.matches?(HPIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HPIMMSpecs)).to be_truthy + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the private instance method" do matcher = HavePrivateInstanceMethodMatcher.new :another_method - matcher.matches?(HPIMMSpecs).should be_false + expect(matcher.matches?(HPIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HavePrivateInstanceMethodMatcher.new :private_method, false - matcher.matches?(HPIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HavePrivateInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPIMMSpecs to have private instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure message for #should_not" do matcher = HavePrivateInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPIMMSpecs NOT to have private instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_private_method_spec.rb b/spec/mspec/spec/matchers/have_private_method_spec.rb index e63a9a3c2f..f433288057 100644 --- a/spec/mspec/spec/matchers/have_private_method_spec.rb +++ b/spec/mspec/spec/matchers/have_private_method_spec.rb @@ -9,36 +9,36 @@ class HPMMSpecs private_class_method :private_method end -describe HavePrivateMethodMatcher do +RSpec.describe HavePrivateMethodMatcher do it "inherits from MethodMatcher" do - HavePrivateMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HavePrivateMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the private method" do matcher = HavePrivateMethodMatcher.new :private_method - matcher.matches?(HPMMSpecs).should be_true + expect(matcher.matches?(HPMMSpecs)).to be_truthy end it "does not match when mod does not have the private method" do matcher = HavePrivateMethodMatcher.new :another_method - matcher.matches?(HPMMSpecs).should be_false + expect(matcher.matches?(HPMMSpecs)).to be_falsey end it "provides a failure message for #should" do matcher = HavePrivateMethodMatcher.new :some_method matcher.matches?(HPMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPMMSpecs to have private method 'some_method'", "but it does not" - ] + ]) end it "provides a failure message for #should_not" do matcher = HavePrivateMethodMatcher.new :private_method matcher.matches?(HPMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPMMSpecs NOT to have private method 'private_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb b/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb index 460d0368fb..45b39004a3 100644 --- a/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb +++ b/spec/mspec/spec/matchers/have_protected_instance_method_spec.rb @@ -16,42 +16,42 @@ class HPIMMSpecs end end -describe HaveProtectedInstanceMethodMatcher do +RSpec.describe HaveProtectedInstanceMethodMatcher do it "inherits from MethodMatcher" do - HaveProtectedInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveProtectedInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the protected instance method" do matcher = HaveProtectedInstanceMethodMatcher.new :protected_method - matcher.matches?(HPIMMSpecs).should be_true - matcher.matches?(HPIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HPIMMSpecs)).to be_truthy + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the protected instance method" do matcher = HaveProtectedInstanceMethodMatcher.new :another_method - matcher.matches?(HPIMMSpecs).should be_false + expect(matcher.matches?(HPIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HaveProtectedInstanceMethodMatcher.new :protected_method, false - matcher.matches?(HPIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HaveProtectedInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPIMMSpecs to have protected instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HaveProtectedInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPIMMSpecs NOT to have protected instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_public_instance_method_spec.rb b/spec/mspec/spec/matchers/have_public_instance_method_spec.rb index bff1046f04..771d5b7911 100644 --- a/spec/mspec/spec/matchers/have_public_instance_method_spec.rb +++ b/spec/mspec/spec/matchers/have_public_instance_method_spec.rb @@ -12,42 +12,42 @@ class HPIMMSpecs end end -describe HavePublicInstanceMethodMatcher do +RSpec.describe HavePublicInstanceMethodMatcher do it "inherits from MethodMatcher" do - HavePublicInstanceMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HavePublicInstanceMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when mod has the public instance method" do matcher = HavePublicInstanceMethodMatcher.new :public_method - matcher.matches?(HPIMMSpecs).should be_true - matcher.matches?(HPIMMSpecs::Subclass).should be_true + expect(matcher.matches?(HPIMMSpecs)).to be_truthy + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_truthy end it "does not match when mod does not have the public instance method" do matcher = HavePublicInstanceMethodMatcher.new :another_method - matcher.matches?(HPIMMSpecs).should be_false + expect(matcher.matches?(HPIMMSpecs)).to be_falsey end it "does not match if the method is in a superclass and include_super is false" do matcher = HavePublicInstanceMethodMatcher.new :public_method, false - matcher.matches?(HPIMMSpecs::Subclass).should be_false + expect(matcher.matches?(HPIMMSpecs::Subclass)).to be_falsey end it "provides a failure message for #should" do matcher = HavePublicInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HPIMMSpecs to have public instance method 'some_method'", "but it does not" - ] + ]) end it "provides a failure messoge for #should_not" do matcher = HavePublicInstanceMethodMatcher.new :some_method matcher.matches?(HPIMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HPIMMSpecs NOT to have public instance method 'some_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/have_singleton_method_spec.rb b/spec/mspec/spec/matchers/have_singleton_method_spec.rb index 57c37e01d9..61ef00d49c 100644 --- a/spec/mspec/spec/matchers/have_singleton_method_spec.rb +++ b/spec/mspec/spec/matchers/have_singleton_method_spec.rb @@ -7,14 +7,14 @@ class HSMMSpecs end end -describe HaveSingletonMethodMatcher do +RSpec.describe HaveSingletonMethodMatcher do it "inherits from MethodMatcher" do - HaveSingletonMethodMatcher.new(:m).should be_kind_of(MethodMatcher) + expect(HaveSingletonMethodMatcher.new(:m)).to be_kind_of(MethodMatcher) end it "matches when the class has a singleton method" do matcher = HaveSingletonMethodMatcher.new :singleton_method - matcher.matches?(HSMMSpecs).should be_true + expect(matcher.matches?(HSMMSpecs)).to be_truthy end it "matches when the object has a singleton method" do @@ -22,24 +22,24 @@ describe HaveSingletonMethodMatcher do def obj.singleton_method; end matcher = HaveSingletonMethodMatcher.new :singleton_method - matcher.matches?(obj).should be_true + expect(matcher.matches?(obj)).to be_truthy end it "provides a failure message for #should" do matcher = HaveSingletonMethodMatcher.new :some_method matcher.matches?(HSMMSpecs) - matcher.failure_message.should == [ + expect(matcher.failure_message).to eq([ "Expected HSMMSpecs to have singleton method 'some_method'", "but it does not" - ] + ]) end it "provides a failure message for #should_not" do matcher = HaveSingletonMethodMatcher.new :singleton_method matcher.matches?(HSMMSpecs) - matcher.negative_failure_message.should == [ + expect(matcher.negative_failure_message).to eq([ "Expected HSMMSpecs NOT to have singleton method 'singleton_method'", "but it does" - ] + ]) end end diff --git a/spec/mspec/spec/matchers/include_any_of_spec.rb b/spec/mspec/spec/matchers/include_any_of_spec.rb new file mode 100644 index 0000000000..1473bb6d0b --- /dev/null +++ b/spec/mspec/spec/matchers/include_any_of_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' +require 'mspec/expectations/expectations' +require 'mspec/matchers' + +RSpec.describe IncludeAnyOfMatcher do + it "matches when actual includes expected" do + expect(IncludeAnyOfMatcher.new(2).matches?([1,2,3])).to eq(true) + expect(IncludeAnyOfMatcher.new("b").matches?("abc")).to eq(true) + end + + it "does not match when actual does not include expected" do + expect(IncludeAnyOfMatcher.new(4).matches?([1,2,3])).to eq(false) + expect(IncludeAnyOfMatcher.new("d").matches?("abc")).to eq(false) + end + + it "matches when actual includes all expected" do + expect(IncludeAnyOfMatcher.new(3, 2, 1).matches?([1,2,3])).to eq(true) + expect(IncludeAnyOfMatcher.new("a", "b", "c").matches?("abc")).to eq(true) + end + + it "matches when actual includes any expected" do + expect(IncludeAnyOfMatcher.new(3, 4, 5).matches?([1,2,3])).to eq(true) + expect(IncludeAnyOfMatcher.new("c", "d", "e").matches?("abc")).to eq(true) + end + + it "does not match when actual does not include any expected" do + expect(IncludeAnyOfMatcher.new(4, 5).matches?([1,2,3])).to eq(false) + expect(IncludeAnyOfMatcher.new("de").matches?("abc")).to eq(false) + end + + it "provides a useful failure message" do + matcher = IncludeAnyOfMatcher.new(5, 6) + matcher.matches?([1,2,3]) + expect(matcher.failure_message).to eq(["Expected [1, 2, 3]", "to include any of [5, 6]"]) + end + + it "provides a useful negative failure message" do + matcher = IncludeAnyOfMatcher.new(1, 2, 3) + matcher.matches?([1,2]) + expect(matcher.negative_failure_message).to eq(["Expected [1, 2]", "not to include any of [1, 2, 3]"]) + end +end diff --git a/spec/mspec/spec/matchers/include_spec.rb b/spec/mspec/spec/matchers/include_spec.rb index f045c5e0cb..6bf1bef085 100644 --- a/spec/mspec/spec/matchers/include_spec.rb +++ b/spec/mspec/spec/matchers/include_spec.rb @@ -2,36 +2,36 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe IncludeMatcher do +RSpec.describe IncludeMatcher do it "matches when actual includes expected" do - IncludeMatcher.new(2).matches?([1,2,3]).should == true - IncludeMatcher.new("b").matches?("abc").should == true + expect(IncludeMatcher.new(2).matches?([1,2,3])).to eq(true) + expect(IncludeMatcher.new("b").matches?("abc")).to eq(true) end it "does not match when actual does not include expected" do - IncludeMatcher.new(4).matches?([1,2,3]).should == false - IncludeMatcher.new("d").matches?("abc").should == false + expect(IncludeMatcher.new(4).matches?([1,2,3])).to eq(false) + expect(IncludeMatcher.new("d").matches?("abc")).to eq(false) end it "matches when actual includes all expected" do - IncludeMatcher.new(3, 2, 1).matches?([1,2,3]).should == true - IncludeMatcher.new("a", "b", "c").matches?("abc").should == true + expect(IncludeMatcher.new(3, 2, 1).matches?([1,2,3])).to eq(true) + expect(IncludeMatcher.new("a", "b", "c").matches?("abc")).to eq(true) end it "does not match when actual does not include all expected" do - IncludeMatcher.new(3, 2, 4).matches?([1,2,3]).should == false - IncludeMatcher.new("a", "b", "c", "d").matches?("abc").should == false + expect(IncludeMatcher.new(3, 2, 4).matches?([1,2,3])).to eq(false) + expect(IncludeMatcher.new("a", "b", "c", "d").matches?("abc")).to eq(false) end it "provides a useful failure message" do matcher = IncludeMatcher.new(5, 2) matcher.matches?([1,2,3]) - matcher.failure_message.should == ["Expected [1, 2, 3]", "to include 5"] + expect(matcher.failure_message).to eq(["Expected [1, 2, 3]", "to include 5"]) end it "provides a useful negative failure message" do matcher = IncludeMatcher.new(1, 2, 3) matcher.matches?([1,2,3]) - matcher.negative_failure_message.should == ["Expected [1, 2, 3]", "not to include 3"] + expect(matcher.negative_failure_message).to eq(["Expected [1, 2, 3]", "not to include 3"]) end end diff --git a/spec/mspec/spec/matchers/infinity_spec.rb b/spec/mspec/spec/matchers/infinity_spec.rb index 6eb8ac2940..78c4194526 100644 --- a/spec/mspec/spec/matchers/infinity_spec.rb +++ b/spec/mspec/spec/matchers/infinity_spec.rb @@ -4,31 +4,31 @@ require 'mspec/guards' require 'mspec/helpers' require 'mspec/matchers' -describe InfinityMatcher do +RSpec.describe InfinityMatcher do it "matches when actual is infinite and has the correct sign" do - InfinityMatcher.new(1).matches?(infinity_value).should == true - InfinityMatcher.new(-1).matches?(-infinity_value).should == true + expect(InfinityMatcher.new(1).matches?(infinity_value)).to eq(true) + expect(InfinityMatcher.new(-1).matches?(-infinity_value)).to eq(true) end it "does not match when actual is not infinite" do - InfinityMatcher.new(1).matches?(1.0).should == false - InfinityMatcher.new(-1).matches?(-1.0).should == false + expect(InfinityMatcher.new(1).matches?(1.0)).to eq(false) + expect(InfinityMatcher.new(-1).matches?(-1.0)).to eq(false) end it "does not match when actual is infinite but has the incorrect sign" do - InfinityMatcher.new(1).matches?(-infinity_value).should == false - InfinityMatcher.new(-1).matches?(infinity_value).should == false + expect(InfinityMatcher.new(1).matches?(-infinity_value)).to eq(false) + expect(InfinityMatcher.new(-1).matches?(infinity_value)).to eq(false) end it "provides a useful failure message" do matcher = InfinityMatcher.new(-1) matcher.matches?(0) - matcher.failure_message.should == ["Expected 0", "to be -Infinity"] + expect(matcher.failure_message).to eq(["Expected 0", "to be -Infinity"]) end it "provides a useful negative failure message" do matcher = InfinityMatcher.new(1) matcher.matches?(infinity_value) - matcher.negative_failure_message.should == ["Expected Infinity", "not to be Infinity"] + expect(matcher.negative_failure_message).to eq(["Expected Infinity", "not to be Infinity"]) end end diff --git a/spec/mspec/spec/matchers/match_yaml_spec.rb b/spec/mspec/spec/matchers/match_yaml_spec.rb index 4f16aee0ec..85123bb87d 100644 --- a/spec/mspec/spec/matchers/match_yaml_spec.rb +++ b/spec/mspec/spec/matchers/match_yaml_spec.rb @@ -2,38 +2,38 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe MatchYAMLMatcher do +RSpec.describe MatchYAMLMatcher do before :each do @matcher = MatchYAMLMatcher.new("--- \nfoo: bar\n") end it "compares YAML documents and matches if they're equivalent" do - @matcher.matches?("--- \nfoo: bar\n").should == true + expect(@matcher.matches?("--- \nfoo: bar\n")).to eq(true) end it "compares YAML documents and does not match if they're not equivalent" do - @matcher.matches?("--- \nbar: foo\n").should == false - @matcher.matches?("--- \nfoo: \nbar\n").should == false + expect(@matcher.matches?("--- \nbar: foo\n")).to eq(false) + expect(@matcher.matches?("--- \nfoo: \nbar\n")).to eq(false) end it "also receives objects that respond_to to_yaml" do matcher = MatchYAMLMatcher.new("some string") - matcher.matches?("some string").should == true + expect(matcher.matches?("some string")).to eq(true) matcher = MatchYAMLMatcher.new(['a', 'b']) - matcher.matches?("--- \n- a\n- b\n").should == true + expect(matcher.matches?("--- \n- a\n- b\n")).to eq(true) matcher = MatchYAMLMatcher.new("foo" => "bar") - matcher.matches?("--- \nfoo: bar\n").should == true + expect(matcher.matches?("--- \nfoo: bar\n")).to eq(true) end it "matches documents with trailing whitespace" do - @matcher.matches?("--- \nfoo: bar \n").should == true - @matcher.matches?("--- \nfoo: bar \n").should == true + expect(@matcher.matches?("--- \nfoo: bar \n")).to eq(true) + expect(@matcher.matches?("--- \nfoo: bar \n")).to eq(true) end it "fails with a descriptive error message" do - @matcher.matches?("foo").should == false - @matcher.failure_message.should == ["Expected \"foo\"", " to match \"--- \\nfoo: bar\\n\""] + expect(@matcher.matches?("foo")).to eq(false) + expect(@matcher.failure_message).to eq(["Expected \"foo\"", " to match \"--- \\nfoo: bar\\n\""]) end end diff --git a/spec/mspec/spec/matchers/output_spec.rb b/spec/mspec/spec/matchers/output_spec.rb index 264da3b569..3baad9a4b2 100644 --- a/spec/mspec/spec/matchers/output_spec.rb +++ b/spec/mspec/spec/matchers/output_spec.rb @@ -2,73 +2,83 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe OutputMatcher do +RSpec.describe OutputMatcher do it "matches when executing the proc results in the expected output to $stdout" do proc = Proc.new { puts "bang!" } - OutputMatcher.new("bang!\n", nil).matches?(proc).should == true - OutputMatcher.new("pop", nil).matches?(proc).should == false - OutputMatcher.new(/bang/, nil).matches?(proc).should == true - OutputMatcher.new(/po/, nil).matches?(proc).should == false + expect(OutputMatcher.new("bang!\n", nil).matches?(proc)).to eq(true) + expect(OutputMatcher.new("pop", nil).matches?(proc)).to eq(false) + expect(OutputMatcher.new(/bang/, nil).matches?(proc)).to eq(true) + expect(OutputMatcher.new(/po/, nil).matches?(proc)).to eq(false) end it "matches when executing the proc results in the expected output to $stderr" do proc = Proc.new { $stderr.write "boom!" } - OutputMatcher.new(nil, "boom!").matches?(proc).should == true - OutputMatcher.new(nil, "fizzle").matches?(proc).should == false - OutputMatcher.new(nil, /boom/).matches?(proc).should == true - OutputMatcher.new(nil, /fizzl/).matches?(proc).should == false + expect(OutputMatcher.new(nil, "boom!").matches?(proc)).to eq(true) + expect(OutputMatcher.new(nil, "fizzle").matches?(proc)).to eq(false) + expect(OutputMatcher.new(nil, /boom/).matches?(proc)).to eq(true) + expect(OutputMatcher.new(nil, /fizzl/).matches?(proc)).to eq(false) end it "provides a useful failure message" do proc = Proc.new { print "unexpected"; $stderr.print "unerror" } matcher = OutputMatcher.new("expected", "error") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stdout: \"expected\"\n $stderr: \"error\"\n", " got:\n $stdout: \"unexpected\"\n $stderr: \"unerror\"\n"] + ) matcher = OutputMatcher.new("expected", nil) matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stdout: \"expected\"\n", " got:\n $stdout: \"unexpected\"\n"] + ) matcher = OutputMatcher.new(nil, "error") matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stderr: \"error\"\n", " got:\n $stderr: \"unerror\"\n"] + ) matcher = OutputMatcher.new(/base/, nil) matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stdout: /base/\n", " got:\n $stdout: \"unexpected\"\n"] + ) matcher = OutputMatcher.new(nil, /octave/) matcher.matches?(proc) - matcher.failure_message.should == + expect(matcher.failure_message).to eq( ["Expected:\n $stderr: /octave/\n", " got:\n $stderr: \"unerror\"\n"] + ) end it "provides a useful negative failure message" do proc = Proc.new { puts "expected"; $stderr.puts "error" } matcher = OutputMatcher.new("expected", "error") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stdout: \"expected\"\n $stderr: \"error\"\n"] + ) matcher = OutputMatcher.new("expected", nil) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stdout: \"expected\"\n"] + ) matcher = OutputMatcher.new(nil, "error") matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stderr: \"error\"\n"] + ) matcher = OutputMatcher.new(/expect/, nil) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stdout: \"expected\"\n"] + ) matcher = OutputMatcher.new(nil, /err/) matcher.matches?(proc) - matcher.negative_failure_message.should == + expect(matcher.negative_failure_message).to eq( ["Expected output not to be:\n", " $stderr: \"error\"\n"] + ) end end diff --git a/spec/mspec/spec/matchers/output_to_fd_spec.rb b/spec/mspec/spec/matchers/output_to_fd_spec.rb index e584c4e003..a39cab3206 100644 --- a/spec/mspec/spec/matchers/output_to_fd_spec.rb +++ b/spec/mspec/spec/matchers/output_to_fd_spec.rb @@ -2,43 +2,43 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe OutputToFDMatcher do +RSpec.describe OutputToFDMatcher do # Figure out how in the hell to achieve this it "matches when running the block produces the expected output to the given FD" do - OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" }).should == true + expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" })).to eq(true) end it "does not match if running the block does not produce the expected output to the FD" do - OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") }).should == false + expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") })).to eq(false) end it "propagate the exception if one is thrown while matching" do exc = RuntimeError.new("propagates") - lambda { - OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { + expect { + expect(OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { raise exc - }).should == false - }.should raise_error(exc) + })).to eq(false) + }.to raise_error(exc) end it "defaults to matching against STDOUT" do object = Object.new object.extend MSpecMatchers - object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" }).should == true + expect(object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" })).to eq(true) end it "accepts any IO instance" do io = IO.new STDOUT.fileno - OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" }).should == true + expect(OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" })).to eq(true) end it "allows matching with a Regexp" do s = "Hi there\n" - OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s }).should == true - OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s }).should == false + expect(OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s })).to eq(true) + expect(OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s })).to eq(false) end end diff --git a/spec/mspec/spec/matchers/raise_error_spec.rb b/spec/mspec/spec/matchers/raise_error_spec.rb index 7c93f0f64c..3849c7dd2a 100644 --- a/spec/mspec/spec/matchers/raise_error_spec.rb +++ b/spec/mspec/spec/matchers/raise_error_spec.rb @@ -1,93 +1,153 @@ require 'spec_helper' -require 'mspec/expectations/expectations' -require 'mspec/matchers' class ExpectedException < Exception; end class UnexpectedException < Exception; end -describe RaiseErrorMatcher do +RSpec.describe RaiseErrorMatcher do + before :each do + state = double("run state").as_null_object + allow(MSpec).to receive(:current).and_return(state) + end + it "matches when the proc raises the expected exception" do proc = Proc.new { raise ExpectedException } matcher = RaiseErrorMatcher.new(ExpectedException, nil) - matcher.matches?(proc).should == true + expect(matcher.matches?(proc)).to eq(true) end - it "executes it's optional block if matched" do + it "executes its optional {/} block if matched" do + ensure_mspec_method(-> {}.method(:should)) + run = false - proc = Proc.new { raise ExpectedException } - matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error| + -> { raise ExpectedException }.should PublicMSpecMatchers.raise_error { |error| + expect(error.class).to eq(ExpectedException) run = true - error.class.should == ExpectedException } + expect(run).to eq(true) + end - matcher.matches?(proc).should == true - run.should == true + it "executes its optional do/end block if matched" do + ensure_mspec_method(-> {}.method(:should)) + + run = false + -> { raise ExpectedException }.should PublicMSpecMatchers.raise_error do |error| + expect(error.class).to eq(ExpectedException) + run = true + end + expect(run).to eq(true) end it "matches when the proc raises the expected exception with the expected message" do proc = Proc.new { raise ExpectedException, "message" } matcher = RaiseErrorMatcher.new(ExpectedException, "message") - matcher.matches?(proc).should == true + expect(matcher.matches?(proc)).to eq(true) end it "matches when the proc raises the expected exception with a matching message" do proc = Proc.new { raise ExpectedException, "some message" } matcher = RaiseErrorMatcher.new(ExpectedException, /some/) - matcher.matches?(proc).should == true + expect(matcher.matches?(proc)).to eq(true) end it "does not match when the proc does not raise the expected exception" do exc = UnexpectedException.new matcher = RaiseErrorMatcher.new(ExpectedException, nil) - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + expect { matcher.matches?(Proc.new { raise exc }) - }.should raise_error(UnexpectedException) + }.to raise_error(UnexpectedException) end it "does not match when the proc raises the expected exception with an unexpected message" do exc = ExpectedException.new("unexpected") matcher = RaiseErrorMatcher.new(ExpectedException, "expected") - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + expect { matcher.matches?(Proc.new { raise exc }) - }.should raise_error(ExpectedException) + }.to raise_error(ExpectedException) end it "does not match when the proc does not raise an exception" do proc = Proc.new {} matcher = RaiseErrorMatcher.new(ExpectedException, "expected") - matcher.matches?(proc).should == false + expect(matcher.matches?(proc)).to eq(false) + end + + it "provides a useful failure message when the exception class differs" do + exc = UnexpectedException.new("message") + matcher = RaiseErrorMatcher.new(ExpectedException, "message") + + expect(matcher.matching_exception?(exc)).to eq(false) + begin + matcher.matches?(Proc.new { raise exc }) + rescue UnexpectedException => e + expect(matcher.failure_message).to eq( + ['Expected ExpectedException("message")', 'but got: UnexpectedException("message")'] + ) + expect(ExceptionState.new(nil, nil, e).message).to eq( + "Expected ExpectedException(\"message\")\nbut got: UnexpectedException(\"message\")" + ) + else + raise "no exception" + end + end + + it "provides a useful failure message when the proc raises the expected exception with an unexpected message" do + exc = ExpectedException.new("unexpected") + matcher = RaiseErrorMatcher.new(ExpectedException, "expected") + + expect(matcher.matching_exception?(exc)).to eq(false) + begin + matcher.matches?(Proc.new { raise exc }) + rescue ExpectedException => e + expect(matcher.failure_message).to eq( + ['Expected ExpectedException("expected")', 'but got: ExpectedException("unexpected")'] + ) + expect(ExceptionState.new(nil, nil, e).message).to eq( + "Expected ExpectedException(\"expected\")\nbut got: ExpectedException(\"unexpected\")" + ) + else + raise "no exception" + end end - it "provides a useful failure message" do + it "provides a useful failure message when both the exception class and message differ" do exc = UnexpectedException.new("unexpected") matcher = RaiseErrorMatcher.new(ExpectedException, "expected") - matcher.matching_exception?(exc).should == false - lambda { + expect(matcher.matching_exception?(exc)).to eq(false) + begin matcher.matches?(Proc.new { raise exc }) - }.should raise_error(UnexpectedException) - matcher.failure_message.should == - ["Expected ExpectedException (expected)", "but got UnexpectedException (unexpected)"] + rescue UnexpectedException => e + expect(matcher.failure_message).to eq( + ['Expected ExpectedException("expected")', 'but got: UnexpectedException("unexpected")'] + ) + expect(ExceptionState.new(nil, nil, e).message).to eq( + "Expected ExpectedException(\"expected\")\nbut got: UnexpectedException(\"unexpected\")" + ) + else + raise "no exception" + end end it "provides a useful failure message when no exception is raised" do proc = Proc.new { 120 } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.failure_message.should == - ["Expected ExpectedException (expected)", "but no exception was raised (120 was returned)"] + expect(matcher.failure_message).to eq( + ['Expected ExpectedException("expected")', "but no exception was raised (120 was returned)"] + ) end it "provides a useful failure message when no exception is raised and nil is returned" do proc = Proc.new { nil } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.failure_message.should == - ["Expected ExpectedException (expected)", "but no exception was raised (nil was returned)"] + expect(matcher.failure_message).to eq( + ['Expected ExpectedException("expected")', "but no exception was raised (nil was returned)"] + ) end it "provides a useful failure message when no exception is raised and the result raises in #pretty_inspect" do @@ -98,23 +158,77 @@ describe RaiseErrorMatcher do 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)"] + expect(matcher.failure_message).to eq( + ['Expected ExpectedException("expected")', 'but no exception was raised (#<Object>(#pretty_inspect raised #<ArgumentError: bad>) was returned)'] + ) end it "provides a useful negative failure message" do proc = Proc.new { raise ExpectedException, "expected" } matcher = RaiseErrorMatcher.new(ExpectedException, "expected") matcher.matches?(proc) - matcher.negative_failure_message.should == - ["Expected to not get ExpectedException (expected)", ""] + expect(matcher.negative_failure_message).to eq( + ['Expected to not get ExpectedException("expected")', ""] + ) end it "provides a useful negative failure message for strict subclasses of the matched exception class" do proc = Proc.new { raise UnexpectedException, "unexpected" } matcher = RaiseErrorMatcher.new(Exception, nil) matcher.matches?(proc) - matcher.negative_failure_message.should == - ["Expected to not get Exception", "but got UnexpectedException (unexpected)"] + expect(matcher.negative_failure_message).to eq( + ['Expected to not get Exception', 'but got: UnexpectedException'] + ) + end + + it "matches cause if given" do + cause = RuntimeError.new("foo") + proc = -> do + raise cause + rescue + raise "bar" + end + + matcher = RaiseErrorMatcher.new(RuntimeError, cause: cause) + expect(matcher.matches?(proc)).to eq(true) + end + + it "matches message and cause if given" do + cause = RuntimeError.new("foo") + proc = -> do + raise cause + rescue + raise "bar" + end + + matcher = RaiseErrorMatcher.new(RuntimeError, "bar", cause: cause) + expect(matcher.matches?(proc)).to eq(true) + end + + it "provides useful negative failure message when cause does not match" do + cause = RuntimeError.new("bar") + proc = -> do + raise "foo" + end + + matcher = RaiseErrorMatcher.new(RuntimeError, cause: cause) + + begin + matcher.matches?(proc) + rescue RuntimeError + expect(matcher.failure_message).to eq( + ['Expected RuntimeError(cause: #<RuntimeError: bar>)', 'but got: RuntimeError(cause: nil)'] + ) + end + + matcher = RaiseErrorMatcher.new(RuntimeError, "foo", cause: cause) + + begin + matcher.matches?(proc) + rescue RuntimeError + expect(matcher.failure_message).to eq( + ['Expected RuntimeError("foo", cause: #<RuntimeError: bar>)', 'but got: RuntimeError("foo", cause: nil)'] + ) + end end end diff --git a/spec/mspec/spec/matchers/respond_to_spec.rb b/spec/mspec/spec/matchers/respond_to_spec.rb index 988caf4dff..6f1cd8d148 100644 --- a/spec/mspec/spec/matchers/respond_to_spec.rb +++ b/spec/mspec/spec/matchers/respond_to_spec.rb @@ -2,32 +2,32 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe RespondToMatcher do +RSpec.describe RespondToMatcher do it "matches when actual does respond_to? expected" do - RespondToMatcher.new(:to_s).matches?(Object.new).should == true - RespondToMatcher.new(:inject).matches?([]).should == true - RespondToMatcher.new(:[]).matches?(1).should == true - RespondToMatcher.new(:[]=).matches?("string").should == true + expect(RespondToMatcher.new(:to_s).matches?(Object.new)).to eq(true) + expect(RespondToMatcher.new(:inject).matches?([])).to eq(true) + expect(RespondToMatcher.new(:[]).matches?(1)).to eq(true) + expect(RespondToMatcher.new(:[]=).matches?("string")).to eq(true) end it "does not match when actual does not respond_to? expected" do - RespondToMatcher.new(:to_i).matches?(Object.new).should == false - RespondToMatcher.new(:inject).matches?(1).should == false - RespondToMatcher.new(:non_existent_method).matches?([]).should == false - RespondToMatcher.new(:[]=).matches?(1).should == false + expect(RespondToMatcher.new(:to_i).matches?(Object.new)).to eq(false) + expect(RespondToMatcher.new(:inject).matches?(1)).to eq(false) + expect(RespondToMatcher.new(:non_existent_method).matches?([])).to eq(false) + expect(RespondToMatcher.new(:[]=).matches?(1)).to eq(false) end it "provides a useful failure message" do matcher = RespondToMatcher.new(:non_existent_method) matcher.matches?('string') - matcher.failure_message.should == [ - "Expected \"string\" (String)", "to respond to non_existent_method"] + expect(matcher.failure_message).to eq([ + "Expected \"string\" (String)", "to respond to non_existent_method"]) end it "provides a useful negative failure message" do matcher = RespondToMatcher.new(:to_i) matcher.matches?(4.0) - matcher.negative_failure_message.should == [ - "Expected 4.0 (Float)", "not to respond to to_i"] + expect(matcher.negative_failure_message).to eq([ + "Expected 4.0 (Float)", "not to respond to to_i"]) end end diff --git a/spec/mspec/spec/matchers/signed_zero_spec.rb b/spec/mspec/spec/matchers/signed_zero_spec.rb index 9c5c50c602..6d1c1007bc 100644 --- a/spec/mspec/spec/matchers/signed_zero_spec.rb +++ b/spec/mspec/spec/matchers/signed_zero_spec.rb @@ -2,31 +2,31 @@ require 'spec_helper' require 'mspec/expectations/expectations' require 'mspec/matchers' -describe SignedZeroMatcher do +RSpec.describe SignedZeroMatcher do it "matches when actual is zero and has the correct sign" do - SignedZeroMatcher.new(1).matches?(0.0).should == true - SignedZeroMatcher.new(-1).matches?(-0.0).should == true + expect(SignedZeroMatcher.new(1).matches?(0.0)).to eq(true) + expect(SignedZeroMatcher.new(-1).matches?(-0.0)).to eq(true) end it "does not match when actual is non-zero" do - SignedZeroMatcher.new(1).matches?(1.0).should == false - SignedZeroMatcher.new(-1).matches?(-1.0).should == false + expect(SignedZeroMatcher.new(1).matches?(1.0)).to eq(false) + expect(SignedZeroMatcher.new(-1).matches?(-1.0)).to eq(false) end it "does not match when actual is zero but has the incorrect sign" do - SignedZeroMatcher.new(1).matches?(-0.0).should == false - SignedZeroMatcher.new(-1).matches?(0.0).should == false + expect(SignedZeroMatcher.new(1).matches?(-0.0)).to eq(false) + expect(SignedZeroMatcher.new(-1).matches?(0.0)).to eq(false) end it "provides a useful failure message" do matcher = SignedZeroMatcher.new(-1) matcher.matches?(0.0) - matcher.failure_message.should == ["Expected 0.0", "to be -0.0"] + expect(matcher.failure_message).to eq(["Expected 0.0", "to be -0.0"]) end it "provides a useful negative failure message" do matcher = SignedZeroMatcher.new(-1) matcher.matches?(-0.0) - matcher.negative_failure_message.should == ["Expected -0.0", "not to be -0.0"] + expect(matcher.negative_failure_message).to eq(["Expected -0.0", "not to be -0.0"]) end end diff --git a/spec/mspec/spec/mocks/mock_spec.rb b/spec/mspec/spec/mocks/mock_spec.rb index c814ec7bfe..7426e0ff88 100644 --- a/spec/mspec/spec/mocks/mock_spec.rb +++ b/spec/mspec/spec/mocks/mock_spec.rb @@ -7,78 +7,78 @@ require 'mspec/runner/mspec' require 'mspec/mocks/mock' require 'mspec/mocks/proxy' -describe Mock, ".mocks" do +RSpec.describe Mock, ".mocks" do it "returns a Hash" do - Mock.mocks.should be_kind_of(Hash) + expect(Mock.mocks).to be_kind_of(Hash) end end -describe Mock, ".stubs" do +RSpec.describe Mock, ".stubs" do it "returns a Hash" do - Mock.stubs.should be_kind_of(Hash) + expect(Mock.stubs).to be_kind_of(Hash) end end -describe Mock, ".replaced_name" do +RSpec.describe Mock, ".replaced_name" do it "returns the name for a method that is being replaced by a mock method" do m = double('a fake id') - Mock.replaced_name(m, :method_call).should == :"__mspec_#{m.object_id}_method_call__" + expect(Mock.replaced_name(Mock.replaced_key(m, :method_call))).to eq(:"__mspec_method_call__") end end -describe Mock, ".replaced_key" do +RSpec.describe Mock, ".replaced_key" do it "returns a key used internally by Mock" do m = double('a fake id') - Mock.replaced_key(m, :method_call).should == [:"__mspec_#{m.object_id}_method_call__", :method_call] + expect(Mock.replaced_key(m, :method_call)).to eq([m.object_id, :method_call]) end end -describe Mock, ".replaced?" do +RSpec.describe Mock, ".replaced?" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end it "returns true if a method has been stubbed on an object" do Mock.install_method @mock, :method_call - Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_true + expect(Mock.replaced?(Mock.replaced_key(@mock, :method_call))).to be_truthy end it "returns true if a method has been mocked on an object" do Mock.install_method @mock, :method_call, :stub - Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_true + expect(Mock.replaced?(Mock.replaced_key(@mock, :method_call))).to be_truthy end it "returns false if a method has not been stubbed or mocked" do - Mock.replaced?(Mock.replaced_name(@mock, :method_call)).should be_false + expect(Mock.replaced?(Mock.replaced_key(@mock, :method_call))).to be_falsey end end -describe Mock, ".name_or_inspect" do +RSpec.describe Mock, ".name_or_inspect" do before :each do @mock = double("I have a #name") end it "returns the value of @name if set" do @mock.instance_variable_set(:@name, "Myself") - Mock.name_or_inspect(@mock).should == "Myself" + expect(Mock.name_or_inspect(@mock)).to eq("Myself") end end -describe Mock, ".install_method for mocks" do +RSpec.describe Mock, ".install_method for mocks" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end after :each do - Mock.cleanup + Mock.reset end it "returns a MockProxy instance" do - Mock.install_method(@mock, :method_call).should be_an_instance_of(MockProxy) + expect(Mock.install_method(@mock, :method_call)).to be_an_instance_of(MockProxy) end it "does not override a previously mocked method with the same name" do @@ -86,7 +86,7 @@ describe Mock, ".install_method for mocks" do Mock.install_method(@mock, :method_call).with(:c).and_return(2) @mock.method_call(:a, :b) @mock.method_call(:c) - lambda { @mock.method_call(:d) }.should raise_error(SpecExpectationNotMetError) + expect { @mock.method_call(:d) }.to raise_error(SpecExpectationNotMetError) end # This illustrates RSpec's behavior. This spec fails in mock call count verification @@ -105,44 +105,44 @@ describe Mock, ".install_method for mocks" do # it "does not override a previously mocked method having the same arguments" do Mock.install_method(@mock, :method_call).with(:a).and_return(true) - @mock.method_call(:a).should == true + expect(@mock.method_call(:a)).to eq(true) Mock.install_method(@mock, :method_call).with(:a).and_return(false) - @mock.method_call(:a).should == true - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect(@mock.method_call(:a)).to eq(true) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "properly sends #respond_to? calls to the aliased respond_to? method when not matching mock expectations" do Mock.install_method(@mock, :respond_to?).with(:to_str).and_return('mock to_str') Mock.install_method(@mock, :respond_to?).with(:to_int).and_return('mock to_int') - @mock.respond_to?(:to_str).should == 'mock to_str' - @mock.respond_to?(:to_int).should == 'mock to_int' - @mock.respond_to?(:to_s).should == true - @mock.respond_to?(:not_really_a_real_method_seriously).should == false + expect(@mock.respond_to?(:to_str)).to eq('mock to_str') + expect(@mock.respond_to?(:to_int)).to eq('mock to_int') + expect(@mock.respond_to?(:to_s)).to eq(true) + expect(@mock.respond_to?(:not_really_a_real_method_seriously)).to eq(false) end it "adds to the expectation tally" do state = double("run state").as_null_object - state.stub(:state).and_return(double("spec state")) - MSpec.should_receive(:current).and_return(state) - MSpec.should_receive(:actions).with(:expectation, state.state) + allow(state).to receive(:state).and_return(double("spec state")) + expect(MSpec).to receive(:current).and_return(state) + expect(MSpec).to receive(:actions).with(:expectation, state.state) Mock.install_method(@mock, :method_call).and_return(1) - @mock.method_call.should == 1 + expect(@mock.method_call).to eq(1) end it "registers that an expectation has been encountered" do state = double("run state").as_null_object - state.stub(:state).and_return(double("spec state")) - MSpec.should_receive(:expectation) + allow(state).to receive(:state).and_return(double("spec state")) + expect(MSpec).to receive(:expectation) Mock.install_method(@mock, :method_call).and_return(1) - @mock.method_call.should == 1 + expect(@mock.method_call).to eq(1) end end -describe Mock, ".install_method for stubs" do +RSpec.describe Mock, ".install_method for stubs" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end after :each do @@ -150,7 +150,7 @@ describe Mock, ".install_method for stubs" do end it "returns a MockProxy instance" do - Mock.install_method(@mock, :method_call, :stub).should be_an_instance_of(MockProxy) + expect(Mock.install_method(@mock, :method_call, :stub)).to be_an_instance_of(MockProxy) end # This illustrates RSpec's behavior. This spec passes on RSpec and we mimic it @@ -166,26 +166,26 @@ describe Mock, ".install_method for stubs" do # end it "inserts new stubs before old stubs" do Mock.install_method(@mock, :method_call, :stub).with(:a).and_return(true) - @mock.method_call(:a).should == true + expect(@mock.method_call(:a)).to eq(true) Mock.install_method(@mock, :method_call, :stub).with(:a).and_return(false) - @mock.method_call(:a).should == false + expect(@mock.method_call(:a)).to eq(false) Mock.verify_count end it "does not add to the expectation tally" do state = double("run state").as_null_object - state.stub(:state).and_return(double("spec state")) - MSpec.should_not_receive(:actions) + allow(state).to receive(:state).and_return(double("spec state")) + expect(MSpec).not_to receive(:actions) Mock.install_method(@mock, :method_call, :stub).and_return(1) - @mock.method_call.should == 1 + expect(@mock.method_call).to eq(1) end end -describe Mock, ".install_method" do +RSpec.describe Mock, ".install_method" do before :each do @mock = double('install_method') - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) end after :each do @@ -193,24 +193,24 @@ describe Mock, ".install_method" do end it "does not alias a mocked or stubbed method when installing a new mock or stub" do - @mock.should_not respond_to(:method_call) + expect(@mock).not_to respond_to(:method_call) Mock.install_method @mock, :method_call - @mock.should respond_to(:method_call) - @mock.should_not respond_to(Mock.replaced_name(@mock, :method_call)) + expect(@mock).to respond_to(:method_call) + expect(@mock).not_to respond_to(Mock.replaced_name(Mock.replaced_key(@mock, :method_call))) Mock.install_method @mock, :method_call, :stub - @mock.should respond_to(:method_call) - @mock.should_not respond_to(Mock.replaced_name(@mock, :method_call)) + expect(@mock).to respond_to(:method_call) + expect(@mock).not_to respond_to(Mock.replaced_name(Mock.replaced_key(@mock, :method_call))) end end class MockAndRaiseError < Exception; end -describe Mock, ".verify_call" do +RSpec.describe Mock, ".verify_call" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_call') @proxy = Mock.install_method @mock, :method_call @@ -228,23 +228,23 @@ describe Mock, ".verify_call" do it "raises an SpecExpectationNotMetError when the mock method does not receive the expected arguments" do @proxy.with(4, 2) - lambda { + expect { Mock.verify_call @mock, :method_call, 42 - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "raises an SpecExpectationNotMetError when the mock method is called with arguments but expects none" do - lambda { + expect { @proxy.with(:no_args) Mock.verify_call @mock, :method_call, "hello" - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "raises an SpecExpectationNotMetError when the mock method is called with no arguments but expects some" do @proxy.with("hello", "beautiful", "world") - lambda { + expect { Mock.verify_call @mock, :method_call - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when the mock method is called with arguments and is expecting :any_args" do @@ -257,14 +257,14 @@ describe Mock, ".verify_call" do Mock.verify_call @mock, :method_call do ScratchPad.record true end - ScratchPad.recorded.should == true + expect(ScratchPad.recorded).to eq(true) end it "does not yield a passed block when it is not expected to" do Mock.verify_call @mock, :method_call do ScratchPad.record true end - ScratchPad.recorded.should == nil + expect(ScratchPad.recorded).to eq(nil) end it "can yield subsequently" do @@ -274,28 +274,28 @@ describe Mock, ".verify_call" do Mock.verify_call @mock, :method_call do |arg| ScratchPad << arg end - ScratchPad.recorded.should == [1, 2, 3] + expect(ScratchPad.recorded).to eq([1, 2, 3]) end it "can yield and return an expected value" do @proxy.and_yield(1).and_return(3) - Mock.verify_call(@mock, :method_call) { |arg| ScratchPad.record arg }.should == 3 - ScratchPad.recorded.should == 1 + expect(Mock.verify_call(@mock, :method_call) { |arg| ScratchPad.record arg }).to eq(3) + expect(ScratchPad.recorded).to eq(1) end it "raises an exception when it is expected to yield but no block is given" do @proxy.and_yield(1, 2, 3) - lambda { + expect { Mock.verify_call(@mock, :method_call) - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "raises an exception when it is expected to yield more arguments than the block can take" do @proxy.and_yield(1, 2, 3) - lambda { + expect { Mock.verify_call(@mock, :method_call) {|a, b|} - }.should raise_error(SpecExpectationNotMetError) + }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when it is expected to yield to a block that can take any number of arguments" do @@ -307,16 +307,68 @@ describe Mock, ".verify_call" do it "raises an exception when expected to" do @proxy.and_raise(MockAndRaiseError) - lambda { + expect { Mock.verify_call @mock, :method_call - }.should raise_error(MockAndRaiseError) + }.to raise_error(MockAndRaiseError) + end +end + +RSpec.describe Mock, ".verify_call mixing mocks and stubs" do + before :each do + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) + + @mock = double('verify_call') + end + + after :each do + ScratchPad.clear + Mock.cleanup + end + + it "checks the mock arguments when a mock is defined after a stub" do + Mock.install_method @mock, :method_call, :stub + Mock.install_method(@mock, :method_call, :mock).with("arg") + + expect { + @mock.method_call + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/) + + expect { + @mock.method_call("a", "b") + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/) + + expect { + @mock.method_call("foo") + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/) + + @mock.method_call("arg") + end + + it "checks the mock arguments when a stub is defined after a mock" do + Mock.install_method(@mock, :method_call, :mock).with("arg") + Mock.install_method @mock, :method_call, :stub + + expect { + @mock.method_call + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \(\)/) + + expect { + @mock.method_call("a", "b") + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("a", "b"\)/) + + expect { + @mock.method_call("foo") + }.to raise_error(SpecExpectationNotMetError, /called with unexpected arguments \("foo"\)/) + + @mock.method_call("arg") end end -describe Mock, ".verify_count" do +RSpec.describe Mock, ".verify_count" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_count') @proxy = Mock.install_method @mock, :method_call @@ -336,7 +388,7 @@ describe Mock, ".verify_count" do it "raises an SpecExpectationNotMetError when the mock receives less than at least the expected number of calls" do @proxy.at_least(2) @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when the mock receives at most the expected number of calls" do @@ -351,7 +403,7 @@ describe Mock, ".verify_count" do @mock.method_call @mock.method_call @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "does not raise an exception when the mock receives exactly the expected number of calls" do @@ -364,7 +416,7 @@ describe Mock, ".verify_count" do it "raises an SpecExpectationNotMetError when the mock receives less than exactly the expected number of calls" do @proxy.exactly(2) @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end it "raises an SpecExpectationNotMetError when the mock receives more than exactly the expected number of calls" do @@ -372,14 +424,14 @@ describe Mock, ".verify_count" do @mock.method_call @mock.method_call @mock.method_call - lambda { Mock.verify_count }.should raise_error(SpecExpectationNotMetError) + expect { Mock.verify_count }.to raise_error(SpecExpectationNotMetError) end end -describe Mock, ".verify_count mixing mocks and stubs" do +RSpec.describe Mock, ".verify_count mixing mocks and stubs" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('verify_count') end @@ -396,6 +448,11 @@ describe Mock, ".verify_count mixing mocks and stubs" do it "verifies the calls to the mocked method when a mock is defined after a stub" do Mock.install_method @mock, :method_call, :stub Mock.install_method @mock, :method_call, :mock + + expect { + Mock.verify_count + }.to raise_error(SpecExpectationNotMetError, /received it 0 times/) + @mock.method_call Mock.verify_count end @@ -403,19 +460,23 @@ describe Mock, ".verify_count mixing mocks and stubs" do it "verifies the calls to the mocked method when a mock is defined before a stub" do Mock.install_method @mock, :method_call, :mock Mock.install_method @mock, :method_call, :stub + + expect { + Mock.verify_count + }.to raise_error(SpecExpectationNotMetError, /received it 0 times/) + @mock.method_call Mock.verify_count end end -describe Mock, ".cleanup" do +RSpec.describe Mock, ".cleanup" do before :each do - MSpec.stub(:actions) - MSpec.stub(:current).and_return(double("spec state").as_null_object) + allow(MSpec).to receive(:actions) + allow(MSpec).to receive(:current).and_return(double("spec state").as_null_object) @mock = double('cleanup') @proxy = Mock.install_method @mock, :method_call - @stub = Mock.install_method @mock, :method_call, :stub end after :each do @@ -423,45 +484,46 @@ describe Mock, ".cleanup" do end it "removes the mock method call if it did not override an existing method" do - @mock.should respond_to(:method_call) + expect(@mock).to respond_to(:method_call) Mock.cleanup - @mock.should_not respond_to(:method_call) + expect(@mock).not_to respond_to(:method_call) end it "removes the replaced method if the mock method overrides an existing method" do def @mock.already_here() :hey end - @mock.should respond_to(:already_here) - replaced_name = Mock.replaced_name(@mock, :already_here) + expect(@mock).to respond_to(:already_here) + replaced_name = Mock.replaced_name(Mock.replaced_key(@mock, :already_here)) Mock.install_method @mock, :already_here - @mock.should respond_to(replaced_name) + expect(@mock).to respond_to(replaced_name) Mock.cleanup - @mock.should_not respond_to(replaced_name) - @mock.should respond_to(:already_here) - @mock.already_here.should == :hey + expect(@mock).not_to respond_to(replaced_name) + expect(@mock).to respond_to(:already_here) + expect(@mock.already_here).to eq(:hey) end it "removes all mock expectations" do - Mock.mocks.should == { Mock.replaced_key(@mock, :method_call) => [@proxy] } + expect(Mock.mocks).to eq({ Mock.replaced_key(@mock, :method_call) => [@proxy] }) Mock.cleanup - Mock.mocks.should == {} + expect(Mock.mocks).to eq({}) end it "removes all stubs" do - Mock.stubs.should == { Mock.replaced_key(@mock, :method_call) => [@stub] } + Mock.cleanup # remove @proxy + @stub = Mock.install_method @mock, :method_call, :stub + expect(Mock.stubs).to eq({ Mock.replaced_key(@mock, :method_call) => [@stub] }) Mock.cleanup - Mock.stubs.should == {} + expect(Mock.stubs).to eq({}) end it "removes the replaced name for mocks" do replaced_key = Mock.replaced_key(@mock, :method_call) - Mock.should_receive(:clear_replaced).with(replaced_key) + expect(Mock).to receive(:clear_replaced).with(replaced_key) - replaced_name = Mock.replaced_name(@mock, :method_call) - Mock.replaced?(replaced_name).should be_true + expect(Mock.replaced?(replaced_key)).to be_truthy Mock.cleanup - Mock.replaced?(replaced_name).should be_false + expect(Mock.replaced?(replaced_key)).to be_falsey end end diff --git a/spec/mspec/spec/mocks/proxy_spec.rb b/spec/mspec/spec/mocks/proxy_spec.rb index d9e754b972..b994634694 100644 --- a/spec/mspec/spec/mocks/proxy_spec.rb +++ b/spec/mspec/spec/mocks/proxy_spec.rb @@ -1,276 +1,276 @@ require 'spec_helper' require 'mspec/mocks/proxy' -describe MockObject, ".new" do +RSpec.describe MockObject, ".new" do it "creates a new mock object" do m = MockObject.new('not a null object') - lambda { m.not_a_method }.should raise_error(NoMethodError) + expect { m.not_a_method }.to raise_error(NoMethodError) end it "creates a new mock object that follows the NullObject pattern" do m = MockObject.new('null object', :null_object => true) - m.not_really_a_method.should equal(m) + expect(m.not_really_a_method).to equal(m) end end -describe MockProxy, ".new" do +RSpec.describe MockProxy, ".new" do it "creates a mock proxy by default" do - MockProxy.new.mock?.should be_true + expect(MockProxy.new.mock?).to be_truthy end it "creates a stub proxy by request" do - MockProxy.new(:stub).stub?.should be_true + expect(MockProxy.new(:stub).stub?).to be_truthy end it "sets the call expectation to 1 call for a mock" do - MockProxy.new.count.should == [:exactly, 1] + expect(MockProxy.new.count).to eq([:exactly, 1]) end it "sets the call expectation to any number of times for a stub" do - MockProxy.new(:stub).count.should == [:any_number_of_times, 0] + expect(MockProxy.new(:stub).count).to eq([:any_number_of_times, 0]) end end -describe MockProxy, "#count" do +RSpec.describe MockProxy, "#count" do before :each do @proxy = MockProxy.new end it "returns the expected number of calls the mock should receive" do - @proxy.count.should == [:exactly, 1] - @proxy.at_least(3).count.should == [:at_least, 3] + expect(@proxy.count).to eq([:exactly, 1]) + expect(@proxy.at_least(3).count).to eq([:at_least, 3]) end end -describe MockProxy, "#arguments" do +RSpec.describe MockProxy, "#arguments" do before :each do @proxy = MockProxy.new end it "returns the expected arguments" do - @proxy.arguments.should == :any_args + expect(@proxy.arguments).to eq(:any_args) end end -describe MockProxy, "#with" do +RSpec.describe MockProxy, "#with" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.with(:a).should be_equal(@proxy) + expect(@proxy.with(:a)).to be_equal(@proxy) end it "raises an ArgumentError if no arguments are given" do - lambda { @proxy.with }.should raise_error(ArgumentError) + expect { @proxy.with }.to raise_error(ArgumentError) end it "accepts any number of arguments" do - @proxy.with(1, 2, 3).should be_an_instance_of(MockProxy) - @proxy.arguments.should == [1,2,3] + expect(@proxy.with(1, 2, 3)).to be_an_instance_of(MockProxy) + expect(@proxy.arguments).to eq([1,2,3]) end end -describe MockProxy, "#once" do +RSpec.describe MockProxy, "#once" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.once.should be_equal(@proxy) + expect(@proxy.once).to be_equal(@proxy) end it "sets the expected calls to 1" do @proxy.once - @proxy.count.should == [:exactly, 1] + expect(@proxy.count).to eq([:exactly, 1]) end it "accepts no arguments" do - lambda { @proxy.once(:a) }.should raise_error + expect { @proxy.once(:a) }.to raise_error end end -describe MockProxy, "#twice" do +RSpec.describe MockProxy, "#twice" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.twice.should be_equal(@proxy) + expect(@proxy.twice).to be_equal(@proxy) end it "sets the expected calls to 2" do @proxy.twice - @proxy.count.should == [:exactly, 2] + expect(@proxy.count).to eq([:exactly, 2]) end it "accepts no arguments" do - lambda { @proxy.twice(:b) }.should raise_error + expect { @proxy.twice(:b) }.to raise_error end end -describe MockProxy, "#exactly" do +RSpec.describe MockProxy, "#exactly" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.exactly(2).should be_equal(@proxy) + expect(@proxy.exactly(2)).to be_equal(@proxy) end it "sets the expected calls to exactly n" do @proxy.exactly(5) - @proxy.count.should == [:exactly, 5] + expect(@proxy.count).to eq([:exactly, 5]) end it "does not accept an argument that Integer() cannot convert" do - lambda { @proxy.exactly('x') }.should raise_error + expect { @proxy.exactly('x') }.to raise_error end end -describe MockProxy, "#at_least" do +RSpec.describe MockProxy, "#at_least" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.at_least(3).should be_equal(@proxy) + expect(@proxy.at_least(3)).to be_equal(@proxy) end it "sets the expected calls to at least n" do @proxy.at_least(3) - @proxy.count.should == [:at_least, 3] + expect(@proxy.count).to eq([:at_least, 3]) end it "accepts :once :twice" do @proxy.at_least(:once) - @proxy.count.should == [:at_least, 1] + expect(@proxy.count).to eq([:at_least, 1]) @proxy.at_least(:twice) - @proxy.count.should == [:at_least, 2] + expect(@proxy.count).to eq([:at_least, 2]) end it "does not accept an argument that Integer() cannot convert" do - lambda { @proxy.at_least('x') }.should raise_error + expect { @proxy.at_least('x') }.to raise_error end end -describe MockProxy, "#at_most" do +RSpec.describe MockProxy, "#at_most" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.at_most(2).should be_equal(@proxy) + expect(@proxy.at_most(2)).to be_equal(@proxy) end it "sets the expected calls to at most n" do @proxy.at_most(2) - @proxy.count.should == [:at_most, 2] + expect(@proxy.count).to eq([:at_most, 2]) end it "accepts :once, :twice" do @proxy.at_most(:once) - @proxy.count.should == [:at_most, 1] + expect(@proxy.count).to eq([:at_most, 1]) @proxy.at_most(:twice) - @proxy.count.should == [:at_most, 2] + expect(@proxy.count).to eq([:at_most, 2]) end it "does not accept an argument that Integer() cannot convert" do - lambda { @proxy.at_most('x') }.should raise_error + expect { @proxy.at_most('x') }.to raise_error end end -describe MockProxy, "#any_number_of_times" do +RSpec.describe MockProxy, "#any_number_of_times" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.any_number_of_times.should be_equal(@proxy) + expect(@proxy.any_number_of_times).to be_equal(@proxy) end it "sets the expected calls to any number of times" do @proxy.any_number_of_times - @proxy.count.should == [:any_number_of_times, 0] + expect(@proxy.count).to eq([:any_number_of_times, 0]) end it "does not accept an argument" do - lambda { @proxy.any_number_of_times(2) }.should raise_error + expect { @proxy.any_number_of_times(2) }.to raise_error end end -describe MockProxy, "#and_return" do +RSpec.describe MockProxy, "#and_return" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.and_return(false).should equal(@proxy) + expect(@proxy.and_return(false)).to equal(@proxy) end it "sets the expected return value" do @proxy.and_return(false) - @proxy.returning.should == false + expect(@proxy.returning).to eq(false) end it "accepts any number of return values" do @proxy.and_return(1, 2, 3) - @proxy.returning.should == 1 - @proxy.returning.should == 2 - @proxy.returning.should == 3 + expect(@proxy.returning).to eq(1) + expect(@proxy.returning).to eq(2) + expect(@proxy.returning).to eq(3) end it "implicitly sets the expected number of calls" do @proxy.and_return(1, 2, 3) - @proxy.count.should == [:exactly, 3] + expect(@proxy.count).to eq([:exactly, 3]) end it "only sets the expected number of calls if it is higher than what is already set" do @proxy.at_least(5).times.and_return(1, 2, 3) - @proxy.count.should == [:at_least, 5] + expect(@proxy.count).to eq([:at_least, 5]) @proxy.at_least(2).times.and_return(1, 2, 3) - @proxy.count.should == [:at_least, 3] + expect(@proxy.count).to eq([:at_least, 3]) end end -describe MockProxy, "#returning" do +RSpec.describe MockProxy, "#returning" do before :each do @proxy = MockProxy.new end it "returns nil by default" do - @proxy.returning.should be_nil + expect(@proxy.returning).to be_nil end it "returns the value set by #and_return" do @proxy.and_return(2) - @proxy.returning.should == 2 - @proxy.returning.should == 2 + expect(@proxy.returning).to eq(2) + expect(@proxy.returning).to eq(2) end it "returns a sequence of values set by #and_return" do @proxy.and_return(1,2,3,4) - @proxy.returning.should == 1 - @proxy.returning.should == 2 - @proxy.returning.should == 3 - @proxy.returning.should == 4 - @proxy.returning.should == 4 - @proxy.returning.should == 4 + expect(@proxy.returning).to eq(1) + expect(@proxy.returning).to eq(2) + expect(@proxy.returning).to eq(3) + expect(@proxy.returning).to eq(4) + expect(@proxy.returning).to eq(4) + expect(@proxy.returning).to eq(4) end end -describe MockProxy, "#calls" do +RSpec.describe MockProxy, "#calls" do before :each do @proxy = MockProxy.new end it "returns the number of times the proxy is called" do - @proxy.calls.should == 0 + expect(@proxy.calls).to eq(0) end end -describe MockProxy, "#called" do +RSpec.describe MockProxy, "#called" do before :each do @proxy = MockProxy.new end @@ -278,128 +278,128 @@ describe MockProxy, "#called" do it "increments the number of times the proxy is called" do @proxy.called @proxy.called - @proxy.calls.should == 2 + expect(@proxy.calls).to eq(2) end end -describe MockProxy, "#times" do +RSpec.describe MockProxy, "#times" do before :each do @proxy = MockProxy.new end it "is a no-op" do - @proxy.times.should == @proxy + expect(@proxy.times).to eq(@proxy) end end -describe MockProxy, "#stub?" do +RSpec.describe MockProxy, "#stub?" do it "returns true if the proxy is created as a stub" do - MockProxy.new(:stub).stub?.should be_true + expect(MockProxy.new(:stub).stub?).to be_truthy end it "returns false if the proxy is created as a mock" do - MockProxy.new(:mock).stub?.should be_false + expect(MockProxy.new(:mock).stub?).to be_falsey end end -describe MockProxy, "#mock?" do +RSpec.describe MockProxy, "#mock?" do it "returns true if the proxy is created as a mock" do - MockProxy.new(:mock).mock?.should be_true + expect(MockProxy.new(:mock).mock?).to be_truthy end it "returns false if the proxy is created as a stub" do - MockProxy.new(:stub).mock?.should be_false + expect(MockProxy.new(:stub).mock?).to be_falsey end end -describe MockProxy, "#and_yield" do +RSpec.describe MockProxy, "#and_yield" do before :each do @proxy = MockProxy.new end it "returns self" do - @proxy.and_yield(false).should equal(@proxy) + expect(@proxy.and_yield(false)).to equal(@proxy) end it "sets the expected values to yield" do - @proxy.and_yield(1).yielding.should == [[1]] + expect(@proxy.and_yield(1).yielding).to eq([[1]]) end it "accepts multiple values to yield" do - @proxy.and_yield(1, 2, 3).yielding.should == [[1, 2, 3]] + expect(@proxy.and_yield(1, 2, 3).yielding).to eq([[1, 2, 3]]) end end -describe MockProxy, "#raising" do +RSpec.describe MockProxy, "#raising" do before :each do @proxy = MockProxy.new end it "returns nil by default" do - @proxy.raising.should be_nil + expect(@proxy.raising).to be_nil end it "returns the exception object passed to #and_raise" do exc = double("exception") @proxy.and_raise(exc) - @proxy.raising.should equal(exc) + expect(@proxy.raising).to equal(exc) end it "returns an instance of RuntimeError when a String is passed to #and_raise" do @proxy.and_raise("an error") exc = @proxy.raising - exc.should be_an_instance_of(RuntimeError) - exc.message.should == "an error" + expect(exc).to be_an_instance_of(RuntimeError) + expect(exc.message).to eq("an error") end end -describe MockProxy, "#yielding" do +RSpec.describe MockProxy, "#yielding" do before :each do @proxy = MockProxy.new end it "returns an empty array by default" do - @proxy.yielding.should == [] + expect(@proxy.yielding).to eq([]) end it "returns an array of arrays of values the proxy should yield" do @proxy.and_yield(3) - @proxy.yielding.should == [[3]] + expect(@proxy.yielding).to eq([[3]]) end it "returns an accumulation of arrays of values the proxy should yield" do @proxy.and_yield(1).and_yield(2, 3) - @proxy.yielding.should == [[1], [2, 3]] + expect(@proxy.yielding).to eq([[1], [2, 3]]) end end -describe MockProxy, "#yielding?" do +RSpec.describe MockProxy, "#yielding?" do before :each do @proxy = MockProxy.new end it "returns false if the proxy is not yielding" do - @proxy.yielding?.should be_false + expect(@proxy.yielding?).to be_falsey end it "returns true if the proxy is yielding" do @proxy.and_yield(1) - @proxy.yielding?.should be_true + expect(@proxy.yielding?).to be_truthy end end -describe MockIntObject, "#to_int" do +RSpec.describe MockIntObject, "#to_int" do before :each do @int = MockIntObject.new(10) end it "returns the number if to_int is called" do - @int.to_int.should == 10 - @int.count.should == [:at_least, 1] + expect(@int.to_int).to eq(10) + expect(@int.count).to eq([:at_least, 1]) end it "tries to convert the target to int if to_int is called" do - MockIntObject.new(@int).to_int.should == 10 - @int.count.should == [:at_least, 1] + expect(MockIntObject.new(@int).to_int).to eq(10) + expect(@int.count).to eq([:at_least, 1]) end end diff --git a/spec/mspec/spec/runner/actions/filter_spec.rb b/spec/mspec/spec/runner/actions/filter_spec.rb index d185781757..7582b31c1d 100644 --- a/spec/mspec/spec/runner/actions/filter_spec.rb +++ b/spec/mspec/spec/runner/actions/filter_spec.rb @@ -3,82 +3,82 @@ require 'mspec/runner/actions/filter' require 'mspec/runner/mspec' require 'mspec/runner/tag' -describe ActionFilter do +RSpec.describe ActionFilter do it "creates a filter when not passed a description" do - MatchFilter.should_not_receive(:new) + expect(MatchFilter).not_to receive(:new) ActionFilter.new(nil, nil) end it "creates a filter from a single description" do - MatchFilter.should_receive(:new).with(nil, "match me") + expect(MatchFilter).to receive(:new).with(nil, "match me") ActionFilter.new(nil, "match me") end it "creates a filter from an array of descriptions" do - MatchFilter.should_receive(:new).with(nil, "match me", "again") + expect(MatchFilter).to receive(:new).with(nil, "match me", "again") ActionFilter.new(nil, ["match me", "again"]) end end -describe ActionFilter, "#===" do +RSpec.describe ActionFilter, "#===" do before :each do - MSpec.stub(:read_tags).and_return(["match"]) + allow(MSpec).to receive(:read_tags).and_return(["match"]) @action = ActionFilter.new(nil, ["catch", "if you"]) end it "returns false if there are no filters" do action = ActionFilter.new - action.===("anything").should == false + expect(action.===("anything")).to eq(false) end it "returns true if the argument matches any of the descriptions" do - @action.===("catch").should == true - @action.===("if you can").should == true + expect(@action.===("catch")).to eq(true) + expect(@action.===("if you can")).to eq(true) end it "returns false if the argument does not match any of the descriptions" do - @action.===("patch me").should == false - @action.===("if I can").should == false + expect(@action.===("patch me")).to eq(false) + expect(@action.===("if I can")).to eq(false) end end -describe ActionFilter, "#load" do +RSpec.describe ActionFilter, "#load" do before :each do @tag = SpecTag.new "tag(comment):description" end it "creates a filter from a single tag" do - MSpec.should_receive(:read_tags).with(["tag"]).and_return([@tag]) - MatchFilter.should_receive(:new).with(nil, "description") + expect(MSpec).to receive(:read_tags).with(["tag"]).and_return([@tag]) + expect(MatchFilter).to receive(:new).with(nil, "description") ActionFilter.new("tag", nil).load end it "creates a filter from an array of tags" do - MSpec.should_receive(:read_tags).with(["tag", "key"]).and_return([@tag]) - MatchFilter.should_receive(:new).with(nil, "description") + expect(MSpec).to receive(:read_tags).with(["tag", "key"]).and_return([@tag]) + expect(MatchFilter).to receive(:new).with(nil, "description") ActionFilter.new(["tag", "key"], nil).load end it "creates a filter from both tags and descriptions" do - MSpec.should_receive(:read_tags).and_return([@tag]) + expect(MSpec).to receive(:read_tags).and_return([@tag]) filter = ActionFilter.new("tag", ["match me", "again"]) - MatchFilter.should_receive(:new).with(nil, "description") + expect(MatchFilter).to receive(:new).with(nil, "description") filter.load end end -describe ActionFilter, "#register" do +RSpec.describe ActionFilter, "#register" do it "registers itself with MSpec for the :load actions" do filter = ActionFilter.new - MSpec.should_receive(:register).with(:load, filter) + expect(MSpec).to receive(:register).with(:load, filter) filter.register end end -describe ActionFilter, "#unregister" do +RSpec.describe ActionFilter, "#unregister" do it "unregisters itself with MSpec for the :load actions" do filter = ActionFilter.new - MSpec.should_receive(:unregister).with(:load, filter) + expect(MSpec).to receive(:unregister).with(:load, filter) filter.unregister end end diff --git a/spec/mspec/spec/runner/actions/tag_spec.rb b/spec/mspec/spec/runner/actions/tag_spec.rb index 92df362d02..738e9a18c9 100644 --- a/spec/mspec/spec/runner/actions/tag_spec.rb +++ b/spec/mspec/spec/runner/actions/tag_spec.rb @@ -4,211 +4,211 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/runner/tag' -describe TagAction, ".new" do +RSpec.describe TagAction, ".new" do it "creates an MatchFilter with its tag and desc arguments" do filter = double('action filter').as_null_object - MatchFilter.should_receive(:new).with(nil, "some", "thing").and_return(filter) + expect(MatchFilter).to receive(:new).with(nil, "some", "thing").and_return(filter) TagAction.new :add, :all, nil, nil, ["tag", "key"], ["some", "thing"] end end -describe TagAction, "#===" do +RSpec.describe TagAction, "#===" do before :each do - MSpec.stub(:read_tags).and_return(["match"]) + allow(MSpec).to receive(:read_tags).and_return(["match"]) @action = TagAction.new :add, :fail, nil, nil, nil, ["catch", "if you"] end it "returns true if there are no filters" do action = TagAction.new :add, :all, nil, nil - action.===("anything").should == true + expect(action.===("anything")).to eq(true) end it "returns true if the argument matches any of the descriptions" do - @action.===("catch").should == true - @action.===("if you can").should == true + expect(@action.===("catch")).to eq(true) + expect(@action.===("if you can")).to eq(true) end it "returns false if the argument does not match any of the descriptions" do - @action.===("patch me").should == false - @action.===("if I can").should == false + expect(@action.===("patch me")).to eq(false) + expect(@action.===("if I can")).to eq(false) end end -describe TagAction, "#exception?" do +RSpec.describe TagAction, "#exception?" do before :each do @action = TagAction.new :add, :fail, nil, nil, nil, nil end it "returns false if no exception has been raised while evaluating an example" do - @action.exception?.should be_false + expect(@action.exception?).to be_falsey end it "returns true if an exception was raised while evaluating an example" do @action.exception ExceptionState.new nil, nil, Exception.new("failed") - @action.exception?.should be_true + expect(@action.exception?).to be_truthy end end -describe TagAction, "#outcome?" do +RSpec.describe TagAction, "#outcome?" do before :each do - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) @exception = ExceptionState.new nil, nil, Exception.new("failed") end it "returns true if outcome is :fail and the spec fails" do action = TagAction.new :add, :fail, nil, nil, nil, nil action.exception @exception - action.outcome?.should == true + expect(action.outcome?).to eq(true) end it "returns false if the outcome is :fail and the spec passes" do action = TagAction.new :add, :fail, nil, nil, nil, nil - action.outcome?.should == false + expect(action.outcome?).to eq(false) end it "returns true if the outcome is :pass and the spec passes" do action = TagAction.new :del, :pass, nil, nil, nil, nil - action.outcome?.should == true + expect(action.outcome?).to eq(true) end it "returns false if the outcome is :pass and the spec fails" do action = TagAction.new :del, :pass, nil, nil, nil, nil action.exception @exception - action.outcome?.should == false + expect(action.outcome?).to eq(false) end it "returns true if the outcome is :all" do action = TagAction.new :add, :all, nil, nil, nil, nil action.exception @exception - action.outcome?.should == true + expect(action.outcome?).to eq(true) end end -describe TagAction, "#before" do +RSpec.describe TagAction, "#before" do it "resets the #exception? flag to false" do action = TagAction.new :add, :fail, nil, nil, nil, nil - action.exception?.should be_false + expect(action.exception?).to be_falsey action.exception ExceptionState.new(nil, nil, Exception.new("Fail!")) - action.exception?.should be_true + expect(action.exception?).to be_truthy action.before(ExampleState.new(ContextState.new("describe"), "it")) - action.exception?.should be_false + expect(action.exception?).to be_falsey end end -describe TagAction, "#exception" do +RSpec.describe TagAction, "#exception" do it "sets the #exception? flag" do action = TagAction.new :add, :fail, nil, nil, nil, nil - action.exception?.should be_false + expect(action.exception?).to be_falsey action.exception ExceptionState.new(nil, nil, Exception.new("Fail!")) - action.exception?.should be_true + expect(action.exception?).to be_truthy end end -describe TagAction, "#after when action is :add" do +RSpec.describe TagAction, "#after when action is :add" do before :each do - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) context = ContextState.new "Catch#me" @state = ExampleState.new context, "if you can" @tag = SpecTag.new "tag(comment):Catch#me if you can" - SpecTag.stub(:new).and_return(@tag) + allow(SpecTag).to receive(:new).and_return(@tag) @exception = ExceptionState.new nil, nil, Exception.new("failed") end it "does not write a tag if the description does not match" do - MSpec.should_not_receive(:write_tag) + expect(MSpec).not_to receive(:write_tag) action = TagAction.new :add, :all, "tag", "comment", nil, "match" action.after @state end it "does not write a tag if outcome is :fail and the spec passed" do - MSpec.should_not_receive(:write_tag) + expect(MSpec).not_to receive(:write_tag) action = TagAction.new :add, :fail, "tag", "comment", nil, "can" action.after @state end it "writes a tag if the outcome is :fail and the spec failed" do - MSpec.should_receive(:write_tag).with(@tag) + expect(MSpec).to receive(:write_tag).with(@tag) action = TagAction.new :add, :fail, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "does not write a tag if outcome is :pass and the spec failed" do - MSpec.should_not_receive(:write_tag) + expect(MSpec).not_to receive(:write_tag) action = TagAction.new :add, :pass, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "writes a tag if the outcome is :pass and the spec passed" do - MSpec.should_receive(:write_tag).with(@tag) + expect(MSpec).to receive(:write_tag).with(@tag) action = TagAction.new :add, :pass, "tag", "comment", nil, "can" action.after @state end it "writes a tag if the outcome is :all" do - MSpec.should_receive(:write_tag).with(@tag) + expect(MSpec).to receive(:write_tag).with(@tag) action = TagAction.new :add, :all, "tag", "comment", nil, "can" action.after @state end end -describe TagAction, "#after when action is :del" do +RSpec.describe TagAction, "#after when action is :del" do before :each do - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) context = ContextState.new "Catch#me" @state = ExampleState.new context, "if you can" @tag = SpecTag.new "tag(comment):Catch#me if you can" - SpecTag.stub(:new).and_return(@tag) + allow(SpecTag).to receive(:new).and_return(@tag) @exception = ExceptionState.new nil, nil, Exception.new("failed") end it "does not delete a tag if the description does not match" do - MSpec.should_not_receive(:delete_tag) + expect(MSpec).not_to receive(:delete_tag) action = TagAction.new :del, :all, "tag", "comment", nil, "match" action.after @state end it "does not delete a tag if outcome is :fail and the spec passed" do - MSpec.should_not_receive(:delete_tag) + expect(MSpec).not_to receive(:delete_tag) action = TagAction.new :del, :fail, "tag", "comment", nil, "can" action.after @state end it "deletes a tag if the outcome is :fail and the spec failed" do - MSpec.should_receive(:delete_tag).with(@tag) + expect(MSpec).to receive(:delete_tag).with(@tag) action = TagAction.new :del, :fail, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "does not delete a tag if outcome is :pass and the spec failed" do - MSpec.should_not_receive(:delete_tag) + expect(MSpec).not_to receive(:delete_tag) action = TagAction.new :del, :pass, "tag", "comment", nil, "can" action.exception @exception action.after @state end it "deletes a tag if the outcome is :pass and the spec passed" do - MSpec.should_receive(:delete_tag).with(@tag) + expect(MSpec).to receive(:delete_tag).with(@tag) action = TagAction.new :del, :pass, "tag", "comment", nil, "can" action.after @state end it "deletes a tag if the outcome is :all" do - MSpec.should_receive(:delete_tag).with(@tag) + expect(MSpec).to receive(:delete_tag).with(@tag) action = TagAction.new :del, :all, "tag", "comment", nil, "can" action.after @state end end -describe TagAction, "#finish" do +RSpec.describe TagAction, "#finish" do before :each do $stdout = @out = IOStub.new context = ContextState.new "Catch#me" @state = ExampleState.new context, "if you can" - MSpec.stub(:write_tag).and_return(true) - MSpec.stub(:delete_tag).and_return(true) + allow(MSpec).to receive(:write_tag).and_return(true) + allow(MSpec).to receive(:delete_tag).and_return(true) end after :each do @@ -217,99 +217,97 @@ describe TagAction, "#finish" do it "reports no specs tagged if none where tagged" do action = TagAction.new :add, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(false) + allow(action).to receive(:outcome?).and_return(false) action.after @state action.finish - @out.should == "\nTagAction: no specs were tagged with 'tag'\n" + expect(@out).to eq("\nTagAction: no specs were tagged with 'tag'\n") end it "reports no specs tagged if none where tagged" do action = TagAction.new :del, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(false) + allow(action).to receive(:outcome?).and_return(false) action.after @state action.finish - @out.should == "\nTagAction: no tags 'tag' were deleted\n" + expect(@out).to eq("\nTagAction: no tags 'tag' were deleted\n") end it "reports the spec descriptions that were tagged" do action = TagAction.new :add, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(true) + allow(action).to receive(:outcome?).and_return(true) action.after @state action.finish - @out.should == -%[ + expect(@out).to eq(%[ TagAction: specs tagged with 'tag': Catch#me if you can -] +]) end it "reports the spec descriptions for the tags that were deleted" do action = TagAction.new :del, :fail, "tag", "comment", nil, "can" - action.stub(:outcome?).and_return(true) + allow(action).to receive(:outcome?).and_return(true) action.after @state action.finish - @out.should == -%[ + expect(@out).to eq(%[ TagAction: tag 'tag' deleted for specs: Catch#me if you can -] +]) end end -describe TagAction, "#register" do +RSpec.describe TagAction, "#register" do before :each do - MSpec.stub(:register) - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:register) + allow(MSpec).to receive(:read_tags).and_return([]) @action = TagAction.new :add, :all, nil, nil, nil, nil end it "registers itself with MSpec for the :before event" do - MSpec.should_receive(:register).with(:before, @action) + expect(MSpec).to receive(:register).with(:before, @action) @action.register end it "registers itself with MSpec for the :after event" do - MSpec.should_receive(:register).with(:after, @action) + expect(MSpec).to receive(:register).with(:after, @action) @action.register end it "registers itself with MSpec for the :exception event" do - MSpec.should_receive(:register).with(:exception, @action) + expect(MSpec).to receive(:register).with(:exception, @action) @action.register end it "registers itself with MSpec for the :finish event" do - MSpec.should_receive(:register).with(:finish, @action) + expect(MSpec).to receive(:register).with(:finish, @action) @action.register end end -describe TagAction, "#unregister" do +RSpec.describe TagAction, "#unregister" do before :each do - MSpec.stub(:unregister) - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:unregister) + allow(MSpec).to receive(:read_tags).and_return([]) @action = TagAction.new :add, :all, nil, nil, nil, nil end it "unregisters itself with MSpec for the :before event" do - MSpec.should_receive(:unregister).with(:before, @action) + expect(MSpec).to receive(:unregister).with(:before, @action) @action.unregister end it "unregisters itself with MSpec for the :after event" do - MSpec.should_receive(:unregister).with(:after, @action) + expect(MSpec).to receive(:unregister).with(:after, @action) @action.unregister end it "unregisters itself with MSpec for the :exception event" do - MSpec.should_receive(:unregister).with(:exception, @action) + expect(MSpec).to receive(:unregister).with(:exception, @action) @action.unregister end it "unregisters itself with MSpec for the :finish event" do - MSpec.should_receive(:unregister).with(:finish, @action) + expect(MSpec).to receive(:unregister).with(:finish, @action) @action.unregister end end diff --git a/spec/mspec/spec/runner/actions/taglist_spec.rb b/spec/mspec/spec/runner/actions/taglist_spec.rb index 418c761c2d..b6a5400f7d 100644 --- a/spec/mspec/spec/runner/actions/taglist_spec.rb +++ b/spec/mspec/spec/runner/actions/taglist_spec.rb @@ -4,34 +4,34 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/runner/tag' -describe TagListAction, "#include?" do +RSpec.describe TagListAction, "#include?" do it "returns true" do - TagListAction.new.include?(:anything).should be_true + expect(TagListAction.new.include?(:anything)).to be_truthy end end -describe TagListAction, "#===" do +RSpec.describe TagListAction, "#===" do before :each do tag = SpecTag.new "fails:description" - MSpec.stub(:read_tags).and_return([tag]) + allow(MSpec).to receive(:read_tags).and_return([tag]) @filter = double("MatchFilter").as_null_object - MatchFilter.stub(:new).and_return(@filter) + allow(MatchFilter).to receive(:new).and_return(@filter) @action = TagListAction.new @action.load end it "returns true if filter === string returns true" do - @filter.should_receive(:===).with("str").and_return(true) - @action.===("str").should be_true + expect(@filter).to receive(:===).with("str").and_return(true) + expect(@action.===("str")).to be_truthy end it "returns false if filter === string returns false" do - @filter.should_receive(:===).with("str").and_return(false) - @action.===("str").should be_false + expect(@filter).to receive(:===).with("str").and_return(false) + expect(@action.===("str")).to be_falsey end end -describe TagListAction, "#start" do +RSpec.describe TagListAction, "#start" do before :each do @stdout = $stdout $stdout = IOStub.new @@ -44,48 +44,48 @@ describe TagListAction, "#start" do it "prints a banner for specific tags" do action = TagListAction.new ["fails", "unstable"] action.start - $stdout.should == "\nListing specs tagged with 'fails', 'unstable'\n\n" + expect($stdout).to eq("\nListing specs tagged with 'fails', 'unstable'\n\n") end it "prints a banner for all tags" do action = TagListAction.new action.start - $stdout.should == "\nListing all tagged specs\n\n" + expect($stdout).to eq("\nListing all tagged specs\n\n") end end -describe TagListAction, "#load" do +RSpec.describe TagListAction, "#load" do before :each do @t1 = SpecTag.new "fails:I fail" @t2 = SpecTag.new "unstable:I'm unstable" end it "creates a MatchFilter for matching tags" do - MSpec.should_receive(:read_tags).with(["fails"]).and_return([@t1]) - MatchFilter.should_receive(:new).with(nil, "I fail") + expect(MSpec).to receive(:read_tags).with(["fails"]).and_return([@t1]) + expect(MatchFilter).to receive(:new).with(nil, "I fail") TagListAction.new(["fails"]).load end it "creates a MatchFilter for all tags" do - MSpec.should_receive(:read_tags).and_return([@t1, @t2]) - MatchFilter.should_receive(:new).with(nil, "I fail", "I'm unstable") + expect(MSpec).to receive(:read_tags).and_return([@t1, @t2]) + expect(MatchFilter).to receive(:new).with(nil, "I fail", "I'm unstable") TagListAction.new.load end it "does not create a MatchFilter if there are no matching tags" do - MSpec.stub(:read_tags).and_return([]) - MatchFilter.should_not_receive(:new) + allow(MSpec).to receive(:read_tags).and_return([]) + expect(MatchFilter).not_to receive(:new) TagListAction.new(["fails"]).load end end -describe TagListAction, "#after" do +RSpec.describe TagListAction, "#after" do before :each do @stdout = $stdout $stdout = IOStub.new @state = double("ExampleState") - @state.stub(:description).and_return("str") + allow(@state).to receive(:description).and_return("str") @action = TagListAction.new end @@ -95,58 +95,58 @@ describe TagListAction, "#after" do end it "prints nothing if the filter does not match" do - @action.should_receive(:===).with("str").and_return(false) + expect(@action).to receive(:===).with("str").and_return(false) @action.after(@state) - $stdout.should == "" + expect($stdout).to eq("") end it "prints the example description if the filter matches" do - @action.should_receive(:===).with("str").and_return(true) + expect(@action).to receive(:===).with("str").and_return(true) @action.after(@state) - $stdout.should == "str\n" + expect($stdout).to eq("str\n") end end -describe TagListAction, "#register" do +RSpec.describe TagListAction, "#register" do before :each do - MSpec.stub(:register) + allow(MSpec).to receive(:register) @action = TagListAction.new end it "registers itself with MSpec for the :start event" do - MSpec.should_receive(:register).with(:start, @action) + expect(MSpec).to receive(:register).with(:start, @action) @action.register end it "registers itself with MSpec for the :load event" do - MSpec.should_receive(:register).with(:load, @action) + expect(MSpec).to receive(:register).with(:load, @action) @action.register end it "registers itself with MSpec for the :after event" do - MSpec.should_receive(:register).with(:after, @action) + expect(MSpec).to receive(:register).with(:after, @action) @action.register end end -describe TagListAction, "#unregister" do +RSpec.describe TagListAction, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) @action = TagListAction.new end it "unregisters itself with MSpec for the :start event" do - MSpec.should_receive(:unregister).with(:start, @action) + expect(MSpec).to receive(:unregister).with(:start, @action) @action.unregister end it "unregisters itself with MSpec for the :load event" do - MSpec.should_receive(:unregister).with(:load, @action) + expect(MSpec).to receive(:unregister).with(:load, @action) @action.unregister end it "unregisters itself with MSpec for the :after event" do - MSpec.should_receive(:unregister).with(:after, @action) + expect(MSpec).to receive(:unregister).with(:after, @action) @action.unregister end end diff --git a/spec/mspec/spec/runner/actions/tagpurge_spec.rb b/spec/mspec/spec/runner/actions/tagpurge_spec.rb index 27ad2a1470..37df0afd5a 100644 --- a/spec/mspec/spec/runner/actions/tagpurge_spec.rb +++ b/spec/mspec/spec/runner/actions/tagpurge_spec.rb @@ -4,7 +4,7 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/runner/tag' -describe TagPurgeAction, "#start" do +RSpec.describe TagPurgeAction, "#start" do before :each do @stdout = $stdout $stdout = IOStub.new @@ -17,45 +17,45 @@ describe TagPurgeAction, "#start" do it "prints a banner" do action = TagPurgeAction.new action.start - $stdout.should == "\nRemoving tags not matching any specs\n\n" + expect($stdout).to eq("\nRemoving tags not matching any specs\n\n") end end -describe TagPurgeAction, "#load" do +RSpec.describe TagPurgeAction, "#load" do before :each do @t1 = SpecTag.new "fails:I fail" @t2 = SpecTag.new "unstable:I'm unstable" end it "creates a MatchFilter for all tags" do - MSpec.should_receive(:read_tags).and_return([@t1, @t2]) - MatchFilter.should_receive(:new).with(nil, "I fail", "I'm unstable") + expect(MSpec).to receive(:read_tags).and_return([@t1, @t2]) + expect(MatchFilter).to receive(:new).with(nil, "I fail", "I'm unstable") TagPurgeAction.new.load end end -describe TagPurgeAction, "#after" do +RSpec.describe TagPurgeAction, "#after" do before :each do @state = double("ExampleState") - @state.stub(:description).and_return("str") + allow(@state).to receive(:description).and_return("str") @action = TagPurgeAction.new end it "does not save the description if the filter does not match" do - @action.should_receive(:===).with("str").and_return(false) + expect(@action).to receive(:===).with("str").and_return(false) @action.after @state - @action.matching.should == [] + expect(@action.matching).to eq([]) end it "saves the description if the filter matches" do - @action.should_receive(:===).with("str").and_return(true) + expect(@action).to receive(:===).with("str").and_return(true) @action.after @state - @action.matching.should == ["str"] + expect(@action.matching).to eq(["str"]) end end -describe TagPurgeAction, "#unload" do +RSpec.describe TagPurgeAction, "#unload" do before :each do @stdout = $stdout $stdout = IOStub.new @@ -64,11 +64,11 @@ describe TagPurgeAction, "#unload" do @t2 = SpecTag.new "unstable:I'm unstable" @t3 = SpecTag.new "fails:I'm unstable" - MSpec.stub(:read_tags).and_return([@t1, @t2, @t3]) - MSpec.stub(:write_tags) + allow(MSpec).to receive(:read_tags).and_return([@t1, @t2, @t3]) + allow(MSpec).to receive(:write_tags) @state = double("ExampleState") - @state.stub(:description).and_return("I'm unstable") + allow(@state).to receive(:description).and_return("I'm unstable") @action = TagPurgeAction.new @action.load @@ -80,37 +80,37 @@ describe TagPurgeAction, "#unload" do end it "does not rewrite any tags if there were no tags for the specs" do - MSpec.should_receive(:read_tags).and_return([]) - MSpec.should_receive(:delete_tags) - MSpec.should_not_receive(:write_tags) + expect(MSpec).to receive(:read_tags).and_return([]) + expect(MSpec).to receive(:delete_tags) + expect(MSpec).not_to receive(:write_tags) @action.load @action.after @state @action.unload - $stdout.should == "" + expect($stdout).to eq("") end it "rewrites tags that were matched" do - MSpec.should_receive(:write_tags).with([@t2, @t3]) + expect(MSpec).to receive(:write_tags).with([@t2, @t3]) @action.unload end it "prints tags that were not matched" do @action.unload - $stdout.should == "I fail\n" + expect($stdout).to eq("I fail\n") end end -describe TagPurgeAction, "#unload" do +RSpec.describe TagPurgeAction, "#unload" do before :each do @stdout = $stdout $stdout = IOStub.new - MSpec.stub(:read_tags).and_return([]) + allow(MSpec).to receive(:read_tags).and_return([]) @state = double("ExampleState") - @state.stub(:description).and_return("I'm unstable") + allow(@state).to receive(:description).and_return("I'm unstable") @action = TagPurgeAction.new @action.load @@ -122,33 +122,33 @@ describe TagPurgeAction, "#unload" do end it "deletes the tag file if no tags were found" do - MSpec.should_not_receive(:write_tags) - MSpec.should_receive(:delete_tags) + expect(MSpec).not_to receive(:write_tags) + expect(MSpec).to receive(:delete_tags) @action.unload - $stdout.should == "" + expect($stdout).to eq("") end end -describe TagPurgeAction, "#register" do +RSpec.describe TagPurgeAction, "#register" do before :each do - MSpec.stub(:register) + allow(MSpec).to receive(:register) @action = TagPurgeAction.new end it "registers itself with MSpec for the :unload event" do - MSpec.should_receive(:register).with(:unload, @action) + expect(MSpec).to receive(:register).with(:unload, @action) @action.register end end -describe TagPurgeAction, "#unregister" do +RSpec.describe TagPurgeAction, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) @action = TagPurgeAction.new end it "unregisters itself with MSpec for the :unload event" do - MSpec.should_receive(:unregister).with(:unload, @action) + expect(MSpec).to receive(:unregister).with(:unload, @action) @action.unregister end end diff --git a/spec/mspec/spec/runner/actions/tally_spec.rb b/spec/mspec/spec/runner/actions/tally_spec.rb index be4635ffeb..d80ab1164a 100644 --- a/spec/mspec/spec/runner/actions/tally_spec.rb +++ b/spec/mspec/spec/runner/actions/tally_spec.rb @@ -4,169 +4,169 @@ require 'mspec/runner/actions/tally' require 'mspec/runner/mspec' require 'mspec/runner/example' -describe Tally, "#files!" do +RSpec.describe Tally, "#files!" do before :each do @tally = Tally.new end it "increments the count returned by #files" do @tally.files! 3 - @tally.files.should == 3 + expect(@tally.files).to eq(3) @tally.files! - @tally.files.should == 4 + expect(@tally.files).to eq(4) end end -describe Tally, "#examples!" do +RSpec.describe Tally, "#examples!" do before :each do @tally = Tally.new end it "increments the count returned by #examples" do @tally.examples! 2 - @tally.examples.should == 2 + expect(@tally.examples).to eq(2) @tally.examples! 2 - @tally.examples.should == 4 + expect(@tally.examples).to eq(4) end end -describe Tally, "#expectations!" do +RSpec.describe Tally, "#expectations!" do before :each do @tally = Tally.new end it "increments the count returned by #expectations" do @tally.expectations! - @tally.expectations.should == 1 + expect(@tally.expectations).to eq(1) @tally.expectations! 3 - @tally.expectations.should == 4 + expect(@tally.expectations).to eq(4) end end -describe Tally, "#failures!" do +RSpec.describe Tally, "#failures!" do before :each do @tally = Tally.new end it "increments the count returned by #failures" do @tally.failures! 1 - @tally.failures.should == 1 + expect(@tally.failures).to eq(1) @tally.failures! - @tally.failures.should == 2 + expect(@tally.failures).to eq(2) end end -describe Tally, "#errors!" do +RSpec.describe Tally, "#errors!" do before :each do @tally = Tally.new end it "increments the count returned by #errors" do @tally.errors! - @tally.errors.should == 1 + expect(@tally.errors).to eq(1) @tally.errors! 2 - @tally.errors.should == 3 + expect(@tally.errors).to eq(3) end end -describe Tally, "#guards!" do +RSpec.describe Tally, "#guards!" do before :each do @tally = Tally.new end it "increments the count returned by #guards" do @tally.guards! - @tally.guards.should == 1 + expect(@tally.guards).to eq(1) @tally.guards! 2 - @tally.guards.should == 3 + expect(@tally.guards).to eq(3) end end -describe Tally, "#file" do +RSpec.describe Tally, "#file" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #files" do - @tally.file.should == "0 files" + expect(@tally.file).to eq("0 files") @tally.files! - @tally.file.should == "1 file" + expect(@tally.file).to eq("1 file") @tally.files! - @tally.file.should == "2 files" + expect(@tally.file).to eq("2 files") end end -describe Tally, "#example" do +RSpec.describe Tally, "#example" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #examples" do - @tally.example.should == "0 examples" + expect(@tally.example).to eq("0 examples") @tally.examples! - @tally.example.should == "1 example" + expect(@tally.example).to eq("1 example") @tally.examples! - @tally.example.should == "2 examples" + expect(@tally.example).to eq("2 examples") end end -describe Tally, "#expectation" do +RSpec.describe Tally, "#expectation" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #expectations" do - @tally.expectation.should == "0 expectations" + expect(@tally.expectation).to eq("0 expectations") @tally.expectations! - @tally.expectation.should == "1 expectation" + expect(@tally.expectation).to eq("1 expectation") @tally.expectations! - @tally.expectation.should == "2 expectations" + expect(@tally.expectation).to eq("2 expectations") end end -describe Tally, "#failure" do +RSpec.describe Tally, "#failure" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #failures" do - @tally.failure.should == "0 failures" + expect(@tally.failure).to eq("0 failures") @tally.failures! - @tally.failure.should == "1 failure" + expect(@tally.failure).to eq("1 failure") @tally.failures! - @tally.failure.should == "2 failures" + expect(@tally.failure).to eq("2 failures") end end -describe Tally, "#error" do +RSpec.describe Tally, "#error" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #errors" do - @tally.error.should == "0 errors" + expect(@tally.error).to eq("0 errors") @tally.errors! - @tally.error.should == "1 error" + expect(@tally.error).to eq("1 error") @tally.errors! - @tally.error.should == "2 errors" + expect(@tally.error).to eq("2 errors") end end -describe Tally, "#guard" do +RSpec.describe Tally, "#guard" do before :each do @tally = Tally.new end it "returns a formatted string of the number of #guards" do - @tally.guard.should == "0 guards" + expect(@tally.guard).to eq("0 guards") @tally.guards! - @tally.guard.should == "1 guard" + expect(@tally.guard).to eq("1 guard") @tally.guards! - @tally.guard.should == "2 guards" + expect(@tally.guard).to eq("2 guards") end end -describe Tally, "#format" do +RSpec.describe Tally, "#format" do before :each do @tally = Tally.new end @@ -181,7 +181,7 @@ describe Tally, "#format" do @tally.expectations! 4 @tally.errors! @tally.tagged! - @tally.format.should == "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged" + expect(@tally.format).to eq("1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged") end it "includes guards if MSpec is in verify mode" do @@ -192,8 +192,9 @@ describe Tally, "#format" do @tally.errors! @tally.tagged! @tally.guards! - @tally.format.should == + expect(@tally.format).to eq( "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged, 1 guard" + ) end it "includes guards if MSpec is in report mode" do @@ -204,8 +205,9 @@ describe Tally, "#format" do @tally.errors! @tally.tagged! @tally.guards! 2 - @tally.format.should == + expect(@tally.format).to eq( "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 1 tagged, 2 guards" + ) end it "includes guards if MSpec is in report_on mode" do @@ -215,23 +217,24 @@ describe Tally, "#format" do @tally.expectations! 4 @tally.errors! @tally.guards! 2 - @tally.format.should == + expect(@tally.format).to eq( "1 file, 2 examples, 4 expectations, 0 failures, 1 error, 0 tagged, 2 guards" + ) end end -describe TallyAction, "#counter" do +RSpec.describe TallyAction, "#counter" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") end it "returns the Tally object" do - @tally.counter.should be_kind_of(Tally) + expect(@tally.counter).to be_kind_of(Tally) end end -describe TallyAction, "#load" do +RSpec.describe TallyAction, "#load" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -239,11 +242,11 @@ describe TallyAction, "#load" do it "increments the count returned by Tally#files" do @tally.load - @tally.counter.files.should == 1 + expect(@tally.counter.files).to eq(1) end end -describe TallyAction, "#expectation" do +RSpec.describe TallyAction, "#expectation" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -251,11 +254,11 @@ describe TallyAction, "#expectation" do it "increments the count returned by Tally#expectations" do @tally.expectation @state - @tally.counter.expectations.should == 1 + expect(@tally.counter.expectations).to eq(1) end end -describe TallyAction, "#example" do +RSpec.describe TallyAction, "#example" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -263,14 +266,14 @@ describe TallyAction, "#example" do it "increments counts returned by Tally#examples" do @tally.example @state, nil - @tally.counter.examples.should == 1 - @tally.counter.expectations.should == 0 - @tally.counter.failures.should == 0 - @tally.counter.errors.should == 0 + expect(@tally.counter.examples).to eq(1) + expect(@tally.counter.expectations).to eq(0) + expect(@tally.counter.failures).to eq(0) + expect(@tally.counter.errors).to eq(0) end end -describe TallyAction, "#exception" do +RSpec.describe TallyAction, "#exception" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -279,14 +282,14 @@ describe TallyAction, "#exception" do it "increments counts returned by Tally#failures" do exc = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("Failed!") @tally.exception exc - @tally.counter.examples.should == 0 - @tally.counter.expectations.should == 0 - @tally.counter.failures.should == 1 - @tally.counter.errors.should == 0 + expect(@tally.counter.examples).to eq(0) + expect(@tally.counter.expectations).to eq(0) + expect(@tally.counter.failures).to eq(1) + expect(@tally.counter.errors).to eq(0) end end -describe TallyAction, "#exception" do +RSpec.describe TallyAction, "#exception" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -295,14 +298,14 @@ describe TallyAction, "#exception" do it "increments counts returned by Tally#errors" do exc = ExceptionState.new nil, nil, Exception.new("Error!") @tally.exception exc - @tally.counter.examples.should == 0 - @tally.counter.expectations.should == 0 - @tally.counter.failures.should == 0 - @tally.counter.errors.should == 1 + expect(@tally.counter.examples).to eq(0) + expect(@tally.counter.expectations).to eq(0) + expect(@tally.counter.failures).to eq(0) + expect(@tally.counter.errors).to eq(1) end end -describe TallyAction, "#format" do +RSpec.describe TallyAction, "#format" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") @@ -315,38 +318,38 @@ describe TallyAction, "#format" do @tally.expectation @state exc = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("Failed!") @tally.exception exc - @tally.format.should == "1 file, 1 example, 2 expectations, 1 failure, 0 errors, 0 tagged" + expect(@tally.format).to eq("1 file, 1 example, 2 expectations, 1 failure, 0 errors, 0 tagged") end end -describe TallyAction, "#register" do +RSpec.describe TallyAction, "#register" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") end it "registers itself with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:load, @tally) - MSpec.should_receive(:register).with(:exception, @tally) - MSpec.should_receive(:register).with(:example, @tally) - MSpec.should_receive(:register).with(:tagged, @tally) - MSpec.should_receive(:register).with(:expectation, @tally) + expect(MSpec).to receive(:register).with(:load, @tally) + expect(MSpec).to receive(:register).with(:exception, @tally) + expect(MSpec).to receive(:register).with(:example, @tally) + expect(MSpec).to receive(:register).with(:tagged, @tally) + expect(MSpec).to receive(:register).with(:expectation, @tally) @tally.register end end -describe TallyAction, "#unregister" do +RSpec.describe TallyAction, "#unregister" do before :each do @tally = TallyAction.new @state = ExampleState.new("describe", "it") end it "unregisters itself with MSpec for appropriate actions" do - MSpec.should_receive(:unregister).with(:load, @tally) - MSpec.should_receive(:unregister).with(:exception, @tally) - MSpec.should_receive(:unregister).with(:example, @tally) - MSpec.should_receive(:unregister).with(:tagged, @tally) - MSpec.should_receive(:unregister).with(:expectation, @tally) + expect(MSpec).to receive(:unregister).with(:load, @tally) + expect(MSpec).to receive(:unregister).with(:exception, @tally) + expect(MSpec).to receive(:unregister).with(:example, @tally) + expect(MSpec).to receive(:unregister).with(:tagged, @tally) + expect(MSpec).to receive(:unregister).with(:expectation, @tally) @tally.unregister end end diff --git a/spec/mspec/spec/runner/actions/timer_spec.rb b/spec/mspec/spec/runner/actions/timer_spec.rb index 417367d5a2..28a317177b 100644 --- a/spec/mspec/spec/runner/actions/timer_spec.rb +++ b/spec/mspec/spec/runner/actions/timer_spec.rb @@ -3,7 +3,7 @@ require 'mspec/runner/actions/timer' require 'mspec/runner/mspec' require 'time' -describe TimerAction do +RSpec.describe TimerAction do before :each do @timer = TimerAction.new @start_time = Time.utc(2009, 3, 30, 14, 5, 19) @@ -11,34 +11,34 @@ describe TimerAction do end it "responds to #start by recording the current time" do - Time.should_receive(:now) + expect(Time).to receive(:now) @timer.start end it "responds to #finish by recording the current time" do - Time.should_receive(:now) + expect(Time).to receive(:now) @timer.finish end it "responds to #elapsed by returning the difference between stop and start" do - Time.stub(:now).and_return(@start_time) + allow(Time).to receive(:now).and_return(@start_time) @timer.start - Time.stub(:now).and_return(@stop_time) + allow(Time).to receive(:now).and_return(@stop_time) @timer.finish - @timer.elapsed.should == 33 + expect(@timer.elapsed).to eq(33) end it "responds to #format by returning a readable string of elapsed time" do - Time.stub(:now).and_return(@start_time) + allow(Time).to receive(:now).and_return(@start_time) @timer.start - Time.stub(:now).and_return(@stop_time) + allow(Time).to receive(:now).and_return(@stop_time) @timer.finish - @timer.format.should == "Finished in 33.000000 seconds" + expect(@timer.format).to eq("Finished in 33.000000 seconds") end it "responds to #register by registering itself with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:start, @timer) - MSpec.should_receive(:register).with(:finish, @timer) + expect(MSpec).to receive(:register).with(:start, @timer) + expect(MSpec).to receive(:register).with(:finish, @timer) @timer.register end end diff --git a/spec/mspec/spec/runner/context_spec.rb b/spec/mspec/spec/runner/context_spec.rb index d9c20aa0cf..9ebc708c0c 100644 --- a/spec/mspec/spec/runner/context_spec.rb +++ b/spec/mspec/spec/runner/context_spec.rb @@ -6,7 +6,7 @@ require 'mspec/mocks/mock' require 'mspec/runner/context' require 'mspec/runner/example' -describe ContextState, "#describe" do +RSpec.describe ContextState, "#describe" do before :each do @state = ContextState.new "C#m" @proc = proc { ScratchPad.record :a } @@ -15,79 +15,63 @@ describe ContextState, "#describe" do it "evaluates the passed block" do @state.describe(&@proc) - ScratchPad.recorded.should == :a + expect(ScratchPad.recorded).to eq(:a) end it "evaluates the passed block via #protect" do - @state.should_receive(:protect).with("C#m", @proc, false) + expect(@state).to receive(:protect).with("C#m", @proc, false) @state.describe(&@proc) end it "registers #parent as the current MSpec ContextState" do parent = ContextState.new "" @state.parent = parent - MSpec.should_receive(:register_current).with(parent) + expect(MSpec).to receive(:register_current).with(parent) @state.describe { } end it "registers self with MSpec when #shared? is true" do state = ContextState.new "something shared", :shared => true - MSpec.should_receive(:register_shared).with(state) + expect(MSpec).to receive(:register_shared).with(state) state.describe { } end end -describe ContextState, "#shared?" do +RSpec.describe ContextState, "#shared?" do it "returns false when the ContextState is not shared" do - ContextState.new("").shared?.should be_false + expect(ContextState.new("").shared?).to be_falsey end it "returns true when the ContextState is shared" do - ContextState.new("", {:shared => true}).shared?.should be_true + expect(ContextState.new("", {:shared => true}).shared?).to be_truthy end end -describe ContextState, "#to_s" do +RSpec.describe ContextState, "#to_s" do it "returns a description string for self when passed a Module" do - ContextState.new(Object).to_s.should == "Object" + expect(ContextState.new(Object).to_s).to eq("Object") end it "returns a description string for self when passed a String" do - ContextState.new("SomeClass").to_s.should == "SomeClass" - end - - it "returns a description string for self when passed a Module, String" do - ContextState.new(Object, "when empty").to_s.should == "Object when empty" - end - - it "returns a description string for self when passed a Module and String beginning with '#'" do - ContextState.new(Object, "#to_s").to_s.should == "Object#to_s" - end - - it "returns a description string for self when passed a Module and String beginning with '.'" do - ContextState.new(Object, ".to_s").to_s.should == "Object.to_s" - end - - it "returns a description string for self when passed a Module and String beginning with '::'" do - ContextState.new(Object, "::to_s").to_s.should == "Object::to_s" + expect(ContextState.new("SomeClass").to_s).to eq("SomeClass") end end -describe ContextState, "#description" do +RSpec.describe ContextState, "#description" do before :each do @state = ContextState.new "when empty" @parent = ContextState.new "Toplevel" end it "returns a composite description string from self and all parents" do - @parent.description.should == "Toplevel" - @state.description.should == "when empty" + expect(@parent.description).to eq("Toplevel") + expect(@state.description).to eq("when empty") @state.parent = @parent - @state.description.should == "Toplevel when empty" + expect(@state.description).to eq("Toplevel when empty") end end -describe ContextState, "#it" do +RSpec.describe ContextState, "#it" do before :each do @state = ContextState.new "" @proc = lambda {|*| } @@ -96,25 +80,25 @@ describe ContextState, "#it" do end it "creates an ExampleState instance for the block" do - ExampleState.should_receive(:new).with(@state, "it", @proc).and_return(@ex) + expect(ExampleState).to receive(:new).with(@state, "it", @proc).and_return(@ex) @state.describe(&@proc) @state.it("it", &@proc) end it "calls registered :add actions" do - ExampleState.should_receive(:new).with(@state, "it", @proc).and_return(@ex) + expect(ExampleState).to receive(:new).with(@state, "it", @proc).and_return(@ex) add_action = double("add") - add_action.should_receive(:add).with(@ex).and_return { ScratchPad.record :add } + expect(add_action).to receive(:add).with(@ex) { ScratchPad.record :add } MSpec.register :add, add_action @state.it("it", &@proc) - ScratchPad.recorded.should == :add + expect(ScratchPad.recorded).to eq(:add) MSpec.unregister :add, add_action end end -describe ContextState, "#examples" do +RSpec.describe ContextState, "#examples" do before :each do @state = ContextState.new "" end @@ -122,11 +106,11 @@ describe ContextState, "#examples" do it "returns a list of all examples in this ContextState" do @state.it("first") { } @state.it("second") { } - @state.examples.size.should == 2 + expect(@state.examples.size).to eq(2) end end -describe ContextState, "#before" do +RSpec.describe ContextState, "#before" do before :each do @state = ContextState.new "" @proc = lambda {|*| } @@ -134,16 +118,16 @@ describe ContextState, "#before" do it "records the block for :each" do @state.before(:each, &@proc) - @state.before(:each).should == [@proc] + expect(@state.before(:each)).to eq([@proc]) end it "records the block for :all" do @state.before(:all, &@proc) - @state.before(:all).should == [@proc] + expect(@state.before(:all)).to eq([@proc]) end end -describe ContextState, "#after" do +RSpec.describe ContextState, "#after" do before :each do @state = ContextState.new "" @proc = lambda {|*| } @@ -151,16 +135,16 @@ describe ContextState, "#after" do it "records the block for :each" do @state.after(:each, &@proc) - @state.after(:each).should == [@proc] + expect(@state.after(:each)).to eq([@proc]) end it "records the block for :all" do @state.after(:all, &@proc) - @state.after(:all).should == [@proc] + expect(@state.after(:all)).to eq([@proc]) end end -describe ContextState, "#pre" do +RSpec.describe ContextState, "#pre" do before :each do @a = lambda {|*| } @b = lambda {|*| } @@ -177,17 +161,17 @@ describe ContextState, "#pre" do it "returns before(:each) actions in the order they were defined" do @state.before(:each, &@a) @state.before(:each, &@b) - @state.pre(:each).should == [@c, @a, @b] + expect(@state.pre(:each)).to eq([@c, @a, @b]) end it "returns before(:all) actions in the order they were defined" do @state.before(:all, &@a) @state.before(:all, &@b) - @state.pre(:all).should == [@c, @a, @b] + expect(@state.pre(:all)).to eq([@c, @a, @b]) end end -describe ContextState, "#post" do +RSpec.describe ContextState, "#post" do before :each do @a = lambda {|*| } @b = lambda {|*| } @@ -204,17 +188,17 @@ describe ContextState, "#post" do it "returns after(:each) actions in the reverse order they were defined" do @state.after(:each, &@a) @state.after(:each, &@b) - @state.post(:each).should == [@b, @a, @c] + expect(@state.post(:each)).to eq([@b, @a, @c]) end it "returns after(:all) actions in the reverse order they were defined" do @state.after(:all, &@a) @state.after(:all, &@b) - @state.post(:all).should == [@b, @a, @c] + expect(@state.post(:all)).to eq([@b, @a, @c]) end end -describe ContextState, "#protect" do +RSpec.describe ContextState, "#protect" do before :each do ScratchPad.record [] @a = lambda {|*| ScratchPad << :a } @@ -223,41 +207,41 @@ describe ContextState, "#protect" do end it "returns true and does execute any blocks if check and MSpec.mode?(:pretend) are true" do - MSpec.should_receive(:mode?).with(:pretend).and_return(true) - ContextState.new("").protect("message", [@a, @b]).should be_true - ScratchPad.recorded.should == [] + expect(MSpec).to receive(:mode?).with(:pretend).and_return(true) + expect(ContextState.new("").protect("message", [@a, @b])).to be_truthy + expect(ScratchPad.recorded).to eq([]) end it "executes the blocks if MSpec.mode?(:pretend) is false" do - MSpec.should_receive(:mode?).with(:pretend).and_return(false) + expect(MSpec).to receive(:mode?).with(:pretend).and_return(false) ContextState.new("").protect("message", [@a, @b]) - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "executes the blocks if check is false" do ContextState.new("").protect("message", [@a, @b], false) - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "returns true if none of the blocks raise an exception" do - ContextState.new("").protect("message", [@a, @b]).should be_true + expect(ContextState.new("").protect("message", [@a, @b])).to be_truthy end it "returns false if any of the blocks raise an exception" do - ContextState.new("").protect("message", [@a, @c, @b]).should be_false + expect(ContextState.new("").protect("message", [@a, @c, @b])).to be_falsey end end -describe ContextState, "#parent=" do +RSpec.describe ContextState, "#parent=" do before :each do @state = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "does not set self as a child of parent if shared" do - @parent.should_not_receive(:child) + expect(@parent).not_to receive(:child) state = ContextState.new "", :shared => true state.parent = @parent end @@ -265,70 +249,70 @@ describe ContextState, "#parent=" do it "does not set parents if shared" do state = ContextState.new "", :shared => true state.parent = @parent - state.parents.should == [state] + expect(state.parents).to eq([state]) end it "sets self as a child of parent" do - @parent.should_receive(:child).with(@state) + expect(@parent).to receive(:child).with(@state) @state.parent = @parent end it "creates the list of parents" do @state.parent = @parent - @state.parents.should == [@parent, @state] + expect(@state.parents).to eq([@parent, @state]) end end -describe ContextState, "#parent" do +RSpec.describe ContextState, "#parent" do before :each do @state = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "returns nil if parent has not been set" do - @state.parent.should be_nil + expect(@state.parent).to be_nil end it "returns the parent" do @state.parent = @parent - @state.parent.should == @parent + expect(@state.parent).to eq(@parent) end end -describe ContextState, "#parents" do +RSpec.describe ContextState, "#parents" do before :each do @first = ContextState.new "" @second = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "returns a list of all enclosing ContextState instances" do @first.parent = @parent @second.parent = @first - @second.parents.should == [@parent, @first, @second] + expect(@second.parents).to eq([@parent, @first, @second]) end end -describe ContextState, "#child" do +RSpec.describe ContextState, "#child" do before :each do @first = ContextState.new "" @second = ContextState.new "" @parent = double("describe") - @parent.stub(:parent).and_return(nil) - @parent.stub(:child) + allow(@parent).to receive(:parent).and_return(nil) + allow(@parent).to receive(:child) end it "adds the ContextState to the list of contained ContextStates" do @first.child @second - @first.children.should == [@second] + expect(@first.children).to eq([@second]) end end -describe ContextState, "#children" do +RSpec.describe ContextState, "#children" do before :each do @parent = ContextState.new "" @first = ContextState.new "" @@ -338,12 +322,12 @@ describe ContextState, "#children" do it "returns the list of directly contained ContextStates" do @first.parent = @parent @second.parent = @first - @parent.children.should == [@first] - @first.children.should == [@second] + expect(@parent.children).to eq([@first]) + expect(@first.children).to eq([@second]) end end -describe ContextState, "#state" do +RSpec.describe ContextState, "#state" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -352,7 +336,7 @@ describe ContextState, "#state" do end it "returns nil if no spec is being executed" do - @state.state.should == nil + expect(@state.state).to eq(nil) end it "returns a ExampleState instance if an example is being executed" do @@ -360,16 +344,16 @@ describe ContextState, "#state" do @state.describe { } @state.it("") { ScratchPad.record ScratchPad.recorded.state } @state.process - @state.state.should == nil - ScratchPad.recorded.should be_kind_of(ExampleState) + expect(@state.state).to eq(nil) + expect(ScratchPad.recorded).to be_kind_of(ExampleState) end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :before, [] MSpec.store :after, [] - MSpec.stub(:register_current) + allow(MSpec).to receive(:register_current) @state = ContextState.new "" @state.describe { } @@ -384,7 +368,7 @@ describe ContextState, "#process" do @state.before(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "calls each after(:all) block" do @@ -392,22 +376,22 @@ describe ContextState, "#process" do @state.after(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:b, :a] + expect(ScratchPad.recorded).to eq([:b, :a]) end it "calls each it block" do @state.it("one", &@a) @state.it("two", &@b) @state.process - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "does not call the #it block if #filtered? returns true" do @state.it("one", &@a) @state.it("two", &@b) - @state.examples.first.stub(:filtered?).and_return(true) + allow(@state.examples.first).to receive(:filtered?).and_return(true) @state.process - ScratchPad.recorded.should == [:b] + expect(ScratchPad.recorded).to eq([:b]) end it "calls each before(:each) block" do @@ -415,7 +399,7 @@ describe ContextState, "#process" do @state.before(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:a, :b] + expect(ScratchPad.recorded).to eq([:a, :b]) end it "calls each after(:each) block" do @@ -423,20 +407,20 @@ describe ContextState, "#process" do @state.after(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [:b, :a] + expect(ScratchPad.recorded).to eq([:b, :a]) end it "calls Mock.cleanup for each it block" do @state.it("") { } @state.it("") { } - Mock.should_receive(:cleanup).twice + expect(Mock).to receive(:cleanup).twice @state.process end it "calls Mock.verify_count for each it block" do @state.it("") { } @state.it("") { } - Mock.should_receive(:verify_count).twice + expect(Mock).to receive(:verify_count).twice @state.process end @@ -444,7 +428,7 @@ describe ContextState, "#process" do ScratchPad.record [] @state.describe { ScratchPad << :a } @state.process - ScratchPad.recorded.should == [:a] + expect(ScratchPad.recorded).to eq([:a]) end it "creates a new ExampleState instance for each example" do @@ -452,44 +436,47 @@ describe ContextState, "#process" do @state.describe { } @state.it("it") { ScratchPad.record ScratchPad.recorded.state } @state.process - ScratchPad.recorded.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to be_kind_of(ExampleState) end it "clears the expectations flag before evaluating the #it block" do MSpec.clear_expectations - MSpec.should_receive(:clear_expectations) + expect(MSpec).to receive(:clear_expectations) @state.it("it") { ScratchPad.record MSpec.expectation? } @state.process - ScratchPad.recorded.should be_false + expect(ScratchPad.recorded).to be_falsey end it "shuffles the spec list if MSpec.randomize? is true" do - MSpec.randomize - MSpec.should_receive(:shuffle) - @state.it("") { } - @state.process - MSpec.randomize false + MSpec.randomize = true + begin + expect(MSpec).to receive(:shuffle) + @state.it("") { } + @state.process + ensure + MSpec.randomize = false + end end it "sets the current MSpec ContextState" do - MSpec.should_receive(:register_current).with(@state) + expect(MSpec).to receive(:register_current).with(@state) @state.process end it "resets the current MSpec ContextState to nil when there are examples" do - MSpec.should_receive(:register_current).with(nil) + expect(MSpec).to receive(:register_current).with(nil) @state.it("") { } @state.process end it "resets the current MSpec ContextState to nil when there are no examples" do - MSpec.should_receive(:register_current).with(nil) + expect(MSpec).to receive(:register_current).with(nil) @state.process end it "call #process on children when there are examples" do child = ContextState.new "" - child.should_receive(:process) + expect(child).to receive(:process) @state.child child @state.it("") { } @state.process @@ -497,13 +484,13 @@ describe ContextState, "#process" do it "call #process on children when there are no examples" do child = ContextState.new "" - child.should_receive(:process) + expect(child).to receive(:process) @state.child child @state.process end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :exception, [] @@ -527,23 +514,23 @@ describe ContextState, "#process" do it "raises an SpecExpectationNotFoundError if an #it block does not contain an expectation" do @state.it("it") { } @state.process - ScratchPad.recorded.should == :exception + expect(ScratchPad.recorded).to eq(:exception) end it "does not raise an SpecExpectationNotFoundError if an #it block does contain an expectation" do @state.it("it") { MSpec.expectation } @state.process - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end it "does not raise an SpecExpectationNotFoundError if the #it block causes a failure" do @state.it("it") { raise Exception, "Failed!" } @state.process - ScratchPad.recorded.should be_nil + expect(ScratchPad.recorded).to be_nil end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :example, [] @@ -567,18 +554,18 @@ describe ContextState, "#process" do @state.it("") { MSpec.expectation } @state.process - ScratchPad.recorded.first.should be_kind_of(ExampleState) - ScratchPad.recorded.last.should be_kind_of(Proc) + expect(ScratchPad.recorded.first).to be_kind_of(ExampleState) + expect(ScratchPad.recorded.last).to be_kind_of(Proc) end it "does not call registered example actions if the example has no block" do @state.it("empty example") @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -595,30 +582,30 @@ describe ContextState, "#process" do it "calls registered :before actions with the current ExampleState instance" do before = double("before") - before.should_receive(:before).and_return { + expect(before).to receive(:before) { ScratchPad.record :before @spec_state = @state.state } MSpec.register :before, before @state.process - ScratchPad.recorded.should == :before - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:before) + expect(@spec_state).to be_kind_of(ExampleState) end it "calls registered :after actions with the current ExampleState instance" do after = double("after") - after.should_receive(:after).and_return { + expect(after).to receive(:after) { ScratchPad.record :after @spec_state = @state.state } MSpec.register :after, after @state.process - ScratchPad.recorded.should == :after - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:after) + expect(@spec_state).to be_kind_of(ExampleState) end end -describe ContextState, "#process" do +RSpec.describe ContextState, "#process" do before :each do MSpec.store :enter, [] MSpec.store :leave, [] @@ -635,22 +622,22 @@ describe ContextState, "#process" do it "calls registered :enter actions with the current #describe string" do enter = double("enter") - enter.should_receive(:enter).with("C#m").and_return { ScratchPad.record :enter } + expect(enter).to receive(:enter).with("C#m") { ScratchPad.record :enter } MSpec.register :enter, enter @state.process - ScratchPad.recorded.should == :enter + expect(ScratchPad.recorded).to eq(:enter) end it "calls registered :leave actions" do leave = double("leave") - leave.should_receive(:leave).and_return { ScratchPad.record :leave } + expect(leave).to receive(:leave) { ScratchPad.record :leave } MSpec.register :leave, leave @state.process - ScratchPad.recorded.should == :leave + expect(ScratchPad.recorded).to eq(:leave) end end -describe ContextState, "#process when an exception is raised in before(:all)" do +RSpec.describe ContextState, "#process when an exception is raised in before(:all)" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -674,43 +661,43 @@ describe ContextState, "#process when an exception is raised in before(:all)" do @state.before(:each, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call the it block" do @state.it("one", &@a) @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call after(:each)" do @state.after(:each, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call after(:each)" do @state.after(:all, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call Mock.verify_count" do @state.it("") { } - Mock.should_not_receive(:verify_count) + expect(Mock).not_to receive(:verify_count) @state.process end it "calls Mock.cleanup" do @state.it("") { } - Mock.should_receive(:cleanup) + expect(Mock).to receive(:cleanup) @state.process end end -describe ContextState, "#process when an exception is raised in before(:each)" do +RSpec.describe ContextState, "#process when an exception is raised in before(:each)" do before :each do MSpec.store :before, [] MSpec.store :after, [] @@ -733,24 +720,24 @@ describe ContextState, "#process when an exception is raised in before(:each)" d it "does not call the it block" do @state.it("one", &@a) @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end - it "does call after(:each)" do + it "calls after(:each)" do @state.after(:each, &@a) @state.it("") { } @state.process - ScratchPad.recorded.should == [:a] + expect(ScratchPad.recorded).to eq([:a]) end - it "does not call Mock.verify_count" do + it "calls Mock.verify_count" do @state.it("") { } - Mock.should_not_receive(:verify_count) + expect(Mock).to receive(:verify_count) @state.process end end -describe ContextState, "#process in pretend mode" do +RSpec.describe ContextState, "#process in pretend mode" do before :all do MSpec.register_mode :pretend end @@ -776,30 +763,30 @@ describe ContextState, "#process in pretend mode" do it "calls registered :before actions with the current ExampleState instance" do before = double("before") - before.should_receive(:before).and_return { + expect(before).to receive(:before) { ScratchPad.record :before @spec_state = @state.state } MSpec.register :before, before @state.process - ScratchPad.recorded.should == :before - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:before) + expect(@spec_state).to be_kind_of(ExampleState) end it "calls registered :after actions with the current ExampleState instance" do after = double("after") - after.should_receive(:after).and_return { + expect(after).to receive(:after) { ScratchPad.record :after @spec_state = @state.state } MSpec.register :after, after @state.process - ScratchPad.recorded.should == :after - @spec_state.should be_kind_of(ExampleState) + expect(ScratchPad.recorded).to eq(:after) + expect(@spec_state).to be_kind_of(ExampleState) end end -describe ContextState, "#process in pretend mode" do +RSpec.describe ContextState, "#process in pretend mode" do before :all do MSpec.register_mode :pretend end @@ -824,7 +811,7 @@ describe ContextState, "#process in pretend mode" do ScratchPad.record [] @state.describe { ScratchPad << :a } @state.process - ScratchPad.recorded.should == [:a] + expect(ScratchPad.recorded).to eq([:a]) end it "does not call any before(:all) block" do @@ -832,7 +819,7 @@ describe ContextState, "#process in pretend mode" do @state.before(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any after(:all) block" do @@ -840,14 +827,14 @@ describe ContextState, "#process in pretend mode" do @state.after(:all, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any it block" do @state.it("one", &@a) @state.it("two", &@b) @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any before(:each) block" do @@ -855,7 +842,7 @@ describe ContextState, "#process in pretend mode" do @state.before(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call any after(:each) block" do @@ -863,18 +850,18 @@ describe ContextState, "#process in pretend mode" do @state.after(:each, &@b) @state.it("") { } @state.process - ScratchPad.recorded.should == [] + expect(ScratchPad.recorded).to eq([]) end it "does not call Mock.cleanup" do @state.it("") { } @state.it("") { } - Mock.should_not_receive(:cleanup) + expect(Mock).not_to receive(:cleanup) @state.process end end -describe ContextState, "#process in pretend mode" do +RSpec.describe ContextState, "#process in pretend mode" do before :all do MSpec.register_mode :pretend end @@ -899,26 +886,26 @@ describe ContextState, "#process in pretend mode" do it "calls registered :enter actions with the current #describe string" do enter = double("enter") - enter.should_receive(:enter).and_return { ScratchPad.record :enter } + expect(enter).to receive(:enter) { ScratchPad.record :enter } MSpec.register :enter, enter @state.process - ScratchPad.recorded.should == :enter + expect(ScratchPad.recorded).to eq(:enter) end it "calls registered :leave actions" do leave = double("leave") - leave.should_receive(:leave).and_return { ScratchPad.record :leave } + expect(leave).to receive(:leave) { ScratchPad.record :leave } MSpec.register :leave, leave @state.process - ScratchPad.recorded.should == :leave + expect(ScratchPad.recorded).to eq(:leave) end end -describe ContextState, "#it_should_behave_like" do +RSpec.describe ContextState, "#it_should_behave_like" do before :each do @shared_desc = :shared_context @shared = ContextState.new(@shared_desc, :shared => true) - MSpec.stub(:retrieve_shared).and_return(@shared) + allow(MSpec).to receive(:retrieve_shared).and_return(@shared) @state = ContextState.new "Top level" @a = lambda {|*| } @@ -926,8 +913,8 @@ describe ContextState, "#it_should_behave_like" do end it "raises an Exception if unable to find the shared ContextState" do - MSpec.should_receive(:retrieve_shared).and_return(nil) - lambda { @state.it_should_behave_like "this" }.should raise_error(Exception) + expect(MSpec).to receive(:retrieve_shared).and_return(nil) + expect { @state.it_should_behave_like :this }.to raise_error(Exception) end describe "for nested ContextState instances" do @@ -938,24 +925,24 @@ describe ContextState, "#it_should_behave_like" do @shared.children << @nested @nested_dup = @nested.dup - @nested.stub(:dup).and_return(@nested_dup) + allow(@nested).to receive(:dup).and_return(@nested_dup) end it "duplicates the nested ContextState" do @state.it_should_behave_like @shared_desc - @state.children.first.should equal(@nested_dup) + expect(@state.children.first).to equal(@nested_dup) end it "sets the parent of the nested ContextState to the containing ContextState" do @state.it_should_behave_like @shared_desc - @nested_dup.parent.should equal(@state) + expect(@nested_dup.parent).to equal(@state) end it "sets the context for nested examples to the nested ContextState's dup" do @shared.it "an example", &@a @shared.it "another example", &@b @state.it_should_behave_like @shared_desc - @nested_dup.examples.each { |x| x.context.should equal(@nested_dup) } + @nested_dup.examples.each { |x| expect(x.context).to equal(@nested_dup) } end it "omits the shored ContextState's description" do @@ -963,58 +950,58 @@ describe ContextState, "#it_should_behave_like" do @nested.it "another example", &@b @state.it_should_behave_like @shared_desc - @nested_dup.description.should == "Top level nested context" - @nested_dup.examples.first.description.should == "Top level nested context an example" - @nested_dup.examples.last.description.should == "Top level nested context another example" + expect(@nested_dup.description).to eq("Top level nested context") + expect(@nested_dup.examples.first.description).to eq("Top level nested context an example") + expect(@nested_dup.examples.last.description).to eq("Top level nested context another example") end end it "adds duped examples from the shared ContextState" do @shared.it "some method", &@a ex_dup = @shared.examples.first.dup - @shared.examples.first.stub(:dup).and_return(ex_dup) + allow(@shared.examples.first).to receive(:dup).and_return(ex_dup) @state.it_should_behave_like @shared_desc - @state.examples.should == [ex_dup] + expect(@state.examples).to eq([ex_dup]) end it "sets the context for examples to the containing ContextState" do @shared.it "an example", &@a @shared.it "another example", &@b @state.it_should_behave_like @shared_desc - @state.examples.each { |x| x.context.should equal(@state) } + @state.examples.each { |x| expect(x.context).to equal(@state) } end it "adds before(:all) blocks from the shared ContextState" do @shared.before :all, &@a @shared.before :all, &@b @state.it_should_behave_like @shared_desc - @state.before(:all).should include(*@shared.before(:all)) + expect(@state.before(:all)).to include(*@shared.before(:all)) end it "adds before(:each) blocks from the shared ContextState" do @shared.before :each, &@a @shared.before :each, &@b @state.it_should_behave_like @shared_desc - @state.before(:each).should include(*@shared.before(:each)) + expect(@state.before(:each)).to include(*@shared.before(:each)) end it "adds after(:each) blocks from the shared ContextState" do @shared.after :each, &@a @shared.after :each, &@b @state.it_should_behave_like @shared_desc - @state.after(:each).should include(*@shared.after(:each)) + expect(@state.after(:each)).to include(*@shared.after(:each)) end it "adds after(:all) blocks from the shared ContextState" do @shared.after :all, &@a @shared.after :all, &@b @state.it_should_behave_like @shared_desc - @state.after(:all).should include(*@shared.after(:all)) + expect(@state.after(:all)).to include(*@shared.after(:all)) end end -describe ContextState, "#filter_examples" do +RSpec.describe ContextState, "#filter_examples" do before :each do @state = ContextState.new "" @state.it("one") { } @@ -1022,20 +1009,20 @@ describe ContextState, "#filter_examples" do end it "removes examples that are filtered" do - @state.examples.first.stub(:filtered?).and_return(true) - @state.examples.size.should == 2 + allow(@state.examples.first).to receive(:filtered?).and_return(true) + expect(@state.examples.size).to eq(2) @state.filter_examples - @state.examples.size.should == 1 + expect(@state.examples.size).to eq(1) end it "returns true if there are remaining examples to evaluate" do - @state.examples.first.stub(:filtered?).and_return(true) - @state.filter_examples.should be_true + allow(@state.examples.first).to receive(:filtered?).and_return(true) + expect(@state.filter_examples).to be_truthy end it "returns false if there are no remaining examples to evaluate" do - @state.examples.first.stub(:filtered?).and_return(true) - @state.examples.last.stub(:filtered?).and_return(true) - @state.filter_examples.should be_false + allow(@state.examples.first).to receive(:filtered?).and_return(true) + allow(@state.examples.last).to receive(:filtered?).and_return(true) + expect(@state.filter_examples).to be_falsey end end diff --git a/spec/mspec/spec/runner/example_spec.rb b/spec/mspec/spec/runner/example_spec.rb index b4391f802d..8bac166da8 100644 --- a/spec/mspec/spec/runner/example_spec.rb +++ b/spec/mspec/spec/runner/example_spec.rb @@ -4,36 +4,36 @@ require 'mspec/runner/mspec' require 'mspec/mocks/mock' require 'mspec/runner/example' -describe ExampleState do +RSpec.describe ExampleState do it "is initialized with the ContextState, #it string, and #it block" do prc = lambda { } context = ContextState.new "" - ExampleState.new(context, "does", prc).should be_kind_of(ExampleState) + expect(ExampleState.new(context, "does", prc)).to be_kind_of(ExampleState) end end -describe ExampleState, "#describe" do +RSpec.describe ExampleState, "#describe" do before :each do - @context = ContextState.new Object, "#to_s" + @context = ContextState.new "Object#to_s" @state = ExampleState.new @context, "it" end it "returns the ContextState#description" do - @state.describe.should == @context.description + expect(@state.describe).to eq(@context.description) end end -describe ExampleState, "#it" do +RSpec.describe ExampleState, "#it" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" end it "returns the argument to the #it block" do - @state.it.should == "it" + expect(@state.it).to eq("it") end end -describe ExampleState, "#context=" do +RSpec.describe ExampleState, "#context=" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" @context = ContextState.new "New#context" @@ -41,77 +41,77 @@ describe ExampleState, "#context=" do it "sets the containing ContextState" do @state.context = @context - @state.context.should == @context + expect(@state.context).to eq(@context) end it "resets the description" do - @state.description.should == "describe it" + expect(@state.description).to eq("describe it") @state.context = @context - @state.description.should == "New#context it" + expect(@state.description).to eq("New#context it") end end -describe ExampleState, "#example" do +RSpec.describe ExampleState, "#example" do before :each do @proc = lambda { } @state = ExampleState.new ContextState.new("describe"), "it", @proc end it "returns the #it block" do - @state.example.should == @proc + expect(@state.example).to eq(@proc) end end -describe ExampleState, "#filtered?" do +RSpec.describe ExampleState, "#filtered?" do before :each do - MSpec.store :include, nil - MSpec.store :exclude, nil + MSpec.store :include, [] + MSpec.store :exclude, [] @state = ExampleState.new ContextState.new("describe"), "it" @filter = double("filter") end after :each do - MSpec.store :include, nil - MSpec.store :exclude, nil + MSpec.store :include, [] + MSpec.store :exclude, [] end it "returns false if MSpec include filters list is empty" do - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns false if MSpec include filters match this spec" do - @filter.should_receive(:===).and_return(true) + expect(@filter).to receive(:===).and_return(true) MSpec.register :include, @filter - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns true if MSpec include filters do not match this spec" do - @filter.should_receive(:===).and_return(false) + expect(@filter).to receive(:===).and_return(false) MSpec.register :include, @filter - @state.filtered?.should == true + expect(@state.filtered?).to eq(true) end it "returns false if MSpec exclude filters list is empty" do - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns false if MSpec exclude filters do not match this spec" do - @filter.should_receive(:===).and_return(false) + expect(@filter).to receive(:===).and_return(false) MSpec.register :exclude, @filter - @state.filtered?.should == false + expect(@state.filtered?).to eq(false) end it "returns true if MSpec exclude filters match this spec" do - @filter.should_receive(:===).and_return(true) + expect(@filter).to receive(:===).and_return(true) MSpec.register :exclude, @filter - @state.filtered?.should == true + expect(@state.filtered?).to eq(true) end it "returns true if MSpec include and exclude filters match this spec" do - @filter.should_receive(:===).twice.and_return(true) + expect(@filter).to receive(:===).twice.and_return(true) MSpec.register :include, @filter MSpec.register :exclude, @filter - @state.filtered?.should == true + expect(@state.filtered?).to eq(true) end end diff --git a/spec/mspec/spec/runner/exception_spec.rb b/spec/mspec/spec/runner/exception_spec.rb index 309442435c..a77a2c9cf4 100644 --- a/spec/mspec/spec/runner/exception_spec.rb +++ b/spec/mspec/spec/runner/exception_spec.rb @@ -4,16 +4,16 @@ require 'mspec/runner/example' require 'mspec/runner/exception' require 'mspec/utils/script' -describe ExceptionState, "#initialize" do +RSpec.describe ExceptionState, "#initialize" do it "takes a state, location (e.g. before :each), and exception" do context = ContextState.new "Class#method" state = ExampleState.new context, "does something" exc = Exception.new "Fail!" - ExceptionState.new(state, "location", exc).should be_kind_of(ExceptionState) + expect(ExceptionState.new(state, "location", exc)).to be_kind_of(ExceptionState) end end -describe ExceptionState, "#description" do +RSpec.describe ExceptionState, "#description" do before :each do context = ContextState.new "Class#method" @state = ExampleState.new context, "does something" @@ -21,99 +21,99 @@ describe ExceptionState, "#description" do it "returns the state description if state was not nil" do exc = ExceptionState.new(@state, nil, nil) - exc.description.should == "Class#method does something" + expect(exc.description).to eq("Class#method does something") end it "returns the location if it is not nil and description is nil" do exc = ExceptionState.new(nil, "location", nil) - exc.description.should == "An exception occurred during: location" + expect(exc.description).to eq("An exception occurred during: location") end it "returns both description and location if neither are nil" do exc = ExceptionState.new(@state, "location", nil) - exc.description.should == "An exception occurred during: location\nClass#method does something" + expect(exc.description).to eq("An exception occurred during: location\nClass#method does something") end end -describe ExceptionState, "#describe" do +RSpec.describe ExceptionState, "#describe" do before :each do context = ContextState.new "Class#method" @state = ExampleState.new context, "does something" end it "returns the ExampleState#describe string if created with a non-nil state" do - ExceptionState.new(@state, nil, nil).describe.should == @state.describe + expect(ExceptionState.new(@state, nil, nil).describe).to eq(@state.describe) end it "returns an empty string if created with a nil state" do - ExceptionState.new(nil, nil, nil).describe.should == "" + expect(ExceptionState.new(nil, nil, nil).describe).to eq("") end end -describe ExceptionState, "#it" do +RSpec.describe ExceptionState, "#it" do before :each do context = ContextState.new "Class#method" @state = ExampleState.new context, "does something" end it "returns the ExampleState#it string if created with a non-nil state" do - ExceptionState.new(@state, nil, nil).it.should == @state.it + expect(ExceptionState.new(@state, nil, nil).it).to eq(@state.it) end it "returns an empty string if created with a nil state" do - ExceptionState.new(nil, nil, nil).it.should == "" + expect(ExceptionState.new(nil, nil, nil).it).to eq("") end end -describe ExceptionState, "#failure?" do +RSpec.describe ExceptionState, "#failure?" do before :each do @state = ExampleState.new ContextState.new("C#m"), "works" end it "returns true if the exception is an SpecExpectationNotMetError" do exc = ExceptionState.new @state, "", SpecExpectationNotMetError.new("Fail!") - exc.failure?.should be_true + expect(exc.failure?).to be_truthy end it "returns true if the exception is an SpecExpectationNotFoundError" do exc = ExceptionState.new @state, "", SpecExpectationNotFoundError.new("Fail!") - exc.failure?.should be_true + expect(exc.failure?).to be_truthy end it "returns false if the exception is not an SpecExpectationNotMetError or an SpecExpectationNotFoundError" do exc = ExceptionState.new @state, "", Exception.new("Fail!") - exc.failure?.should be_false + expect(exc.failure?).to be_falsey end end -describe ExceptionState, "#message" do +RSpec.describe ExceptionState, "#message" do before :each do @state = ExampleState.new ContextState.new("C#m"), "works" end it "returns <No message> if the exception message is empty" do exc = ExceptionState.new @state, "", Exception.new("") - exc.message.should == "<No message>" + expect(exc.message).to eq("Exception: <No message>") end it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do exc = ExceptionState.new @state, "", SpecExpectationNotMetError.new("Fail!") - exc.message.should == "Fail!" + expect(exc.message).to eq("Fail!") end it "returns SpecExpectationNotFoundError#message when the exception is an SpecExpectationNotFoundError" do e = SpecExpectationNotFoundError.new exc = ExceptionState.new @state, "", e - exc.message.should == e.message + expect(exc.message).to eq(e.message) end it "returns the message with exception class when the exception is not an SpecExpectationNotMetError or an SpecExpectationNotFoundError" do exc = ExceptionState.new @state, "", Exception.new("Fail!") - exc.message.should == "Exception: Fail!" + expect(exc.message).to eq("Exception: Fail!") end end -describe ExceptionState, "#backtrace" do +RSpec.describe ExceptionState, "#backtrace" do before :each do @state = ExampleState.new ContextState.new("C#m"), "works" begin @@ -128,19 +128,19 @@ describe ExceptionState, "#backtrace" do end it "returns a string representation of the exception backtrace" do - @exc.backtrace.should be_kind_of(String) + expect(@exc.backtrace).to be_kind_of(String) end it "does not filter files from the backtrace if $MSPEC_DEBUG is true" do $MSPEC_DEBUG = true - @exc.backtrace.should == @exception.backtrace.join("\n") + expect(@exc.backtrace).to eq(@exception.backtrace.join("\n")) end it "filters files matching config[:backtrace_filter]" do MSpecScript.set :backtrace_filter, %r[mspec/lib] $MSPEC_DEBUG = nil @exc.backtrace.split("\n").each do |line| - line.should_not =~ %r[mspec/lib] + expect(line).not_to match(%r[mspec/lib]) end end end diff --git a/spec/mspec/spec/runner/filters/match_spec.rb b/spec/mspec/spec/runner/filters/match_spec.rb index f2c665c495..970da00446 100644 --- a/spec/mspec/spec/runner/filters/match_spec.rb +++ b/spec/mspec/spec/runner/filters/match_spec.rb @@ -2,33 +2,33 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/mspec' require 'mspec/runner/filters/match' -describe MatchFilter, "#===" do +RSpec.describe MatchFilter, "#===" do before :each do @filter = MatchFilter.new nil, 'a', 'b', 'c' end it "returns true if the argument matches any of the #initialize strings" do - @filter.===('aaa').should == true - @filter.===('bccb').should == true + expect(@filter.===('aaa')).to eq(true) + expect(@filter.===('bccb')).to eq(true) end it "returns false if the argument matches none of the #initialize strings" do - @filter.===('d').should == false + expect(@filter.===('d')).to eq(false) end end -describe MatchFilter, "#register" do +RSpec.describe MatchFilter, "#register" do it "registers itself with MSpec for the designated action list" do filter = MatchFilter.new :include - MSpec.should_receive(:register).with(:include, filter) + expect(MSpec).to receive(:register).with(:include, filter) filter.register end end -describe MatchFilter, "#unregister" do +RSpec.describe MatchFilter, "#unregister" do it "unregisters itself with MSpec for the designated action list" do filter = MatchFilter.new :exclude - MSpec.should_receive(:unregister).with(:exclude, filter) + expect(MSpec).to receive(:unregister).with(:exclude, filter) filter.unregister end end diff --git a/spec/mspec/spec/runner/filters/profile_spec.rb b/spec/mspec/spec/runner/filters/profile_spec.rb index 89d0ad1911..25f5e07aef 100644 --- a/spec/mspec/spec/runner/filters/profile_spec.rb +++ b/spec/mspec/spec/runner/filters/profile_spec.rb @@ -2,45 +2,45 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/mspec' require 'mspec/runner/filters/profile' -describe ProfileFilter, "#find" do +RSpec.describe ProfileFilter, "#find" do before :each do @filter = ProfileFilter.new nil - File.stub(:exist?).and_return(false) + allow(File).to receive(:exist?).and_return(false) @file = "rails.yaml" end it "attempts to locate the file through the expanded path name" do - File.should_receive(:expand_path).with(@file).and_return(@file) - File.should_receive(:exist?).with(@file).and_return(true) - @filter.find(@file).should == @file + expect(File).to receive(:expand_path).with(@file).and_return(@file) + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(@filter.find(@file)).to eq(@file) end it "attempts to locate the file in 'spec/profiles'" do path = File.join "spec/profiles", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end it "attempts to locate the file in 'spec'" do path = File.join "spec", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end it "attempts to locate the file in 'profiles'" do path = File.join "profiles", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end it "attempts to locate the file in '.'" do path = File.join ".", @file - File.should_receive(:exist?).with(path).and_return(true) - @filter.find(@file).should == path + expect(File).to receive(:exist?).with(path).and_return(true) + expect(@filter.find(@file)).to eq(path) end end -describe ProfileFilter, "#parse" do +RSpec.describe ProfileFilter, "#parse" do before :each do @filter = ProfileFilter.new nil @file = File.open(File.dirname(__FILE__) + "/b.yaml", "r") @@ -51,14 +51,14 @@ describe ProfileFilter, "#parse" do end it "creates a Hash of the contents of the YAML file" do - @filter.parse(@file).should == { + expect(@filter.parse(@file)).to eq({ "B." => ["b", "bb"], "B::C#" => ["b!", "b=", "b?", "-", "[]", "[]="] - } + }) end end -describe ProfileFilter, "#load" do +RSpec.describe ProfileFilter, "#load" do before :each do @filter = ProfileFilter.new nil @files = [ @@ -68,50 +68,50 @@ describe ProfileFilter, "#load" do end it "generates a composite hash from multiple YAML files" do - @filter.load(*@files).should == { + expect(@filter.load(*@files)).to eq({ "A#" => ["a", "aa"], "B." => ["b", "bb"], "B::C#" => ["b!", "b=", "b?", "-", "[]", "[]="] - } + }) end end -describe ProfileFilter, "#===" do +RSpec.describe ProfileFilter, "#===" do before :each do @filter = ProfileFilter.new nil - @filter.stub(:load).and_return({ "A#" => ["[]=", "a", "a!", "a?", "aa="]}) + allow(@filter).to receive(:load).and_return({ "A#" => ["[]=", "a", "a!", "a?", "aa="]}) @filter.send :initialize, nil end it "returns true if the spec description is for a method in the profile" do - @filter.===("The A#[]= method").should == true - @filter.===("A#a returns").should == true - @filter.===("A#a! replaces").should == true - @filter.===("A#a? returns").should == true - @filter.===("A#aa= raises").should == true + expect(@filter.===("The A#[]= method")).to eq(true) + expect(@filter.===("A#a returns")).to eq(true) + expect(@filter.===("A#a! replaces")).to eq(true) + expect(@filter.===("A#a? returns")).to eq(true) + expect(@filter.===("A#aa= raises")).to eq(true) end it "returns false if the spec description is for a method not in the profile" do - @filter.===("The A#[] method").should == false - @filter.===("B#a returns").should == false - @filter.===("A.a! replaces").should == false - @filter.===("AA#a? returns").should == false - @filter.===("A#aa raises").should == false + expect(@filter.===("The A#[] method")).to eq(false) + expect(@filter.===("B#a returns")).to eq(false) + expect(@filter.===("A.a! replaces")).to eq(false) + expect(@filter.===("AA#a? returns")).to eq(false) + expect(@filter.===("A#aa raises")).to eq(false) end end -describe ProfileFilter, "#register" do +RSpec.describe ProfileFilter, "#register" do it "registers itself with MSpec for the designated action list" do filter = ProfileFilter.new :include - MSpec.should_receive(:register).with(:include, filter) + expect(MSpec).to receive(:register).with(:include, filter) filter.register end end -describe ProfileFilter, "#unregister" do +RSpec.describe ProfileFilter, "#unregister" do it "unregisters itself with MSpec for the designated action list" do filter = ProfileFilter.new :exclude - MSpec.should_receive(:unregister).with(:exclude, filter) + expect(MSpec).to receive(:unregister).with(:exclude, filter) filter.unregister end end diff --git a/spec/mspec/spec/runner/filters/regexp_spec.rb b/spec/mspec/spec/runner/filters/regexp_spec.rb index 6c05b0f42f..1d1d3554f6 100644 --- a/spec/mspec/spec/runner/filters/regexp_spec.rb +++ b/spec/mspec/spec/runner/filters/regexp_spec.rb @@ -2,12 +2,30 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/mspec' require 'mspec/runner/filters/regexp' -describe RegexpFilter, "#to_regexp" do +RSpec.describe MatchFilter, "#===" do + before :each do + @filter = RegexpFilter.new nil, 'a(b|c)', 'b[^ab]', 'cc?' + end + + it "returns true if the argument matches any of the #initialize strings" do + expect(@filter.===('ab')).to eq(true) + expect(@filter.===('bc suffix')).to eq(true) + expect(@filter.===('prefix cc')).to eq(true) + end + + it "returns false if the argument matches none of the #initialize strings" do + expect(@filter.===('aa')).to eq(false) + expect(@filter.===('ba')).to eq(false) + expect(@filter.===('prefix d suffix')).to eq(false) + end +end + +RSpec.describe RegexpFilter, "#to_regexp" do before :each do @filter = RegexpFilter.new nil end it "converts its arguments to Regexp instances" do - @filter.to_regexp('a(b|c)', 'b[^ab]', 'cc?').should == [/a(b|c)/, /b[^ab]/, /cc?/] + expect(@filter.send(:to_regexp, 'a(b|c)', 'b[^ab]', 'cc?')).to eq([/a(b|c)/, /b[^ab]/, /cc?/]) end end diff --git a/spec/mspec/spec/runner/filters/tag_spec.rb b/spec/mspec/spec/runner/filters/tag_spec.rb index fe1f3df039..356175a754 100644 --- a/spec/mspec/spec/runner/filters/tag_spec.rb +++ b/spec/mspec/spec/runner/filters/tag_spec.rb @@ -3,90 +3,90 @@ require 'mspec/runner/mspec' require 'mspec/runner/filters/match' require 'mspec/runner/filters/tag' -describe TagFilter, "#load" do +RSpec.describe TagFilter, "#load" do before :each do @match = double("match filter").as_null_object @filter = TagFilter.new :include, "tag", "key" @tag = SpecTag.new "tag(comment):description" - MSpec.stub(:read_tags).and_return([@tag]) - MSpec.stub(:register) + allow(MSpec).to receive(:read_tags).and_return([@tag]) + allow(MSpec).to receive(:register) end it "loads tags from the tag file" do - MSpec.should_receive(:read_tags).with(["tag", "key"]).and_return([]) + expect(MSpec).to receive(:read_tags).with(["tag", "key"]).and_return([]) @filter.load end it "registers itself with MSpec for the :include action" do filter = TagFilter.new(:include) - MSpec.should_receive(:register).with(:include, filter) + expect(MSpec).to receive(:register).with(:include, filter) filter.load end it "registers itself with MSpec for the :exclude action" do filter = TagFilter.new(:exclude) - MSpec.should_receive(:register).with(:exclude, filter) + expect(MSpec).to receive(:register).with(:exclude, filter) filter.load end end -describe TagFilter, "#unload" do +RSpec.describe TagFilter, "#unload" do before :each do @filter = TagFilter.new :include, "tag", "key" @tag = SpecTag.new "tag(comment):description" - MSpec.stub(:read_tags).and_return([@tag]) - MSpec.stub(:register) + allow(MSpec).to receive(:read_tags).and_return([@tag]) + allow(MSpec).to receive(:register) end it "unregisters itself" do @filter.load - MSpec.should_receive(:unregister).with(:include, @filter) + expect(MSpec).to receive(:unregister).with(:include, @filter) @filter.unload end end -describe TagFilter, "#register" do +RSpec.describe TagFilter, "#register" do before :each do - MSpec.stub(:register) + allow(MSpec).to receive(:register) end it "registers itself with MSpec for the :load, :unload actions" do filter = TagFilter.new(nil) - MSpec.should_receive(:register).with(:load, filter) - MSpec.should_receive(:register).with(:unload, filter) + expect(MSpec).to receive(:register).with(:load, filter) + expect(MSpec).to receive(:register).with(:unload, filter) filter.register end end -describe TagFilter, "#unregister" do +RSpec.describe TagFilter, "#unregister" do before :each do - MSpec.stub(:unregister) + allow(MSpec).to receive(:unregister) end it "unregisters itself with MSpec for the :load, :unload actions" do filter = TagFilter.new(nil) - MSpec.should_receive(:unregister).with(:load, filter) - MSpec.should_receive(:unregister).with(:unload, filter) + expect(MSpec).to receive(:unregister).with(:load, filter) + expect(MSpec).to receive(:unregister).with(:unload, filter) filter.unregister end end -describe TagFilter, "#===" do +RSpec.describe TagFilter, "#===" do before :each do @filter = TagFilter.new nil, "tag", "key" @tag = SpecTag.new "tag(comment):description" - MSpec.stub(:read_tags).and_return([@tag]) - MSpec.stub(:register) + allow(MSpec).to receive(:read_tags).and_return([@tag]) + allow(MSpec).to receive(:register) @filter.load end it "returns true if the argument matches any of the descriptions" do - @filter.===('description').should == true + expect(@filter.===('description')).to eq(true) end it "returns false if the argument matches none of the descriptions" do - @filter.===('descriptionA').should == false - @filter.===('adescription').should == false + expect(@filter.===('descriptionA')).to eq(false) + expect(@filter.===('adescription')).to eq(false) end end diff --git a/spec/mspec/spec/runner/formatters/describe_spec.rb b/spec/mspec/spec/runner/formatters/describe_spec.rb index 415ced71fb..55f497aca6 100644 --- a/spec/mspec/spec/runner/formatters/describe_spec.rb +++ b/spec/mspec/spec/runner/formatters/describe_spec.rb @@ -2,14 +2,14 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/describe' require 'mspec/runner/example' -describe DescribeFormatter, "#finish" do +RSpec.describe DescribeFormatter, "#finish" do before :each do - MSpec.stub(:register) - MSpec.stub(:unregister) + allow(MSpec).to receive(:register) + allow(MSpec).to receive(:unregister) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) - @timer.stub(:format).and_return("Finished in 2.0 seconds") + allow(TimerAction).to receive(:new).and_return(@timer) + allow(@timer).to receive(:format).and_return("Finished in 2.0 seconds") $stdout = @out = IOStub.new context = ContextState.new "Class#method" @@ -32,36 +32,36 @@ describe DescribeFormatter, "#finish" do it "prints a summary of elapsed time" do @formatter.finish - @out.should =~ /^Finished in 2.0 seconds$/ + expect(@out).to match(/^Finished in 2.0 seconds$/) end it "prints a tally of counts" do @formatter.finish - @out.should =~ /^1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged$/ + expect(@out).to match(/^1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged$/) end it "does not print exceptions" do @formatter.finish - @out.should == %[ + expect(@out).to eq(%[ Finished in 2.0 seconds 1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged -] +]) end it "prints a summary of failures and errors for each describe block" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.finish - @out.should == %[ + expect(@out).to eq(%[ Class#method 0 failures, 1 error Finished in 2.0 seconds 1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged -] +]) end end diff --git a/spec/mspec/spec/runner/formatters/dotted_spec.rb b/spec/mspec/spec/runner/formatters/dotted_spec.rb index 1e9b06f6e1..336b1227ed 100644 --- a/spec/mspec/spec/runner/formatters/dotted_spec.rb +++ b/spec/mspec/spec/runner/formatters/dotted_spec.rb @@ -4,7 +4,7 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/utils/script' -describe DottedFormatter, "#initialize" do +RSpec.describe DottedFormatter, "#initialize" do it "permits zero arguments" do DottedFormatter.new end @@ -14,33 +14,33 @@ describe DottedFormatter, "#initialize" do end end -describe DottedFormatter, "#register" do +RSpec.describe DottedFormatter, "#register" do before :each do @formatter = DottedFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) end it "registers self with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:exception, @formatter) - MSpec.should_receive(:register).with(:before, @formatter) - MSpec.should_receive(:register).with(:after, @formatter) - MSpec.should_receive(:register).with(:finish, @formatter) + expect(MSpec).to receive(:register).with(:exception, @formatter) + expect(MSpec).to receive(:register).with(:before, @formatter) + expect(MSpec).to receive(:register).with(:after, @formatter) + expect(MSpec).to receive(:register).with(:finish, @formatter) @formatter.register end it "creates TimerAction and TallyAction" do timer = double("timer") tally = double("tally") - timer.should_receive(:register) - tally.should_receive(:register) - tally.should_receive(:counter) - TimerAction.should_receive(:new).and_return(timer) - TallyAction.should_receive(:new).and_return(tally) + expect(timer).to receive(:register) + expect(tally).to receive(:register) + expect(tally).to receive(:counter) + expect(TimerAction).to receive(:new).and_return(timer) + expect(TallyAction).to receive(:new).and_return(tally) @formatter.register end end -describe DottedFormatter, "#print" do +RSpec.describe DottedFormatter, "#print" do before :each do $stdout = IOStub.new end @@ -52,25 +52,25 @@ describe DottedFormatter, "#print" do it "writes to $stdout by default" do formatter = DottedFormatter.new formatter.print "begonias" - $stdout.should == "begonias" + expect($stdout).to eq("begonias") end it "writes to the file specified when the formatter was created" do out = IOStub.new - File.should_receive(:open).with("some/file", "w").and_return(out) + expect(File).to receive(:open).with("some/file", "w").and_return(out) formatter = DottedFormatter.new "some/file" formatter.print "begonias" - out.should == "begonias" + expect(out).to eq("begonias") end it "flushes the IO output" do - $stdout.should_receive(:flush) + expect($stdout).to receive(:flush) formatter = DottedFormatter.new formatter.print "begonias" end end -describe DottedFormatter, "#exception" do +RSpec.describe DottedFormatter, "#exception" do before :each do @formatter = DottedFormatter.new @failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed") @@ -79,27 +79,27 @@ describe DottedFormatter, "#exception" do it "sets the #failure? flag" do @formatter.exception @failure - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy @formatter.exception @error - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "sets the #exception? flag" do @formatter.exception @error - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.exception @failure - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end - it "addes the exception to the list of exceptions" do - @formatter.exceptions.should == [] + it "adds the exception to the list of exceptions" do + expect(@formatter.exceptions).to eq([]) @formatter.exception @error @formatter.exception @failure - @formatter.exceptions.should == [@error, @failure] + expect(@formatter.exceptions).to eq([@error, @failure]) end end -describe DottedFormatter, "#exception?" do +RSpec.describe DottedFormatter, "#exception?" do before :each do @formatter = DottedFormatter.new @failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed") @@ -107,29 +107,29 @@ describe DottedFormatter, "#exception?" do end it "returns false if there have been no exceptions" do - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end it "returns true if any exceptions are errors" do @formatter.exception @failure @formatter.exception @error - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end it "returns true if all exceptions are failures" do @formatter.exception @failure @formatter.exception @failure - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end it "returns true if all exceptions are errors" do @formatter.exception @error @formatter.exception @error - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy end end -describe DottedFormatter, "#failure?" do +RSpec.describe DottedFormatter, "#failure?" do before :each do @formatter = DottedFormatter.new @failure = ExceptionState.new nil, nil, SpecExpectationNotMetError.new("failed") @@ -137,23 +137,23 @@ describe DottedFormatter, "#failure?" do end it "returns false if there have been no exceptions" do - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "returns false if any exceptions are errors" do @formatter.exception @failure @formatter.exception @error - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "returns true if all exceptions are failures" do @formatter.exception @failure @formatter.exception @failure - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy end end -describe DottedFormatter, "#before" do +RSpec.describe DottedFormatter, "#before" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" @formatter = DottedFormatter.new @@ -161,19 +161,19 @@ describe DottedFormatter, "#before" do end it "resets the #failure? flag to false" do - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy @formatter.before @state - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "resets the #exception? flag to false" do - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.before @state - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end end -describe DottedFormatter, "#after" do +RSpec.describe DottedFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = DottedFormatter.new @@ -186,21 +186,21 @@ describe DottedFormatter, "#after" do it "prints a '.' if there was no exception raised" do @formatter.after(@state) - @out.should == "." + expect(@out).to eq(".") end it "prints an 'F' if there was an expectation failure" do exc = SpecExpectationNotMetError.new "failed" @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.after(@state) - @out.should == "F" + expect(@out).to eq("F") end it "prints an 'E' if there was an exception other than expectation failure" do exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.after(@state) - @out.should == "E" + expect(@out).to eq("E") end it "prints an 'E' if there are mixed exceptions and exepctation failures" do @@ -209,21 +209,21 @@ describe DottedFormatter, "#after" do exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.after(@state) - @out.should == "E" + expect(@out).to eq("E") end end -describe DottedFormatter, "#finish" do +RSpec.describe DottedFormatter, "#finish" do before :each do @tally = double("tally").as_null_object - TallyAction.stub(:new).and_return(@tally) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) $stdout = @out = IOStub.new context = ContextState.new "Class#method" @state = ExampleState.new(context, "runs") - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter = DottedFormatter.new @formatter.register end @@ -237,40 +237,39 @@ describe DottedFormatter, "#finish" do @formatter.exception exc @formatter.after @state @formatter.finish - @out.should =~ /^1\)\nClass#method runs ERROR$/ + expect(@out).to match(/^1\)\nClass#method runs ERROR$/) end it "prints a backtrace for an exception" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state @formatter.finish - @out.should =~ %r[path/to/some/file.rb:35:in method$] + expect(@out).to match(%r[path/to/some/file.rb:35:in method$]) end it "prints a summary of elapsed time" do - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") @formatter.finish - @out.should =~ /^Finished in 2.0 seconds$/ + expect(@out).to match(/^Finished in 2.0 seconds$/) end it "prints a tally of counts" do - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should =~ /^1 example, 0 failures$/ + expect(@out).to match(/^1 example, 0 failures$/) end it "prints errors, backtraces, elapsed time, and tallies" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") - @tally.should_receive(:format).and_return("1 example, 1 failure") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") + expect(@tally).to receive(:format).and_return("1 example, 1 failure") @formatter.after @state @formatter.finish - @out.should == -%[E + expect(@out).to eq(%[E 1) Class#method runs ERROR @@ -280,6 +279,6 @@ path/to/some/file.rb:35:in method Finished in 2.0 seconds 1 example, 1 failure -] +]) end end diff --git a/spec/mspec/spec/runner/formatters/file_spec.rb b/spec/mspec/spec/runner/formatters/file_spec.rb index 946683ad58..ae11d60845 100644 --- a/spec/mspec/spec/runner/formatters/file_spec.rb +++ b/spec/mspec/spec/runner/formatters/file_spec.rb @@ -3,27 +3,27 @@ require 'mspec/runner/formatters/file' require 'mspec/runner/mspec' require 'mspec/runner/example' -describe FileFormatter, "#register" do +RSpec.describe FileFormatter, "#register" do before :each do @formatter = FileFormatter.new - MSpec.stub(:register) - MSpec.stub(:unregister) + allow(MSpec).to receive(:register) + allow(MSpec).to receive(:unregister) end it "registers self with MSpec for :load, :unload actions" do - MSpec.should_receive(:register).with(:load, @formatter) - MSpec.should_receive(:register).with(:unload, @formatter) + expect(MSpec).to receive(:register).with(:load, @formatter) + expect(MSpec).to receive(:register).with(:unload, @formatter) @formatter.register end it "unregisters self with MSpec for :before, :after actions" do - MSpec.should_receive(:unregister).with(:before, @formatter) - MSpec.should_receive(:unregister).with(:after, @formatter) + expect(MSpec).to receive(:unregister).with(:before, @formatter) + expect(MSpec).to receive(:unregister).with(:after, @formatter) @formatter.register end end -describe FileFormatter, "#load" do +RSpec.describe FileFormatter, "#load" do before :each do @state = ExampleState.new ContextState.new("describe"), "it" @formatter = FileFormatter.new @@ -31,19 +31,19 @@ describe FileFormatter, "#load" do end it "resets the #failure? flag to false" do - @formatter.failure?.should be_true + expect(@formatter.failure?).to be_truthy @formatter.load @state - @formatter.failure?.should be_false + expect(@formatter.failure?).to be_falsey end it "resets the #exception? flag to false" do - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.load @state - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end end -describe FileFormatter, "#unload" do +RSpec.describe FileFormatter, "#unload" do before :each do $stdout = @out = IOStub.new @formatter = FileFormatter.new @@ -56,21 +56,21 @@ describe FileFormatter, "#unload" do it "prints a '.' if there was no exception raised" do @formatter.unload(@state) - @out.should == "." + expect(@out).to eq(".") end it "prints an 'F' if there was an expectation failure" do exc = SpecExpectationNotMetError.new "failed" @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.unload(@state) - @out.should == "F" + expect(@out).to eq("F") end it "prints an 'E' if there was an exception other than expectation failure" do exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.unload(@state) - @out.should == "E" + expect(@out).to eq("E") end it "prints an 'E' if there are mixed exceptions and exepctation failures" do @@ -79,6 +79,6 @@ describe FileFormatter, "#unload" do exc = MSpecExampleError.new("boom!") @formatter.exception ExceptionState.new(@state, nil, exc) @formatter.unload(@state) - @out.should == "E" + expect(@out).to eq("E") end end diff --git a/spec/mspec/spec/runner/formatters/html_spec.rb b/spec/mspec/spec/runner/formatters/html_spec.rb index 3783ab6a89..ed973ad93f 100644 --- a/spec/mspec/spec/runner/formatters/html_spec.rb +++ b/spec/mspec/spec/runner/formatters/html_spec.rb @@ -4,22 +4,23 @@ require 'mspec/runner/formatters/html' require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/utils/script' +require 'mspec/helpers' -describe HtmlFormatter do +RSpec.describe HtmlFormatter do before :each do @formatter = HtmlFormatter.new end it "responds to #register by registering itself with MSpec for appropriate actions" do - MSpec.stub(:register) - MSpec.should_receive(:register).with(:start, @formatter) - MSpec.should_receive(:register).with(:enter, @formatter) - MSpec.should_receive(:register).with(:leave, @formatter) + allow(MSpec).to receive(:register) + expect(MSpec).to receive(:register).with(:start, @formatter) + expect(MSpec).to receive(:register).with(:enter, @formatter) + expect(MSpec).to receive(:register).with(:leave, @formatter) @formatter.register end end -describe HtmlFormatter, "#start" do +RSpec.describe HtmlFormatter, "#start" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -32,9 +33,8 @@ describe HtmlFormatter, "#start" do it "prints the HTML head" do @formatter.start ruby_engine = RUBY_ENGINE - ruby_engine.should =~ /^#{ruby_engine}/ - @out.should == -%[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + expect(ruby_engine).to match(/^#{ruby_engine}/) + expect(@out).to eq(%[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> @@ -55,11 +55,11 @@ ul { </style> </head> <body> -] +]) end end -describe HtmlFormatter, "#enter" do +RSpec.describe HtmlFormatter, "#enter" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -71,11 +71,11 @@ describe HtmlFormatter, "#enter" do it "prints the #describe string" do @formatter.enter "describe" - @out.should == "<div><p>describe</p>\n<ul>\n" + expect(@out).to eq("<div><p>describe</p>\n<ul>\n") end end -describe HtmlFormatter, "#leave" do +RSpec.describe HtmlFormatter, "#leave" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -87,11 +87,11 @@ describe HtmlFormatter, "#leave" do it "prints the closing tags for the #describe string" do @formatter.leave - @out.should == "</ul>\n</div>\n" + expect(@out).to eq("</ul>\n</div>\n") end end -describe HtmlFormatter, "#exception" do +RSpec.describe HtmlFormatter, "#exception" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -108,14 +108,13 @@ describe HtmlFormatter, "#exception" do @formatter.exception exc exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc - @out.should == -%[<li class="fail">- it (<a href="#details-1">FAILED - 1</a>)</li> + expect(@out).to eq(%[<li class="fail">- it (<a href="#details-1">FAILED - 1</a>)</li> <li class="fail">- it (<a href="#details-2">ERROR - 2</a>)</li> -] +]) end end -describe HtmlFormatter, "#after" do +RSpec.describe HtmlFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = HtmlFormatter.new @@ -129,7 +128,7 @@ describe HtmlFormatter, "#after" do it "prints the #it once when there are no exceptions raised" do @formatter.after @state - @out.should == %[<li class="pass">- it</li>\n] + expect(@out).to eq(%[<li class="pass">- it</li>\n]) end it "does not print any output if an exception is raised" do @@ -137,68 +136,73 @@ describe HtmlFormatter, "#after" do @formatter.exception exc out = @out.dup @formatter.after @state - @out.should == out + expect(@out).to eq(out) end end -describe HtmlFormatter, "#finish" do +RSpec.describe HtmlFormatter, "#finish" do before :each do @tally = double("tally").as_null_object - TallyAction.stub(:new).and_return(@tally) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) + + @out = tmp("HtmlFormatter") - $stdout = @out = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - MSpec.stub(:register) - @formatter = HtmlFormatter.new + allow(MSpec).to receive(:register) + @formatter = HtmlFormatter.new(@out) @formatter.register @exception = MSpecExampleError.new("broken") - @exception.stub(:backtrace).and_return(["file.rb:1", "file.rb:2"]) + allow(@exception).to receive(:backtrace).and_return(["file.rb:1", "file.rb:2"]) end after :each do - $stdout = STDOUT + rm_r @out end it "prints a failure message for an exception" do exc = ExceptionState.new @state, nil, @exception @formatter.exception exc @formatter.finish - @out.should include "<p>describe it ERROR</p>" + output = File.read(@out) + expect(output).to include "<p>describe it ERROR</p>" end it "prints a backtrace for an exception" do exc = ExceptionState.new @state, nil, @exception - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.finish - @out.should =~ %r[<pre>.*path/to/some/file.rb:35:in method.*</pre>]m + output = File.read(@out) + expect(output).to match(%r[<pre>.*path/to/some/file.rb:35:in method.*</pre>]m) end it "prints a summary of elapsed time" do - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") @formatter.finish - @out.should include "<p>Finished in 2.0 seconds</p>\n" + output = File.read(@out) + expect(output).to include "<p>Finished in 2.0 seconds</p>\n" end it "prints a tally of counts" do - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should include '<p class="pass">1 example, 0 failures</p>' + output = File.read(@out) + expect(output).to include '<p class="pass">1 example, 0 failures</p>' end it "prints errors, backtraces, elapsed time, and tallies" do exc = ExceptionState.new @state, nil, @exception - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") - @tally.should_receive(:format).and_return("1 example, 1 failures") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") + expect(@tally).to receive(:format).and_return("1 example, 1 failures") @formatter.finish - @out.should == -%[<li class=\"fail\">- it (<a href=\"#details-1\">ERROR - 1</a>)</li> + output = File.read(@out) + expect(output).to eq(%[<li class=\"fail\">- it (<a href=\"#details-1\">ERROR - 1</a>)</li> <hr> <ol id="details"> <li id="details-1"><p>describe it ERROR</p> @@ -211,6 +215,6 @@ path/to/some/file.rb:35:in method</pre> <p class="fail">1 example, 1 failures</p> </body> </html> -] +]) end end diff --git a/spec/mspec/spec/runner/formatters/junit_spec.rb b/spec/mspec/spec/runner/formatters/junit_spec.rb index 66e7d70e92..3b3da73849 100644 --- a/spec/mspec/spec/runner/formatters/junit_spec.rb +++ b/spec/mspec/spec/runner/formatters/junit_spec.rb @@ -2,22 +2,23 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/junit' require 'mspec/runner/example' +require 'mspec/helpers' -describe JUnitFormatter, "#initialize" do +RSpec.describe JUnitFormatter, "#initialize" do it "permits zero arguments" do - lambda { JUnitFormatter.new }.should_not raise_error + expect { JUnitFormatter.new }.not_to raise_error end it "accepts one argument" do - lambda { JUnitFormatter.new nil }.should_not raise_error + expect { JUnitFormatter.new nil }.not_to raise_error end end -describe JUnitFormatter, "#print" do +RSpec.describe JUnitFormatter, "#print" do before :each do $stdout = IOStub.new @out = IOStub.new - File.stub(:open).and_return(@out) + allow(File).to receive(:open).and_return(@out) @formatter = JUnitFormatter.new "some/file" end @@ -27,121 +28,132 @@ describe JUnitFormatter, "#print" do it "writes to $stdout if #switch has not been called" do @formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end it "writes to the file passed to #initialize once #switch has been called" do @formatter.switch @formatter.print "begonias" - $stdout.should == "" - @out.should == "begonias" + expect($stdout).to eq("") + expect(@out).to eq("begonias") end it "writes to $stdout once #switch is called if no file was passed to #initialize" do formatter = JUnitFormatter.new formatter.switch formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end end -describe JUnitFormatter, "#finish" do +RSpec.describe JUnitFormatter, "#finish" do before :each do @tally = double("tally").as_null_object @counter = double("counter").as_null_object - @tally.stub(:counter).and_return(@counter) - TallyAction.stub(:new).and_return(@tally) + allow(@tally).to receive(:counter).and_return(@counter) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) + + @out = tmp("JUnitFormatter") - $stdout = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - @formatter = JUnitFormatter.new - @formatter.stub(:backtrace).and_return("") - MSpec.stub(:register) + @formatter = JUnitFormatter.new(@out) + allow(@formatter).to receive(:backtrace).and_return("") + allow(MSpec).to receive(:register) @formatter.register exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state end after :each do - $stdout = STDOUT + rm_r @out end it "calls #switch" do - @formatter.should_receive(:switch) + expect(@formatter).to receive(:switch).and_call_original @formatter.finish end it "outputs a failure message and backtrace" do @formatter.finish - $stdout.should include 'message="error in describe it" type="error"' - $stdout.should include "MSpecExampleError: broken\n" - $stdout.should include "path/to/some/file.rb:35:in method" + output = File.read(@out) + expect(output).to include 'message="error in describe it" type="error"' + expect(output).to include "MSpecExampleError: broken\n" + expect(output).to include "path/to/some/file.rb:35:in method" end it "encodes message and backtrace in latin1 for jenkins" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken…") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in methød") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in methød") @formatter.exception exc @formatter.finish - $stdout.should =~ /MSpecExampleError: broken((\.\.\.)|\?)\n/ - $stdout.should =~ /path\/to\/some\/file\.rb:35:in meth(\?|o)d/ + output = File.binread(@out) + expect(output).to match(/MSpecExampleError: broken((\.\.\.)|\?)\n/) + expect(output).to match(/path\/to\/some\/file\.rb:35:in meth(\?|o)d/) end it "outputs an elapsed time" do - @timer.should_receive(:elapsed).and_return(4.2) + expect(@timer).to receive(:elapsed).and_return(4.2) @formatter.finish - $stdout.should include 'time="4.2"' + output = File.read(@out) + expect(output).to include 'time="4.2"' end it "outputs overall elapsed time" do - @timer.should_receive(:elapsed).and_return(4.2) + expect(@timer).to receive(:elapsed).and_return(4.2) @formatter.finish - $stdout.should include 'timeCount="4.2"' + output = File.read(@out) + expect(output).to include 'timeCount="4.2"' end it "outputs the number of examples as test count" do - @counter.should_receive(:examples).and_return(9) + expect(@counter).to receive(:examples).and_return(9) @formatter.finish - $stdout.should include 'tests="9"' + output = File.read(@out) + expect(output).to include 'tests="9"' end it "outputs overall number of examples as test count" do - @counter.should_receive(:examples).and_return(9) + expect(@counter).to receive(:examples).and_return(9) @formatter.finish - $stdout.should include 'testCount="9"' + output = File.read(@out) + expect(output).to include 'testCount="9"' end it "outputs a failure count" do - @counter.should_receive(:failures).and_return(2) + expect(@counter).to receive(:failures).and_return(2) @formatter.finish - $stdout.should include 'failureCount="2"' + output = File.read(@out) + expect(output).to include 'failureCount="2"' end it "outputs overall failure count" do - @counter.should_receive(:failures).and_return(2) + expect(@counter).to receive(:failures).and_return(2) @formatter.finish - $stdout.should include 'failures="2"' + output = File.read(@out) + expect(output).to include 'failures="2"' end it "outputs an error count" do - @counter.should_receive(:errors).and_return(1) + expect(@counter).to receive(:errors).and_return(1) @formatter.finish - $stdout.should include 'errors="1"' + output = File.read(@out) + expect(output).to include 'errors="1"' end it "outputs overall error count" do - @counter.should_receive(:errors).and_return(1) + expect(@counter).to receive(:errors).and_return(1) @formatter.finish - $stdout.should include 'errorCount="1"' + output = File.read(@out) + expect(output).to include 'errorCount="1"' end end diff --git a/spec/mspec/spec/runner/formatters/method_spec.rb b/spec/mspec/spec/runner/formatters/method_spec.rb index 77204f74c5..02bf47d538 100644 --- a/spec/mspec/spec/runner/formatters/method_spec.rb +++ b/spec/mspec/spec/runner/formatters/method_spec.rb @@ -4,29 +4,29 @@ require 'mspec/runner/mspec' require 'mspec/runner/example' require 'mspec/utils/script' -describe MethodFormatter, "#method_type" do +RSpec.describe MethodFormatter, "#method_type" do before :each do @formatter = MethodFormatter.new end it "returns 'class' if the separator is '.' or '::'" do - @formatter.method_type('.').should == "class" - @formatter.method_type('::').should == "class" + expect(@formatter.method_type('.')).to eq("class") + expect(@formatter.method_type('::')).to eq("class") end it "returns 'instance' if the separator is '#'" do - @formatter.method_type('#').should == "instance" + expect(@formatter.method_type('#')).to eq("instance") end it "returns 'unknown' for all other cases" do - @formatter.method_type(nil).should == "unknown" + expect(@formatter.method_type(nil)).to eq("unknown") end end -describe MethodFormatter, "#before" do +RSpec.describe MethodFormatter, "#before" do before :each do @formatter = MethodFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter.register end @@ -38,32 +38,32 @@ describe MethodFormatter, "#before" do state = ExampleState.new ContextState.new("describe"), "it" @formatter.before state - @formatter.tally.counter.examples.should == 0 - @formatter.tally.counter.expectations.should == 0 - @formatter.tally.counter.failures.should == 0 - @formatter.tally.counter.errors.should == 0 + expect(@formatter.tally.counter.examples).to eq(0) + expect(@formatter.tally.counter.expectations).to eq(0) + expect(@formatter.tally.counter.failures).to eq(0) + expect(@formatter.tally.counter.errors).to eq(0) end it "records the class, method if available" do state = ExampleState.new ContextState.new("Some#method"), "it" @formatter.before state key = "Some#method" - @formatter.methods.keys.should include(key) + expect(@formatter.methods.keys).to include(key) h = @formatter.methods[key] - h[:class].should == "Some" - h[:method].should == "method" - h[:description].should == "Some#method it" + expect(h[:class]).to eq("Some") + expect(h[:method]).to eq("method") + expect(h[:description]).to eq("Some#method it") end it "does not record class, method unless both are available" do state = ExampleState.new ContextState.new("Some method"), "it" @formatter.before state key = "Some method" - @formatter.methods.keys.should include(key) + expect(@formatter.methods.keys).to include(key) h = @formatter.methods[key] - h[:class].should == "" - h[:method].should == "" - h[:description].should == "Some method it" + expect(h[:class]).to eq("") + expect(h[:method]).to eq("") + expect(h[:description]).to eq("Some method it") end it "sets the method type to unknown if class and method are not available" do @@ -71,7 +71,7 @@ describe MethodFormatter, "#before" do @formatter.before state key = "Some method" h = @formatter.methods[key] - h[:type].should == "unknown" + expect(h[:type]).to eq("unknown") end it "sets the method type based on the class, method separator" do @@ -79,7 +79,7 @@ describe MethodFormatter, "#before" do state = ExampleState.new ContextState.new(k), "it" @formatter.before state h = @formatter.methods[k] - h[:type].should == t + expect(h[:type]).to eq(t) end end @@ -87,14 +87,14 @@ describe MethodFormatter, "#before" do state = ExampleState.new ContextState.new("describe"), "it" @formatter.exceptions << "stuff" @formatter.before state - @formatter.exceptions.should be_empty + expect(@formatter.exceptions).to be_empty end end -describe MethodFormatter, "#after" do +RSpec.describe MethodFormatter, "#after" do before :each do @formatter = MethodFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter.register end @@ -109,10 +109,10 @@ describe MethodFormatter, "#after" do @formatter.after state h = @formatter.methods["Some#method"] - h[:examples].should == 3 - h[:expectations].should == 4 - h[:failures].should == 2 - h[:errors].should == 1 + expect(h[:examples]).to eq(3) + expect(h[:expectations]).to eq(4) + expect(h[:failures]).to eq(2) + expect(h[:errors]).to eq(1) end it "renders the list of exceptions" do @@ -125,20 +125,20 @@ describe MethodFormatter, "#after" do @formatter.after state h = @formatter.methods["Some#method"] - h[:exceptions].should == [ + expect(h[:exceptions]).to eq([ %[failed\n\n], %[failed\n\n] - ] + ]) end end -describe MethodFormatter, "#after" do +RSpec.describe MethodFormatter, "#after" do before :each do $stdout = IOStub.new context = ContextState.new "Class#method" @state = ExampleState.new(context, "runs") @formatter = MethodFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter.register end @@ -159,8 +159,7 @@ describe MethodFormatter, "#after" do @formatter.after @state @formatter.finish - $stdout.should == -%[--- + expect($stdout).to eq(%[--- "Class#method": class: "Class" method: "method" @@ -173,6 +172,6 @@ describe MethodFormatter, "#after" do exceptions: - "failed\\n\\n" - "failed\\n\\n" -] +]) end end diff --git a/spec/mspec/spec/runner/formatters/multi_spec.rb b/spec/mspec/spec/runner/formatters/multi_spec.rb index afcc7e9cea..2d13c05836 100644 --- a/spec/mspec/spec/runner/formatters/multi_spec.rb +++ b/spec/mspec/spec/runner/formatters/multi_spec.rb @@ -1,21 +1,23 @@ require File.dirname(__FILE__) + '/../../spec_helper' +require 'mspec/runner/formatters/dotted' require 'mspec/runner/formatters/multi' require 'mspec/runner/example' +require 'yaml' -describe MultiFormatter, "#aggregate_results" do +RSpec.describe MultiFormatter, "#aggregate_results" do before :each do @stdout, $stdout = $stdout, IOStub.new @file = double("file").as_null_object - File.stub(:delete) - YAML.stub(:load) + allow(File).to receive(:delete) + allow(File).to receive(:read) @hash = { "files"=>1, "examples"=>1, "expectations"=>2, "failures"=>0, "errors"=>0 } - File.stub(:open).and_yield(@file).and_return(@hash) + allow(YAML).to receive(:load).and_return(@hash) - @formatter = MultiFormatter.new - @formatter.timer.stub(:format).and_return("Finished in 42 seconds") + @formatter = DottedFormatter.new.extend(MultiFormatter) + allow(@formatter.timer).to receive(:format).and_return("Finished in 42 seconds") end after :each do @@ -25,13 +27,12 @@ describe MultiFormatter, "#aggregate_results" do it "outputs a summary without errors" do @formatter.aggregate_results(["a", "b"]) @formatter.finish - $stdout.should == -%[ + expect($stdout).to eq(%[ Finished in 42 seconds 2 files, 2 examples, 4 expectations, 0 failures, 0 errors, 0 tagged -] +]) end it "outputs a summary with errors" do @@ -41,8 +42,7 @@ Finished in 42 seconds ] @formatter.aggregate_results(["a"]) @formatter.finish - $stdout.should == -%[ + expect($stdout).to eq(%[ 1) Some#method works real good FAILED @@ -63,6 +63,6 @@ foo.rb:2 Finished in 42 seconds 1 file, 1 example, 2 expectations, 0 failures, 0 errors, 0 tagged -] +]) end end diff --git a/spec/mspec/spec/runner/formatters/specdoc_spec.rb b/spec/mspec/spec/runner/formatters/specdoc_spec.rb index edb439fc11..54b5e2cf0d 100644 --- a/spec/mspec/spec/runner/formatters/specdoc_spec.rb +++ b/spec/mspec/spec/runner/formatters/specdoc_spec.rb @@ -2,19 +2,19 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/specdoc' require 'mspec/runner/example' -describe SpecdocFormatter do +RSpec.describe SpecdocFormatter do before :each do @formatter = SpecdocFormatter.new end it "responds to #register by registering itself with MSpec for appropriate actions" do - MSpec.stub(:register) - MSpec.should_receive(:register).with(:enter, @formatter) + allow(MSpec).to receive(:register) + expect(MSpec).to receive(:register).with(:enter, @formatter) @formatter.register end end -describe SpecdocFormatter, "#enter" do +RSpec.describe SpecdocFormatter, "#enter" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -26,11 +26,11 @@ describe SpecdocFormatter, "#enter" do it "prints the #describe string" do @formatter.enter("describe") - @out.should == "\ndescribe\n" + expect(@out).to eq("\ndescribe\n") end end -describe SpecdocFormatter, "#before" do +RSpec.describe SpecdocFormatter, "#before" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -43,19 +43,19 @@ describe SpecdocFormatter, "#before" do it "prints the #it string" do @formatter.before @state - @out.should == "- it" + expect(@out).to eq("- it") end it "resets the #exception? flag" do exc = ExceptionState.new @state, nil, SpecExpectationNotMetError.new("disappointing") @formatter.exception exc - @formatter.exception?.should be_true + expect(@formatter.exception?).to be_truthy @formatter.before @state - @formatter.exception?.should be_false + expect(@formatter.exception?).to be_falsey end end -describe SpecdocFormatter, "#exception" do +RSpec.describe SpecdocFormatter, "#exception" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -70,13 +70,13 @@ describe SpecdocFormatter, "#exception" do it "prints 'ERROR' if an exception is not an SpecExpectationNotMetError" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc - @out.should == " (ERROR - 1)" + expect(@out).to eq(" (ERROR - 1)") end it "prints 'FAILED' if an exception is an SpecExpectationNotMetError" do exc = ExceptionState.new @state, nil, SpecExpectationNotMetError.new("disappointing") @formatter.exception exc - @out.should == " (FAILED - 1)" + expect(@out).to eq(" (FAILED - 1)") end it "prints the #it string if an exception has already been raised" do @@ -84,11 +84,11 @@ describe SpecdocFormatter, "#exception" do @formatter.exception exc exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc - @out.should == " (FAILED - 1)\n- it (ERROR - 2)" + expect(@out).to eq(" (FAILED - 1)\n- it (ERROR - 2)") end end -describe SpecdocFormatter, "#after" do +RSpec.describe SpecdocFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = SpecdocFormatter.new @@ -101,6 +101,6 @@ describe SpecdocFormatter, "#after" do it "prints a newline character" do @formatter.after @state - @out.should == "\n" + expect(@out).to eq("\n") end end diff --git a/spec/mspec/spec/runner/formatters/spinner_spec.rb b/spec/mspec/spec/runner/formatters/spinner_spec.rb index a122620e39..5c93d38822 100644 --- a/spec/mspec/spec/runner/formatters/spinner_spec.rb +++ b/spec/mspec/spec/runner/formatters/spinner_spec.rb @@ -3,7 +3,7 @@ require 'mspec/runner/formatters/spinner' require 'mspec/runner/mspec' require 'mspec/runner/example' -describe SpinnerFormatter, "#initialize" do +RSpec.describe SpinnerFormatter, "#initialize" do it "permits zero arguments" do SpinnerFormatter.new end @@ -13,33 +13,33 @@ describe SpinnerFormatter, "#initialize" do end end -describe SpinnerFormatter, "#register" do +RSpec.describe SpinnerFormatter, "#register" do before :each do @formatter = SpinnerFormatter.new - MSpec.stub(:register) + allow(MSpec).to receive(:register) end it "registers self with MSpec for appropriate actions" do - MSpec.should_receive(:register).with(:start, @formatter) - MSpec.should_receive(:register).with(:unload, @formatter) - MSpec.should_receive(:register).with(:after, @formatter) - MSpec.should_receive(:register).with(:finish, @formatter) + expect(MSpec).to receive(:register).with(:start, @formatter) + expect(MSpec).to receive(:register).with(:unload, @formatter) + expect(MSpec).to receive(:register).with(:after, @formatter) + expect(MSpec).to receive(:register).with(:finish, @formatter) @formatter.register end it "creates TimerAction and TallyAction" do timer = double("timer") tally = double("tally") - timer.should_receive(:register) - tally.should_receive(:register) - tally.should_receive(:counter) - TimerAction.should_receive(:new).and_return(timer) - TallyAction.should_receive(:new).and_return(tally) + expect(timer).to receive(:register) + expect(tally).to receive(:register) + expect(tally).to receive(:counter) + expect(TimerAction).to receive(:new).and_return(timer) + expect(TallyAction).to receive(:new).and_return(tally) @formatter.register end end -describe SpinnerFormatter, "#print" do +RSpec.describe SpinnerFormatter, "#print" do after :each do $stdout = STDOUT end @@ -48,11 +48,11 @@ describe SpinnerFormatter, "#print" do $stdout = IOStub.new formatter = SpinnerFormatter.new "some/file" formatter.print "begonias" - $stdout.should == "begonias" + expect($stdout).to eq("begonias") end end -describe SpinnerFormatter, "#after" do +RSpec.describe SpinnerFormatter, "#after" do before :each do $stdout = IOStub.new MSpec.store(:files, ["a", "b", "c", "d"]) @@ -78,6 +78,6 @@ describe SpinnerFormatter, "#after" do output = "\r[/ | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset} " \ "\r[- | 0% | 00:00:00] #{green} 0F #{green} 0E#{reset} " \ "\r[\\ | ========== 25% | 00:00:00] #{green} 0F #{green} 0E#{reset} " - $stdout.should == output + expect($stdout).to eq(output) end end diff --git a/spec/mspec/spec/runner/formatters/summary_spec.rb b/spec/mspec/spec/runner/formatters/summary_spec.rb index 16a156b695..c87d940042 100644 --- a/spec/mspec/spec/runner/formatters/summary_spec.rb +++ b/spec/mspec/spec/runner/formatters/summary_spec.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/summary' require 'mspec/runner/example' -describe SummaryFormatter, "#after" do +RSpec.describe SummaryFormatter, "#after" do before :each do $stdout = @out = IOStub.new @formatter = SummaryFormatter.new @@ -21,6 +21,6 @@ describe SummaryFormatter, "#after" do exc = ExceptionState.new @state, nil, MSpecExampleError.new("painful") @formatter.exception exc @formatter.after(@state) - @out.should == "" + expect(@out).to eq("") end end diff --git a/spec/mspec/spec/runner/formatters/unit_spec.rb b/spec/mspec/spec/runner/formatters/unit_spec.rb index 18167a32b8..d349e6871d 100644 --- a/spec/mspec/spec/runner/formatters/unit_spec.rb +++ b/spec/mspec/spec/runner/formatters/unit_spec.rb @@ -3,17 +3,17 @@ require 'mspec/runner/formatters/unit' require 'mspec/runner/example' require 'mspec/utils/script' -describe UnitdiffFormatter, "#finish" do +RSpec.describe UnitdiffFormatter, "#finish" do before :each do @tally = double("tally").as_null_object - TallyAction.stub(:new).and_return(@tally) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) $stdout = @out = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - MSpec.stub(:register) + allow(MSpec).to receive(:register) @formatter = UnitdiffFormatter.new @formatter.register end @@ -27,39 +27,38 @@ describe UnitdiffFormatter, "#finish" do @formatter.exception exc @formatter.after @state @formatter.finish - @out.should =~ /^1\)\ndescribe it ERROR$/ + expect(@out).to match(/^1\)\ndescribe it ERROR$/) end it "prints a backtrace for an exception" do exc = ExceptionState.new @state, nil, Exception.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.finish - @out.should =~ %r[path/to/some/file.rb:35:in method$] + expect(@out).to match(%r[path/to/some/file.rb:35:in method$]) end it "prints a summary of elapsed time" do - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") @formatter.finish - @out.should =~ /^Finished in 2.0 seconds$/ + expect(@out).to match(/^Finished in 2.0 seconds$/) end it "prints a tally of counts" do - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should =~ /^1 example, 0 failures$/ + expect(@out).to match(/^1 example, 0 failures$/) end it "prints errors, backtraces, elapsed time, and tallies" do exc = ExceptionState.new @state, nil, Exception.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state - @timer.should_receive(:format).and_return("Finished in 2.0 seconds") - @tally.should_receive(:format).and_return("1 example, 0 failures") + expect(@timer).to receive(:format).and_return("Finished in 2.0 seconds") + expect(@tally).to receive(:format).and_return("1 example, 0 failures") @formatter.finish - @out.should == -%[E + expect(@out).to eq(%[E Finished in 2.0 seconds @@ -69,6 +68,6 @@ Exception: broken: path/to/some/file.rb:35:in method 1 example, 0 failures -] +]) end end diff --git a/spec/mspec/spec/runner/formatters/yaml_spec.rb b/spec/mspec/spec/runner/formatters/yaml_spec.rb index eb4d99f74c..2e334fdbb9 100644 --- a/spec/mspec/spec/runner/formatters/yaml_spec.rb +++ b/spec/mspec/spec/runner/formatters/yaml_spec.rb @@ -1,8 +1,9 @@ require File.dirname(__FILE__) + '/../../spec_helper' require 'mspec/runner/formatters/yaml' require 'mspec/runner/example' +require 'mspec/helpers' -describe YamlFormatter, "#initialize" do +RSpec.describe YamlFormatter, "#initialize" do it "permits zero arguments" do YamlFormatter.new end @@ -12,11 +13,11 @@ describe YamlFormatter, "#initialize" do end end -describe YamlFormatter, "#print" do +RSpec.describe YamlFormatter, "#print" do before :each do $stdout = IOStub.new @out = IOStub.new - File.stub(:open).and_return(@out) + allow(File).to receive(:open).and_return(@out) @formatter = YamlFormatter.new "some/file" end @@ -26,100 +27,108 @@ describe YamlFormatter, "#print" do it "writes to $stdout if #switch has not been called" do @formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end it "writes to the file passed to #initialize once #switch has been called" do @formatter.switch @formatter.print "begonias" - $stdout.should == "" - @out.should == "begonias" + expect($stdout).to eq("") + expect(@out).to eq("begonias") end it "writes to $stdout once #switch is called if no file was passed to #initialize" do formatter = YamlFormatter.new formatter.switch formatter.print "begonias" - $stdout.should == "begonias" - @out.should == "" + expect($stdout).to eq("begonias") + expect(@out).to eq("") end end -describe YamlFormatter, "#finish" do +RSpec.describe YamlFormatter, "#finish" do before :each do @tally = double("tally").as_null_object @counter = double("counter").as_null_object - @tally.stub(:counter).and_return(@counter) - TallyAction.stub(:new).and_return(@tally) + allow(@tally).to receive(:counter).and_return(@counter) + allow(TallyAction).to receive(:new).and_return(@tally) @timer = double("timer").as_null_object - TimerAction.stub(:new).and_return(@timer) + allow(TimerAction).to receive(:new).and_return(@timer) + + @out = tmp("YamlFormatter") - $stdout = IOStub.new context = ContextState.new "describe" @state = ExampleState.new(context, "it") - @formatter = YamlFormatter.new - @formatter.stub(:backtrace).and_return("") - MSpec.stub(:register) + @formatter = YamlFormatter.new(@out) + allow(@formatter).to receive(:backtrace).and_return("") + allow(MSpec).to receive(:register) @formatter.register exc = ExceptionState.new @state, nil, MSpecExampleError.new("broken") - exc.stub(:backtrace).and_return("path/to/some/file.rb:35:in method") + allow(exc).to receive(:backtrace).and_return("path/to/some/file.rb:35:in method") @formatter.exception exc @formatter.after @state end after :each do - $stdout = STDOUT + rm_r @out end it "calls #switch" do - @formatter.should_receive(:switch) + expect(@formatter).to receive(:switch).and_call_original @formatter.finish end it "outputs a failure message and backtrace" do @formatter.finish - $stdout.should include "describe it ERROR" - $stdout.should include "MSpecExampleError: broken\\n" - $stdout.should include "path/to/some/file.rb:35:in method" + output = File.read(@out) + expect(output).to include "describe it ERROR" + expect(output).to include "MSpecExampleError: broken\\n" + expect(output).to include "path/to/some/file.rb:35:in method" end it "outputs an elapsed time" do - @timer.should_receive(:elapsed).and_return(4.2) + expect(@timer).to receive(:elapsed).and_return(4.2) @formatter.finish - $stdout.should include "time: 4.2" + output = File.read(@out) + expect(output).to include "time: 4.2" end it "outputs a file count" do - @counter.should_receive(:files).and_return(3) + expect(@counter).to receive(:files).and_return(3) @formatter.finish - $stdout.should include "files: 3" + output = File.read(@out) + expect(output).to include "files: 3" end it "outputs an example count" do - @counter.should_receive(:examples).and_return(3) + expect(@counter).to receive(:examples).and_return(3) @formatter.finish - $stdout.should include "examples: 3" + output = File.read(@out) + expect(output).to include "examples: 3" end it "outputs an expectation count" do - @counter.should_receive(:expectations).and_return(9) + expect(@counter).to receive(:expectations).and_return(9) @formatter.finish - $stdout.should include "expectations: 9" + output = File.read(@out) + expect(output).to include "expectations: 9" end it "outputs a failure count" do - @counter.should_receive(:failures).and_return(2) + expect(@counter).to receive(:failures).and_return(2) @formatter.finish - $stdout.should include "failures: 2" + output = File.read(@out) + expect(output).to include "failures: 2" end it "outputs an error count" do - @counter.should_receive(:errors).and_return(1) + expect(@counter).to receive(:errors).and_return(1) @formatter.finish - $stdout.should include "errors: 1" + output = File.read(@out) + expect(output).to include "errors: 1" end end diff --git a/spec/mspec/spec/runner/mspec_spec.rb b/spec/mspec/spec/runner/mspec_spec.rb index 91338c6ddb..4af01806c0 100644 --- a/spec/mspec/spec/runner/mspec_spec.rb +++ b/spec/mspec/spec/runner/mspec_spec.rb @@ -1,97 +1,98 @@ require 'spec_helper' +require 'mspec/expectations/expectations' require 'mspec/helpers/tmp' require 'mspec/helpers/fs' require 'mspec/matchers/base' require 'mspec/runner/mspec' require 'mspec/runner/example' -describe MSpec, ".register_files" do +RSpec.describe MSpec, ".register_files" do it "records which spec files to run" do MSpec.register_files [:one, :two, :three] - MSpec.retrieve(:files).should == [:one, :two, :three] + expect(MSpec.files_array).to eq([:one, :two, :three]) end end -describe MSpec, ".register_mode" do +RSpec.describe MSpec, ".register_mode" do before :each do MSpec.clear_modes end it "sets execution mode flags" do MSpec.register_mode :verify - MSpec.retrieve(:modes).should == [:verify] + expect(MSpec.retrieve(:modes)).to eq([:verify]) end end -describe MSpec, ".register_tags_patterns" do +RSpec.describe MSpec, ".register_tags_patterns" do it "records the patterns for generating a tag file from a spec file" do MSpec.register_tags_patterns [[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]] - MSpec.retrieve(:tags_patterns).should == [[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]] + expect(MSpec.retrieve(:tags_patterns)).to eq([[/spec\/ruby/, "spec/tags"], [/frozen/, "ruby"]]) end end -describe MSpec, ".register_exit" do +RSpec.describe MSpec, ".register_exit" do before :each do MSpec.store :exit, 0 end it "records the exit code" do - MSpec.exit_code.should == 0 + expect(MSpec.exit_code).to eq(0) MSpec.register_exit 1 - MSpec.exit_code.should == 1 + expect(MSpec.exit_code).to eq(1) end end -describe MSpec, ".exit_code" do +RSpec.describe MSpec, ".exit_code" do it "retrieves the code set with .register_exit" do MSpec.register_exit 99 - MSpec.exit_code.should == 99 + expect(MSpec.exit_code).to eq(99) end end -describe MSpec, ".store" do +RSpec.describe MSpec, ".store" do it "records data for MSpec settings" do MSpec.store :anything, :value - MSpec.retrieve(:anything).should == :value + expect(MSpec.retrieve(:anything)).to eq(:value) end end -describe MSpec, ".retrieve" do +RSpec.describe MSpec, ".retrieve" do it "accesses .store'd data" do MSpec.register :retrieve, :first - MSpec.retrieve(:retrieve).should == [:first] + expect(MSpec.retrieve(:retrieve)).to eq([:first]) end end -describe MSpec, ".randomize" do +RSpec.describe MSpec, ".randomize" do it "sets the flag to randomize spec execution order" do - MSpec.randomize?.should == false - MSpec.randomize - MSpec.randomize?.should == true - MSpec.randomize false - MSpec.randomize?.should == false + expect(MSpec.randomize?).to eq(false) + MSpec.randomize = true + expect(MSpec.randomize?).to eq(true) + MSpec.randomize = false + expect(MSpec.randomize?).to eq(false) end end -describe MSpec, ".register" do +RSpec.describe MSpec, ".register" do it "is the gateway behind the register(symbol, action) facility" do MSpec.register :bonus, :first MSpec.register :bonus, :second MSpec.register :bonus, :second - MSpec.retrieve(:bonus).should == [:first, :second] + expect(MSpec.retrieve(:bonus)).to eq([:first, :second]) end end -describe MSpec, ".unregister" do +RSpec.describe MSpec, ".unregister" do it "is the gateway behind the unregister(symbol, actions) facility" do MSpec.register :unregister, :first MSpec.register :unregister, :second MSpec.unregister :unregister, :second - MSpec.retrieve(:unregister).should == [:first] + expect(MSpec.retrieve(:unregister)).to eq([:first]) end end -describe MSpec, ".protect" do +RSpec.describe MSpec, ".protect" do before :each do MSpec.clear_current @cs = ContextState.new "C#m" @@ -102,11 +103,11 @@ describe MSpec, ".protect" do end it "returns true if no exception is raised" do - MSpec.protect("passed") { 1 }.should be_true + expect(MSpec.protect("passed") { 1 }).to be_truthy end it "returns false if an exception is raised" do - MSpec.protect("testing") { raise ScratchPad.recorded }.should be_false + expect(MSpec.protect("testing") { raise ScratchPad.recorded }).to be_falsey end it "rescues any exceptions raised when evaluating the block argument" do @@ -119,244 +120,245 @@ describe MSpec, ".protect" do rescue SystemExit ScratchPad.record :system_exit end - ScratchPad.recorded.should == :system_exit + expect(ScratchPad.recorded).to eq(:system_exit) end it "calls all the exception actions" do exc = ExceptionState.new @es, "testing", ScratchPad.recorded - ExceptionState.stub(:new).and_return(exc) + allow(ExceptionState).to receive(:new).and_return(exc) action = double("exception") - action.should_receive(:exception).with(exc) + expect(action).to receive(:exception).with(exc) MSpec.register :exception, action MSpec.protect("testing") { raise ScratchPad.recorded } MSpec.unregister :exception, action end it "registers a non-zero exit code when an exception is raised" do - MSpec.should_receive(:register_exit).with(1) + expect(MSpec).to receive(:register_exit).with(1) MSpec.protect("testing") { raise ScratchPad.recorded } end end -describe MSpec, ".register_current" do +RSpec.describe MSpec, ".register_current" do before :each do MSpec.clear_current end it "sets the value returned by MSpec.current" do - MSpec.current.should be_nil + expect(MSpec.current).to be_nil MSpec.register_current :a - MSpec.current.should == :a + expect(MSpec.current).to eq(:a) end end -describe MSpec, ".clear_current" do +RSpec.describe MSpec, ".clear_current" do it "sets the value returned by MSpec.current to nil" do MSpec.register_current :a - MSpec.current.should_not be_nil + expect(MSpec.current).not_to be_nil MSpec.clear_current - MSpec.current.should be_nil + expect(MSpec.current).to be_nil end end -describe MSpec, ".current" do +RSpec.describe MSpec, ".current" do before :each do MSpec.clear_current end it "returns nil if no ContextState has been registered" do - MSpec.current.should be_nil + expect(MSpec.current).to be_nil end it "returns the most recently registered ContextState" do first = ContextState.new "" second = ContextState.new "" MSpec.register_current first - MSpec.current.should == first + expect(MSpec.current).to eq(first) MSpec.register_current second - MSpec.current.should == second + expect(MSpec.current).to eq(second) end end -describe MSpec, ".actions" do +RSpec.describe MSpec, ".actions" do before :each do MSpec.store :start, [] ScratchPad.record [] start_one = double("one") - start_one.stub(:start).and_return { ScratchPad << :one } + allow(start_one).to receive(:start) { ScratchPad << :one } start_two = double("two") - start_two.stub(:start).and_return { ScratchPad << :two } + allow(start_two).to receive(:start) { ScratchPad << :two } MSpec.register :start, start_one MSpec.register :start, start_two end it "does not attempt to run any actions if none have been registered" do MSpec.store :finish, nil - lambda { MSpec.actions :finish }.should_not raise_error + expect { MSpec.actions :finish }.not_to raise_error end it "runs each action registered as a start action" do MSpec.actions :start - ScratchPad.recorded.should == [:one, :two] + expect(ScratchPad.recorded).to eq([:one, :two]) end end -describe MSpec, ".mode?" do +RSpec.describe MSpec, ".mode?" do before :each do MSpec.clear_modes end it "returns true if the mode has been set" do - MSpec.mode?(:verify).should == false + expect(MSpec.mode?(:verify)).to eq(false) MSpec.register_mode :verify - MSpec.mode?(:verify).should == true + expect(MSpec.mode?(:verify)).to eq(true) end end -describe MSpec, ".clear_modes" do +RSpec.describe MSpec, ".clear_modes" do it "clears all registered modes" do MSpec.register_mode(:pretend) MSpec.register_mode(:verify) - MSpec.mode?(:pretend).should == true - MSpec.mode?(:verify).should == true + expect(MSpec.mode?(:pretend)).to eq(true) + expect(MSpec.mode?(:verify)).to eq(true) MSpec.clear_modes - MSpec.mode?(:pretend).should == false - MSpec.mode?(:verify).should == false + expect(MSpec.mode?(:pretend)).to eq(false) + expect(MSpec.mode?(:verify)).to eq(false) end end -describe MSpec, ".guarded?" do +RSpec.describe MSpec, ".guarded?" do before :each do MSpec.instance_variable_set :@guarded, [] end it "returns false if no guard has run" do - MSpec.guarded?.should == false + expect(MSpec.guarded?).to eq(false) end it "returns true if a single guard has run" do MSpec.guard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) end it "returns true if more than one guard has run" do MSpec.guard MSpec.guard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) end it "returns true until all guards have finished" do MSpec.guard MSpec.guard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) MSpec.unguard - MSpec.guarded?.should == true + expect(MSpec.guarded?).to eq(true) MSpec.unguard - MSpec.guarded?.should == false + expect(MSpec.guarded?).to eq(false) end end -describe MSpec, ".describe" do +RSpec.describe MSpec, ".describe" do before :each do MSpec.clear_current @cs = ContextState.new "" - ContextState.stub(:new).and_return(@cs) - MSpec.stub(:current).and_return(nil) - MSpec.stub(:register_current) + allow(ContextState).to receive(:new).and_return(@cs) + allow(MSpec).to receive(:current).and_return(nil) + allow(MSpec).to receive(:register_current) end it "creates a new ContextState for the block" do - ContextState.should_receive(:new).and_return(@cs) + expect(ContextState).to receive(:new).and_return(@cs) MSpec.describe(Object) { } end it "accepts an optional second argument" do - ContextState.should_receive(:new).and_return(@cs) + expect(ContextState).to receive(:new).and_return(@cs) MSpec.describe(Object, "msg") { } end it "registers the newly created ContextState" do - MSpec.should_receive(:register_current).with(@cs).twice + expect(MSpec).to receive(:register_current).with(@cs).twice MSpec.describe(Object) { } end it "invokes the ContextState#describe method" do - prc = lambda { } - @cs.should_receive(:describe).with(&prc) - MSpec.describe(Object, "msg", &prc) + expect(@cs).to receive(:describe) + MSpec.describe(Object, "msg") {} end end -describe MSpec, ".process" do +RSpec.describe MSpec, ".process" do before :each do - MSpec.stub(:files) + allow(MSpec).to receive(:files) MSpec.store :start, [] MSpec.store :finish, [] - STDOUT.stub(:puts) + allow(STDOUT).to receive(:puts) end it "prints the RUBY_DESCRIPTION" do - STDOUT.should_receive(:puts).with(RUBY_DESCRIPTION) + expect(STDOUT).to receive(:puts).with(RUBY_DESCRIPTION) MSpec.process end it "calls all start actions" do start = double("start") - start.stub(:start).and_return { ScratchPad.record :start } + allow(start).to receive(:start) { ScratchPad.record :start } MSpec.register :start, start MSpec.process - ScratchPad.recorded.should == :start + expect(ScratchPad.recorded).to eq(:start) end it "calls all finish actions" do finish = double("finish") - finish.stub(:finish).and_return { ScratchPad.record :finish } + allow(finish).to receive(:finish) { ScratchPad.record :finish } MSpec.register :finish, finish MSpec.process - ScratchPad.recorded.should == :finish + expect(ScratchPad.recorded).to eq(:finish) end it "calls the files method" do - MSpec.should_receive(:files) + expect(MSpec).to receive(:files) MSpec.process end end -describe MSpec, ".files" do +RSpec.describe MSpec, ".files" do before :each do MSpec.store :load, [] MSpec.store :unload, [] MSpec.register_files [:one, :two, :three] - Kernel.stub(:load) + allow(Kernel).to receive(:load) end it "calls load actions before each file" do load = double("load") - load.stub(:load).and_return { ScratchPad.record :load } + allow(load).to receive(:load) { ScratchPad.record :load } MSpec.register :load, load MSpec.files - ScratchPad.recorded.should == :load + expect(ScratchPad.recorded).to eq(:load) end it "shuffles the file list if .randomize? is true" do - MSpec.randomize - MSpec.should_receive(:shuffle) + MSpec.randomize = true + expect(MSpec).to receive(:shuffle) MSpec.files - MSpec.randomize false + MSpec.randomize = false end it "registers the current file" do - MSpec.should_receive(:store).with(:file, :one) - MSpec.should_receive(:store).with(:file, :two) - MSpec.should_receive(:store).with(:file, :three) + load = double("load") + files = [] + allow(load).to receive(:load) { files << MSpec.file } + MSpec.register :load, load MSpec.files + expect(files).to eq([:one, :two, :three]) end end -describe MSpec, ".shuffle" do +RSpec.describe MSpec, ".shuffle" do before :each do @base = (0..100).to_a @list = @base.clone @@ -365,30 +367,30 @@ describe MSpec, ".shuffle" do it "does not alter the elements in the list" do @base.each do |elt| - @list.should include(elt) + expect(@list).to include(elt) end end it "changes the order of the list" do # obviously, this spec has a certain probability # of failing. If it fails, run it again. - @list.should_not == @base + expect(@list).not_to eq(@base) end end -describe MSpec, ".tags_file" do +RSpec.describe MSpec, ".tags_file" do before :each do MSpec.store :file, "path/to/spec/something/some_spec.rb" MSpec.store :tags_patterns, nil end it "returns the default tags file for the current spec file" do - MSpec.tags_file.should == "path/to/spec/tags/something/some_tags.txt" + expect(MSpec.tags_file).to eq("path/to/spec/tags/something/some_tags.txt") end it "returns the tags file for the current spec file with custom tags_patterns" do MSpec.register_tags_patterns [[/^(.*)\/spec/, '\1/tags'], [/_spec.rb/, "_tags.txt"]] - MSpec.tags_file.should == "path/to/tags/something/some_tags.txt" + expect(MSpec.tags_file).to eq("path/to/tags/something/some_tags.txt") end it "performs multiple substitutions" do @@ -397,31 +399,31 @@ describe MSpec, ".tags_file" do [%r(/spec/), "/spec/tags/"], [/_spec.rb/, "_tags.txt"] ] - MSpec.tags_file.should == "path/to/spec/tags/other/some_tags.txt" + expect(MSpec.tags_file).to eq("path/to/spec/tags/other/some_tags.txt") end it "handles cases where no substitution is performed" do MSpec.register_tags_patterns [[/nothing/, "something"]] - MSpec.tags_file.should == "path/to/spec/something/some_spec.rb" + expect(MSpec.tags_file).to eq("path/to/spec/something/some_spec.rb") end end -describe MSpec, ".read_tags" do +RSpec.describe MSpec, ".read_tags" do before :each do - MSpec.stub(:tags_file).and_return(File.dirname(__FILE__) + '/tags.txt') + allow(MSpec).to receive(:tags_file).and_return(File.dirname(__FILE__) + '/tags.txt') end it "returns a list of tag instances for matching tag names found" do one = SpecTag.new "fail(broken):Some#method? works" - MSpec.read_tags(["fail", "pass"]).should == [one] + expect(MSpec.read_tags(["fail", "pass"])).to eq([one]) end it "returns [] if no tags names match" do - MSpec.read_tags("super").should == [] + expect(MSpec.read_tags("super")).to eq([]) end end -describe MSpec, ".read_tags" do +RSpec.describe MSpec, ".read_tags" do before :each do @tag = SpecTag.new "fails:Some#method" File.open(tmp("tags.txt", false), "w") do |f| @@ -429,18 +431,18 @@ describe MSpec, ".read_tags" do f.puts @tag f.puts "" end - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) end it "does not return a tag object for empty lines" do - MSpec.read_tags(["fails"]).should == [@tag] + expect(MSpec.read_tags(["fails"])).to eq([@tag]) end end -describe MSpec, ".write_tags" do +RSpec.describe MSpec, ".write_tags" do before :each do FileUtils.cp File.dirname(__FILE__) + "/tags.txt", tmp("tags.txt", false) - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) @tag1 = SpecTag.new "check(broken):Tag#rewrite works" @tag2 = SpecTag.new "broken:Tag#write_tags fails" end @@ -450,22 +452,22 @@ describe MSpec, ".write_tags" do end it "overwrites the tags in the tag file" do - IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works + expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today extended():\"Multi-line\\ntext\\ntag\" -] +]) MSpec.write_tags [@tag1, @tag2] - IO.read(tmp("tags.txt", false)).should == %[check(broken):Tag#rewrite works + expect(IO.read(tmp("tags.txt", false))).to eq(%[check(broken):Tag#rewrite works broken:Tag#write_tags fails -] +]) end end -describe MSpec, ".write_tag" do +RSpec.describe MSpec, ".write_tag" do before :each do - FileUtils.stub(:mkdir_p) - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(FileUtils).to receive(:mkdir_p) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) @tag = SpecTag.new "fail(broken):Some#method works" end @@ -475,20 +477,20 @@ describe MSpec, ".write_tag" do it "writes a tag to the tags file for the current spec file" do MSpec.write_tag @tag - IO.read(tmp("tags.txt", false)).should == "fail(broken):Some#method works\n" + expect(IO.read(tmp("tags.txt", false))).to eq("fail(broken):Some#method works\n") end it "does not write a duplicate tag" do File.open(tmp("tags.txt", false), "w") { |f| f.puts @tag } MSpec.write_tag @tag - IO.read(tmp("tags.txt", false)).should == "fail(broken):Some#method works\n" + expect(IO.read(tmp("tags.txt", false))).to eq("fail(broken):Some#method works\n") end end -describe MSpec, ".delete_tag" do +RSpec.describe MSpec, ".delete_tag" do before :each do FileUtils.cp File.dirname(__FILE__) + "/tags.txt", tmp("tags.txt", false) - MSpec.stub(:tags_file).and_return(tmp("tags.txt", false)) + allow(MSpec).to receive(:tags_file).and_return(tmp("tags.txt", false)) @tag = SpecTag.new "fail(Comments don't matter):Some#method? works" end @@ -497,84 +499,84 @@ describe MSpec, ".delete_tag" do end it "deletes the tag if it exists" do - MSpec.delete_tag(@tag).should == true - IO.read(tmp("tags.txt", false)).should == %[incomplete(20%):The#best method ever + expect(MSpec.delete_tag(@tag)).to eq(true) + expect(IO.read(tmp("tags.txt", false))).to eq(%[incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today extended():\"Multi-line\\ntext\\ntag\" -] +]) end it "deletes a tag with escaped newlines" do - MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true - IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works + expect(MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"'))).to eq(true) + expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today -] +]) end it "does not change the tags file contents if the tag doesn't exist" do @tag.tag = "failed" - MSpec.delete_tag(@tag).should == false - IO.read(tmp("tags.txt", false)).should == %[fail(broken):Some#method? works + expect(MSpec.delete_tag(@tag)).to eq(false) + expect(IO.read(tmp("tags.txt", false))).to eq(%[fail(broken):Some#method? works incomplete(20%):The#best method ever benchmark(0.01825):The#fastest method today extended():\"Multi-line\\ntext\\ntag\" -] +]) end it "deletes the tag file if it is empty" do - MSpec.delete_tag(@tag).should == true - MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever")).should == true - MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today")).should == true - MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"')).should == true - File.exist?(tmp("tags.txt", false)).should == false + expect(MSpec.delete_tag(@tag)).to eq(true) + expect(MSpec.delete_tag(SpecTag.new("incomplete:The#best method ever"))).to eq(true) + expect(MSpec.delete_tag(SpecTag.new("benchmark:The#fastest method today"))).to eq(true) + expect(MSpec.delete_tag(SpecTag.new('extended:"Multi-line\ntext\ntag"'))).to eq(true) + expect(File.exist?(tmp("tags.txt", false))).to eq(false) end end -describe MSpec, ".delete_tags" do +RSpec.describe MSpec, ".delete_tags" do before :each do @tags = tmp("tags.txt", false) FileUtils.cp File.dirname(__FILE__) + "/tags.txt", @tags - MSpec.stub(:tags_file).and_return(@tags) + allow(MSpec).to receive(:tags_file).and_return(@tags) end it "deletes the tag file" do MSpec.delete_tags - File.exist?(@tags).should be_false + expect(File.exist?(@tags)).to be_falsey end end -describe MSpec, ".expectation" do +RSpec.describe MSpec, ".expectation" do it "sets the flag that an expectation has been reported" do MSpec.clear_expectations - MSpec.expectation?.should be_false + expect(MSpec.expectation?).to be_falsey MSpec.expectation - MSpec.expectation?.should be_true + expect(MSpec.expectation?).to be_truthy end end -describe MSpec, ".expectation?" do +RSpec.describe MSpec, ".expectation?" do it "returns true if an expectation has been reported" do MSpec.expectation - MSpec.expectation?.should be_true + expect(MSpec.expectation?).to be_truthy end it "returns false if an expectation has not been reported" do MSpec.clear_expectations - MSpec.expectation?.should be_false + expect(MSpec.expectation?).to be_falsey end end -describe MSpec, ".clear_expectations" do +RSpec.describe MSpec, ".clear_expectations" do it "clears the flag that an expectation has been reported" do MSpec.expectation - MSpec.expectation?.should be_true + expect(MSpec.expectation?).to be_truthy MSpec.clear_expectations - MSpec.expectation?.should be_false + expect(MSpec.expectation?).to be_falsey end end -describe MSpec, ".register_shared" do +RSpec.describe MSpec, ".register_shared" do it "stores a shared ContextState by description" do parent = ContextState.new "container" state = ContextState.new "shared" @@ -582,14 +584,14 @@ describe MSpec, ".register_shared" do prc = lambda { } state.describe(&prc) MSpec.register_shared(state) - MSpec.retrieve(:shared)["shared"].should == state + expect(MSpec.retrieve(:shared)["shared"]).to eq(state) end end -describe MSpec, ".retrieve_shared" do +RSpec.describe MSpec, ".retrieve_shared" do it "retrieves the shared ContextState matching description" do state = ContextState.new "" MSpec.retrieve(:shared)["shared"] = state - MSpec.retrieve_shared(:shared).should == state + expect(MSpec.retrieve_shared(:shared)).to eq(state) end end diff --git a/spec/mspec/spec/runner/shared_spec.rb b/spec/mspec/spec/runner/shared_spec.rb index b91800b7db..153b8f0698 100644 --- a/spec/mspec/spec/runner/shared_spec.rb +++ b/spec/mspec/spec/runner/shared_spec.rb @@ -3,7 +3,7 @@ require 'mspec/runner/shared' require 'mspec/runner/context' require 'mspec/runner/example' -describe Object, "#it_behaves_like" do +RSpec.describe Object, "#it_behaves_like" do before :each do ScratchPad.clear @@ -14,14 +14,14 @@ describe Object, "#it_behaves_like" do @state.singleton_class.send(:public, :it_behaves_like) @shared = ContextState.new :shared_spec, :shared => true - MSpec.stub(:retrieve_shared).and_return(@shared) + allow(MSpec).to receive(:retrieve_shared).and_return(@shared) end it "creates @method set to the name of the aliased method" do @shared.it("an example") { ScratchPad.record @method } @state.it_behaves_like :shared_spec, :some_method @state.process - ScratchPad.recorded.should == :some_method + expect(ScratchPad.recorded).to eq(:some_method) end it "creates @object if the passed object" do @@ -29,7 +29,7 @@ describe Object, "#it_behaves_like" do @shared.it("an example") { ScratchPad.record @object } @state.it_behaves_like :shared_spec, :some_method, object @state.process - ScratchPad.recorded.should == object + expect(ScratchPad.recorded).to eq(object) end it "creates @object if the passed false" do @@ -37,11 +37,11 @@ describe Object, "#it_behaves_like" do @shared.it("an example") { ScratchPad.record @object } @state.it_behaves_like :shared_spec, :some_method, object @state.process - ScratchPad.recorded.should == object + expect(ScratchPad.recorded).to eq(object) end it "sends :it_should_behave_like" do - @state.should_receive(:it_should_behave_like) + expect(@state).to receive(:it_should_behave_like) @state.it_behaves_like :shared_spec, :some_method end @@ -61,12 +61,12 @@ describe Object, "#it_behaves_like" do @state.it_behaves_like :shared_spec, :some_method, @obj @state.process - ScratchPad.recorded.should == [:some_method, @obj] + expect(ScratchPad.recorded).to eq([:some_method, @obj]) @state2.it_behaves_like :shared_spec, :another_method, @obj2 @state2.process - ScratchPad.recorded.should == [:another_method, @obj2] + expect(ScratchPad.recorded).to eq([:another_method, @obj2]) end it "ensures the shared spec state is distinct for nested shared specs" do @@ -79,12 +79,12 @@ describe Object, "#it_behaves_like" do @state.it_behaves_like :shared_spec, :some_method, @obj @state.process - ScratchPad.recorded.should == [:shared, :some_method, @obj] + expect(ScratchPad.recorded).to eq([:shared, :some_method, @obj]) @state2.it_behaves_like :shared_spec, :another_method, @obj2 @state2.process - ScratchPad.recorded.should == [:shared, :another_method, @obj2] + expect(ScratchPad.recorded).to eq([:shared, :another_method, @obj2]) end end end diff --git a/spec/mspec/spec/runner/tag_spec.rb b/spec/mspec/spec/runner/tag_spec.rb index db55a1b186..bda9ac4280 100644 --- a/spec/mspec/spec/runner/tag_spec.rb +++ b/spec/mspec/spec/runner/tag_spec.rb @@ -1,123 +1,123 @@ require 'spec_helper' require 'mspec/runner/tag' -describe SpecTag do +RSpec.describe SpecTag do it "accepts an optional string to parse into fields" do tag = SpecTag.new "tag(comment):description" - tag.tag.should == "tag" - tag.comment.should == "comment" - tag.description.should == "description" + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq("comment") + expect(tag.description).to eq("description") end end -describe SpecTag, "#parse" do +RSpec.describe SpecTag, "#parse" do before :each do @tag = SpecTag.new end it "accepts 'tag(comment):description'" do @tag.parse "tag(I'm real):Some#method returns a value" - @tag.tag.should == "tag" - @tag.comment.should == "I'm real" - @tag.description.should == "Some#method returns a value" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("I'm real") + expect(@tag.description).to eq("Some#method returns a value") end it "accepts 'tag:description'" do @tag.parse "tag:Another#method" - @tag.tag.should == "tag" - @tag.comment.should == nil - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq("Another#method") end it "accepts 'tag():description'" do @tag.parse "tag():Another#method" - @tag.tag.should == "tag" - @tag.comment.should == nil - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq("Another#method") end it "accepts 'tag:'" do @tag.parse "tag:" - @tag.tag.should == "tag" - @tag.comment.should == nil - @tag.description.should == "" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq("") end it "accepts 'tag(bug:555):Another#method'" do @tag.parse "tag(bug:555):Another#method" - @tag.tag.should == "tag" - @tag.comment.should == "bug:555" - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("bug:555") + expect(@tag.description).to eq("Another#method") end it "accepts 'tag(http://someplace.com/neato):Another#method'" do @tag.parse "tag(http://someplace.com/neato):Another#method" - @tag.tag.should == "tag" - @tag.comment.should == "http://someplace.com/neato" - @tag.description.should == "Another#method" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("http://someplace.com/neato") + expect(@tag.description).to eq("Another#method") end it "accepts 'tag(comment):\"Multi-line\\ntext\"'" do @tag.parse 'tag(comment):"Multi-line\ntext"' - @tag.tag.should == "tag" - @tag.comment.should == "comment" - @tag.description.should == "Multi-line\ntext" + expect(@tag.tag).to eq("tag") + expect(@tag.comment).to eq("comment") + expect(@tag.description).to eq("Multi-line\ntext") end it "ignores '#anything'" do @tag.parse "# this could be a comment" - @tag.tag.should == nil - @tag.comment.should == nil - @tag.description.should == nil + expect(@tag.tag).to eq(nil) + expect(@tag.comment).to eq(nil) + expect(@tag.description).to eq(nil) end end -describe SpecTag, "#to_s" do +RSpec.describe SpecTag, "#to_s" do it "formats itself as 'tag(comment):description'" do txt = "tag(comment):description" tag = SpecTag.new txt - tag.tag.should == "tag" - tag.comment.should == "comment" - tag.description.should == "description" - tag.to_s.should == txt + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq("comment") + expect(tag.description).to eq("description") + expect(tag.to_s).to eq(txt) end it "formats itself as 'tag:description" do txt = "tag:description" tag = SpecTag.new txt - tag.tag.should == "tag" - tag.comment.should == nil - tag.description.should == "description" - tag.to_s.should == txt + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq(nil) + expect(tag.description).to eq("description") + expect(tag.to_s).to eq(txt) end it "formats itself as 'tag(comment):\"multi-line\\ntext\\ntag\"'" do txt = 'tag(comment):"multi-line\ntext\ntag"' tag = SpecTag.new txt - tag.tag.should == "tag" - tag.comment.should == "comment" - tag.description.should == "multi-line\ntext\ntag" - tag.to_s.should == txt + expect(tag.tag).to eq("tag") + expect(tag.comment).to eq("comment") + expect(tag.description).to eq("multi-line\ntext\ntag") + expect(tag.to_s).to eq(txt) end end -describe SpecTag, "#==" do +RSpec.describe SpecTag, "#==" do it "returns true if the tags have the same fields" do one = SpecTag.new "tag(this):unicorn" two = SpecTag.new "tag(this):unicorn" - one.==(two).should == true - [one].==([two]).should == true + expect(one.==(two)).to eq(true) + expect([one].==([two])).to eq(true) end end -describe SpecTag, "#unescape" do +RSpec.describe SpecTag, "#unescape" do it "replaces \\n by LF when the description is quoted" do tag = SpecTag.new 'tag:"desc with\nnew line"' - tag.description.should == "desc with\nnew line" + expect(tag.description).to eq("desc with\nnew line") end it "does not replaces \\n by LF when the description is not quoted " do tag = SpecTag.new 'tag:desc with\nnew line' - tag.description.should == "desc with\\nnew line" + expect(tag.description).to eq("desc with\\nnew line") end end diff --git a/spec/mspec/spec/spec_helper.rb b/spec/mspec/spec/spec_helper.rb index 0d497f6627..5cabfe5626 100644 --- a/spec/mspec/spec/spec_helper.rb +++ b/spec/mspec/spec/spec_helper.rb @@ -1,6 +1,9 @@ -require 'pp' -require 'mspec/helpers/io' -require 'mspec/helpers/scratch' +RSpec.configure do |config| + config.disable_monkey_patching! + config.raise_errors_for_deprecations! +end + +require 'mspec' # Remove this when MRI has intelligent warnings $VERBOSE = nil unless $VERBOSE @@ -37,7 +40,7 @@ class MSpecExampleError < Exception end def hide_deprecation_warnings - MSpec.stub(:deprecate) + allow(MSpec).to receive(:deprecate) end def run_mspec(command, args) @@ -53,3 +56,15 @@ def run_mspec(command, args) out = out.gsub(cwd, "CWD") return out, ret end + +def ensure_mspec_method(method) + file, _line = method.source_location + expect(file).to start_with(File.expand_path('../../lib/mspec', __FILE__ )) +end + +PublicMSpecMatchers = Class.new { + include MSpecMatchers + public :raise_error +}.new + +BACKTRACE_QUOTE = RUBY_VERSION >= "3.4" ? "'" : "`" diff --git a/spec/mspec/spec/utils/deprecate_spec.rb b/spec/mspec/spec/utils/deprecate_spec.rb index 7fa60df26a..73eaf7d04e 100644 --- a/spec/mspec/spec/utils/deprecate_spec.rb +++ b/spec/mspec/spec/utils/deprecate_spec.rb @@ -1,17 +1,17 @@ require 'spec_helper' require 'mspec/utils/deprecate' -describe MSpec, "#deprecate" do +RSpec.describe MSpec, "#deprecate" do it "warns when using a deprecated method" do warning = nil - $stderr.stub(:puts) { |str| warning = str } + allow($stderr).to receive(:puts) { |str| warning = str } MSpec.deprecate(:some_method, :other_method) - warning.should start_with(<<-EOS.chomp) + expect(warning).to start_with(<<-EOS.chomp) some_method is deprecated, use other_method instead. from EOS - warning.should include(__FILE__) - warning.should include('8') + expect(warning).to include(__FILE__) + expect(warning).to include('8') end end diff --git a/spec/mspec/spec/utils/fixtures/this_file_raises.rb b/spec/mspec/spec/utils/fixtures/this_file_raises.rb new file mode 100644 index 0000000000..8e37a587bf --- /dev/null +++ b/spec/mspec/spec/utils/fixtures/this_file_raises.rb @@ -0,0 +1 @@ +raise "This is a BAD file" diff --git a/spec/mspec/spec/utils/fixtures/this_file_raises2.rb b/spec/mspec/spec/utils/fixtures/this_file_raises2.rb new file mode 100644 index 0000000000..8efc10199a --- /dev/null +++ b/spec/mspec/spec/utils/fixtures/this_file_raises2.rb @@ -0,0 +1 @@ +raise "This is a BAD file 2" diff --git a/spec/mspec/spec/utils/name_map_spec.rb b/spec/mspec/spec/utils/name_map_spec.rb index d38230ce06..a42dc9ffec 100644 --- a/spec/mspec/spec/utils/name_map_spec.rb +++ b/spec/mspec/spec/utils/name_map_spec.rb @@ -21,50 +21,53 @@ module NameMapSpecs def f; end end + autoload :BadFile, "#{__dir__}/fixtures/this_file_raises.rb" + autoload :BadFile2, "#{__dir__}/fixtures/this_file_raises2.rb" + def self.n; end def n; end end -describe NameMap, "#exception?" do +RSpec.describe NameMap, "#exception?" do before :each do @map = NameMap.new end it "returns true if the constant is Errno" do - @map.exception?("Errno").should == true + expect(@map.exception?("Errno")).to eq(true) end it "returns true if the constant is a kind of Exception" do - @map.exception?("Errno::EBADF").should == true - @map.exception?("LoadError").should == true - @map.exception?("SystemExit").should == true + expect(@map.exception?("Errno::EBADF")).to eq(true) + expect(@map.exception?("LoadError")).to eq(true) + expect(@map.exception?("SystemExit")).to eq(true) end it "returns false if the constant is not a kind of Exception" do - @map.exception?("NameMapSpecs::Error").should == false - @map.exception?("NameMapSpecs").should == false + expect(@map.exception?("NameMapSpecs::Error")).to eq(false) + expect(@map.exception?("NameMapSpecs")).to eq(false) end it "returns false if the constant does not exist" do - @map.exception?("Nonexistent").should == false + expect(@map.exception?("Nonexistent")).to eq(false) end end -describe NameMap, "#class_or_module" do +RSpec.describe NameMap, "#class_or_module" do before :each do @map = NameMap.new true end it "returns the constant specified by the string" do - @map.class_or_module("NameMapSpecs").should == NameMapSpecs + expect(@map.class_or_module("NameMapSpecs")).to eq(NameMapSpecs) end it "returns the constant specified by the 'A::B' string" do - @map.class_or_module("NameMapSpecs::A").should == NameMapSpecs::A + expect(@map.class_or_module("NameMapSpecs::A")).to eq(NameMapSpecs::A) end it "returns nil if the constant is not a class or module" do - @map.class_or_module("Float::MAX").should == nil + expect(@map.class_or_module("Float::MAX")).to eq(nil) end it "returns nil if the constant is in the set of excluded constants" do @@ -75,101 +78,110 @@ describe NameMap, "#class_or_module" do ] excluded.each do |const| - @map.class_or_module(const).should == nil + expect(@map.class_or_module(const)).to eq(nil) end end it "returns nil if the constant does not exist" do - @map.class_or_module("Heaven").should == nil - @map.class_or_module("Hell").should == nil - @map.class_or_module("Bush::Brain").should == nil + expect(@map.class_or_module("Heaven")).to eq(nil) + expect(@map.class_or_module("Hell")).to eq(nil) + expect(@map.class_or_module("Bush::Brain")).to eq(nil) + end + + it "returns nil if accessing the constant raises RuntimeError" do + expect { NameMapSpecs::BadFile }.to raise_error(RuntimeError) + expect(@map.class_or_module("NameMapSpecs::BadFile")).to eq(nil) + end + + it "returns nil if accessing the constant raises RuntimeError when not triggering the autoload before" do + expect(@map.class_or_module("NameMapSpecs::BadFile2")).to eq(nil) end end -describe NameMap, "#dir_name" do +RSpec.describe NameMap, "#dir_name" do before :each do @map = NameMap.new end it "returns a directory name from the base name and constant" do - @map.dir_name("NameMapSpecs", 'spec/core').should == 'spec/core/namemapspecs' + expect(@map.dir_name("NameMapSpecs", 'spec/core')).to eq('spec/core/namemapspecs') end it "returns a directory name from the components in the constants name" do - @map.dir_name("NameMapSpecs::A", 'spec').should == 'spec/namemapspecs/a' - @map.dir_name("NameMapSpecs::A::B", 'spec').should == 'spec/namemapspecs/a/b' + expect(@map.dir_name("NameMapSpecs::A", 'spec')).to eq('spec/namemapspecs/a') + expect(@map.dir_name("NameMapSpecs::A::B", 'spec')).to eq('spec/namemapspecs/a/b') end it "returns a directory name without 'class' for constants like TrueClass" do - @map.dir_name("TrueClass", 'spec').should == 'spec/true' - @map.dir_name("FalseClass", 'spec').should == 'spec/false' + expect(@map.dir_name("TrueClass", 'spec')).to eq('spec/true') + expect(@map.dir_name("FalseClass", 'spec')).to eq('spec/false') end it "returns 'exception' for the directory name of any Exception subclass" do - @map.dir_name("SystemExit", 'spec').should == 'spec/exception' - @map.dir_name("Errno::EBADF", 'spec').should == 'spec/exception' + expect(@map.dir_name("SystemExit", 'spec')).to eq('spec/exception') + expect(@map.dir_name("Errno::EBADF", 'spec')).to eq('spec/exception') end it "returns 'class' for Class" do - @map.dir_name("Class", 'spec').should == 'spec/class' + expect(@map.dir_name("Class", 'spec')).to eq('spec/class') end end # These specs do not cover all the mappings, but only describe how the # name is derived when the hash item maps to a single value, a hash with # a specific item, or a hash with a :default item. -describe NameMap, "#file_name" do +RSpec.describe NameMap, "#file_name" do before :each do @map = NameMap.new end it "returns the name of the spec file based on the constant and method" do - @map.file_name("[]=", "Array").should == "element_set_spec.rb" + expect(@map.file_name("[]=", "Array")).to eq("element_set_spec.rb") end it "returns the name of the spec file based on the special entry for the method" do - @map.file_name("~", "Regexp").should == "match_spec.rb" - @map.file_name("~", "Fixnum").should == "complement_spec.rb" + expect(@map.file_name("~", "Regexp")).to eq("match_spec.rb") + expect(@map.file_name("~", "Integer")).to eq("complement_spec.rb") end it "returns the name of the spec file based on the default entry for the method" do - @map.file_name("<<", "NameMapSpecs").should == "append_spec.rb" + expect(@map.file_name("<<", "NameMapSpecs")).to eq("append_spec.rb") end it "uses the last component of the constant to look up the method name" do - @map.file_name("^", "NameMapSpecs::Fixnum").should == "bit_xor_spec.rb" + expect(@map.file_name("^", "NameMapSpecs::Integer")).to eq("bit_xor_spec.rb") end end -describe NameMap, "#namespace" do +RSpec.describe NameMap, "#namespace" do before :each do @map = NameMap.new end it "prepends the module to the constant name" do - @map.namespace("SubModule", Integer).should == "SubModule::Integer" + expect(@map.namespace("SubModule", Integer)).to eq("SubModule::Integer") end it "does not prepend Object, Class, or Module to the constant name" do - @map.namespace("Object", String).should == "String" - @map.namespace("Module", Integer).should == "Integer" - @map.namespace("Class", Float).should == "Float" + expect(@map.namespace("Object", String)).to eq("String") + expect(@map.namespace("Module", Integer)).to eq("Integer") + expect(@map.namespace("Class", Float)).to eq("Float") end end -describe NameMap, "#map" do +RSpec.describe NameMap, "#map" do before :each do @map = NameMap.new end it "flattens an object hierarchy into a single Hash" do - @map.map({}, [NameMapSpecs]).should == { + expect(@map.map({}, [NameMapSpecs])).to eq({ "NameMapSpecs." => ["n"], "NameMapSpecs#" => ["n"], "NameMapSpecs::A." => ["a"], "NameMapSpecs::A#" => ["a", "c"], "NameMapSpecs::A::B#" => ["b"], "NameMapSpecs::Fixnum#" => ["f"] - } + }) end end diff --git a/spec/mspec/spec/utils/options_spec.rb b/spec/mspec/spec/utils/options_spec.rb index face909286..2e3925f579 100644 --- a/spec/mspec/spec/utils/options_spec.rb +++ b/spec/mspec/spec/utils/options_spec.rb @@ -5,155 +5,155 @@ require 'mspec/guards/guard' require 'mspec/runner/mspec' require 'mspec/runner/formatters' -describe MSpecOption, ".new" do +RSpec.describe MSpecOption, ".new" do before :each do @opt = MSpecOption.new("-a", "--bdc", "ARG", "desc", :block) end it "sets the short attribute" do - @opt.short.should == "-a" + expect(@opt.short).to eq("-a") end it "sets the long attribute" do - @opt.long.should == "--bdc" + expect(@opt.long).to eq("--bdc") end it "sets the arg attribute" do - @opt.arg.should == "ARG" + expect(@opt.arg).to eq("ARG") end it "sets the description attribute" do - @opt.description.should == "desc" + expect(@opt.description).to eq("desc") end it "sets the block attribute" do - @opt.block.should == :block + expect(@opt.block).to eq(:block) end end -describe MSpecOption, "#arg?" do +RSpec.describe MSpecOption, "#arg?" do it "returns true if arg attribute is not nil" do - MSpecOption.new(nil, nil, "ARG", nil, nil).arg?.should be_true + expect(MSpecOption.new(nil, nil, "ARG", nil, nil).arg?).to be_truthy end it "returns false if arg attribute is nil" do - MSpecOption.new(nil, nil, nil, nil, nil).arg?.should be_false + expect(MSpecOption.new(nil, nil, nil, nil, nil).arg?).to be_falsey end end -describe MSpecOption, "#match?" do +RSpec.describe MSpecOption, "#match?" do before :each do @opt = MSpecOption.new("-a", "--bdc", "ARG", "desc", :block) end it "returns true if the argument matches the short option" do - @opt.match?("-a").should be_true + expect(@opt.match?("-a")).to be_truthy end it "returns true if the argument matches the long option" do - @opt.match?("--bdc").should be_true + expect(@opt.match?("--bdc")).to be_truthy end it "returns false if the argument matches neither the short nor long option" do - @opt.match?("-b").should be_false - @opt.match?("-abdc").should be_false + expect(@opt.match?("-b")).to be_falsey + expect(@opt.match?("-abdc")).to be_falsey end end -describe MSpecOptions, ".new" do +RSpec.describe MSpecOptions, ".new" do before :each do @opt = MSpecOptions.new("cmd", 20, :config) end it "sets the banner attribute" do - @opt.banner.should == "cmd" + expect(@opt.banner).to eq("cmd") end it "sets the config attribute" do - @opt.config.should == :config + expect(@opt.config).to eq(:config) end it "sets the width attribute" do - @opt.width.should == 20 + expect(@opt.width).to eq(20) end it "sets the default width attribute" do - MSpecOptions.new.width.should == 30 + expect(MSpecOptions.new.width).to eq(30) end end -describe MSpecOptions, "#on" do +RSpec.describe MSpecOptions, "#on" do before :each do @opt = MSpecOptions.new end it "adds a short option" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a short option taking an argument" do - @opt.should_receive(:add).with("-a", nil, "ARG", "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, "ARG", "desc", nil) @opt.on("-a", "ARG", "desc") end it "adds a long option" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a long option taking an argument" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a short and long option" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "adds a short and long option taking an argument" do - @opt.should_receive(:add).with("-a", nil, nil, "desc", nil) + expect(@opt).to receive(:add).with("-a", nil, nil, "desc", nil) @opt.on("-a", "desc") end it "raises MSpecOptions::OptionError if pass less than 2 arguments" do - lambda { @opt.on }.should raise_error(MSpecOptions::OptionError) - lambda { @opt.on "" }.should raise_error(MSpecOptions::OptionError) + expect { @opt.on }.to raise_error(MSpecOptions::OptionError) + expect { @opt.on "" }.to raise_error(MSpecOptions::OptionError) end end -describe MSpecOptions, "#add" do +RSpec.describe MSpecOptions, "#add" do before :each do @opt = MSpecOptions.new "cmd", 20 @prc = lambda { } end it "adds documentation for an option" do - @opt.should_receive(:doc).with(" -t, --typo ARG Correct typo ARG") + expect(@opt).to receive(:doc).with(" -t, --typo ARG Correct typo ARG") @opt.add("-t", "--typo", "ARG", "Correct typo ARG", @prc) end it "leaves spaces in the documentation for a missing short option" do - @opt.should_receive(:doc).with(" --typo ARG Correct typo ARG") + expect(@opt).to receive(:doc).with(" --typo ARG Correct typo ARG") @opt.add(nil, "--typo", "ARG", "Correct typo ARG", @prc) end it "handles a short option with argument but no long argument" do - @opt.should_receive(:doc).with(" -t ARG Correct typo ARG") + expect(@opt).to receive(:doc).with(" -t ARG Correct typo ARG") @opt.add("-t", nil, "ARG", "Correct typo ARG", @prc) end it "registers an option" do option = MSpecOption.new "-t", "--typo", "ARG", "Correct typo ARG", @prc - MSpecOption.should_receive(:new).with( + expect(MSpecOption).to receive(:new).with( "-t", "--typo", "ARG", "Correct typo ARG", @prc).and_return(option) @opt.add("-t", "--typo", "ARG", "Correct typo ARG", @prc) - @opt.options.should == [option] + expect(@opt.options).to eq([option]) end end -describe MSpecOptions, "#match?" do +RSpec.describe MSpecOptions, "#match?" do before :each do @opt = MSpecOptions.new end @@ -161,15 +161,15 @@ describe MSpecOptions, "#match?" do it "returns the MSpecOption instance matching the argument" do @opt.on "-a", "--abdc", "desc" option = @opt.match? "-a" - @opt.match?("--abdc").should be(option) - option.should be_kind_of(MSpecOption) - option.short.should == "-a" - option.long.should == "--abdc" - option.description.should == "desc" + expect(@opt.match?("--abdc")).to be(option) + expect(option).to be_kind_of(MSpecOption) + expect(option.short).to eq("-a") + expect(option.long).to eq("--abdc") + expect(option.description).to eq("desc") end end -describe MSpecOptions, "#process" do +RSpec.describe MSpecOptions, "#process" do before :each do @opt = MSpecOptions.new ScratchPad.clear @@ -178,62 +178,62 @@ describe MSpecOptions, "#process" do it "calls the on_extra block if the argument does not match any option" do @opt.on_extra { ScratchPad.record :extra } @opt.process ["-a"], "-a", "-a", nil - ScratchPad.recorded.should == :extra + expect(ScratchPad.recorded).to eq(:extra) end it "returns the matching option" do @opt.on "-a", "ARG", "desc" option = @opt.process [], "-a", "-a", "ARG" - option.should be_kind_of(MSpecOption) - option.short.should == "-a" - option.arg.should == "ARG" - option.description.should == "desc" + expect(option).to be_kind_of(MSpecOption) + expect(option.short).to eq("-a") + expect(option.arg).to eq("ARG") + expect(option.description).to eq("desc") end it "raises an MSpecOptions::ParseError if arg is nil and there are no more entries in argv" do @opt.on "-a", "ARG", "desc" - lambda { @opt.process [], "-a", "-a", nil }.should raise_error(MSpecOptions::ParseError) + expect { @opt.process [], "-a", "-a", nil }.to raise_error(MSpecOptions::ParseError) end it "fetches the argument for the option from argv if arg is nil" do @opt.on("-a", "ARG", "desc") { |o| ScratchPad.record o } @opt.process ["ARG"], "-a", "-a", nil - ScratchPad.recorded.should == "ARG" + expect(ScratchPad.recorded).to eq("ARG") end it "calls the option's block" do @opt.on("-a", "ARG", "desc") { ScratchPad.record :option } @opt.process [], "-a", "-a", "ARG" - ScratchPad.recorded.should == :option + expect(ScratchPad.recorded).to eq(:option) end it "does not call the option's block if it is nil" do @opt.on "-a", "ARG", "desc" - lambda { @opt.process [], "-a", "-a", "ARG" }.should_not raise_error + expect { @opt.process [], "-a", "-a", "ARG" }.not_to raise_error end end -describe MSpecOptions, "#split" do +RSpec.describe MSpecOptions, "#split" do before :each do @opt = MSpecOptions.new end it "breaks a string at the nth character" do opt, arg, rest = @opt.split "-bdc", 2 - opt.should == "-b" - arg.should == "dc" - rest.should == "dc" + expect(opt).to eq("-b") + expect(arg).to eq("dc") + expect(rest).to eq("dc") end it "returns nil for arg if there are no characters left" do opt, arg, rest = @opt.split "-b", 2 - opt.should == "-b" - arg.should == nil - rest.should == "" + expect(opt).to eq("-b") + expect(arg).to eq(nil) + expect(rest).to eq("") end end -describe MSpecOptions, "#parse" do +RSpec.describe MSpecOptions, "#parse" do before :each do @opt = MSpecOptions.new @prc = lambda { ScratchPad.record :parsed } @@ -244,43 +244,43 @@ describe MSpecOptions, "#parse" do it "parses a short option" do @opt.on "-a", "desc", &@prc @opt.parse ["-a"] - ScratchPad.recorded.should == :parsed + expect(ScratchPad.recorded).to eq(:parsed) end it "parse a long option" do @opt.on "--abdc", "desc", &@prc @opt.parse ["--abdc"] - ScratchPad.recorded.should == :parsed + expect(ScratchPad.recorded).to eq(:parsed) end it "parses a short option group" do @opt.on "-a", "ARG", "desc", &@arg_prc @opt.parse ["-a", "ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a short option with an argument" do @opt.on "-a", "ARG", "desc", &@arg_prc @opt.parse ["-a", "ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a short option with connected argument" do @opt.on "-a", "ARG", "desc", &@arg_prc @opt.parse ["-aARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a long option with an argument" do @opt.on "--abdc", "ARG", "desc", &@arg_prc @opt.parse ["--abdc", "ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a long option with an '=' argument" do @opt.on "--abdc", "ARG", "desc", &@arg_prc @opt.parse ["--abdc=ARG"] - ScratchPad.recorded.should == [:parsed, "ARG"] + expect(ScratchPad.recorded).to eq([:parsed, "ARG"]) end it "parses a short option group with the final option taking an argument" do @@ -288,7 +288,7 @@ describe MSpecOptions, "#parse" do @opt.on("-a", "desc") { |o| ScratchPad << :a } @opt.on("-b", "ARG", "desc") { |o| ScratchPad << [:b, o] } @opt.parse ["-ab", "ARG"] - ScratchPad.recorded.should == [:a, [:b, "ARG"]] + expect(ScratchPad.recorded).to eq([:a, [:b, "ARG"]]) end it "parses a short option group with a connected argument" do @@ -297,12 +297,12 @@ describe MSpecOptions, "#parse" do @opt.on("-b", "ARG", "desc") { |o| ScratchPad << [:b, o] } @opt.on("-c", "desc") { |o| ScratchPad << :c } @opt.parse ["-acbARG"] - ScratchPad.recorded.should == [:a, :c, [:b, "ARG"]] + expect(ScratchPad.recorded).to eq([:a, :c, [:b, "ARG"]]) end it "returns the unprocessed entries" do @opt.on "-a", "ARG", "desc", &@arg_prc - @opt.parse(["abdc", "-a", "ilny"]).should == ["abdc"] + expect(@opt.parse(["abdc", "-a", "ilny"])).to eq(["abdc"]) end it "calls the on_extra handler with unrecognized options" do @@ -310,59 +310,59 @@ describe MSpecOptions, "#parse" do @opt.on_extra { |o| ScratchPad << o } @opt.on "-a", "desc" @opt.parse ["-a", "-b"] - ScratchPad.recorded.should == ["-b"] + expect(ScratchPad.recorded).to eq(["-b"]) end it "does not attempt to call the block if it is nil" do @opt.on "-a", "ARG", "desc" - @opt.parse(["-a", "ARG"]).should == [] + expect(@opt.parse(["-a", "ARG"])).to eq([]) end it "raises MSpecOptions::ParseError if passed an unrecognized option" do - @opt.should_receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) - @opt.stub(:puts) - @opt.stub(:exit) + expect(@opt).to receive(:raise).with(MSpecOptions::ParseError, an_instance_of(String)) + allow(@opt).to receive(:puts) + allow(@opt).to receive(:exit) @opt.parse "-u" end end -describe MSpecOptions, "#banner=" do +RSpec.describe MSpecOptions, "#banner=" do before :each do @opt = MSpecOptions.new end it "sets the banner attribute" do - @opt.banner.should == "" + expect(@opt.banner).to eq("") @opt.banner = "banner" - @opt.banner.should == "banner" + expect(@opt.banner).to eq("banner") end end -describe MSpecOptions, "#width=" do +RSpec.describe MSpecOptions, "#width=" do before :each do @opt = MSpecOptions.new end it "sets the width attribute" do - @opt.width.should == 30 + expect(@opt.width).to eq(30) @opt.width = 20 - @opt.width.should == 20 + expect(@opt.width).to eq(20) end end -describe MSpecOptions, "#config=" do +RSpec.describe MSpecOptions, "#config=" do before :each do @opt = MSpecOptions.new end it "sets the config attribute" do - @opt.config.should be_nil + expect(@opt.config).to be_nil @opt.config = :config - @opt.config.should == :config + expect(@opt.config).to eq(:config) end end -describe MSpecOptions, "#doc" do +RSpec.describe MSpecOptions, "#doc" do before :each do @opt = MSpecOptions.new "command" end @@ -370,7 +370,7 @@ describe MSpecOptions, "#doc" do it "adds text to be displayed with #to_s" do @opt.doc "Some message" @opt.doc "Another message" - @opt.to_s.should == <<-EOD + expect(@opt.to_s).to eq <<-EOD command Some message @@ -379,15 +379,15 @@ EOD end end -describe MSpecOptions, "#version" do +RSpec.describe MSpecOptions, "#version" do before :each do @opt = MSpecOptions.new ScratchPad.clear end it "installs a basic -v, --version option" do - @opt.should_receive(:puts) - @opt.should_receive(:exit) + expect(@opt).to receive(:puts) + expect(@opt).to receive(:exit) @opt.version "1.0.0" @opt.parse "-v" end @@ -395,19 +395,19 @@ describe MSpecOptions, "#version" do it "accepts a block instead of using the default block" do @opt.version("1.0.0") { |o| ScratchPad.record :version } @opt.parse "-v" - ScratchPad.recorded.should == :version + expect(ScratchPad.recorded).to eq(:version) end end -describe MSpecOptions, "#help" do +RSpec.describe MSpecOptions, "#help" do before :each do @opt = MSpecOptions.new ScratchPad.clear end it "installs a basic -h, --help option" do - @opt.should_receive(:puts) - @opt.should_receive(:exit).with(1) + expect(@opt).to receive(:puts) + expect(@opt).to receive(:exit).with(1) @opt.help @opt.parse "-h" end @@ -415,11 +415,11 @@ describe MSpecOptions, "#help" do it "accepts a block instead of using the default block" do @opt.help { |o| ScratchPad.record :help } @opt.parse "-h" - ScratchPad.recorded.should == :help + expect(ScratchPad.recorded).to eq(:help) end end -describe MSpecOptions, "#on_extra" do +RSpec.describe MSpecOptions, "#on_extra" do before :each do @opt = MSpecOptions.new ScratchPad.clear @@ -428,18 +428,18 @@ describe MSpecOptions, "#on_extra" do it "registers a block to be called when an option is not recognized" do @opt.on_extra { ScratchPad.record :extra } @opt.parse "-g" - ScratchPad.recorded.should == :extra + expect(ScratchPad.recorded).to eq(:extra) end end -describe MSpecOptions, "#to_s" do +RSpec.describe MSpecOptions, "#to_s" do before :each do @opt = MSpecOptions.new "command" end it "returns the banner and descriptive strings for all registered options" do @opt.on "-t", "--this ARG", "Adds this ARG to the list" - @opt.to_s.should == <<-EOD + expect(@opt.to_s).to eq <<-EOD command -t, --this ARG Adds this ARG to the list @@ -447,13 +447,13 @@ EOD end end -describe "The -B, --config FILE option" do +RSpec.describe "The -B, --config FILE option" do before :each do @options, @config = new_option end it "is enabled with #configure { }" do - @options.should_receive(:on).with("-B", "--config", "FILE", + expect(@options).to receive(:on).with("-B", "--config", "FILE", an_instance_of(String)) @options.configure {} end @@ -464,38 +464,38 @@ describe "The -B, --config FILE option" do @options.configure { |x| ScratchPad.record x } @options.parse [opt, "file"] - ScratchPad.recorded.should == "file" + expect(ScratchPad.recorded).to eq("file") end end end -describe "The -C, --chdir DIR option" do +RSpec.describe "The -C, --chdir DIR option" do before :each do @options, @config = new_option @options.chdir end it "is enabled with #chdir" do - @options.should_receive(:on).with("-C", "--chdir", "DIR", + expect(@options).to receive(:on).with("-C", "--chdir", "DIR", an_instance_of(String)) @options.chdir end it "changes the working directory to DIR" do - Dir.should_receive(:chdir).with("dir").twice + expect(Dir).to receive(:chdir).with("dir").twice ["-C", "--chdir"].each do |opt| @options.parse [opt, "dir"] end end end -describe "The --prefix STR option" do +RSpec.describe "The --prefix STR option" do before :each do @options, @config = new_option end it "is enabled with #prefix" do - @options.should_receive(:on).with("--prefix", "STR", + expect(@options).to receive(:on).with("--prefix", "STR", an_instance_of(String)) @options.prefix end @@ -503,19 +503,19 @@ describe "The --prefix STR option" do it "sets the prefix config value" do @options.prefix @options.parse ["--prefix", "some/dir"] - @config[:prefix].should == "some/dir" + expect(@config[:prefix]).to eq("some/dir") end end -describe "The -t, --target TARGET option" do +RSpec.describe "The -t, --target TARGET option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-t", "--target", "TARGET", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-t", "--target", "TARGET", an_instance_of(String)) @options.targets end @@ -525,7 +525,7 @@ describe "The -t, --target TARGET option" do ["r", "ruby"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "ruby" + expect(@config[:target]).to eq("ruby") end end end @@ -535,7 +535,7 @@ describe "The -t, --target TARGET option" do ["j", "jruby"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "jruby" + expect(@config[:target]).to eq("jruby") end end end @@ -545,7 +545,7 @@ describe "The -t, --target TARGET option" do ["x", "rubinius"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "./bin/rbx" + expect(@config[:target]).to eq("./bin/rbx") end end end @@ -555,7 +555,7 @@ describe "The -t, --target TARGET option" do ["X", "rbx"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "rbx" + expect(@config[:target]).to eq("rbx") end end end @@ -565,7 +565,7 @@ describe "The -t, --target TARGET option" do ["m", "maglev"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "maglev-ruby" + expect(@config[:target]).to eq("maglev-ruby") end end end @@ -575,7 +575,7 @@ describe "The -t, --target TARGET option" do ["t", "topaz"].each do |t| @config[:target] = nil @options.parse [opt, t] - @config[:target].should == "topaz" + expect(@config[:target]).to eq("topaz") end end end @@ -584,20 +584,20 @@ describe "The -t, --target TARGET option" do ["-t", "--target"].each do |opt| @config[:target] = nil @options.parse [opt, "whateva"] - @config[:target].should == "whateva" + expect(@config[:target]).to eq("whateva") end end end -describe "The -T, --target-opt OPT option" do +RSpec.describe "The -T, --target-opt OPT option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-T", "--target-opt", "OPT", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-T", "--target-opt", "OPT", an_instance_of(String)) @options.targets end @@ -606,20 +606,20 @@ describe "The -T, --target-opt OPT option" do ["-T", "--target-opt"].each do |opt| @config[:flags].delete "--whateva" @options.parse [opt, "--whateva"] - @config[:flags].should include("--whateva") + expect(@config[:flags]).to include("--whateva") end end end -describe "The -I, --include DIR option" do +RSpec.describe "The -I, --include DIR option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-I", "--include", "DIR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-I", "--include", "DIR", an_instance_of(String)) @options.targets end @@ -628,20 +628,20 @@ describe "The -I, --include DIR option" do ["-I", "--include"].each do |opt| @config[:loadpath].delete "-Ipackage" @options.parse [opt, "package"] - @config[:loadpath].should include("-Ipackage") + expect(@config[:loadpath]).to include("-Ipackage") end end end -describe "The -r, --require LIBRARY option" do +RSpec.describe "The -r, --require LIBRARY option" do before :each do @options, @config = new_option @options.targets end it "is enabled with #targets" do - @options.stub(:on) - @options.should_receive(:on).with("-r", "--require", "LIBRARY", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-r", "--require", "LIBRARY", an_instance_of(String)) @options.targets end @@ -650,20 +650,20 @@ describe "The -r, --require LIBRARY option" do ["-r", "--require"].each do |opt| @config[:requires].delete "-rlibrick" @options.parse [opt, "librick"] - @config[:requires].should include("-rlibrick") + expect(@config[:requires]).to include("-rlibrick") end end end -describe "The -f, --format FORMAT option" do +RSpec.describe "The -f, --format FORMAT option" do before :each do @options, @config = new_option @options.formatters end it "is enabled with #formatters" do - @options.stub(:on) - @options.should_receive(:on).with("-f", "--format", "FORMAT", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-f", "--format", "FORMAT", an_instance_of(String)) @options.formatters end @@ -673,7 +673,7 @@ describe "The -f, --format FORMAT option" do ["s", "specdoc"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == SpecdocFormatter + expect(@config[:formatter]).to eq(SpecdocFormatter) end end end @@ -683,7 +683,7 @@ describe "The -f, --format FORMAT option" do ["h", "html"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == HtmlFormatter + expect(@config[:formatter]).to eq(HtmlFormatter) end end end @@ -693,7 +693,7 @@ describe "The -f, --format FORMAT option" do ["d", "dot", "dotted"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == DottedFormatter + expect(@config[:formatter]).to eq(DottedFormatter) end end end @@ -703,7 +703,7 @@ describe "The -f, --format FORMAT option" do ["b", "describe"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == DescribeFormatter + expect(@config[:formatter]).to eq(DescribeFormatter) end end end @@ -713,7 +713,7 @@ describe "The -f, --format FORMAT option" do ["f", "file"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == FileFormatter + expect(@config[:formatter]).to eq(FileFormatter) end end end @@ -723,7 +723,7 @@ describe "The -f, --format FORMAT option" do ["u", "unit", "unitdiff"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == UnitdiffFormatter + expect(@config[:formatter]).to eq(UnitdiffFormatter) end end end @@ -733,7 +733,7 @@ describe "The -f, --format FORMAT option" do ["m", "summary"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == SummaryFormatter + expect(@config[:formatter]).to eq(SummaryFormatter) end end end @@ -743,7 +743,7 @@ describe "The -f, --format FORMAT option" do ["a", "*", "spin"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == SpinnerFormatter + expect(@config[:formatter]).to eq(SpinnerFormatter) end end end @@ -753,7 +753,7 @@ describe "The -f, --format FORMAT option" do ["t", "method"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == MethodFormatter + expect(@config[:formatter]).to eq(MethodFormatter) end end end @@ -763,7 +763,7 @@ describe "The -f, --format FORMAT option" do ["y", "yaml"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == YamlFormatter + expect(@config[:formatter]).to eq(YamlFormatter) end end end @@ -773,21 +773,21 @@ describe "The -f, --format FORMAT option" do ["j", "junit"].each do |f| @config[:formatter] = nil @options.parse [opt, f] - @config[:formatter].should == JUnitFormatter + expect(@config[:formatter]).to eq(JUnitFormatter) end end end end -describe "The -o, --output FILE option" do +RSpec.describe "The -o, --output FILE option" do before :each do @options, @config = new_option @options.formatters end it "is enabled with #formatters" do - @options.stub(:on) - @options.should_receive(:on).with("-o", "--output", "FILE", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-o", "--output", "FILE", an_instance_of(String)) @options.formatters end @@ -796,20 +796,20 @@ describe "The -o, --output FILE option" do ["-o", "--output"].each do |opt| @config[:output] = nil @options.parse [opt, "some/file"] - @config[:output].should == "some/file" + expect(@config[:output]).to eq("some/file") end end end -describe "The -e, --example STR" do +RSpec.describe "The -e, --example STR" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-e", "--example", "STR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-e", "--example", "STR", an_instance_of(String)) @options.filters end @@ -818,20 +818,20 @@ describe "The -e, --example STR" do ["-e", "--example"].each do |opt| @config[:includes] = [] @options.parse [opt, "this spec"] - @config[:includes].should include("this spec") + expect(@config[:includes]).to include("this spec") end end end -describe "The -E, --exclude STR" do +RSpec.describe "The -E, --exclude STR" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-E", "--exclude", "STR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-E", "--exclude", "STR", an_instance_of(String)) @options.filters end @@ -840,20 +840,20 @@ describe "The -E, --exclude STR" do ["-E", "--exclude"].each do |opt| @config[:excludes] = [] @options.parse [opt, "this spec"] - @config[:excludes].should include("this spec") + expect(@config[:excludes]).to include("this spec") end end end -describe "The -p, --pattern PATTERN" do +RSpec.describe "The -p, --pattern PATTERN" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-p", "--pattern", "PATTERN", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-p", "--pattern", "PATTERN", an_instance_of(String)) @options.filters end @@ -862,20 +862,20 @@ describe "The -p, --pattern PATTERN" do ["-p", "--pattern"].each do |opt| @config[:patterns] = [] @options.parse [opt, "this spec"] - @config[:patterns].should include(/this spec/) + expect(@config[:patterns]).to include(/this spec/) end end end -describe "The -P, --excl-pattern PATTERN" do +RSpec.describe "The -P, --excl-pattern PATTERN" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-P", "--excl-pattern", "PATTERN", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-P", "--excl-pattern", "PATTERN", an_instance_of(String)) @options.filters end @@ -884,20 +884,20 @@ describe "The -P, --excl-pattern PATTERN" do ["-P", "--excl-pattern"].each do |opt| @config[:xpatterns] = [] @options.parse [opt, "this spec"] - @config[:xpatterns].should include(/this spec/) + expect(@config[:xpatterns]).to include(/this spec/) end end end -describe "The -g, --tag TAG" do +RSpec.describe "The -g, --tag TAG" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-g", "--tag", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-g", "--tag", "TAG", an_instance_of(String)) @options.filters end @@ -906,20 +906,20 @@ describe "The -g, --tag TAG" do ["-g", "--tag"].each do |opt| @config[:tags] = [] @options.parse [opt, "this spec"] - @config[:tags].should include("this spec") + expect(@config[:tags]).to include("this spec") end end end -describe "The -G, --excl-tag TAG" do +RSpec.describe "The -G, --excl-tag TAG" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-G", "--excl-tag", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-G", "--excl-tag", "TAG", an_instance_of(String)) @options.filters end @@ -928,20 +928,20 @@ describe "The -G, --excl-tag TAG" do ["-G", "--excl-tag"].each do |opt| @config[:xtags] = [] @options.parse [opt, "this spec"] - @config[:xtags].should include("this spec") + expect(@config[:xtags]).to include("this spec") end end end -describe "The -w, --profile FILE option" do +RSpec.describe "The -w, --profile FILE option" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-w", "--profile", "FILE", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-w", "--profile", "FILE", an_instance_of(String)) @options.filters end @@ -950,20 +950,20 @@ describe "The -w, --profile FILE option" do ["-w", "--profile"].each do |opt| @config[:profiles] = [] @options.parse [opt, "spec/profiles/rails.yaml"] - @config[:profiles].should include("spec/profiles/rails.yaml") + expect(@config[:profiles]).to include("spec/profiles/rails.yaml") end end end -describe "The -W, --excl-profile FILE option" do +RSpec.describe "The -W, --excl-profile FILE option" do before :each do @options, @config = new_option @options.filters end it "is enabled with #filters" do - @options.stub(:on) - @options.should_receive(:on).with("-W", "--excl-profile", "FILE", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-W", "--excl-profile", "FILE", an_instance_of(String)) @options.filters end @@ -972,93 +972,93 @@ describe "The -W, --excl-profile FILE option" do ["-W", "--excl-profile"].each do |opt| @config[:xprofiles] = [] @options.parse [opt, "spec/profiles/rails.yaml"] - @config[:xprofiles].should include("spec/profiles/rails.yaml") + expect(@config[:xprofiles]).to include("spec/profiles/rails.yaml") end end end -describe "The -Z, --dry-run option" do +RSpec.describe "The -Z, --dry-run option" do before :each do @options, @config = new_option @options.pretend end it "is enabled with #pretend" do - @options.should_receive(:on).with("-Z", "--dry-run", an_instance_of(String)) + expect(@options).to receive(:on).with("-Z", "--dry-run", an_instance_of(String)) @options.pretend end it "registers the MSpec pretend mode" do - MSpec.should_receive(:register_mode).with(:pretend).twice + expect(MSpec).to receive(:register_mode).with(:pretend).twice ["-Z", "--dry-run"].each do |opt| @options.parse opt end end end -describe "The --unguarded option" do +RSpec.describe "The --unguarded option" do before :each do @options, @config = new_option @options.unguarded end it "is enabled with #unguarded" do - @options.stub(:on) - @options.should_receive(:on).with("--unguarded", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--unguarded", an_instance_of(String)) @options.unguarded end it "registers the MSpec unguarded mode" do - MSpec.should_receive(:register_mode).with(:unguarded) + expect(MSpec).to receive(:register_mode).with(:unguarded) @options.parse "--unguarded" end end -describe "The --no-ruby_guard option" do +RSpec.describe "The --no-ruby_guard option" do before :each do @options, @config = new_option @options.unguarded end it "is enabled with #unguarded" do - @options.stub(:on) - @options.should_receive(:on).with("--no-ruby_bug", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--no-ruby_bug", an_instance_of(String)) @options.unguarded end it "registers the MSpec no_ruby_bug mode" do - MSpec.should_receive(:register_mode).with(:no_ruby_bug) + expect(MSpec).to receive(:register_mode).with(:no_ruby_bug) @options.parse "--no-ruby_bug" end end -describe "The -H, --random option" do +RSpec.describe "The -H, --random option" do before :each do @options, @config = new_option @options.randomize end it "is enabled with #randomize" do - @options.should_receive(:on).with("-H", "--random", an_instance_of(String)) + expect(@options).to receive(:on).with("-H", "--random", an_instance_of(String)) @options.randomize end it "registers the MSpec randomize mode" do - MSpec.should_receive(:randomize).twice + expect(MSpec).to receive(:randomize=).twice ["-H", "--random"].each do |opt| @options.parse opt end end end -describe "The -R, --repeat option" do +RSpec.describe "The -R, --repeat option" do before :each do @options, @config = new_option @options.repeat end it "is enabled with #repeat" do - @options.should_receive(:on).with("-R", "--repeat", "NUMBER", an_instance_of(String)) + expect(@options).to receive(:on).with("-R", "--repeat", "NUMBER", an_instance_of(String)) @options.repeat end @@ -1070,117 +1070,115 @@ describe "The -R, --repeat option" do MSpec.repeat do repeat_count += 1 end - repeat_count.should == 10 + expect(repeat_count).to eq(10) end end end -describe "The -V, --verbose option" do +RSpec.describe "The -V, --verbose option" do before :each do @options, @config = new_option @options.verbose end it "is enabled with #verbose" do - @options.stub(:on) - @options.should_receive(:on).with("-V", "--verbose", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-V", "--verbose", an_instance_of(String)) @options.verbose end it "registers a verbose output object with MSpec" do - MSpec.should_receive(:register).with(:start, anything()).twice - MSpec.should_receive(:register).with(:load, anything()).twice + expect(MSpec).to receive(:register).with(:start, anything()).twice + expect(MSpec).to receive(:register).with(:load, anything()).twice ["-V", "--verbose"].each do |opt| @options.parse opt end end end -describe "The -m, --marker MARKER option" do +RSpec.describe "The -m, --marker MARKER option" do before :each do @options, @config = new_option @options.verbose end it "is enabled with #verbose" do - @options.stub(:on) - @options.should_receive(:on).with("-m", "--marker", "MARKER", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-m", "--marker", "MARKER", an_instance_of(String)) @options.verbose end it "registers a marker output object with MSpec" do - MSpec.should_receive(:register).with(:load, anything()).twice + expect(MSpec).to receive(:register).with(:load, anything()).twice ["-m", "--marker"].each do |opt| @options.parse [opt, ","] end end end -describe "The --int-spec option" do +RSpec.describe "The --int-spec option" do before :each do @options, @config = new_option @options.interrupt end it "is enabled with #interrupt" do - @options.should_receive(:on).with("--int-spec", an_instance_of(String)) + expect(@options).to receive(:on).with("--int-spec", an_instance_of(String)) @options.interrupt end it "sets the abort config option to false to only abort the running spec with ^C" do @config[:abort] = true @options.parse "--int-spec" - @config[:abort].should == false + expect(@config[:abort]).to eq(false) end end -describe "The -Y, --verify option" do +RSpec.describe "The -Y, --verify option" do before :each do @options, @config = new_option @options.verify end it "is enabled with #interrupt" do - @options.stub(:on) - @options.should_receive(:on).with("-Y", "--verify", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-Y", "--verify", an_instance_of(String)) @options.verify end it "sets the MSpec mode to :verify" do - MSpec.should_receive(:register_mode).with(:verify).twice + expect(MSpec).to receive(:register_mode).with(:verify).twice ["-Y", "--verify"].each do |m| @options.parse m end end end -describe "The -O, --report option" do +RSpec.describe "The -O, --report option" do before :each do @options, @config = new_option @options.verify end it "is enabled with #interrupt" do - @options.stub(:on) - @options.should_receive(:on).with("-O", "--report", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-O", "--report", an_instance_of(String)) @options.verify end it "sets the MSpec mode to :report" do - MSpec.should_receive(:register_mode).with(:report).twice + expect(MSpec).to receive(:register_mode).with(:report).twice ["-O", "--report"].each do |m| @options.parse m end end end -describe "The --report-on GUARD option" do - before :all do - MSpec.stub(:register_mode) - end - +RSpec.describe "The --report-on GUARD option" do before :each do + allow(MSpec).to receive(:register_mode) + @options, @config = new_option @options.verify @@ -1192,37 +1190,37 @@ describe "The --report-on GUARD option" do end it "is enabled with #interrupt" do - @options.stub(:on) - @options.should_receive(:on).with("--report-on", "GUARD", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("--report-on", "GUARD", an_instance_of(String)) @options.verify end it "sets the MSpec mode to :report_on" do - MSpec.should_receive(:register_mode).with(:report_on) + expect(MSpec).to receive(:register_mode).with(:report_on) @options.parse ["--report-on", "ruby_bug"] end it "converts the guard name to a symbol" do name = double("ruby_bug") - name.should_receive(:to_sym) + expect(name).to receive(:to_sym) @options.parse ["--report-on", name] end it "saves the name of the guard" do @options.parse ["--report-on", "ruby_bug"] - SpecGuard.guards.should == [:ruby_bug] + expect(SpecGuard.guards).to eq([:ruby_bug]) end end -describe "The -K, --action-tag TAG option" do +RSpec.describe "The -K, --action-tag TAG option" do before :each do @options, @config = new_option @options.action_filters end it "is enabled with #action_filters" do - @options.stub(:on) - @options.should_receive(:on).with("-K", "--action-tag", "TAG", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-K", "--action-tag", "TAG", an_instance_of(String)) @options.action_filters end @@ -1231,20 +1229,20 @@ describe "The -K, --action-tag TAG option" do ["-K", "--action-tag"].each do |opt| @config[:atags] = [] @options.parse [opt, "action-tag"] - @config[:atags].should include("action-tag") + expect(@config[:atags]).to include("action-tag") end end end -describe "The -S, --action-string STR option" do +RSpec.describe "The -S, --action-string STR option" do before :each do @options, @config = new_option @options.action_filters end it "is enabled with #action_filters" do - @options.stub(:on) - @options.should_receive(:on).with("-S", "--action-string", "STR", + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-S", "--action-string", "STR", an_instance_of(String)) @options.action_filters end @@ -1253,12 +1251,12 @@ describe "The -S, --action-string STR option" do ["-S", "--action-string"].each do |opt| @config[:astrings] = [] @options.parse [opt, "action-str"] - @config[:astrings].should include("action-str") + expect(@config[:astrings]).to include("action-str") end end end -describe "The -d, --debug option" do +RSpec.describe "The -d, --debug option" do before :each do @options, @config = new_option @options.debug @@ -1269,17 +1267,36 @@ describe "The -d, --debug option" do end it "is enabled with #debug" do - @options.stub(:on) - @options.should_receive(:on).with("-d", "--debug", an_instance_of(String)) + allow(@options).to receive(:on) + expect(@options).to receive(:on).with("-d", "--debug", an_instance_of(String)) @options.debug end it "sets $MSPEC_DEBUG to true" do ["-d", "--debug"].each do |opt| - $MSPEC_DEBUG.should_not be_true + expect($MSPEC_DEBUG).not_to be_truthy @options.parse opt - $MSPEC_DEBUG.should be_true + expect($MSPEC_DEBUG).to be_truthy $MSPEC_DEBUG = nil end end end + +RSpec.describe "MSpecOptions#all" do + it "includes all options" do + meth = MSpecOptions.instance_method(:all) + file, line = meth.source_location + contents = File.read(file) + lines = contents.lines + + from = line + to = from + to += 1 until /^\s*end\s*$/ =~ lines[to] + calls = lines[from...to].map(&:strip) + + option_methods = contents.scan(/def (\w+).*\n\s*on\(/).map(&:first) + option_methods[0].sub!("configure", "configure {}") + + expect(calls).to eq(option_methods) + end +end diff --git a/spec/mspec/spec/utils/script_spec.rb b/spec/mspec/spec/utils/script_spec.rb index 2582809fae..c35bda8b47 100644 --- a/spec/mspec/spec/utils/script_spec.rb +++ b/spec/mspec/spec/utils/script_spec.rb @@ -4,40 +4,40 @@ require 'mspec/runner/mspec' require 'mspec/runner/filters' require 'mspec/runner/actions/filter' -describe MSpecScript, ".config" do +RSpec.describe MSpecScript, ".config" do it "returns a Hash" do - MSpecScript.config.should be_kind_of(Hash) + expect(MSpecScript.config).to be_kind_of(Hash) end end -describe MSpecScript, ".set" do +RSpec.describe MSpecScript, ".set" do it "sets the config hash key, value" do MSpecScript.set :a, 10 - MSpecScript.config[:a].should == 10 + expect(MSpecScript.config[:a]).to eq(10) end end -describe MSpecScript, ".get" do +RSpec.describe MSpecScript, ".get" do it "gets the config hash value for a key" do MSpecScript.set :a, 10 - MSpecScript.get(:a).should == 10 + expect(MSpecScript.get(:a)).to eq(10) end end -describe MSpecScript, "#config" do +RSpec.describe MSpecScript, "#config" do it "returns the MSpecScript config hash" do MSpecScript.set :b, 5 - MSpecScript.new.config[:b].should == 5 + expect(MSpecScript.new.config[:b]).to eq(5) end it "returns the MSpecScript config hash from subclasses" do class MSSClass < MSpecScript; end MSpecScript.set :b, 5 - MSSClass.new.config[:b].should == 5 + expect(MSSClass.new.config[:b]).to eq(5) end end -describe MSpecScript, "#load_default" do +RSpec.describe MSpecScript, "#load_default" do before :all do @verbose = $VERBOSE $VERBOSE = nil @@ -53,7 +53,7 @@ describe MSpecScript, "#load_default" do @engine = Object.const_get :RUBY_ENGINE end @script = MSpecScript.new - MSpecScript.stub(:new).and_return(@script) + allow(MSpecScript).to receive(:new).and_return(@script) end after :each do @@ -62,8 +62,8 @@ describe MSpecScript, "#load_default" do end it "attempts to load 'default.mspec'" do - @script.stub(:try_load) - @script.should_receive(:try_load).with('default.mspec').and_return(true) + allow(@script).to receive(:try_load) + expect(@script).to receive(:try_load).with('default.mspec').and_return(true) @script.load_default end @@ -71,145 +71,140 @@ describe MSpecScript, "#load_default" do Object.const_set :RUBY_ENGINE, "ybur" Object.const_set :RUBY_VERSION, "1.8.9" default = "ybur.1.8.mspec" - @script.should_receive(:try_load).with('default.mspec').and_return(false) - @script.should_receive(:try_load).with(default) - @script.should_receive(:try_load).with('ybur.mspec') + expect(@script).to receive(:try_load).with('default.mspec').and_return(false) + expect(@script).to receive(:try_load).with(default) + expect(@script).to receive(:try_load).with('ybur.mspec') @script.load_default end end -describe MSpecScript, ".main" do +RSpec.describe MSpecScript, ".main" do before :each do @script = double("MSpecScript").as_null_object - MSpecScript.stub(:new).and_return(@script) + allow(MSpecScript).to receive(:new).and_return(@script) # Do not require full mspec as it would conflict with RSpec - MSpecScript.should_receive(:require).with('mspec') + expect(MSpecScript).to receive(:require).with('mspec') end it "creates an instance of MSpecScript" do - MSpecScript.should_receive(:new).and_return(@script) + expect(MSpecScript).to receive(:new).and_return(@script) MSpecScript.main end it "attempts to load the default config" do - @script.should_receive(:load_default) - MSpecScript.main - end - - it "attempts to load the '~/.mspecrc' script" do - @script.should_receive(:try_load).with('~/.mspecrc') + expect(@script).to receive(:load_default) MSpecScript.main end it "calls the #options method on the script" do - @script.should_receive(:options) + expect(@script).to receive(:options) MSpecScript.main end it "calls the #signals method on the script" do - @script.should_receive(:signals) + expect(@script).to receive(:signals) MSpecScript.main end it "calls the #register method on the script" do - @script.should_receive(:register) + expect(@script).to receive(:register) MSpecScript.main end it "calls the #setup_env method on the script" do - @script.should_receive(:setup_env) + expect(@script).to receive(:setup_env) MSpecScript.main end it "calls the #run method on the script" do - @script.should_receive(:run) + expect(@script).to receive(:run) MSpecScript.main end end -describe MSpecScript, "#initialize" do +RSpec.describe MSpecScript, "#initialize" do before :each do @config = MSpecScript.new.config end it "sets the default config values" do - @config[:formatter].should == nil - @config[:includes].should == [] - @config[:excludes].should == [] - @config[:patterns].should == [] - @config[:xpatterns].should == [] - @config[:tags].should == [] - @config[:xtags].should == [] - @config[:atags].should == [] - @config[:astrings].should == [] - @config[:abort].should == true - @config[:config_ext].should == '.mspec' + expect(@config[:formatter]).to eq(nil) + expect(@config[:includes]).to eq([]) + expect(@config[:excludes]).to eq([]) + expect(@config[:patterns]).to eq([]) + expect(@config[:xpatterns]).to eq([]) + expect(@config[:tags]).to eq([]) + expect(@config[:xtags]).to eq([]) + expect(@config[:atags]).to eq([]) + expect(@config[:astrings]).to eq([]) + expect(@config[:abort]).to eq(true) + expect(@config[:config_ext]).to eq('.mspec') end end -describe MSpecScript, "#load" do +RSpec.describe MSpecScript, "#load" do before :each do - File.stub(:exist?).and_return(false) + allow(File).to receive(:exist?).and_return(false) @script = MSpecScript.new @file = "default.mspec" @base = "default" end it "attempts to locate the file through the expanded path name" do - File.should_receive(:expand_path).with(@file, ".").and_return(@file) - File.should_receive(:exist?).with(@file).and_return(true) - Kernel.should_receive(:load).with(@file).and_return(:loaded) - @script.load(@file).should == :loaded + expect(File).to receive(:expand_path).with(@file, ".").and_return(@file) + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(Kernel).to receive(:load).with(@file).and_return(:loaded) + expect(@script.load(@file)).to eq(:loaded) end it "appends config[:config_ext] to the name and attempts to locate the file through the expanded path name" do - File.should_receive(:expand_path).with(@base, ".").and_return(@base) - File.should_receive(:expand_path).with(@base, "spec").and_return(@base) - File.should_receive(:expand_path).with(@file, ".").and_return(@file) - File.should_receive(:exist?).with(@base).and_return(false) - File.should_receive(:exist?).with(@file).and_return(true) - Kernel.should_receive(:load).with(@file).and_return(:loaded) - @script.load(@base).should == :loaded + expect(File).to receive(:expand_path).with(@base, ".").and_return(@base) + expect(File).to receive(:expand_path).with(@base, "spec").and_return(@base) + expect(File).to receive(:expand_path).with(@file, ".").and_return(@file) + expect(File).to receive(:exist?).with(@base).and_return(false) + expect(File).to receive(:exist?).with(@file).and_return(true) + expect(Kernel).to receive(:load).with(@file).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) end it "attempts to locate the file in '.'" do path = File.expand_path @file, "." - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@file).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@file)).to eq(:loaded) end it "appends config[:config_ext] to the name and attempts to locate the file in '.'" do path = File.expand_path @file, "." - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@base).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) end it "attempts to locate the file in 'spec'" do path = File.expand_path @file, "spec" - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@file).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@file)).to eq(:loaded) end it "appends config[:config_ext] to the name and attempts to locate the file in 'spec'" do path = File.expand_path @file, "spec" - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).with(path).and_return(:loaded) - @script.load(@base).should == :loaded + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).with(path).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) end it "loads a given file only once" do path = File.expand_path @file, "spec" - File.should_receive(:exist?).with(path).and_return(true) - Kernel.should_receive(:load).once.with(path).and_return(:loaded) - @script.load(@base).should == :loaded - @script.load(@base).should == true + expect(File).to receive(:exist?).with(path).and_return(true) + expect(Kernel).to receive(:load).once.with(path).and_return(:loaded) + expect(@script.load(@base)).to eq(:loaded) + expect(@script.load(@base)).to eq(true) end end -describe MSpecScript, "#custom_options" do +RSpec.describe MSpecScript, "#custom_options" do before :each do @script = MSpecScript.new end @@ -219,12 +214,12 @@ describe MSpecScript, "#custom_options" do it "prints 'None'" do options = double("options") - options.should_receive(:doc).with(" No custom options registered") + expect(options).to receive(:doc).with(" No custom options registered") @script.custom_options options end end -describe MSpecScript, "#register" do +RSpec.describe MSpecScript, "#register" do before :each do @script = MSpecScript.new @@ -233,8 +228,8 @@ describe MSpecScript, "#register" do end it "creates and registers the formatter" do - @formatter.should_receive(:new).and_return(@formatter) - @formatter.should_receive(:register) + expect(@formatter).to receive(:new).and_return(@formatter) + expect(@formatter).to receive(:register) @script.register end @@ -244,24 +239,24 @@ describe MSpecScript, "#register" do end it "calls #custom_register" do - @script.should_receive(:custom_register) + expect(@script).to receive(:custom_register) @script.register end it "registers :formatter with the formatter instance" do - @formatter.stub(:new).and_return(@formatter) - MSpec.should_receive(:store).with(:formatter, @formatter) + allow(@formatter).to receive(:new).and_return(@formatter) @script.register + expect(MSpec.formatter).to be(@formatter) end it "does not register :formatter if config[:formatter] is false" do @script.config[:formatter] = false - MSpec.should_not_receive(:store) + expect(MSpec).not_to receive(:store) @script.register end end -describe MSpecScript, "#register" do +RSpec.describe MSpecScript, "#register" do before :each do @script = MSpecScript.new @@ -269,61 +264,61 @@ describe MSpecScript, "#register" do @script.config[:formatter] = @formatter @filter = double("filter") - @filter.should_receive(:register) + expect(@filter).to receive(:register) @ary = ["some", "spec"] end it "creates and registers a MatchFilter for include specs" do - MatchFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(MatchFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:includes] = @ary @script.register end it "creates and registers a MatchFilter for excluded specs" do - MatchFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(MatchFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:excludes] = @ary @script.register end it "creates and registers a RegexpFilter for include specs" do - RegexpFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(RegexpFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:patterns] = @ary @script.register end it "creates and registers a RegexpFilter for excluded specs" do - RegexpFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(RegexpFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:xpatterns] = @ary @script.register end it "creates and registers a TagFilter for include specs" do - TagFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(TagFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:tags] = @ary @script.register end it "creates and registers a TagFilter for excluded specs" do - TagFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(TagFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:xtags] = @ary @script.register end it "creates and registers a ProfileFilter for include specs" do - ProfileFilter.should_receive(:new).with(:include, *@ary).and_return(@filter) + expect(ProfileFilter).to receive(:new).with(:include, *@ary).and_return(@filter) @script.config[:profiles] = @ary @script.register end it "creates and registers a ProfileFilter for excluded specs" do - ProfileFilter.should_receive(:new).with(:exclude, *@ary).and_return(@filter) + expect(ProfileFilter).to receive(:new).with(:exclude, *@ary).and_return(@filter) @script.config[:xprofiles] = @ary @script.register end end -describe MSpecScript, "#signals" do +RSpec.describe MSpecScript, "#signals" do before :each do @script = MSpecScript.new @abort = @script.config[:abort] @@ -334,42 +329,42 @@ describe MSpecScript, "#signals" do end it "traps the INT signal if config[:abort] is true" do - Signal.should_receive(:trap).with("INT") + expect(Signal).to receive(:trap).with("INT") @script.config[:abort] = true @script.signals end it "does not trap the INT signal if config[:abort] is not true" do - Signal.should_not_receive(:trap).with("INT") + expect(Signal).not_to receive(:trap).with("INT") @script.config[:abort] = false @script.signals end end -describe MSpecScript, "#entries" do +RSpec.describe MSpecScript, "#entries" do before :each do @script = MSpecScript.new - File.stub(:expand_path).and_return("name") - File.stub(:file?).and_return(false) - File.stub(:directory?).and_return(false) + allow(File).to receive(:realpath).and_return("name") + allow(File).to receive(:file?).and_return(false) + allow(File).to receive(:directory?).and_return(false) end it "returns the pattern in an array if it is a file" do - File.should_receive(:expand_path).with("file").and_return("file/expanded.rb") - File.should_receive(:file?).with("file/expanded.rb").and_return(true) - @script.entries("file").should == ["file/expanded.rb"] + expect(File).to receive(:realpath).with("file").and_return("file/expanded.rb") + expect(File).to receive(:file?).with("file/expanded.rb").and_return(true) + expect(@script.entries("file")).to eq(["file/expanded.rb"]) end it "returns Dir['pattern/**/*_spec.rb'] if pattern is a directory" do - File.should_receive(:directory?).with("name").and_return(true) - File.stub(:expand_path).and_return("name","name/**/*_spec.rb") - Dir.should_receive(:[]).with("name/**/*_spec.rb").and_return(["dir1", "dir2"]) - @script.entries("name").should == ["dir1", "dir2"] + expect(File).to receive(:directory?).with("name").and_return(true) + allow(File).to receive(:realpath).and_return("name", "name/**/*_spec.rb") + expect(Dir).to receive(:[]).with("name/**/*_spec.rb").and_return(["dir1", "dir2"]) + expect(@script.entries("name")).to eq(["dir1", "dir2"]) end it "aborts if pattern cannot be resolved to a file nor a directory" do - @script.should_receive(:abort) + expect(@script).to receive(:abort) @script.entries("pattern") end @@ -382,47 +377,47 @@ describe MSpecScript, "#entries" do it "returns the pattern in an array if it is a file" do name = "#{@name}.rb" - File.should_receive(:expand_path).with(name).and_return(name) - File.should_receive(:file?).with(name).and_return(true) - @script.entries("name.rb").should == [name] + expect(File).to receive(:realpath).with(name).and_return(name) + expect(File).to receive(:file?).with(name).and_return(true) + expect(@script.entries("name.rb")).to eq([name]) end it "returns Dir['pattern/**/*_spec.rb'] if pattern is a directory" do - File.stub(:expand_path).and_return(@name, @name+"/**/*_spec.rb") - File.should_receive(:directory?).with(@name).and_return(true) - Dir.should_receive(:[]).with(@name + "/**/*_spec.rb").and_return(["dir1", "dir2"]) - @script.entries("name").should == ["dir1", "dir2"] + allow(File).to receive(:realpath).and_return(@name, @name+"/**/*_spec.rb") + expect(File).to receive(:directory?).with(@name).and_return(true) + expect(Dir).to receive(:[]).with(@name + "/**/*_spec.rb").and_return(["dir1", "dir2"]) + expect(@script.entries("name")).to eq(["dir1", "dir2"]) end it "aborts if pattern cannot be resolved to a file nor a directory" do - @script.should_receive(:abort) + expect(@script).to receive(:abort) @script.entries("pattern") end end end -describe MSpecScript, "#files" do +RSpec.describe MSpecScript, "#files" do before :each do @script = MSpecScript.new end - it "accumlates the values returned by #entries" do - @script.should_receive(:entries).and_return(["file1"], ["file2"]) - @script.files(["a", "b"]).should == ["file1", "file2"] + it "accumulates the values returned by #entries" do + expect(@script).to receive(:entries).and_return(["file1"], ["file2"]) + expect(@script.files(["a", "b"])).to eq(["file1", "file2"]) end it "strips a leading '^' and removes the values returned by #entries" do - @script.should_receive(:entries).and_return(["file1"], ["file2"], ["file1"]) - @script.files(["a", "b", "^a"]).should == ["file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file2"], ["file1"]) + expect(@script.files(["a", "b", "^a"])).to eq(["file2"]) end it "processes the array elements in order" do - @script.should_receive(:entries).and_return(["file1"], ["file1"], ["file2"]) - @script.files(["^a", "a", "b"]).should == ["file1", "file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file1"], ["file2"]) + expect(@script.files(["^a", "a", "b"])).to eq(["file1", "file2"]) end end -describe MSpecScript, "#files" do +RSpec.describe MSpecScript, "#files" do before :each do MSpecScript.set :files, ["file1", "file2"] @@ -434,21 +429,21 @@ describe MSpecScript, "#files" do end it "looks up items with leading ':' in the config object" do - @script.should_receive(:entries).and_return(["file1"], ["file2"]) - @script.files([":files"]).should == ["file1", "file2"] + expect(@script).to receive(:entries).and_return(["file1"], ["file2"]) + expect(@script.files([":files"])).to eq(["file1", "file2"]) end it "aborts if the config key is not set" do - @script.should_receive(:abort).with("Key :all_files not found in mspec config.") + expect(@script).to receive(:abort).with("Key :all_files not found in mspec config.") @script.files([":all_files"]) end end -describe MSpecScript, "#setup_env" do +RSpec.describe MSpecScript, "#setup_env" do before :each do @script = MSpecScript.new @options, @config = new_option - @script.stub(:config).and_return(@config) + allow(@script).to receive(:config).and_return(@config) end after :each do @@ -457,19 +452,19 @@ describe MSpecScript, "#setup_env" do it "sets MSPEC_RUNNER = '1' in the environment" do ENV["MSPEC_RUNNER"] = "0" @script.setup_env - ENV["MSPEC_RUNNER"].should == "1" + expect(ENV["MSPEC_RUNNER"]).to eq("1") end it "sets RUBY_EXE = config[:target] in the environment" do ENV["RUBY_EXE"] = nil @script.setup_env - ENV["RUBY_EXE"].should == @config[:target] + expect(ENV["RUBY_EXE"]).to eq(@config[:target]) end it "sets RUBY_FLAGS = config[:flags] in the environment" do ENV["RUBY_FLAGS"] = nil @config[:flags] = ["-w", "-Q"] @script.setup_env - ENV["RUBY_FLAGS"].should == "-w -Q" + expect(ENV["RUBY_FLAGS"]).to eq("-w -Q") end end diff --git a/spec/mspec/spec/utils/version_spec.rb b/spec/mspec/spec/utils/version_spec.rb index 0b2d383c6d..ec367d2a1e 100644 --- a/spec/mspec/spec/utils/version_spec.rb +++ b/spec/mspec/spec/utils/version_spec.rb @@ -1,45 +1,45 @@ require 'spec_helper' require 'mspec/utils/version' -describe SpecVersion, "#to_s" do +RSpec.describe SpecVersion, "#to_s" do it "returns the string with which it was initialized" do - SpecVersion.new("1.8").to_s.should == "1.8" - SpecVersion.new("2.118.9").to_s.should == "2.118.9" + expect(SpecVersion.new("1.8").to_s).to eq("1.8") + expect(SpecVersion.new("2.118.9").to_s).to eq("2.118.9") end end -describe SpecVersion, "#to_str" do +RSpec.describe SpecVersion, "#to_str" do it "returns the same string as #to_s" do version = SpecVersion.new("2.118.9") - version.to_str.should == version.to_s + expect(version.to_str).to eq(version.to_s) end end -describe SpecVersion, "#to_i with ceil = false" do +RSpec.describe SpecVersion, "#to_i with ceil = false" do it "returns an integer representation of the version string" do - SpecVersion.new("2.23.10").to_i.should == 1022310 + expect(SpecVersion.new("2.23.10").to_i).to eq(1022310) end it "replaces missing version parts with zeros" do - SpecVersion.new("1.8").to_i.should == 1010800 - SpecVersion.new("1.8.6").to_i.should == 1010806 + expect(SpecVersion.new("1.8").to_i).to eq(1010800) + expect(SpecVersion.new("1.8.6").to_i).to eq(1010806) end end -describe SpecVersion, "#to_i with ceil = true" do +RSpec.describe SpecVersion, "#to_i with ceil = true" do it "returns an integer representation of the version string" do - SpecVersion.new("1.8.6", true).to_i.should == 1010806 + expect(SpecVersion.new("1.8.6", true).to_i).to eq(1010806) end it "fills in 9s for missing tiny values" do - SpecVersion.new("1.8", true).to_i.should == 1010899 - SpecVersion.new("1.8.6", true).to_i.should == 1010806 + expect(SpecVersion.new("1.8", true).to_i).to eq(1010899) + expect(SpecVersion.new("1.8.6", true).to_i).to eq(1010806) end end -describe SpecVersion, "#to_int" do +RSpec.describe SpecVersion, "#to_int" do it "returns the same value as #to_i" do version = SpecVersion.new("4.16.87") - version.to_int.should == version.to_i + expect(version.to_int).to eq(version.to_i) end end diff --git a/spec/mspec/tool/check_require_spec_helper.rb b/spec/mspec/tool/check_require_spec_helper.rb new file mode 100755 index 0000000000..07126e68dc --- /dev/null +++ b/spec/mspec/tool/check_require_spec_helper.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby + +# This script is used to check that each *_spec.rb file has +# a relative_require for spec_helper which should live higher +# up in the ruby/spec repo directory tree. +# +# Prints errors to $stderr and returns a non-zero exit code when +# errors are found. +# +# Related to https://github.com/ruby/spec/pull/992 + +def check_file(fn) + File.foreach(fn) do |line| + return $1 if line =~ /^\s*require_relative\s*['"](.*spec_helper)['"]/ + end + nil +end + +rootdir = ARGV[0] || "." +fglob = File.join(rootdir, "**", "*_spec.rb") +specfiles = Dir.glob(fglob) +raise "No spec files found in #{fglob.inspect}. Give an argument to specify the root-directory of ruby/spec" if specfiles.empty? + +errors = 0 +specfiles.sort.each do |fn| + result = check_file(fn) + if result.nil? + warn "Missing require_relative for *spec_helper for file: #{fn}" + errors += 1 + end +end + +puts "# Found #{errors} files with require_relative spec_helper issues." +exit 1 if errors > 0 diff --git a/spec/mspec/tool/pull-latest-mspec-spec b/spec/mspec/tool/pull-latest-mspec-spec new file mode 100755 index 0000000000..154a353e64 --- /dev/null +++ b/spec/mspec/tool/pull-latest-mspec-spec @@ -0,0 +1,26 @@ +#!/bin/bash + +# Assumes all commits have been synchronized to https://github.com/ruby/spec +# See spec/mspec/tool/sync/sync-rubyspec.rb + +function sync { + dir="$1" + repo="$2" + short_repo_name="ruby/$(basename "$repo" .git)" + + rm -rf "$dir" + git clone --depth 1 "$repo" "$dir" + commit=$(git -C "$dir" log -n 1 --format='%h') + rm -rf "$dir/.git" + + # Remove CI files to avoid confusion + rm -f "$dir/appveyor.yml" + rm -f "$dir/.travis.yml" + rm -rf "$dir/.github" + + git add "$dir" + git commit -m "Update to ${short_repo_name}@${commit}" +} + +sync spec/mspec https://github.com/ruby/mspec.git +sync spec/ruby https://github.com/ruby/spec.git diff --git a/spec/mspec/tool/remove_old_guards.rb b/spec/mspec/tool/remove_old_guards.rb index d0920344eb..bc5612c78d 100644..100755 --- a/spec/mspec/tool/remove_old_guards.rb +++ b/spec/mspec/tool/remove_old_guards.rb @@ -1,4 +1,23 @@ -# Remove old version guards in ruby/spec +#!/usr/bin/env ruby + +# Removes old version guards in ruby/spec. +# Run it from the ruby/spec repository root. +# The argument is the new minimum supported version. +# +# cd spec +# ../mspec/tool/remove_old_guards.rb <ruby-version> +# +# where <ruby-version> is a version guard with which should be removed +# +# Example: +# tool/remove_old_guards.rb 3.1 +# +# As a result guards like +# ruby_version_is "3.1" do +# # ... +# end +# +# will be removed. def dedent(line) if line.start_with?(" ") @@ -8,34 +27,119 @@ def dedent(line) end end +def each_spec_file(&block) + Dir["*/**/*.rb"].each(&block) +end + +def each_file(&block) + Dir["**/*"].each { |path| + yield path if File.file?(path) + } +end + def remove_guards(guard, keep) - Dir["*/**/*.rb"].each do |file| - contents = File.read(file) + each_spec_file do |file| + contents = File.binread(file) if contents =~ guard puts file lines = contents.lines.to_a while first = lines.find_index { |line| line =~ guard } + comment = first + while comment > 0 and lines[comment-1] =~ /^(\s*)#/ + comment -= 1 + end indent = lines[first][/^(\s*)/, 1].length last = (first+1...lines.size).find { |i| space = lines[i][/^(\s*)end$/, 1] and space.length == indent } raise file unless last if keep - lines[first..last] = lines[first+1..last-1].map { |l| dedent(l) } + lines[comment..last] = lines[first+1..last-1].map { |l| dedent(l) } else - if first > 0 and lines[first-1] == "\n" - first -= 1 + if comment > 0 and lines[comment-1] == "\n" + comment -= 1 elsif lines[last+1] == "\n" last += 1 end - lines[first..last] = [] + lines[comment..last] = [] end end - File.write file, lines.join + File.binwrite file, lines.join + end + end +end + +def remove_empty_files + each_spec_file do |file| + unless file.include?("fixtures/") + lines = File.readlines(file) + if lines.all? { |line| line.chomp.empty? or line.start_with?('require', '#') } + puts "Removing empty file #{file}" + File.delete(file) + end end end end -version = "2.2" -remove_guards(/ruby_version_is ["']#{version}["'] do/, true) -remove_guards(/ruby_version_is ["'][0-9.]*["']...["']#{version}["'] do/, false) +def remove_unused_shared_specs + shared_groups = {} + # Dir["**/shared/**/*.rb"].each do |shared| + each_spec_file do |shared| + next if File.basename(shared) == 'constants.rb' + contents = File.binread(shared) + found = false + contents.scan(/^\s*describe (:[\w_?]+), shared: true do$/) { + shared_groups[$1] = 0 + found = true + } + if !found and shared.include?('shared/') and !shared.include?('fixtures/') and !shared.end_with?('/constants.rb') + puts "no shared describe in #{shared} ?" + end + end + + each_spec_file do |file| + contents = File.binread(file) + contents.scan(/(?:it_behaves_like|it_should_behave_like) (:[\w_?]+)[,\s]/) do + puts $1 unless shared_groups.key?($1) + shared_groups[$1] += 1 + end + end + + shared_groups.each_pair do |group, value| + if value == 0 + puts "Shared describe #{group} seems unused" + elsif value == 1 + puts "Shared describe #{group} seems used only once" if $VERBOSE + end + end +end + +def search(regexp) + each_file do |file| + contents = File.binread(file) + if contents =~ regexp + puts file + contents.each_line do |line| + if line =~ regexp + puts line + end + end + end + end +end + +abort "usage: #{$0} <ruby-version>" if ARGV.empty? + +version = Regexp.escape(ARGV.fetch(0)) +version += "(?:\\.0)?" if version.count(".") < 2 +remove_guards(/ruby_version_is (["'])#{version}\1 do/, true) +remove_guards(/ruby_version_is (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, false) +remove_guards(/ruby_bug ["']#\d+["'], (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, true) + +remove_empty_files +remove_unused_shared_specs + +puts "Search:" +search(/(["'])#{version}\1/) +search(/^\s*#.+#{version}/) +search(/RUBY_VERSION_IS_#{version.tr('.', '_')}/) diff --git a/spec/mspec/tool/sync/sync-rubyspec.rb b/spec/mspec/tool/sync/sync-rubyspec.rb index fbd37fe95b..86c43d0dc8 100644 --- a/spec/mspec/tool/sync/sync-rubyspec.rb +++ b/spec/mspec/tool/sync/sync-rubyspec.rb @@ -1,6 +1,9 @@ +# This script is based on commands from the wiki: +# https://github.com/ruby/spec/wiki/Merging-specs-from-JRuby-and-other-sources + IMPLS = { truffleruby: { - git: "https://github.com/graalvm/truffleruby.git", + git: "https://github.com/truffleruby/truffleruby.git", from_commit: "f10ab6988d", }, jruby: { @@ -12,13 +15,16 @@ IMPLS = { }, mri: { git: "https://github.com/ruby/ruby.git", - master: "trunk", - merge_message: "Update to ruby/spec@", }, } MSPEC = ARGV.delete('--mspec') +CHECK_LAST_MERGE = !MSPEC && ENV['CHECK_LAST_MERGE'] != 'false' +TEST_MASTER = ENV['TEST_MASTER'] != 'false' + +ONLY_FILTER = ENV['ONLY_FILTER'] == 'true' + MSPEC_REPO = File.expand_path("../../..", __FILE__) raise MSPEC_REPO if !Dir.exist?(MSPEC_REPO) or !Dir.exist?("#{MSPEC_REPO}/.git") @@ -28,12 +34,22 @@ raise RUBYSPEC_REPO unless Dir.exist?(RUBYSPEC_REPO) SOURCE_REPO = MSPEC ? MSPEC_REPO : RUBYSPEC_REPO +# LAST_MERGE is a commit of ruby/spec or ruby/mspec +# which is the spec/mspec commit that was last imported in the Ruby implementation +# (i.e. the commit in "Update to ruby/spec@commit"). +# It is normally automatically computed, but can be manually set when +# e.g. the last update of specs wasn't merged in the Ruby implementation. +LAST_MERGE = ENV["LAST_MERGE"] + NOW = Time.now BRIGHT_RED = "\e[31;1m" BRIGHT_YELLOW = "\e[33;1m" RESET = "\e[0m" +# git filter-branch --subdirectory-filter works fine for our use case +ENV['FILTER_BRANCH_SQUELCH_WARNING'] = '1' + class RubyImplementation attr_reader :name @@ -46,14 +62,14 @@ class RubyImplementation @data[:git] end - def default_branch - @data[:master] || "master" - end - def repo_name File.basename(git_url, ".git") end + def repo_path + "#{__dir__}/#{repo_name}" + end + def repo_org File.basename(File.dirname(git_url)) end @@ -64,7 +80,7 @@ class RubyImplementation end def last_merge_message - message = @data[:merge_message] || "Merge ruby/spec commit" + message = @data[:merge_message] || "Update to ruby/spec@" message.gsub!("ruby/spec", "ruby/mspec") if MSPEC message end @@ -97,7 +113,7 @@ def update_repo(impl) Dir.chdir(impl.repo_name) do puts Dir.pwd - sh "git", "checkout", impl.default_branch + sh "git", "checkout", "master" sh "git", "pull" end end @@ -133,22 +149,27 @@ def rebase_commits(impl) else sh "git", "checkout", impl.name - if ENV["LAST_MERGE"] - last_merge = `git log -n 1 --format='%H %ct' #{ENV["LAST_MERGE"]}` + if LAST_MERGE + last_merge = `git log -n 1 --format='%H %ct' #{LAST_MERGE}` else last_merge = `git log --grep='^#{impl.last_merge_message}' -n 1 --format='%H %ct'` end - last_merge, commit_timestamp = last_merge.chomp.split(' ') + last_merge, commit_timestamp = last_merge.split(' ') raise "Could not find last merge" unless last_merge puts "Last merge is #{last_merge}" commit_date = Time.at(Integer(commit_timestamp)) days_since_last_merge = (NOW-commit_date) / 86400 - if days_since_last_merge > 60 + if CHECK_LAST_MERGE and days_since_last_merge > 60 raise "#{days_since_last_merge.floor} days since last merge, probably wrong commit" end + puts "Checking if the last merge is consistent with upstream files" + rubyspec_commit = `git log -n 1 --format='%s' #{last_merge}`.chomp.split('@', 2)[-1] + sh "git", "checkout", last_merge + sh "git", "diff", "--exit-code", rubyspec_commit, "--", ":!.github" + puts "Rebasing..." sh "git", "branch", "-D", rebased if branch?(rebased) sh "git", "checkout", "-b", rebased, impl.name @@ -157,53 +178,40 @@ def rebase_commits(impl) end end -def test_new_specs - require "yaml" +def new_commits?(impl) Dir.chdir(SOURCE_REPO) do - if MSPEC - sh "bundle", "exec", "rspec" - else - versions = YAML.load_file(".travis.yml") - versions = versions["matrix"]["include"].map { |job| job["rvm"] } - versions.delete "ruby-head" - min_version, max_version = versions.minmax - - run_rubyspec = -> version { - command = "chruby #{version} && ../mspec/bin/mspec -j" - sh ENV["SHELL"], "-c", command - } - run_rubyspec[min_version] - run_rubyspec[max_version] - run_rubyspec["trunk"] - end + diff = `git diff master #{impl.rebased_branch}` + !diff.empty? end end -def verify_commits(impl) - puts +def test_new_specs + require "yaml" Dir.chdir(SOURCE_REPO) do - history = `git log master...` - history.lines.slice_before(/^commit \h{40}$/).each do |commit, *message| - commit = commit.chomp.split.last - message = message.join - if /\W(#\d+)/ === message - puts "Commit #{commit} contains an unqualified issue number: #{$1}" - puts "Replace it with #{impl.repo_org}/#{impl.repo_name}#{$1}" - sh "git", "rebase", "-i", "#{commit}^" - end - end + workflow = YAML.load_file(".github/workflows/ci.yml") + job_name = MSPEC ? "test" : "specs" + versions = workflow.dig("jobs", job_name, "strategy", "matrix", "ruby").map(&:to_s) + versions = versions.grep(/^\d+\./) # Test on MRI + min_version, max_version = versions.minmax + + test_command = MSPEC ? "bundle install && bundle exec rspec" : "../mspec/bin/mspec -j" + + run_test = -> version { + command = "chruby ruby-#{version} && #{test_command}" + sh ENV["SHELL"], "-c", command + } - puts "Manually check commit messages:" - print "Press enter >" - STDIN.gets - sh "git", "log", "master..." + run_test[min_version] + run_test[max_version] + run_test["master"] if TEST_MASTER end end def fast_forward_master(impl) Dir.chdir(SOURCE_REPO) do sh "git", "checkout", "master" - sh "git", "merge", "--ff-only", "#{impl.name}-rebased" + sh "git", "merge", "--ff-only", impl.rebased_branch + sh "git", "branch", "--delete", impl.rebased_branch end end @@ -221,11 +229,17 @@ def main(impls) impl = RubyImplementation.new(impl, data) update_repo(impl) filter_commits(impl) - rebase_commits(impl) - test_new_specs - verify_commits(impl) - fast_forward_master(impl) - check_ci + unless ONLY_FILTER + rebase_commits(impl) + if new_commits?(impl) + test_new_specs + fast_forward_master(impl) + check_ci + else + STDERR.puts "#{BRIGHT_YELLOW}No new commits#{RESET}" + fast_forward_master(impl) + end + end end end diff --git a/spec/mspec/tool/tag_from_output.rb b/spec/mspec/tool/tag_from_output.rb new file mode 100755 index 0000000000..41aa70f932 --- /dev/null +++ b/spec/mspec/tool/tag_from_output.rb @@ -0,0 +1,65 @@ +#!/usr/bin/env ruby + +# Adds tags based on error and failures output (e.g., from a CI log), +# without running any spec code. + +tag = ENV["TAG"] || "fails" + +tags_dir = %w[ + spec/tags + spec/tags/ruby +].find { |dir| Dir.exist?("#{dir}/language") } +abort 'Could not find tags directory' unless tags_dir + +output = ARGF.readlines + +# Automatically strip datetime of GitHub Actions +if output.first =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z / + output = output.map { |line| line.split(' ', 2).last } +end + +NUMBER = /^\d+\)$/ +ERROR_OR_FAILED = / (ERROR|FAILED)$/ +SPEC_FILE = /^((?:\/|[CD]:\/).+_spec\.rb)\:\d+/ + +output.slice_before(NUMBER).select { |number, *rest| + number =~ NUMBER and rest.any? { |line| line =~ ERROR_OR_FAILED } +}.each { |number, *rest| + error_line = rest.find { |line| line =~ ERROR_OR_FAILED } + description = error_line.match(ERROR_OR_FAILED).pre_match + + spec_file = rest.find { |line| line =~ SPEC_FILE } + if spec_file + spec_file = spec_file[SPEC_FILE, 1] or raise + else + if error_line =~ /^([\w:]+)[#\.](\w+) / + mod, method = $1, $2 + file = "#{mod.downcase.gsub('::', '/')}/#{method}_spec.rb" + spec_file = ['spec/ruby/core', 'spec/ruby/library', *Dir.glob('spec/ruby/library/*')].find { |dir| + path = "#{dir}/#{file}" + break path if File.exist?(path) + } + end + + unless spec_file + warn "Could not find file for:\n#{error_line}" + next + end + end + + prefix = spec_file.index('spec/ruby/') || spec_file.index('spec/truffle/') + spec_file = spec_file[prefix..-1] + + tags_file = spec_file.sub('spec/ruby/', "#{tags_dir}/").sub('spec/truffle/', "#{tags_dir}/truffle/") + tags_file = tags_file.sub(/_spec\.rb$/, '_tags.txt') + + dir = File.dirname(tags_file) + Dir.mkdir(dir) unless Dir.exist?(dir) + + tag_line = "#{tag}:#{description}" + lines = File.exist?(tags_file) ? File.readlines(tags_file, chomp: true) : [] + unless lines.include?(tag_line) + puts tags_file + File.write(tags_file, (lines + [tag_line]).join("\n") + "\n") + end +} diff --git a/spec/mspec/tool/wrap_with_guard.rb b/spec/mspec/tool/wrap_with_guard.rb new file mode 100755 index 0000000000..5b1bf4d7f7 --- /dev/null +++ b/spec/mspec/tool/wrap_with_guard.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +# Wrap the passed the files with a guard (e.g., `ruby_version_is ""..."3.0"`). +# Notably if some methods are removed, this is a convenient way to skip such file from a given version. +# Example usage: +# $ spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.0"' spec/ruby/library/set/sortedset/**/*_spec.rb + +guard, *files = ARGV +abort "Usage: #{$0} GUARD FILES..." if files.empty? + +files.each do |file| + contents = File.binread(file) + lines = contents.lines.to_a + + lines = lines.map { |line| line.chomp.empty? ? line : " #{line}" } + + version_line = "#{guard} do\n" + if lines[0] =~ /^\s*require.+spec_helper/ + lines[0] = lines[0].sub(/^ /, '') + lines.insert 1, "\n", version_line + else + warn "Could not find 'require spec_helper' line in #{file}" + lines.insert 0, version_line + end + + lines << "end\n" + + File.binwrite file, lines.join +end |
