miss_cleo 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/miss_cleo +3 -101
- data/lib/miss_cleo/coverage_filter.rb +1 -1
- data/lib/miss_cleo/coverage_map_helper.rb +117 -0
- data/lib/miss_cleo/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f65320c1042c0c225a420c0a71a9bb176146c2ea
|
4
|
+
data.tar.gz: 9bee07706949fbf2529d07eee3407fe2559039a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16a9d3f6c1820e6f8473a947979950177193afdfc7d195212c6275b532e50e90f75e91ea165820b26cbad6594752cacbff67c4638f211e6490190f6dfad0de0f
|
7
|
+
data.tar.gz: c2b1726859d10f06bc6fdb36a12dab107eba1ad7c4d6347cf22aa15d803188a9ed17ba038f2fd04c7b1303be3bea59b9bb2cabd5cb5f358977e8e2d6d1b9831e
|
data/bin/miss_cleo
CHANGED
@@ -2,112 +2,14 @@
|
|
2
2
|
|
3
3
|
require "miss_cleo"
|
4
4
|
require 'pry'
|
5
|
+
include MissCleo::CoverageMapHelper
|
5
6
|
|
6
7
|
case ARGV.first
|
7
8
|
when "build_deck"
|
8
|
-
|
9
|
-
cov_map = Hash.new { |h, file| h[file] = Hash.new { |i, line| i[line] = [] } }
|
10
|
-
filenames.each do |filename|
|
11
|
-
File.open(filename, "r") do |f|
|
12
|
-
f.read
|
13
|
-
end.tap do |contents|
|
14
|
-
build_coverage_map(cov_map, JSON.parse(contents))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
File.open("total_coverage_map.json", "w") do |f|
|
19
|
-
f.write(JSON.dump(cov_map))
|
20
|
-
end
|
9
|
+
build_deck(ARGV[1..-1])
|
21
10
|
when "predict"
|
22
|
-
|
23
|
-
lines_changed = Set.new
|
24
|
-
|
25
|
-
repo.index.diff.each_patch do |patch|
|
26
|
-
file = patch.delta.old_file[:path]
|
27
|
-
|
28
|
-
patch.each_hunk do |hunk|
|
29
|
-
hunk.each_line do |line|
|
30
|
-
case line.line_origin
|
31
|
-
when :addition
|
32
|
-
lines_changed << [file, line.new_lineno] unless exclude_from_map?(file)
|
33
|
-
when :deletion
|
34
|
-
lines_changed << [file, line.old_lineno] unless exclude_from_map?(file)
|
35
|
-
when :context
|
36
|
-
# do nothing
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
coverage_map = JSON.parse(File.open("total_coverage_map.json").read)
|
43
|
-
tests_to_run = []
|
44
|
-
lines_changed.each do |file, line|
|
45
|
-
coverage_map && coverage_map[File.expand_path(file)] && coverage_map[File.expand_path(file)].fetch(line.to_s, []).uniq.each do |desc|
|
46
|
-
tests_to_run << desc
|
47
|
-
end
|
48
|
-
end
|
49
|
-
if lines_changed.empty?
|
50
|
-
puts "No line changes detected."
|
51
|
-
elsif tests_to_run.empty?
|
52
|
-
puts "No tests found. May be due to blind spot, new tests you've just written, or the changes may be untested."
|
53
|
-
else
|
54
|
-
puts "Run these tests:"
|
55
|
-
puts tests_to_run.uniq.sort
|
56
|
-
end
|
11
|
+
predict
|
57
12
|
else
|
58
13
|
puts "Please run miss_cleo with 'build_deck' or 'predict'."
|
59
14
|
end
|
60
15
|
|
61
|
-
def exclude_from_map?(file_name)
|
62
|
-
# Let's add a configuration for ignored files
|
63
|
-
file_name == "db/structure.sql"
|
64
|
-
end
|
65
|
-
|
66
|
-
def diff before, after
|
67
|
-
after.each_with_object({}) do |(file_name,line_cov), res|
|
68
|
-
before_line_cov = before[file_name] || []
|
69
|
-
|
70
|
-
# skip arrays that are exactly the same
|
71
|
-
next if before_line_cov == line_cov
|
72
|
-
|
73
|
-
# subtract the old coverage from the new coverage
|
74
|
-
cov = line_cov.zip(before_line_cov).map do |line_after, line_before|
|
75
|
-
if line_before
|
76
|
-
line_after - line_before
|
77
|
-
else
|
78
|
-
line_after
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# add the "diffed" coverage to the hash
|
83
|
-
res[file_name] = cov
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def build_coverage_map(cov_map, cov_diffs)
|
88
|
-
cov_diffs.each do |test_to_code_map|
|
89
|
-
if test_to_code_map.length == 4 # for Minitest
|
90
|
-
test_file_and_line = test_to_code_map.first(2).join('#')
|
91
|
-
else # for RSpec
|
92
|
-
test_file_and_line = test_to_code_map.first
|
93
|
-
end
|
94
|
-
before, after = test_to_code_map.last(2)
|
95
|
-
|
96
|
-
# calculate the per test coverage
|
97
|
-
delta = diff before, after
|
98
|
-
|
99
|
-
delta.each_pair do |file, lines|
|
100
|
-
file_map = cov_map[file]
|
101
|
-
|
102
|
-
lines.each_with_index do |val, i|
|
103
|
-
# skip lines that weren't executed
|
104
|
-
next unless val && val > 0
|
105
|
-
|
106
|
-
# add the test name to the map. Multiple tests can execute the same
|
107
|
-
# line, so we need to use an array.
|
108
|
-
file_map[i + 1] << test_file_and_line
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
@@ -14,7 +14,7 @@ module MissCleo
|
|
14
14
|
def self.normalize_paths(result_hash)
|
15
15
|
normalized_hash = Hash.new
|
16
16
|
result_hash.each do |key, value|
|
17
|
-
trimmed_key = key.gsub(/#{Regexp.quote(`pwd`.chomp)}
|
17
|
+
trimmed_key = key.gsub(/#{Regexp.quote(`pwd`.chomp)}\//, "")
|
18
18
|
normalized_hash[trimmed_key] = value
|
19
19
|
end
|
20
20
|
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module MissCleo
|
2
|
+
module CoverageMapHelper
|
3
|
+
|
4
|
+
def build_deck(filenames)
|
5
|
+
cov_map = Hash.new { |h, file| h[file] = Hash.new { |i, line| i[line] = [] } }
|
6
|
+
filenames.each do |filename|
|
7
|
+
File.open(filename, "r") do |f|
|
8
|
+
f.read
|
9
|
+
end.tap do |contents|
|
10
|
+
begin
|
11
|
+
build_coverage_map(cov_map, JSON.parse(contents))
|
12
|
+
rescue
|
13
|
+
puts "#{filename} is malformed, this may affect test predictons"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
File.open("total_coverage_map.json", "w") do |f|
|
19
|
+
f.write(JSON.dump(cov_map))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def predict
|
24
|
+
repo = Rugged::Repository.new '.'
|
25
|
+
lines_changed = Set.new
|
26
|
+
|
27
|
+
repo.index.diff.each_patch do |patch|
|
28
|
+
file = patch.delta.old_file[:path]
|
29
|
+
|
30
|
+
patch.each_hunk do |hunk|
|
31
|
+
hunk.each_line do |line|
|
32
|
+
case line.line_origin
|
33
|
+
when :addition
|
34
|
+
lines_changed << [file, line.new_lineno] unless exclude_from_map?(file)
|
35
|
+
when :deletion
|
36
|
+
lines_changed << [file, line.old_lineno] unless exclude_from_map?(file)
|
37
|
+
when :context
|
38
|
+
# do nothing
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
coverage_map = JSON.parse(File.open("total_coverage_map.json").read)
|
45
|
+
tests_to_run = []
|
46
|
+
lines_changed.each do |file, line|
|
47
|
+
coverage_map && coverage_map[file] && coverage_map[file].fetch(line.to_s, []).uniq.each do |desc|
|
48
|
+
tests_to_run << desc
|
49
|
+
end
|
50
|
+
end
|
51
|
+
if lines_changed.empty?
|
52
|
+
puts "No line changes detected."
|
53
|
+
elsif tests_to_run.empty?
|
54
|
+
puts "No tests found. May be due to blind spot, new tests you've just written, or the changes may be untested."
|
55
|
+
else
|
56
|
+
puts "Run these tests:"
|
57
|
+
puts tests_to_run.uniq.sort
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def exclude_from_map?(file_name)
|
65
|
+
# Let's add a configuration for ignored files
|
66
|
+
file_name == "db/structure.sql"
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_coverage_map(cov_map, cov_diffs)
|
70
|
+
cov_diffs.each do |test_to_code_map|
|
71
|
+
if test_to_code_map.length == 4 # for Minitest
|
72
|
+
test_file_and_line = test_to_code_map.first(2).join('#')
|
73
|
+
else # for RSpec
|
74
|
+
test_file_and_line = test_to_code_map.first
|
75
|
+
end
|
76
|
+
before, after = test_to_code_map.last(2)
|
77
|
+
|
78
|
+
# calculate the per test coverage
|
79
|
+
delta = diff before, after
|
80
|
+
|
81
|
+
delta.each_pair do |file, lines|
|
82
|
+
file_map = cov_map[file]
|
83
|
+
|
84
|
+
lines.each_with_index do |val, i|
|
85
|
+
# skip lines that weren't executed
|
86
|
+
next unless val && val > 0
|
87
|
+
|
88
|
+
# add the test name to the map. Multiple tests can execute the same
|
89
|
+
# line, so we need to use an array.
|
90
|
+
file_map[i + 1] << test_file_and_line
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def diff before, after
|
97
|
+
after.each_with_object({}) do |(file_name,line_cov), res|
|
98
|
+
before_line_cov = before[file_name] || []
|
99
|
+
|
100
|
+
# skip arrays that are exactly the same
|
101
|
+
next if before_line_cov == line_cov
|
102
|
+
|
103
|
+
# subtract the old coverage from the new coverage
|
104
|
+
cov = line_cov.zip(before_line_cov).map do |line_after, line_before|
|
105
|
+
if line_before
|
106
|
+
line_after - line_before
|
107
|
+
else
|
108
|
+
line_after
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# add the "diffed" coverage to the hash
|
113
|
+
res[file_name] = cov
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/miss_cleo/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miss_cleo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dean Hu
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-11-
|
13
|
+
date: 2015-11-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- bin/setup
|
63
63
|
- lib/miss_cleo.rb
|
64
64
|
- lib/miss_cleo/coverage_filter.rb
|
65
|
+
- lib/miss_cleo/coverage_map_helper.rb
|
65
66
|
- lib/miss_cleo/test_configurations/cucumber_config.rb
|
66
67
|
- lib/miss_cleo/test_configurations/rspec_config.rb
|
67
68
|
- lib/miss_cleo/version.rb
|