mutiny 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +30 -30
- data/RELEASES.md +3 -0
- data/bin/mutiny +8 -0
- data/examples/calculator/lib/calculator/min.rb +3 -3
- data/lib/mutiny/analysis/analyser.rb +37 -0
- data/lib/mutiny/analysis/results.rb +41 -0
- data/lib/mutiny/integration/rspec/context.rb +14 -6
- data/lib/mutiny/integration/rspec/parser.rb +1 -1
- data/lib/mutiny/integration/rspec/runner.rb +17 -5
- data/lib/mutiny/integration/rspec/test.rb +9 -2
- data/lib/mutiny/integration/rspec/test_set.rb +7 -1
- data/lib/mutiny/integration/rspec.rb +7 -7
- data/lib/mutiny/integration.rb +12 -0
- data/lib/mutiny/isolation/pipe.rb +25 -0
- data/lib/mutiny/isolation/vacuum.rb +14 -0
- data/lib/mutiny/isolation.rb +42 -0
- data/lib/mutiny/mode/check.rb +1 -1
- data/lib/mutiny/mode/score.rb +49 -0
- data/lib/mutiny/mode.rb +1 -0
- data/lib/mutiny/mutants/mutant.rb +9 -8
- data/lib/mutiny/mutants/mutant_set.rb +26 -21
- data/lib/mutiny/mutants/mutation_set.rb +8 -1
- data/lib/mutiny/output/table.rb +35 -0
- data/lib/mutiny/tests/test_run.rb +11 -2
- data/lib/mutiny/tests/test_set.rb +5 -1
- data/lib/mutiny/version.rb +1 -1
- data/lib/mutiny.rb +1 -0
- data/mutiny.gemspec +4 -4
- data/spec/integration/score_spec.rb +35 -0
- data/spec/unit/isolation_spec.rb +41 -0
- data/spec/unit/mutants/mutant_set_spec.rb +8 -46
- data/spec/unit/mutants/mutant_spec.rb +17 -0
- data/spec/unit/subjects/environment_spec.rb +1 -1
- data/spec/unit/subjects/test_set_spec.rb +8 -8
- metadata +24 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6284685da742cd3e372fb6969484dbef17fcb022
|
4
|
+
data.tar.gz: 4390a6132c28e9c9e6f705307d290ea071f0173a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a144740eaa9e502506eb0c7f07e4c95cb633b61e62b41fb932d756341c5ed920564f008f511224868f4614c782169c2effb68889a64944870e054deade9ad33c
|
7
|
+
data.tar.gz: d96ccc36e280c6df7182d7f8d2eb70f88f2dbf436ded930a1d81ec6009c778d8cc4a863a4c366c70ebb78dac2a7ccad70b5173482536209266e6598229e779c9
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mutiny (0.
|
4
|
+
mutiny (0.2.0)
|
5
5
|
gli (~> 2.13.0)
|
6
6
|
metamorpher (~> 0.2.2)
|
7
7
|
parser (~> 2.2.2)
|
@@ -14,13 +14,13 @@ GEM
|
|
14
14
|
adamantium (0.2.0)
|
15
15
|
ice_nine (~> 0.11.0)
|
16
16
|
memoizable (~> 0.4.0)
|
17
|
-
aruba (0.
|
17
|
+
aruba (0.7.4)
|
18
18
|
childprocess (>= 0.3.6)
|
19
19
|
cucumber (>= 1.1.1)
|
20
20
|
rspec-expectations (>= 2.7.0)
|
21
|
-
ast (2.
|
22
|
-
astrolabe (1.3.
|
23
|
-
parser (
|
21
|
+
ast (2.1.0)
|
22
|
+
astrolabe (1.3.1)
|
23
|
+
parser (~> 2.2)
|
24
24
|
attributable (0.1.0)
|
25
25
|
builder (3.2.2)
|
26
26
|
childprocess (0.5.6)
|
@@ -30,54 +30,54 @@ GEM
|
|
30
30
|
concord (0.1.5)
|
31
31
|
adamantium (~> 0.2.0)
|
32
32
|
equalizer (~> 0.0.9)
|
33
|
-
cucumber (2.0.
|
33
|
+
cucumber (2.0.2)
|
34
34
|
builder (>= 2.1.2)
|
35
|
-
cucumber-core (~> 1.
|
35
|
+
cucumber-core (~> 1.2.0)
|
36
36
|
diff-lcs (>= 1.1.3)
|
37
37
|
gherkin (~> 2.12)
|
38
38
|
multi_json (>= 1.7.5, < 2.0)
|
39
39
|
multi_test (>= 0.1.2)
|
40
|
-
cucumber-core (1.
|
40
|
+
cucumber-core (1.2.0)
|
41
41
|
gherkin (~> 2.12.0)
|
42
42
|
diff-lcs (1.2.5)
|
43
43
|
docile (1.1.5)
|
44
44
|
equalizer (0.0.11)
|
45
|
-
ffi (1.9.
|
45
|
+
ffi (1.9.10)
|
46
46
|
gherkin (2.12.2)
|
47
47
|
multi_json (~> 1.3)
|
48
48
|
gli (2.13.1)
|
49
49
|
ice_nine (0.11.1)
|
50
|
-
json (1.8.
|
50
|
+
json (1.8.3)
|
51
51
|
memoizable (0.4.2)
|
52
52
|
thread_safe (~> 0.3, >= 0.3.1)
|
53
53
|
metamorpher (0.2.2)
|
54
54
|
attributable (~> 0.1.0)
|
55
55
|
parser (~> 2.2.2)
|
56
56
|
unparser (~> 0.2.4)
|
57
|
-
multi_json (1.11.
|
57
|
+
multi_json (1.11.2)
|
58
58
|
multi_test (0.1.2)
|
59
|
-
parser (2.2.2.
|
59
|
+
parser (2.2.2.6)
|
60
60
|
ast (>= 1.1, < 3.0)
|
61
61
|
powerpack (0.1.1)
|
62
62
|
procto (0.0.2)
|
63
63
|
rainbow (2.0.0)
|
64
64
|
rake (10.4.2)
|
65
|
-
rspec (3.
|
66
|
-
rspec-core (~> 3.
|
67
|
-
rspec-expectations (~> 3.
|
68
|
-
rspec-mocks (~> 3.
|
69
|
-
rspec-core (3.2
|
70
|
-
rspec-support (~> 3.
|
71
|
-
rspec-expectations (3.
|
65
|
+
rspec (3.3.0)
|
66
|
+
rspec-core (~> 3.3.0)
|
67
|
+
rspec-expectations (~> 3.3.0)
|
68
|
+
rspec-mocks (~> 3.3.0)
|
69
|
+
rspec-core (3.3.2)
|
70
|
+
rspec-support (~> 3.3.0)
|
71
|
+
rspec-expectations (3.3.1)
|
72
72
|
diff-lcs (>= 1.2.0, < 2.0)
|
73
|
-
rspec-support (~> 3.
|
74
|
-
rspec-mocks (3.2
|
73
|
+
rspec-support (~> 3.3.0)
|
74
|
+
rspec-mocks (3.3.2)
|
75
75
|
diff-lcs (>= 1.2.0, < 2.0)
|
76
|
-
rspec-support (~> 3.
|
77
|
-
rspec-support (3.
|
78
|
-
rubocop (0.
|
76
|
+
rspec-support (~> 3.3.0)
|
77
|
+
rspec-support (3.3.0)
|
78
|
+
rubocop (0.33.0)
|
79
79
|
astrolabe (~> 1.3)
|
80
|
-
parser (>= 2.2.2.
|
80
|
+
parser (>= 2.2.2.5, < 3.0)
|
81
81
|
powerpack (~> 0.1)
|
82
82
|
rainbow (>= 1.99.1, < 3.0)
|
83
83
|
ruby-progressbar (~> 1.4)
|
@@ -101,13 +101,13 @@ PLATFORMS
|
|
101
101
|
ruby
|
102
102
|
|
103
103
|
DEPENDENCIES
|
104
|
-
aruba (~> 0.
|
105
|
-
bundler (~> 1.10.
|
104
|
+
aruba (~> 0.7.0)
|
105
|
+
bundler (~> 1.10.3)
|
106
106
|
codeclimate-test-reporter (~> 0.4.6)
|
107
107
|
mutiny!
|
108
108
|
rake (~> 10.4.2)
|
109
|
-
rspec (~> 3.
|
110
|
-
rubocop (~> 0.
|
109
|
+
rspec (~> 3.3.0)
|
110
|
+
rubocop (~> 0.33.0)
|
111
111
|
|
112
112
|
BUNDLED WITH
|
113
|
-
1.10.
|
113
|
+
1.10.4
|
data/RELEASES.md
CHANGED
data/bin/mutiny
CHANGED
@@ -32,4 +32,12 @@ command :mutate do |c|
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
desc 'Calculates a mutation score for your project'
|
36
|
+
long_desc 'Calculates a mutation score for your project and displays a list of surviving mutants'
|
37
|
+
command :score do |c|
|
38
|
+
c.action do
|
39
|
+
Mutiny::Mode::Score.new(@configuration).run
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
35
43
|
exit run(ARGV)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "results"
|
2
|
+
|
3
|
+
module Mutiny
|
4
|
+
module Analysis
|
5
|
+
class Analyser
|
6
|
+
attr_reader :mutant_set, :integration
|
7
|
+
|
8
|
+
def initialize(mutant_set:, integration:)
|
9
|
+
@mutant_set = mutant_set
|
10
|
+
@integration = integration
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
analyse_all
|
15
|
+
results
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def analyse_all
|
21
|
+
mutant_set.mutants.each do |mutant|
|
22
|
+
mutant.apply
|
23
|
+
test_run = integration.test(mutant.subject)
|
24
|
+
results.add(mutant, test_run)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def results
|
29
|
+
@results ||= Results.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def mutant_set
|
33
|
+
@mutant_set ||= configuration.mutator.mutants_for(environment.subjects)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Mutiny
|
2
|
+
module Analysis
|
3
|
+
class Results
|
4
|
+
def add(mutant, test_run)
|
5
|
+
mutants << mutant
|
6
|
+
test_runs[mutant] = test_run
|
7
|
+
killed << mutant if test_run.failed?
|
8
|
+
end
|
9
|
+
|
10
|
+
def kill_count
|
11
|
+
killed.size
|
12
|
+
end
|
13
|
+
|
14
|
+
def killed?(mutant)
|
15
|
+
killed.include?(mutant)
|
16
|
+
end
|
17
|
+
|
18
|
+
def survived?(mutant)
|
19
|
+
!killed?(mutant)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_run_for(mutant)
|
23
|
+
test_runs[mutant]
|
24
|
+
end
|
25
|
+
|
26
|
+
def mutants
|
27
|
+
@mutants ||= Mutants::MutantSet.new
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def killed
|
33
|
+
@killed ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_runs
|
37
|
+
@test_runs ||= {}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -3,23 +3,31 @@ require "stringio"
|
|
3
3
|
|
4
4
|
module Mutiny
|
5
5
|
class Integration
|
6
|
-
class RSpec
|
6
|
+
class RSpec < self
|
7
7
|
# This code originally based on Markus Schirp's implementation of Mutant::Integration::Rspec
|
8
8
|
# https://github.com/mbj/mutant/blob/master/lib/mutant/integration/rspec.rb
|
9
9
|
class Context
|
10
|
-
|
11
|
-
|
12
|
-
CLI_OPTIONS = %w(spec)
|
10
|
+
DEFAULT_CLI_OPTIONS = %w(spec)
|
11
|
+
FAIL_FAST_CLI_OPTION = %w(--fail-fast)
|
13
12
|
|
14
13
|
attr_reader :runner, :world, :configuration, :output
|
15
14
|
|
16
|
-
def initialize
|
15
|
+
def initialize(options = {})
|
16
|
+
@options = options
|
17
17
|
@output = StringIO.new
|
18
18
|
@world = ::RSpec.world
|
19
19
|
@configuration = ::RSpec.configuration
|
20
|
-
@runner = ::RSpec::Core::Runner.new(::RSpec::Core::ConfigurationOptions.new(
|
20
|
+
@runner = ::RSpec::Core::Runner.new(::RSpec::Core::ConfigurationOptions.new(cli_options))
|
21
21
|
@runner.setup($stderr, @output)
|
22
22
|
end
|
23
|
+
|
24
|
+
def cli_options
|
25
|
+
if @options.fetch(:fail_fast, false)
|
26
|
+
DEFAULT_CLI_OPTIONS + FAIL_FAST_CLI_OPTION
|
27
|
+
else
|
28
|
+
DEFAULT_CLI_OPTIONS
|
29
|
+
end
|
30
|
+
end
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
@@ -3,7 +3,7 @@ require_relative "test_set"
|
|
3
3
|
|
4
4
|
module Mutiny
|
5
5
|
class Integration
|
6
|
-
class RSpec
|
6
|
+
class RSpec < self
|
7
7
|
# This code originally based on Markus Schirp's implementation of Mutant::Integration::Rspec
|
8
8
|
# https://github.com/mbj/mutant/blob/master/lib/mutant/integration/rspec.rb
|
9
9
|
class Parser
|
@@ -2,7 +2,7 @@ require "forwardable"
|
|
2
2
|
|
3
3
|
module Mutiny
|
4
4
|
class Integration
|
5
|
-
class RSpec
|
5
|
+
class RSpec < self
|
6
6
|
# This code originally based on Markus Schirp's implementation of Mutant::Integration::Rspec
|
7
7
|
# https://github.com/mbj/mutant/blob/master/lib/mutant/integration/rspec.rb
|
8
8
|
class Runner
|
@@ -23,11 +23,13 @@ module Mutiny
|
|
23
23
|
private
|
24
24
|
|
25
25
|
def reset
|
26
|
+
@passed_examples = []
|
26
27
|
@failed_examples = []
|
27
28
|
end
|
28
29
|
|
29
30
|
def prepare
|
30
31
|
filter_examples
|
32
|
+
configuration.reporter.register_listener(self, :example_passed)
|
31
33
|
configuration.reporter.register_listener(self, :example_failed)
|
32
34
|
end
|
33
35
|
|
@@ -35,14 +37,24 @@ module Mutiny
|
|
35
37
|
start = Time.now
|
36
38
|
runner.run_specs(world.ordered_example_groups)
|
37
39
|
output.rewind
|
40
|
+
runtime = Time.now - start
|
41
|
+
create_test_run(output.read, runtime)
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_test_run(output, runtime)
|
38
45
|
Tests::TestRun.new(
|
39
|
-
tests: @test_set,
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
tests: @test_set.generalise,
|
47
|
+
passed_tests: @test_set.subset_for_examples(@passed_examples).generalise,
|
48
|
+
failed_tests: @test_set.subset_for_examples(@failed_examples).generalise,
|
49
|
+
output: output,
|
50
|
+
runtime: runtime
|
43
51
|
)
|
44
52
|
end
|
45
53
|
|
54
|
+
def example_passed(notification)
|
55
|
+
@passed_examples << notification.example
|
56
|
+
end
|
57
|
+
|
46
58
|
def example_failed(notification)
|
47
59
|
@failed_examples << notification.example
|
48
60
|
end
|
@@ -2,13 +2,20 @@ require_relative "../../tests"
|
|
2
2
|
|
3
3
|
module Mutiny
|
4
4
|
class Integration
|
5
|
-
class RSpec
|
5
|
+
class RSpec < self
|
6
6
|
class Test < Tests::Test
|
7
|
-
attr_reader :example
|
7
|
+
attr_reader :example, :rest
|
8
8
|
|
9
9
|
def initialize(example:, **rest)
|
10
10
|
super(rest)
|
11
11
|
@example = example
|
12
|
+
@rest = rest
|
13
|
+
end
|
14
|
+
|
15
|
+
# Converts to a Mutiny::Tests::Test, which is independent of
|
16
|
+
# any specific testing framework
|
17
|
+
def generalise
|
18
|
+
Mutiny::Tests::Test.new(@rest)
|
12
19
|
end
|
13
20
|
end
|
14
21
|
end
|
@@ -2,7 +2,7 @@ require_relative "../../tests"
|
|
2
2
|
|
3
3
|
module Mutiny
|
4
4
|
class Integration
|
5
|
-
class RSpec
|
5
|
+
class RSpec < self
|
6
6
|
class TestSet < Tests::TestSet
|
7
7
|
def examples
|
8
8
|
@tests.map(&:example)
|
@@ -11,6 +11,12 @@ module Mutiny
|
|
11
11
|
def subset_for_examples(examples)
|
12
12
|
subset { |test| examples.include?(test.example) }
|
13
13
|
end
|
14
|
+
|
15
|
+
# Converts to a Mutiny::Tests::TestSet, which is independent of
|
16
|
+
# any specific testing framework
|
17
|
+
def generalise
|
18
|
+
Mutiny::Tests::TestSet.new(tests.map(&:generalise))
|
19
|
+
end
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -6,19 +6,19 @@ module Mutiny
|
|
6
6
|
class Integration
|
7
7
|
# This code originally based on Markus Schirp's implementation of Mutant::Integration::Rspec
|
8
8
|
# https://github.com/mbj/mutant/blob/master/lib/mutant/integration/rspec.rb
|
9
|
-
class RSpec
|
10
|
-
def tests
|
11
|
-
Parser.new(context).call
|
9
|
+
class RSpec < self
|
10
|
+
def tests(options = {})
|
11
|
+
Parser.new(context(options)).call
|
12
12
|
end
|
13
13
|
|
14
|
-
def run(test_set)
|
15
|
-
Runner.new(test_set, context).call
|
14
|
+
def run(test_set, options = {})
|
15
|
+
Runner.new(test_set, context(options)).call
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
def context
|
21
|
-
|
20
|
+
def context(options = {})
|
21
|
+
Context.new(options)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Mutiny
|
2
|
+
class Isolation
|
3
|
+
# An inter-process communication mechanism for sending and receiving
|
4
|
+
# (marshalled) data over an IO pipe
|
5
|
+
Pipe = Struct.new(:reader, :writer) do
|
6
|
+
def self.with(&block)
|
7
|
+
IO.pipe(binmode: true) do |reader, writer|
|
8
|
+
writer.binmode
|
9
|
+
block.call(Pipe.new(reader, writer))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def receive
|
14
|
+
writer.close
|
15
|
+
Marshal.load(reader.read)
|
16
|
+
end
|
17
|
+
|
18
|
+
def send(data)
|
19
|
+
reader.close
|
20
|
+
writer.write(Marshal.dump(data))
|
21
|
+
writer.close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Mutiny
|
2
|
+
class Isolation
|
3
|
+
# A mechanism for temporarily silencing a stream by redirecting
|
4
|
+
# the output to the OS's null device (e.g., /dev/null)
|
5
|
+
class Vacuum
|
6
|
+
def self.silence(stream, &block)
|
7
|
+
File.open(File::NULL, File::WRONLY) do |file|
|
8
|
+
stream.reopen(file)
|
9
|
+
block.call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative 'isolation/pipe'
|
2
|
+
require_relative 'isolation/vacuum'
|
3
|
+
|
4
|
+
module Mutiny
|
5
|
+
# This code originally based on Markus Schirp's implementation of Mutant::Isolation::Fork
|
6
|
+
# https://github.com/mbj/mutant/blob/master/lib/mutant/isolation.rb
|
7
|
+
class Isolation
|
8
|
+
# Runs the given block, isolating the global state so that changes cannot
|
9
|
+
# leak out to the caller's runtime
|
10
|
+
def self.call(&block)
|
11
|
+
new(block).run_in_isolation
|
12
|
+
rescue => exception
|
13
|
+
raise Error, exception
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :isolated_code
|
17
|
+
|
18
|
+
def initialize(isolated_code)
|
19
|
+
@isolated_code = isolated_code
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_in_isolation
|
23
|
+
Pipe.with do |comms|
|
24
|
+
begin
|
25
|
+
pid = Process.fork { run_and_send_result_via(comms) }
|
26
|
+
comms.receive # wait to receive the result form the child process
|
27
|
+
ensure
|
28
|
+
Process.waitpid(pid) if pid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_and_send_result_via(comms)
|
34
|
+
Vacuum.silence($stderr) do
|
35
|
+
result = isolated_code.call
|
36
|
+
comms.send(result) # send the result to the parent process over the pipes
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Error = Class.new(RuntimeError)
|
41
|
+
end
|
42
|
+
end
|
data/lib/mutiny/mode/check.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative "../analysis/analyser"
|
2
|
+
require_relative "../output/table"
|
3
|
+
|
4
|
+
module Mutiny
|
5
|
+
class Mode
|
6
|
+
class Score < self
|
7
|
+
def run
|
8
|
+
report "Scoring..."
|
9
|
+
report "#{mutant_set.size} mutants, #{results.kill_count} killed"
|
10
|
+
report ""
|
11
|
+
report summary
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def summary
|
17
|
+
Output::Table.new.tap do |summary|
|
18
|
+
summary.add_row(summary_header)
|
19
|
+
summary.add_rows(results.mutants.ordered.map { |m| summarise(m) })
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def summary_header
|
24
|
+
["Mutant", "Status", "# Tests", "Time"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def summarise(mutant)
|
28
|
+
identifier = mutant.identifier
|
29
|
+
status = results.survived?(mutant) ? "survived" : "killed"
|
30
|
+
executed_count = results.test_run_for(mutant).executed_count
|
31
|
+
total_count = results.test_run_for(mutant).tests.size
|
32
|
+
runtime = results.test_run_for(mutant).runtime
|
33
|
+
[identifier, status, "#{executed_count} (of #{total_count})", runtime]
|
34
|
+
end
|
35
|
+
|
36
|
+
def results
|
37
|
+
@results ||= analyser.call
|
38
|
+
end
|
39
|
+
|
40
|
+
def analyser
|
41
|
+
Analysis::Analyser.new(mutant_set: mutant_set, integration: configuration.integration)
|
42
|
+
end
|
43
|
+
|
44
|
+
def mutant_set
|
45
|
+
@mutant_set ||= configuration.mutator.mutants_for(environment.subjects)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/mutiny/mode.rb
CHANGED
@@ -5,21 +5,22 @@ module Mutiny
|
|
5
5
|
class Mutant
|
6
6
|
attr_reader :subject, :code
|
7
7
|
|
8
|
-
def initialize(subject
|
8
|
+
def initialize(subject: nil, code:)
|
9
9
|
@subject = subject
|
10
10
|
@code = code
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
def apply
|
14
|
+
# Evaluate the mutanted code, overidding any existing version.
|
15
|
+
# We evaluate in the context of TOPLEVEL_BINDING as we want
|
16
|
+
# the unit to be evaluated in its usual namespace.
|
17
|
+
# rubocop:disable Eval
|
18
|
+
eval(code, TOPLEVEL_BINDING)
|
19
|
+
# rubocop:enable Eval
|
19
20
|
end
|
20
21
|
|
21
22
|
def eql?(other)
|
22
|
-
|
23
|
+
other.subject == subject && other.code == code
|
23
24
|
end
|
24
25
|
|
25
26
|
alias_method "==", "eql?"
|
@@ -3,39 +3,44 @@ require_relative "mutant"
|
|
3
3
|
module Mutiny
|
4
4
|
module Mutants
|
5
5
|
class MutantSet
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
def add(subject, mutated_code)
|
11
|
-
mutants = mutated_code.map { |code| create_mutant(subject, code) }
|
12
|
-
@mutants_by_subject[subject] = @mutants_by_subject[subject] + mutants
|
13
|
-
end
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :mutants, :size, :<<, :concat
|
14
8
|
|
15
|
-
def
|
16
|
-
mutants
|
9
|
+
def mutants
|
10
|
+
@mutants ||= []
|
17
11
|
end
|
18
12
|
|
19
13
|
def group_by_subject
|
20
|
-
|
14
|
+
mutants.group_by(&:subject).dup
|
21
15
|
end
|
22
16
|
|
23
|
-
def
|
24
|
-
group_by_subject.
|
25
|
-
mutants.
|
17
|
+
def ordered
|
18
|
+
group_by_subject.flat_map do |_, mutants|
|
19
|
+
mutants.map.with_index do |mutant, index|
|
20
|
+
OrderedMutant.new(mutant, index)
|
21
|
+
end
|
26
22
|
end
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
def create_mutant(subject, code)
|
32
|
-
Mutant.new(subject: subject, code: code)
|
25
|
+
def store(mutant_directory = ".mutants")
|
26
|
+
ordered.each { |m| m.store(mutant_directory) }
|
33
27
|
end
|
34
28
|
|
35
|
-
|
29
|
+
class OrderedMutant < SimpleDelegator
|
30
|
+
def initialize(mutant, number)
|
31
|
+
super(mutant)
|
32
|
+
@number = number
|
33
|
+
end
|
36
34
|
|
37
|
-
|
38
|
-
|
35
|
+
def identifier
|
36
|
+
subject.relative_path.sub(/\.rb$/, ".#{@number}.rb")
|
37
|
+
end
|
38
|
+
|
39
|
+
def store(directory)
|
40
|
+
path = File.join(directory, identifier)
|
41
|
+
FileUtils.mkdir_p(File.dirname(path))
|
42
|
+
File.open(path, 'w') { |f| f.write(code) }
|
43
|
+
end
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
@@ -14,11 +14,18 @@ module Mutiny
|
|
14
14
|
MutantSet.new.tap do |mutants|
|
15
15
|
@mutations.each do |mutation|
|
16
16
|
subjects.each do |subject|
|
17
|
-
|
17
|
+
mutated_codes = mutation.mutate_file(subject.path)
|
18
|
+
mutants.concat(create_mutants(subject, mutated_codes))
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def create_mutants(subject, mutated_codes)
|
27
|
+
mutated_codes.map { |code| Mutant.new(subject: subject, code: code) }
|
28
|
+
end
|
22
29
|
end
|
23
30
|
end
|
24
31
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Mutiny
|
2
|
+
module Output
|
3
|
+
class Table
|
4
|
+
def initialize
|
5
|
+
@rows = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_rows(rows)
|
9
|
+
rows.each { |r| add_row(r) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_row(cells)
|
13
|
+
@rows << cells
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
@rows.map { |r| row_to_s(r) }.join("\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
def row_to_s(cells)
|
21
|
+
"| " +
|
22
|
+
cells.each_with_index.map { |cell, index| cell_to_s(cell, index) }.join(" | ") +
|
23
|
+
" |"
|
24
|
+
end
|
25
|
+
|
26
|
+
def cell_to_s(cell, column_index)
|
27
|
+
cell.to_s.ljust(width_for_column(column_index))
|
28
|
+
end
|
29
|
+
|
30
|
+
def width_for_column(index)
|
31
|
+
@rows.map { |r| r[index].to_s.size }.max
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,18 +1,27 @@
|
|
1
1
|
module Mutiny
|
2
2
|
module Tests
|
3
3
|
class TestRun
|
4
|
-
attr_reader :tests, :failed_tests, :output, :runtime
|
4
|
+
attr_reader :tests, :passed_tests, :failed_tests, :output, :runtime
|
5
5
|
|
6
|
-
def initialize(tests:, failed_tests:, output:, runtime:)
|
6
|
+
def initialize(tests:, passed_tests:, failed_tests:, output:, runtime:)
|
7
7
|
@tests = tests
|
8
|
+
@passed_tests = passed_tests
|
8
9
|
@failed_tests = failed_tests
|
9
10
|
@output = output
|
10
11
|
@runtime = runtime
|
11
12
|
end
|
12
13
|
|
14
|
+
def executed_count
|
15
|
+
passed_tests.size + failed_tests.size
|
16
|
+
end
|
17
|
+
|
13
18
|
def passed?
|
14
19
|
failed_tests.empty?
|
15
20
|
end
|
21
|
+
|
22
|
+
def failed?
|
23
|
+
!passed?
|
24
|
+
end
|
16
25
|
end
|
17
26
|
end
|
18
27
|
end
|
@@ -18,10 +18,14 @@ module Mutiny
|
|
18
18
|
tests.map(&:location)
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def for_all(subject_set)
|
22
22
|
subset { |test| subject_set.names.include?(test.expression) }
|
23
23
|
end
|
24
24
|
|
25
|
+
def for(subject)
|
26
|
+
subset { |test| subject.name == test.expression }
|
27
|
+
end
|
28
|
+
|
25
29
|
def subset(&block)
|
26
30
|
self.class.new(tests.select(&block))
|
27
31
|
end
|
data/lib/mutiny/version.rb
CHANGED
data/lib/mutiny.rb
CHANGED
data/mutiny.gemspec
CHANGED
@@ -23,10 +23,10 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_runtime_dependency "gli", "~> 2.13.0"
|
24
24
|
spec.add_runtime_dependency "metamorpher", "~> 0.2.2"
|
25
25
|
|
26
|
-
spec.add_development_dependency "bundler", "~> 1.10.
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.10.3"
|
27
27
|
spec.add_development_dependency "rake", "~> 10.4.2"
|
28
|
-
spec.add_development_dependency "rspec", "~> 3.
|
29
|
-
spec.add_development_dependency "aruba", "~> 0.
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.3.0"
|
29
|
+
spec.add_development_dependency "aruba", "~> 0.7.0"
|
30
30
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4.6"
|
31
|
-
spec.add_development_dependency "rubocop", "~> 0.
|
31
|
+
spec.add_development_dependency "rubocop", "~> 0.33.0"
|
32
32
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
describe "Using Mutiny to generate mutants" do
|
2
|
+
before(:each) do
|
3
|
+
cd "calculator"
|
4
|
+
run "bundle exec mutiny mutate"
|
5
|
+
run "bundle exec mutiny score"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should report a mutation score" do
|
9
|
+
expected_output = "Scoring...\n" \
|
10
|
+
"14 mutants, 12 killed\n"
|
11
|
+
|
12
|
+
expect(all_output).to include(expected_output)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should report status of mutants" do
|
16
|
+
expect(all_output).to include("calculator/min.0.rb | killed")
|
17
|
+
expect(all_output).to include("calculator/min.1.rb | killed")
|
18
|
+
expect(all_output).to include("calculator/min.2.rb | survived")
|
19
|
+
expect(all_output).to include("calculator/min.3.rb | killed")
|
20
|
+
expect(all_output).to include("calculator/min.4.rb | killed")
|
21
|
+
expect(all_output).to include("calculator/min.5.rb | killed")
|
22
|
+
expect(all_output).to include("calculator/min.6.rb | killed")
|
23
|
+
expect(all_output).to include("calculator/max.0.rb | killed")
|
24
|
+
expect(all_output).to include("calculator/max.1.rb | killed")
|
25
|
+
expect(all_output).to include("calculator/max.2.rb | killed")
|
26
|
+
expect(all_output).to include("calculator/max.3.rb | killed")
|
27
|
+
expect(all_output).to include("calculator/max.4.rb | killed")
|
28
|
+
expect(all_output).to include("calculator/max.5.rb | killed")
|
29
|
+
expect(all_output).to include("calculator/max.6.rb | survived")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should fail fast (not execute all tests for some killed mutants)" do
|
33
|
+
expect(all_output).to include("2 (of 3)")
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "mutiny/isolation"
|
2
|
+
|
3
|
+
module Mutiny
|
4
|
+
# This code originally based on Markus Schirp's implementation of Mutant::Isolation::Fork
|
5
|
+
# https://github.com/mbj/mutant/blob/master/spec/unit/mutant/isolation_spec.rb
|
6
|
+
describe Isolation do
|
7
|
+
subject { described_class }
|
8
|
+
|
9
|
+
before do
|
10
|
+
@initial = 1
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.run' do
|
14
|
+
it 'does isolate side effects' do
|
15
|
+
subject.call { @initial = 2 }
|
16
|
+
expect(@initial).to be(1)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'return block value' do
|
20
|
+
expect(subject.call { :foo }).to be(:foo)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'wraps exceptions' do
|
24
|
+
expect { subject.call { fail } }.to raise_error(Isolation::Error, 'marshal data too short')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'redirects $stderr of children to /dev/null' do
|
28
|
+
begin
|
29
|
+
Tempfile.open('mutiny-test') do |file|
|
30
|
+
$stderr = file
|
31
|
+
subject.call { $stderr.puts('test') }
|
32
|
+
file.rewind
|
33
|
+
expect(file.read).to eql('')
|
34
|
+
end
|
35
|
+
ensure
|
36
|
+
$stderr = STDERR
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,56 +1,18 @@
|
|
1
1
|
module Mutiny
|
2
2
|
module Mutants
|
3
|
-
class ObservableMutantSet < MutantSet
|
4
|
-
def create_mutant(subject, code)
|
5
|
-
MutantSpy.new(subject: subject, code: code)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class MutantSpy < Mutant
|
10
|
-
attr_reader :directory, :index
|
11
|
-
|
12
|
-
def store(directory, index)
|
13
|
-
@directory = directory
|
14
|
-
@index = index
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
3
|
describe MutantSet do
|
19
|
-
subject(:mutant_set) {
|
4
|
+
subject(:mutant_set) { MutantSet.new }
|
5
|
+
let(:m1) { Mutant.new(subject: :min, code: :min_mutant_1) }
|
6
|
+
let(:m2) { Mutant.new(subject: :min, code: :min_mutant_2) }
|
7
|
+
let(:m3) { Mutant.new(subject: :max, code: :max_mutant_1) }
|
8
|
+
let(:m4) { Mutant.new(subject: :min, code: :min_mutant_3) }
|
20
9
|
|
21
10
|
before(:each) do
|
22
|
-
mutant_set
|
23
|
-
mutant_set.add(:max, [:max_mutant_1])
|
24
|
-
mutant_set.add(:min, [:min_mutant_3])
|
25
|
-
end
|
26
|
-
|
27
|
-
it "groups mutants by subject" do
|
28
|
-
groups = mutant_set.group_by_subject.to_a
|
29
|
-
first = groups.first
|
30
|
-
second = groups.last
|
31
|
-
|
32
|
-
expect(first).to eq(mutants_for(:min, :min_mutant_1, :min_mutant_2, :min_mutant_3))
|
33
|
-
expect(second).to eq(mutants_for(:max, :max_mutant_1))
|
34
|
-
end
|
35
|
-
|
36
|
-
it "counts mutants" do
|
37
|
-
expect(mutant_set.size).to eq(4)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "stores by delegating to mutants" do
|
41
|
-
mutant_set.store(:mutant_dir)
|
42
|
-
|
43
|
-
mutant_set.group_by_subject.each do |_, mutants|
|
44
|
-
mutants.each_with_index do |mutant, index|
|
45
|
-
expect(mutant.directory).to eq(:mutant_dir)
|
46
|
-
expect(mutant.index).to eq(index)
|
47
|
-
end
|
48
|
-
end
|
11
|
+
mutant_set << m1 << m2 << m3 << m4
|
49
12
|
end
|
50
13
|
|
51
|
-
|
52
|
-
|
53
|
-
[subject, mutants]
|
14
|
+
it "orders mutants by subject and index" do
|
15
|
+
expect(mutant_set.ordered).to eq([m1, m2, m4, m3])
|
54
16
|
end
|
55
17
|
end
|
56
18
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Mutiny
|
2
|
+
module Mutants
|
3
|
+
describe Mutant do
|
4
|
+
subject(:mutant) { Mutant.new(code: "class Hello; def run; 'Goodbye'; end; end") }
|
5
|
+
|
6
|
+
it "overrides existing code when applied" do
|
7
|
+
expect { mutant.apply }.to change { Hello.new.run }.from("Hello").to("Goodbye")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Hello
|
14
|
+
def run
|
15
|
+
"Hello"
|
16
|
+
end
|
17
|
+
end
|
@@ -35,31 +35,31 @@ module Mutiny
|
|
35
35
|
|
36
36
|
context "for" do
|
37
37
|
it "should return only those tests (whose expression) matches a subject" do
|
38
|
-
|
38
|
+
subjects = subject_set_for("Max", "Min")
|
39
39
|
test_set = test_set_for("Subtract", "Min", "Add")
|
40
40
|
|
41
|
-
expect(test_set.
|
41
|
+
expect(test_set.for_all(subjects)).to eq(test_set.subset { |t| t.expression == "Min" })
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should return multiple tests for a single subject" do
|
45
|
-
|
45
|
+
subjects = subject_set_for("Min")
|
46
46
|
test_set = test_set_for("Min", "Max", "Min", "Max", "Min")
|
47
47
|
|
48
|
-
expect(test_set.
|
48
|
+
expect(test_set.for_all(subjects)).to eq(test_set.subset { |t| t.expression == "Min" })
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should return no tests when there are no tests" do
|
52
|
-
|
52
|
+
subjects = subject_set_for("Max", "Min")
|
53
53
|
test_set = TestSet.empty
|
54
54
|
|
55
|
-
expect(test_set.
|
55
|
+
expect(test_set.for_all(subjects)).to eq(TestSet.empty)
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should return no tests when there are no relevant subjects" do
|
59
|
-
|
59
|
+
subjects = subject_set_for("Max", "Min")
|
60
60
|
test_set = test_set_for("Subtract", "Add")
|
61
61
|
|
62
|
-
expect(test_set.
|
62
|
+
expect(test_set.for_all(subjects)).to eq(TestSet.empty)
|
63
63
|
end
|
64
64
|
|
65
65
|
def subject_set_for(*names)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutiny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Louis Rose
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.10.
|
75
|
+
version: 1.10.3
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.10.
|
82
|
+
version: 1.10.3
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,28 +100,28 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 3.
|
103
|
+
version: 3.3.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 3.
|
110
|
+
version: 3.3.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: aruba
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: 0.7.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
124
|
+
version: 0.7.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: codeclimate-test-reporter
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
145
|
+
version: 0.33.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
152
|
+
version: 0.33.0
|
153
153
|
description: A tiny and experimental mutation testing framework for exploring research
|
154
154
|
ideas.
|
155
155
|
email:
|
@@ -189,16 +189,23 @@ files:
|
|
189
189
|
- examples/untested_calculator/lib/calculator/max.rb
|
190
190
|
- examples/untested_calculator/spec/spec_helper.rb
|
191
191
|
- lib/mutiny.rb
|
192
|
+
- lib/mutiny/analysis/analyser.rb
|
193
|
+
- lib/mutiny/analysis/results.rb
|
192
194
|
- lib/mutiny/configuration.rb
|
195
|
+
- lib/mutiny/integration.rb
|
193
196
|
- lib/mutiny/integration/rspec.rb
|
194
197
|
- lib/mutiny/integration/rspec/context.rb
|
195
198
|
- lib/mutiny/integration/rspec/parser.rb
|
196
199
|
- lib/mutiny/integration/rspec/runner.rb
|
197
200
|
- lib/mutiny/integration/rspec/test.rb
|
198
201
|
- lib/mutiny/integration/rspec/test_set.rb
|
202
|
+
- lib/mutiny/isolation.rb
|
203
|
+
- lib/mutiny/isolation/pipe.rb
|
204
|
+
- lib/mutiny/isolation/vacuum.rb
|
199
205
|
- lib/mutiny/mode.rb
|
200
206
|
- lib/mutiny/mode/check.rb
|
201
207
|
- lib/mutiny/mode/mutate.rb
|
208
|
+
- lib/mutiny/mode/score.rb
|
202
209
|
- lib/mutiny/mutants/mutant.rb
|
203
210
|
- lib/mutiny/mutants/mutant_set.rb
|
204
211
|
- lib/mutiny/mutants/mutation.rb
|
@@ -218,6 +225,7 @@ files:
|
|
218
225
|
- lib/mutiny/mutants/mutation/method/unary_arithmetic_operator_insertion.rb
|
219
226
|
- lib/mutiny/mutants/mutation_set.rb
|
220
227
|
- lib/mutiny/mutants/ruby.rb
|
228
|
+
- lib/mutiny/output/table.rb
|
221
229
|
- lib/mutiny/pattern.rb
|
222
230
|
- lib/mutiny/reporter/stdout.rb
|
223
231
|
- lib/mutiny/subjects.rb
|
@@ -233,13 +241,16 @@ files:
|
|
233
241
|
- mutiny.gemspec
|
234
242
|
- spec/integration/check_spec.rb
|
235
243
|
- spec/integration/mutate_spec.rb
|
244
|
+
- spec/integration/score_spec.rb
|
236
245
|
- spec/spec_helper.rb
|
237
246
|
- spec/support/aruba.rb
|
238
247
|
- spec/support/in_example_project.rb
|
239
248
|
- spec/support/shared_examples/shared_examples_for_an_operator_replacement_mutation.rb
|
240
249
|
- spec/unit/integration/rspec/parser_spec.rb
|
241
250
|
- spec/unit/integration/rspec/runner_spec.rb
|
251
|
+
- spec/unit/isolation_spec.rb
|
242
252
|
- spec/unit/mutants/mutant_set_spec.rb
|
253
|
+
- spec/unit/mutants/mutant_spec.rb
|
243
254
|
- spec/unit/mutants/mutations/method/binary_operator_replacement_spec.rb
|
244
255
|
- spec/unit/mutants/mutations/method/conditional_operator_deletion_spec.rb
|
245
256
|
- spec/unit/mutants/mutations/method/conditional_operator_insertion_spec.rb
|
@@ -284,13 +295,16 @@ summary: A tiny mutation testing framework for Ruby
|
|
284
295
|
test_files:
|
285
296
|
- spec/integration/check_spec.rb
|
286
297
|
- spec/integration/mutate_spec.rb
|
298
|
+
- spec/integration/score_spec.rb
|
287
299
|
- spec/spec_helper.rb
|
288
300
|
- spec/support/aruba.rb
|
289
301
|
- spec/support/in_example_project.rb
|
290
302
|
- spec/support/shared_examples/shared_examples_for_an_operator_replacement_mutation.rb
|
291
303
|
- spec/unit/integration/rspec/parser_spec.rb
|
292
304
|
- spec/unit/integration/rspec/runner_spec.rb
|
305
|
+
- spec/unit/isolation_spec.rb
|
293
306
|
- spec/unit/mutants/mutant_set_spec.rb
|
307
|
+
- spec/unit/mutants/mutant_spec.rb
|
294
308
|
- spec/unit/mutants/mutations/method/binary_operator_replacement_spec.rb
|
295
309
|
- spec/unit/mutants/mutations/method/conditional_operator_deletion_spec.rb
|
296
310
|
- spec/unit/mutants/mutations/method/conditional_operator_insertion_spec.rb
|