mutant 0.3.6 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/Changelog.md +13 -0
  4. data/Gemfile +1 -1
  5. data/Guardfile +7 -25
  6. data/LICENSE +1 -1
  7. data/README.md +16 -10
  8. data/config/flay.yml +1 -1
  9. data/config/reek.yml +11 -11
  10. data/config/rubocop.yml +1 -1
  11. data/lib/mutant.rb +3 -10
  12. data/lib/mutant/cli.rb +199 -80
  13. data/lib/mutant/config.rb +3 -3
  14. data/lib/mutant/killer.rb +20 -0
  15. data/lib/mutant/matcher/filter.rb +3 -8
  16. data/lib/mutant/matcher/method/instance.rb +1 -1
  17. data/lib/mutant/matcher/namespace.rb +31 -2
  18. data/lib/mutant/matcher/null.rb +26 -0
  19. data/lib/mutant/mutation.rb +0 -1
  20. data/lib/mutant/reporter/cli/printer.rb +29 -0
  21. data/lib/mutant/reporter/cli/printer/config.rb +16 -116
  22. data/lib/mutant/runner/config.rb +47 -1
  23. data/lib/mutant/strategy.rb +39 -1
  24. data/lib/mutant/version.rb +1 -1
  25. data/lib/mutant/walker.rb +51 -0
  26. data/mutant-rspec.gemspec +24 -0
  27. data/mutant.gemspec +7 -3
  28. data/spec/integration/mutant/rspec_spec.rb +11 -6
  29. data/spec/integration/mutant/zombie_spec.rb +2 -2
  30. data/spec/shared/method_matcher_behavior.rb +6 -6
  31. data/spec/spec_helper.rb +2 -2
  32. data/spec/unit/mutant/cli_new_spec.rb +49 -34
  33. data/spec/unit/mutant/context/scope/root_spec.rb +1 -1
  34. data/spec/unit/mutant/loader/eval_spec.rb +2 -2
  35. data/spec/unit/mutant/matcher/chain_spec.rb +1 -1
  36. data/spec/unit/mutant/matcher/methods/instance_spec.rb +1 -1
  37. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +1 -1
  38. data/spec/unit/mutant/matcher/namespace_spec.rb +1 -1
  39. data/spec/unit/mutant/mutation_spec.rb +1 -1
  40. data/spec/unit/mutant/{killer/rspec_spec.rb → rspec/killer_spec.rb} +2 -1
  41. data/spec/unit/mutant/runner/config_spec.rb +36 -21
  42. data/spec/unit/mutant_spec.rb +7 -9
  43. metadata +25 -22
  44. data/lib/mutant/cli/builder.rb +0 -167
  45. data/lib/mutant/killer/rspec.rb +0 -95
  46. data/lib/mutant/predicate.rb +0 -70
  47. data/lib/mutant/predicate/attribute.rb +0 -68
  48. data/lib/mutant/predicate/blacklist.rb +0 -27
  49. data/lib/mutant/predicate/matcher.rb +0 -38
  50. data/lib/mutant/predicate/whitelist.rb +0 -28
  51. data/lib/mutant/strategy/rspec.rb +0 -76
  52. data/spec/unit/mutant/cli/builder/rspec_spec.rb +0 -38
  53. data/spec/unit/mutant/matcher/filter_spec.rb +0 -19
  54. data/spec/unit/mutant/predicate_spec.rb +0 -135
@@ -1,95 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Killer
5
- # Runner for rspec tests
6
- class Rspec < self
7
-
8
- private
9
-
10
- # Run rspec test
11
- #
12
- # @return [true]
13
- # when test is NOT successful
14
- #
15
- # @return [false]
16
- # otherwise
17
- #
18
- # @api private
19
- #
20
- def run
21
- mutation.insert
22
-
23
- groups =
24
- if mutation.is_a?(Mutation::Neutral::Noop)
25
- [example_groups.first]
26
- else
27
- example_groups
28
- end
29
-
30
- unless groups
31
- $stderr.puts("No rspec example groups found for: #{match_prefixes.join(', ')}")
32
- return false
33
- end
34
-
35
- reporter = RSpec::Core::Reporter.new
36
-
37
- example_groups.each do |group|
38
- return true unless group.run(reporter)
39
- end
40
-
41
- false
42
- end
43
-
44
- # Return match prefixes
45
- #
46
- # @return [Enumerble<String>]
47
- #
48
- # @api private
49
- #
50
- def match_prefixes
51
- subject.match_prefixes
52
- end
53
-
54
- # Return example groups
55
- #
56
- # @return [Array<RSpec::Example>]
57
- #
58
- # @api private
59
- #
60
- def example_groups
61
- match_prefixes.each do |match_expression|
62
- example_groups = find_with(match_expression)
63
- return example_groups unless example_groups.empty?
64
- end
65
-
66
- nil
67
- end
68
-
69
- # Return example groups that match expression
70
- #
71
- # @param [String] match_expression
72
- #
73
- # @return [Enumerable<String>]
74
- #
75
- # @api private
76
- #
77
- def find_with(match_expression)
78
- all_example_groups.select do |example_group|
79
- example_group.description.start_with?(match_expression)
80
- end
81
- end
82
-
83
- # Return all example groups
84
- #
85
- # @return [Enumerable<RSpec::Example>]
86
- #
87
- # @api private
88
- #
89
- def all_example_groups
90
- strategy.example_groups
91
- end
92
-
93
- end # Rspec
94
- end # Killer
95
- end # Mutant
@@ -1,70 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- # Abstract base class for predicates used to filter subjects / mutations
5
- class Predicate
6
- include Adamantium::Flat, AbstractType
7
- extend DescendantsTracker
8
-
9
- # Check for match
10
- #
11
- # @param [Object] object
12
- #
13
- # @return [true]
14
- # if object is matched by predicate
15
- #
16
- # @return [false]
17
- # otherwise
18
- #
19
- # @api private
20
- #
21
- abstract_method :match?
22
-
23
- # Return predicate for handle
24
- #
25
- # @param [String] _notation
26
- #
27
- # @return [nil]
28
- #
29
- # @api private
30
- #
31
- def self.handle(_notation)
32
- nil
33
- end
34
-
35
- # Mutation predicate matching no inputs
36
- Mutant.singleton_subclass_instance('CONTRADICTION', self) do
37
-
38
- # Test for match
39
- #
40
- # @pram [Mutation] _mutation
41
- #
42
- # @return [true]
43
- #
44
- # @api private
45
- #
46
- def match?(_mutation)
47
- false
48
- end
49
-
50
- end
51
-
52
- # Mutation predicate matching all inputs
53
- Mutant.singleton_subclass_instance('TAUTOLOGY', self) do
54
-
55
- # Test for match
56
- #
57
- # @pram [Mutation] _mutation
58
- #
59
- # @return [true]
60
- #
61
- # @api private
62
- #
63
- def match?(_mutation)
64
- true
65
- end
66
-
67
- end
68
-
69
- end # Filter
70
- end # Mutant
@@ -1,68 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Predicate
5
- # Base class for predicates on object attributes
6
- class Attribute < self
7
- include Concord.new(:attribute_name, :expectation)
8
-
9
- private
10
-
11
- # Return value for object
12
- #
13
- # @param [Object] object
14
- #
15
- # @return [Object]
16
- #
17
- # @api private
18
- #
19
- def value(object)
20
- object.public_send(attribute_name)
21
- end
22
-
23
- # Regexp based attribute predicate
24
- class Regexp < self
25
-
26
- # Test for match
27
- #
28
- # @param [Object] object
29
- #
30
- # @return [true]
31
- # if attribute value matches expectation
32
- #
33
- # @return [false]
34
- # otherwise
35
- #
36
- # @api private
37
- #
38
- def match?(object)
39
- !!(expectation =~ value(object))
40
- end
41
-
42
- end # Regexp
43
-
44
- # Equality based attribute predicate
45
- class Equality < self
46
-
47
- PATTERN = /\Acode:(?<code>[[:xdigit:]]{1,6})\z/.freeze
48
-
49
- # Test for match
50
- #
51
- # @param [Object] object
52
- #
53
- # @return [true]
54
- # if attribute value matches expectation
55
- #
56
- # @return [false]
57
- # otherwise
58
- #
59
- # @api private
60
- #
61
- def match?(object)
62
- expectation.eql?(value(object))
63
- end
64
-
65
- end # Equality
66
- end # Attribute
67
- end # Filter
68
- end # Mutant
@@ -1,27 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Predicate
5
- # Blacklist predicate
6
- class Blacklist < self
7
- include Adamantium::Flat, Concord.new(:blacklist)
8
-
9
- # Test for match
10
- #
11
- # @param [Object] object
12
- #
13
- # @return [true]
14
- # if object matches blacklist
15
- #
16
- # @return [false]
17
- # otherwise
18
- #
19
- # @api private
20
- #
21
- def match?(object)
22
- blacklist.none? { |predicate| predicate.match?(object) }
23
- end
24
-
25
- end # Whitelist
26
- end # Filter
27
- end # Mutant
@@ -1,38 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Predicate
5
- # Return matcher
6
- class Matcher < self
7
- include Concord.new(:matcher)
8
-
9
- # Test if subject matches
10
- #
11
- # @param [Subject] subject
12
- #
13
- # @return [true]
14
- # if subject is handled by matcher
15
- #
16
- # @return [false]
17
- # otherwise
18
- #
19
- def match?(subject)
20
- subjects.include?(subject)
21
- end
22
-
23
- private
24
-
25
- # Return subjects matched by matcher
26
- #
27
- # @return [Set<Subject>]
28
- #
29
- # @api private
30
- #
31
- def subjects
32
- matcher.to_a.to_set
33
- end
34
- memoize :subjects
35
-
36
- end # Matcher
37
- end # Predicate
38
- end # Mutant
@@ -1,28 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Predicate
5
-
6
- # Whiltelist filter
7
- class Whitelist < self
8
- include Adamantium::Flat, Concord.new(:whitelist)
9
-
10
- # Test for match
11
- #
12
- # @param [Object] object
13
- #
14
- # @return [true]
15
- # if mutation matches whitelist
16
- #
17
- # @return [false]
18
- # otherwise
19
- #
20
- # @api private
21
- #
22
- def match?(object)
23
- whitelist.any? { |filter| filter.match?(object) }
24
- end
25
-
26
- end # Whitelist
27
- end # Predicate
28
- end # Mutant
@@ -1,76 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Strategy
5
- # Rspec killer strategy
6
- class Rspec < self
7
- include Concord.new(:level)
8
-
9
- KILLER = Killer::Forking.new(Killer::Rspec)
10
-
11
- # Setup rspec strategy
12
- #
13
- # @return [self]
14
- #
15
- # @api private
16
- #
17
- def setup
18
- output = StringIO.new
19
- configuration.error_stream = output
20
- configuration.output_stream = output
21
- options.configure(configuration)
22
- configuration.load_spec_files
23
- self
24
- end
25
- memoize :setup
26
-
27
- # Return configuration
28
- #
29
- # @return [RSpec::Core::Configuration]
30
- #
31
- # @api private
32
- #
33
- def configuration
34
- RSpec::Core::Configuration.new
35
- end
36
- memoize :configuration, freezer: :noop
37
-
38
- # Return example groups
39
- #
40
- # @return [Enumerable<RSpec::Core::ExampleGroup>]
41
- #
42
- # @api private
43
- #
44
- def example_groups
45
- world.example_groups
46
- end
47
-
48
- private
49
-
50
- # Return world
51
- #
52
- # @return [RSpec::Core::World]
53
- #
54
- # @api private
55
- #
56
- def world
57
- RSpec.world
58
- end
59
- memoize :world, freezer: :noop
60
-
61
- # Return options
62
- #
63
- # @return [RSpec::Core::ConfigurationOptions]
64
- #
65
- # @api private
66
- #
67
- def options
68
- options = RSpec::Core::ConfigurationOptions.new(%w(--fail-fast spec))
69
- options.parse_options
70
- options
71
- end
72
- memoize :options, freezer: :noop
73
-
74
- end # Rspec
75
- end # Strategy
76
- end # Mutant
@@ -1,38 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Mutant::CLI::Builder::Rspec do
6
-
7
- let(:option_parser) { OptionParser.new }
8
-
9
- let(:cache) { Mutant::Cache.new }
10
- let(:object) { described_class.new(cache, option_parser) }
11
- let(:level) { double('Level') }
12
-
13
- let(:default_strategy) do
14
- Mutant::Strategy::Rspec.new(0)
15
- end
16
-
17
- let(:altered_strategy) do
18
- Mutant::Strategy::Rspec.new(1)
19
- end
20
-
21
- describe 'default' do
22
- specify do
23
- object
24
- option_parser.parse!(%w[--rspec])
25
- expect(object.output).to eql(default_strategy)
26
- end
27
- end
28
-
29
- describe 'parsing a level' do
30
-
31
- specify do
32
- object
33
- option_parser.parse!(%w[--rspec --rspec-level 1])
34
- expect(object.output).to eql(altered_strategy)
35
- end
36
- end
37
-
38
- end