2014-06-30 13:55:58 +00:00
|
|
|
# encoding: UTF-8
|
|
|
|
require 'rspec/core'
|
|
|
|
require 'rspec/core/formatters/base_text_formatter'
|
|
|
|
|
2012-12-07 16:55:53 +01:00
|
|
|
module Mutant
|
2014-06-28 23:04:18 +00:00
|
|
|
class Integration
|
2014-06-28 23:54:04 +00:00
|
|
|
# Shared parts of rspec2/3 integration
|
2014-06-28 23:04:18 +00:00
|
|
|
class Rspec < self
|
2014-06-28 23:54:04 +00:00
|
|
|
include AbstractType
|
2014-05-23 02:33:15 +00:00
|
|
|
|
2014-07-12 16:38:51 +00:00
|
|
|
register 'rspec'
|
|
|
|
|
|
|
|
RSPEC_2_VERSION_PREFIX = '2.'.freeze
|
|
|
|
|
|
|
|
# Return integration compatible to currently loaded rspec
|
|
|
|
#
|
|
|
|
# @return [Integration]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def self.build
|
|
|
|
if RSpec::Core::Version::STRING.start_with?(RSPEC_2_VERSION_PREFIX)
|
|
|
|
Rspec2.new
|
|
|
|
else
|
|
|
|
Rspec3.new
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-06-28 23:04:18 +00:00
|
|
|
# Setup rspec integration
|
2013-01-18 21:38:46 +01:00
|
|
|
#
|
|
|
|
# @return [self]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2013-07-17 19:59:44 +02:00
|
|
|
def setup
|
2013-08-04 18:49:42 +02:00
|
|
|
options.configure(configuration)
|
|
|
|
configuration.load_spec_files
|
2013-01-18 21:38:46 +01:00
|
|
|
self
|
|
|
|
end
|
2013-08-04 18:49:42 +02:00
|
|
|
memoize :setup
|
|
|
|
|
2014-05-23 02:33:15 +00:00
|
|
|
# Return report for test
|
|
|
|
#
|
|
|
|
# @param [Rspec::Test] test
|
2014-04-28 19:17:25 +00:00
|
|
|
#
|
2014-07-03 21:16:12 +00:00
|
|
|
# @return [Test::Result]
|
2014-06-28 20:52:47 +00:00
|
|
|
#
|
2014-04-28 19:17:25 +00:00
|
|
|
# @api private
|
|
|
|
#
|
2014-07-03 21:16:12 +00:00
|
|
|
# rubocop:disable MethodLength
|
|
|
|
#
|
2014-05-23 02:33:15 +00:00
|
|
|
def run(test)
|
|
|
|
output = StringIO.new
|
2014-07-02 20:27:04 +00:00
|
|
|
failed = false
|
2014-07-03 21:16:12 +00:00
|
|
|
start = Time.now
|
2014-05-23 02:33:15 +00:00
|
|
|
reporter = new_reporter(output)
|
|
|
|
reporter.report(1) do
|
2014-07-02 20:27:04 +00:00
|
|
|
example_group_index.fetch(test.expression.syntax).each do |example_group|
|
2014-07-03 21:16:12 +00:00
|
|
|
next if example_group.run(reporter)
|
|
|
|
failed = true
|
|
|
|
break
|
2014-07-02 20:27:04 +00:00
|
|
|
end
|
2014-04-28 19:17:25 +00:00
|
|
|
end
|
2014-05-23 02:33:15 +00:00
|
|
|
output.rewind
|
2014-07-03 21:16:12 +00:00
|
|
|
Result::Test.new(
|
|
|
|
test: self,
|
|
|
|
output: output.read,
|
|
|
|
runtime: Time.now - start,
|
|
|
|
mutation: nil,
|
|
|
|
passed: !failed
|
2014-05-23 02:33:15 +00:00
|
|
|
)
|
2014-04-28 19:17:25 +00:00
|
|
|
end
|
|
|
|
|
2014-05-23 02:33:15 +00:00
|
|
|
# Return all available tests
|
2014-04-28 19:17:25 +00:00
|
|
|
#
|
2014-05-23 02:33:15 +00:00
|
|
|
# @return [Enumerable<Test>]
|
2014-04-28 19:17:25 +00:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2014-05-23 02:33:15 +00:00
|
|
|
def all_tests
|
2014-06-28 22:48:56 +00:00
|
|
|
example_group_index.keys.each_with_object([]) do |full_description, aggregate|
|
2014-06-29 23:16:34 +00:00
|
|
|
expression = Expression.try_parse(full_description) or next
|
2014-06-28 20:47:46 +00:00
|
|
|
|
2014-06-28 22:48:56 +00:00
|
|
|
aggregate << Test.new(self, expression)
|
2014-06-28 20:47:46 +00:00
|
|
|
end
|
2014-04-28 19:17:25 +00:00
|
|
|
end
|
2014-05-23 02:33:15 +00:00
|
|
|
memoize :all_tests
|
2014-04-28 19:17:25 +00:00
|
|
|
|
2014-05-23 02:33:15 +00:00
|
|
|
private
|
|
|
|
|
2014-06-28 20:47:46 +00:00
|
|
|
# Return all example groups
|
|
|
|
#
|
2014-06-28 22:48:56 +00:00
|
|
|
# @return [Hash<String, RSpec::Core::ExampleGroup]
|
2014-06-28 20:47:46 +00:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2014-06-28 22:48:56 +00:00
|
|
|
def example_group_index
|
2014-07-02 20:27:04 +00:00
|
|
|
index = Hash.new { |hash, key| hash[key] = [] }
|
|
|
|
|
|
|
|
RSpec.world.example_groups.flat_map(&:descendants).each do |example_group|
|
|
|
|
full_description = full_description(example_group)
|
|
|
|
index[full_description] << example_group
|
|
|
|
end
|
|
|
|
|
|
|
|
index
|
2014-06-28 20:47:46 +00:00
|
|
|
end
|
2014-06-28 22:48:56 +00:00
|
|
|
memoize :example_group_index
|
2014-06-28 20:47:46 +00:00
|
|
|
|
2014-05-23 02:33:15 +00:00
|
|
|
# Return configuration
|
2014-04-28 19:17:25 +00:00
|
|
|
#
|
2014-05-23 02:33:15 +00:00
|
|
|
# @return [RSpec::Core::Configuration]
|
2014-04-28 19:17:25 +00:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2014-05-23 02:33:15 +00:00
|
|
|
def configuration
|
|
|
|
RSpec::Core::Configuration.new
|
2014-04-28 19:17:25 +00:00
|
|
|
end
|
2014-05-23 02:33:15 +00:00
|
|
|
memoize :configuration, freezer: :noop
|
2014-04-28 19:17:25 +00:00
|
|
|
|
2013-08-04 18:49:42 +02:00
|
|
|
# Return options
|
|
|
|
#
|
|
|
|
# @return [RSpec::Core::ConfigurationOptions]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def options
|
2014-06-28 23:54:04 +00:00
|
|
|
RSpec::Core::ConfigurationOptions.new(%w[--fail-fast spec])
|
2013-08-04 18:49:42 +02:00
|
|
|
end
|
2013-09-07 20:27:06 +02:00
|
|
|
memoize :options, freezer: :noop
|
2013-01-18 21:38:46 +01:00
|
|
|
|
2014-07-12 16:38:51 +00:00
|
|
|
# Rspec2 integration
|
|
|
|
class Rspec2 < self
|
|
|
|
|
|
|
|
register 'rspec'
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# Return options
|
|
|
|
#
|
|
|
|
# @return [RSpec::Core::ConfigurationOptions]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def options
|
|
|
|
super.tap(&:parse_options)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return full description of example group
|
|
|
|
#
|
|
|
|
# @param [RSpec::Core::ExampleGroup] example_group
|
|
|
|
#
|
|
|
|
# @return [String]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def full_description(example_group)
|
|
|
|
example_group.metadata.fetch(:example_group).fetch(:full_description)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return new reporter
|
|
|
|
#
|
|
|
|
# @param [StringIO] output
|
|
|
|
#
|
|
|
|
# @return [RSpec::Core::Reporter]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def new_reporter(output)
|
|
|
|
formatter = RSpec::Core::Formatters::BaseTextFormatter.new(output)
|
|
|
|
|
|
|
|
RSpec::Core::Reporter.new(formatter)
|
|
|
|
end
|
|
|
|
|
|
|
|
end # Rspec2
|
|
|
|
|
|
|
|
# Rspec 3 integration
|
|
|
|
class Rspec3 < self
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# Return full description for example group
|
|
|
|
#
|
|
|
|
# @param [RSpec::Core::ExampleGroup] example_group
|
|
|
|
#
|
|
|
|
# @return [String]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def full_description(example_group)
|
|
|
|
example_group.metadata.fetch(:full_description)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return new reporter
|
|
|
|
#
|
|
|
|
# @param [StringIO] output
|
|
|
|
#
|
|
|
|
# @return [RSpec::Core::Reporter]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def new_reporter(output)
|
|
|
|
formatter = RSpec::Core::Formatters::BaseTextFormatter.new(output)
|
|
|
|
notifications = RSpec::Core::Formatters::Loader.allocate.send(:notifications_for, formatter.class)
|
|
|
|
|
|
|
|
RSpec::Core::Reporter.new(configuration).tap do |reporter|
|
|
|
|
reporter.register_listener(formatter, *notifications)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end # Rspec3
|
2014-06-28 23:04:18 +00:00
|
|
|
end # Rspec
|
|
|
|
end # Integration
|
2013-06-14 20:54:02 +02:00
|
|
|
end # Mutant
|