mutant 0.3.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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