devtools 0.1.0 → 0.1.5
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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/Gemfile +0 -2
- data/README.md +3 -3
- data/circle.yml +1 -1
- data/config/devtools.yml +2 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/mutant.yml +2 -0
- data/config/reek.yml +7 -12
- data/config/rubocop.yml +8 -0
- data/devtools.gemspec +21 -19
- data/lib/devtools/config.rb +76 -55
- data/lib/devtools/flay.rb +94 -0
- data/lib/devtools/project/initializer/rake.rb +9 -7
- data/lib/devtools/project/initializer/rspec.rb +28 -55
- data/lib/devtools/project/initializer.rb +2 -12
- data/lib/devtools/project.rb +28 -105
- data/lib/devtools/rake/flay.rb +126 -0
- data/lib/devtools/spec_helper.rb +1 -3
- data/lib/devtools.rb +34 -83
- data/shared/spec/shared/abstract_type_behavior.rb +0 -2
- data/shared/spec/shared/command_method_behavior.rb +0 -2
- data/shared/spec/shared/each_method_behaviour.rb +0 -2
- data/shared/spec/shared/hash_method_behavior.rb +0 -2
- data/shared/spec/shared/idempotent_method_behavior.rb +0 -2
- data/shared/spec/support/ice_nine_config.rb +0 -2
- data/spec/integration/devtools/rake/flay/verify_spec.rb +164 -0
- data/spec/spec_helper.rb +2 -8
- data/spec/unit/devtools/config/yardstick_spec.rb +17 -0
- data/spec/unit/devtools/config_spec.rb +78 -0
- data/spec/unit/devtools/flay/file_list/call_spec.rb +19 -0
- data/spec/unit/devtools/flay/scale/flay_report_spec.rb +17 -0
- data/spec/unit/devtools/flay/scale/measure_spec.rb +43 -0
- data/spec/unit/devtools/project/initializer/rake_spec.rb +21 -0
- data/spec/unit/devtools/project/initializer/rspec_spec.rb +52 -0
- data/spec/unit/devtools/project_spec.rb +34 -0
- data/spec/unit/devtools_spec.rb +14 -0
- data/tasks/metrics/ci.rake +2 -3
- data/tasks/metrics/coverage.rake +0 -2
- data/tasks/metrics/flay.rake +6 -33
- data/tasks/metrics/flog.rake +0 -2
- data/tasks/metrics/mutant.rake +31 -39
- data/tasks/metrics/reek.rake +5 -4
- data/tasks/metrics/rubocop.rake +0 -2
- data/tasks/metrics/yardstick.rake +0 -14
- data/tasks/spec.rake +0 -2
- data/tasks/yard.rake +0 -2
- metadata +99 -35
- data/.travis.yml +0 -15
- data/TODO +0 -0
- data/bin/devtools +0 -18
- data/default/config/devtools.yml +0 -2
- data/default/config/flay.yml +0 -3
- data/default/config/flog.yml +0 -2
- data/default/config/mutant.yml +0 -3
- data/default/config/reek.yml +0 -103
- data/default/config/rubocop.yml +0 -91
- data/default/config/yardstick.yml +0 -2
- data/lib/devtools/platform.rb +0 -118
- data/lib/devtools/site/initializer.rb +0 -57
- data/lib/devtools/site.rb +0 -41
data/lib/devtools/project.rb
CHANGED
|
@@ -1,87 +1,22 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
1
|
module Devtools
|
|
4
2
|
|
|
5
3
|
# The project devtools supports
|
|
6
4
|
class Project
|
|
5
|
+
include Concord.new(:root)
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# @return [Config::Rubocop]
|
|
18
|
-
#
|
|
19
|
-
# @api private
|
|
20
|
-
attr_reader :rubocop
|
|
7
|
+
CONFIGS = {
|
|
8
|
+
devtools: Config::Devtools,
|
|
9
|
+
flay: Config::Flay,
|
|
10
|
+
flog: Config::Flog,
|
|
11
|
+
reek: Config::Reek,
|
|
12
|
+
mutant: Config::Mutant,
|
|
13
|
+
rubocop: Config::Rubocop,
|
|
14
|
+
yardstick: Config::Yardstick
|
|
15
|
+
}.freeze
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
# @return [Config::Flog]
|
|
25
|
-
#
|
|
26
|
-
# @api private
|
|
27
|
-
attr_reader :flog
|
|
17
|
+
private_constant(*constants(false))
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
#
|
|
31
|
-
# @return [Config::Yardstick]
|
|
32
|
-
#
|
|
33
|
-
# @api private
|
|
34
|
-
attr_reader :yardstick
|
|
35
|
-
|
|
36
|
-
# The flay configuration
|
|
37
|
-
#
|
|
38
|
-
# @return [Config::Flay]
|
|
39
|
-
#
|
|
40
|
-
# @api private
|
|
41
|
-
attr_reader :flay
|
|
42
|
-
|
|
43
|
-
# The mutant configuration
|
|
44
|
-
#
|
|
45
|
-
# @return [Config::Mutant]
|
|
46
|
-
#
|
|
47
|
-
# @api private
|
|
48
|
-
attr_reader :mutant
|
|
49
|
-
|
|
50
|
-
# The devtools configuration
|
|
51
|
-
#
|
|
52
|
-
# @return [Config::Devtools]
|
|
53
|
-
#
|
|
54
|
-
# @api private
|
|
55
|
-
attr_reader :devtools
|
|
56
|
-
|
|
57
|
-
# Return project root
|
|
58
|
-
#
|
|
59
|
-
# @return [Pathname]
|
|
60
|
-
#
|
|
61
|
-
# @api private
|
|
62
|
-
#
|
|
63
|
-
attr_reader :root
|
|
64
|
-
|
|
65
|
-
# The default config path
|
|
66
|
-
#
|
|
67
|
-
# @return [Pathname]
|
|
68
|
-
#
|
|
69
|
-
# @api private
|
|
70
|
-
attr_reader :default_config_path
|
|
71
|
-
|
|
72
|
-
# The lib directory
|
|
73
|
-
#
|
|
74
|
-
# @return [Pathname]
|
|
75
|
-
#
|
|
76
|
-
# @api private
|
|
77
|
-
attr_reader :lib_dir
|
|
78
|
-
|
|
79
|
-
# The Ruby file pattern
|
|
80
|
-
#
|
|
81
|
-
# @return [Pathname]
|
|
82
|
-
#
|
|
83
|
-
# @api private
|
|
84
|
-
attr_reader :file_pattern
|
|
19
|
+
attr_reader(*CONFIGS.keys)
|
|
85
20
|
|
|
86
21
|
# The spec root
|
|
87
22
|
#
|
|
@@ -90,20 +25,6 @@ module Devtools
|
|
|
90
25
|
# @api private
|
|
91
26
|
attr_reader :spec_root
|
|
92
27
|
|
|
93
|
-
# Return config directory
|
|
94
|
-
#
|
|
95
|
-
# @return [Pathname]
|
|
96
|
-
#
|
|
97
|
-
# @api private
|
|
98
|
-
attr_reader :config_dir
|
|
99
|
-
|
|
100
|
-
# The unit test timeout
|
|
101
|
-
#
|
|
102
|
-
# @return [Numeric]
|
|
103
|
-
#
|
|
104
|
-
# @api private
|
|
105
|
-
attr_reader :unit_test_timeout
|
|
106
|
-
|
|
107
28
|
# Initialize object
|
|
108
29
|
#
|
|
109
30
|
# @param [Pathname] root
|
|
@@ -113,12 +34,20 @@ module Devtools
|
|
|
113
34
|
# @api private
|
|
114
35
|
#
|
|
115
36
|
def initialize(root)
|
|
116
|
-
|
|
37
|
+
super(root)
|
|
117
38
|
|
|
118
39
|
initialize_environment
|
|
119
40
|
initialize_configs
|
|
41
|
+
end
|
|
120
42
|
|
|
121
|
-
|
|
43
|
+
# Init rspec
|
|
44
|
+
#
|
|
45
|
+
# @return [self]
|
|
46
|
+
#
|
|
47
|
+
# @api private
|
|
48
|
+
def init_rspec
|
|
49
|
+
Initializer::Rspec.call(self)
|
|
50
|
+
self
|
|
122
51
|
end
|
|
123
52
|
|
|
124
53
|
private
|
|
@@ -130,11 +59,7 @@ module Devtools
|
|
|
130
59
|
# @api private
|
|
131
60
|
#
|
|
132
61
|
def initialize_environment
|
|
133
|
-
@
|
|
134
|
-
@lib_dir = @root.join(LIB_DIRECTORY_NAME).freeze
|
|
135
|
-
@spec_root = @root.join(SPEC_DIRECTORY_NAME).freeze
|
|
136
|
-
@file_pattern = @lib_dir.join(RB_FILE_PATTERN).freeze
|
|
137
|
-
@config_dir = @default_config_path
|
|
62
|
+
@spec_root = root.join(SPEC_DIRECTORY_NAME)
|
|
138
63
|
end
|
|
139
64
|
|
|
140
65
|
# Initialize configs
|
|
@@ -144,13 +69,11 @@ module Devtools
|
|
|
144
69
|
# @api private
|
|
145
70
|
#
|
|
146
71
|
def initialize_configs
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
@mutant = Config::Mutant.new(self)
|
|
153
|
-
@devtools = Config::Devtools.new(self)
|
|
72
|
+
config_dir = root.join(DEFAULT_CONFIG_DIR_NAME)
|
|
73
|
+
|
|
74
|
+
CONFIGS.each do |name, klass|
|
|
75
|
+
instance_variable_set(:"@#{name}", klass.new(config_dir))
|
|
76
|
+
end
|
|
154
77
|
end
|
|
155
78
|
|
|
156
79
|
end # class Project
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
module Devtools
|
|
2
|
+
module Rake
|
|
3
|
+
# Flay metric runner
|
|
4
|
+
class Flay
|
|
5
|
+
include Anima.new(:threshold, :total_score, :lib_dirs, :excludes),
|
|
6
|
+
Procto.call(:verify),
|
|
7
|
+
Adamantium
|
|
8
|
+
|
|
9
|
+
BELOW_THRESHOLD = 'Adjust flay threshold down to %d'.freeze
|
|
10
|
+
TOTAL_MISMATCH = 'Flay total is now %d, but expected %d'.freeze
|
|
11
|
+
ABOVE_THRESHOLD = '%d chunks have a duplicate mass > %d'.freeze
|
|
12
|
+
|
|
13
|
+
# Verify code specified by `files` does not violate flay expectations
|
|
14
|
+
#
|
|
15
|
+
# @raise [SystemExit] if a violation is found
|
|
16
|
+
# @return [undefined] otherwise
|
|
17
|
+
#
|
|
18
|
+
# rubocop:disable MethodLength
|
|
19
|
+
#
|
|
20
|
+
# @api private
|
|
21
|
+
def verify
|
|
22
|
+
# Run flay first to ensure the max mass matches the threshold
|
|
23
|
+
Devtools.notify_metric_violation(
|
|
24
|
+
BELOW_THRESHOLD % largest_mass
|
|
25
|
+
) if below_threshold?
|
|
26
|
+
|
|
27
|
+
Devtools.notify_metric_violation(
|
|
28
|
+
TOTAL_MISMATCH % [total_mass, total_score]
|
|
29
|
+
) if total_mismatch?
|
|
30
|
+
|
|
31
|
+
# Run flay a second time with the threshold set
|
|
32
|
+
return unless above_threshold?
|
|
33
|
+
|
|
34
|
+
restricted_flay_scale.flay_report
|
|
35
|
+
Devtools.notify_metric_violation(
|
|
36
|
+
ABOVE_THRESHOLD % [restricted_mass_size, threshold]
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# List of files flay will analyze
|
|
43
|
+
#
|
|
44
|
+
# @return [Set<Pathname>]
|
|
45
|
+
#
|
|
46
|
+
# @api private
|
|
47
|
+
def files
|
|
48
|
+
Devtools::Flay::FileList.call(lib_dirs, excludes)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Is there mass duplication which exceeds specified `threshold`
|
|
52
|
+
#
|
|
53
|
+
# @return [Boolean]
|
|
54
|
+
#
|
|
55
|
+
# @api private
|
|
56
|
+
def above_threshold?
|
|
57
|
+
restricted_mass_size.nonzero?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Is the specified `threshold` greater than the largest flay mass
|
|
61
|
+
#
|
|
62
|
+
# @return [Boolean]
|
|
63
|
+
#
|
|
64
|
+
# @api private
|
|
65
|
+
def below_threshold?
|
|
66
|
+
threshold > largest_mass
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Is the expected mass total different from the actual mass total
|
|
70
|
+
#
|
|
71
|
+
# @return [Boolean]
|
|
72
|
+
#
|
|
73
|
+
# @api private
|
|
74
|
+
def total_mismatch?
|
|
75
|
+
!total_mass.equal?(total_score)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Size of mass measured by `Flay::Scale` and filtered by `threshold`
|
|
79
|
+
#
|
|
80
|
+
# @return [Integer]
|
|
81
|
+
#
|
|
82
|
+
# @api private
|
|
83
|
+
def restricted_mass_size
|
|
84
|
+
restricted_flay_scale.measure.size
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Sum of all flay mass
|
|
88
|
+
#
|
|
89
|
+
# @return [Integer]
|
|
90
|
+
#
|
|
91
|
+
# @api private
|
|
92
|
+
def total_mass
|
|
93
|
+
flay_masses.reduce(:+).to_i
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Largest flay mass found
|
|
97
|
+
#
|
|
98
|
+
# @return [Integer]
|
|
99
|
+
#
|
|
100
|
+
# @api private
|
|
101
|
+
def largest_mass
|
|
102
|
+
flay_masses.max.to_i
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Flay scale which only measures mass above `threshold`
|
|
106
|
+
#
|
|
107
|
+
# @return [Flay::Scale]
|
|
108
|
+
#
|
|
109
|
+
# @api private
|
|
110
|
+
def restricted_flay_scale
|
|
111
|
+
Devtools::Flay::Scale.new(minimum_mass: threshold.succ, files: files)
|
|
112
|
+
end
|
|
113
|
+
memoize :restricted_flay_scale
|
|
114
|
+
|
|
115
|
+
# All flay masses found in `files`
|
|
116
|
+
#
|
|
117
|
+
# @return [Array<Rational>]
|
|
118
|
+
#
|
|
119
|
+
# @api private
|
|
120
|
+
def flay_masses
|
|
121
|
+
Devtools::Flay::Scale.call(minimum_mass: 0, files: files)
|
|
122
|
+
end
|
|
123
|
+
memoize :flay_masses
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
data/lib/devtools/spec_helper.rb
CHANGED
data/lib/devtools.rb
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# Stdlib infrastructure
|
|
3
2
|
require 'pathname'
|
|
4
3
|
require 'rake'
|
|
5
4
|
require 'timeout'
|
|
6
5
|
require 'yaml'
|
|
7
6
|
require 'fileutils'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
require '
|
|
11
|
-
require '
|
|
12
|
-
require '
|
|
13
|
-
require '
|
|
14
|
-
require 'devtools/project/initializer'
|
|
15
|
-
require 'devtools/project/initializer/rake'
|
|
16
|
-
require 'devtools/project/initializer/rspec'
|
|
8
|
+
# Non stdlib infrastructure
|
|
9
|
+
require 'procto'
|
|
10
|
+
require 'anima'
|
|
11
|
+
require 'concord'
|
|
12
|
+
require 'adamantium'
|
|
17
13
|
|
|
18
|
-
#
|
|
19
|
-
|
|
14
|
+
# Wrapped tools
|
|
15
|
+
require 'flay'
|
|
16
|
+
require 'rspec'
|
|
17
|
+
require 'rspec/its'
|
|
18
|
+
require 'simplecov'
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
# Main devtools namespace population
|
|
21
|
+
module Devtools
|
|
22
22
|
|
|
23
23
|
ROOT = Pathname.new(__FILE__).parent.parent.freeze
|
|
24
24
|
PROJECT_ROOT = Pathname.pwd.freeze
|
|
@@ -28,17 +28,12 @@ module Devtools
|
|
|
28
28
|
RAKE_FILES_GLOB = ROOT.join('tasks/**/*.rake').to_s.freeze
|
|
29
29
|
LIB_DIRECTORY_NAME = 'lib'.freeze
|
|
30
30
|
SPEC_DIRECTORY_NAME = 'spec'.freeze
|
|
31
|
-
RB_FILE_PATTERN = '**/*.rb'.freeze
|
|
32
31
|
RAKE_FILE_NAME = 'Rakefile'.freeze
|
|
33
|
-
REQUIRE = "require 'devtools'".freeze
|
|
34
|
-
INIT_RAKE_TASKS = 'Devtools.init_rake_tasks'.freeze
|
|
35
32
|
SHARED_SPEC_PATTERN = '{shared,support}/**/*.rb'.freeze
|
|
36
33
|
UNIT_TEST_PATH_REGEXP = %r{\bspec/unit/}.freeze
|
|
37
34
|
DEFAULT_CONFIG_DIR_NAME = 'config'.freeze
|
|
38
|
-
ANNOTATION_WRAPPER = "\n# Added by devtools\n%s\n".freeze
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
SITE = Site.new(Project.new(PROJECT_ROOT))
|
|
36
|
+
private_constant(*constants(false))
|
|
42
37
|
|
|
43
38
|
# React to metric violation
|
|
44
39
|
#
|
|
@@ -63,26 +58,13 @@ module Devtools
|
|
|
63
58
|
self
|
|
64
59
|
end
|
|
65
60
|
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
# Expects to be called from $application_root/spec/spec_helper.rb
|
|
61
|
+
# Return devtools root path
|
|
69
62
|
#
|
|
70
|
-
# @return [
|
|
63
|
+
# @return [Pathname]
|
|
71
64
|
#
|
|
72
|
-
# @api
|
|
73
|
-
def self.
|
|
74
|
-
|
|
75
|
-
self
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Initialize devtools using default config
|
|
79
|
-
#
|
|
80
|
-
# @return [undefined]
|
|
81
|
-
#
|
|
82
|
-
# @api public
|
|
83
|
-
def self.init
|
|
84
|
-
SITE.init
|
|
85
|
-
self
|
|
65
|
+
# @api private
|
|
66
|
+
def self.root
|
|
67
|
+
ROOT
|
|
86
68
|
end
|
|
87
69
|
|
|
88
70
|
# Return project
|
|
@@ -91,53 +73,22 @@ module Devtools
|
|
|
91
73
|
#
|
|
92
74
|
# @api private
|
|
93
75
|
def self.project
|
|
94
|
-
|
|
76
|
+
PROJECT
|
|
95
77
|
end
|
|
96
78
|
|
|
97
|
-
|
|
98
|
-
#
|
|
99
|
-
# @param [Pathname] dir
|
|
100
|
-
# the directory containing the files to require
|
|
101
|
-
#
|
|
102
|
-
# @param [String] pattern
|
|
103
|
-
# the file pattern to match inside directory
|
|
104
|
-
#
|
|
105
|
-
# @return [self]
|
|
106
|
-
#
|
|
107
|
-
# @api private
|
|
108
|
-
def self.require_files(dir, pattern)
|
|
109
|
-
Dir[dir.join(pattern)].each { |file| require file }
|
|
110
|
-
self
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
# Detect ci
|
|
114
|
-
#
|
|
115
|
-
# @return [Boolean]
|
|
116
|
-
#
|
|
117
|
-
# @api private
|
|
118
|
-
#
|
|
119
|
-
def self.ci?
|
|
120
|
-
ENV.key?('CI')
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Detect circle ci
|
|
124
|
-
#
|
|
125
|
-
# @return [Boolean]
|
|
126
|
-
#
|
|
127
|
-
# @api private
|
|
128
|
-
#
|
|
129
|
-
def self.circle_ci?
|
|
130
|
-
ENV.key?('CIRCLECI')
|
|
131
|
-
end
|
|
79
|
+
end # module Devtools
|
|
132
80
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
81
|
+
# Devtools implementation
|
|
82
|
+
require 'devtools/config'
|
|
83
|
+
require 'devtools/project'
|
|
84
|
+
require 'devtools/project/initializer'
|
|
85
|
+
require 'devtools/project/initializer/rake'
|
|
86
|
+
require 'devtools/project/initializer/rspec'
|
|
87
|
+
require 'devtools/flay'
|
|
88
|
+
require 'devtools/rake/flay'
|
|
142
89
|
|
|
143
|
-
|
|
90
|
+
# Devtools self initialization
|
|
91
|
+
module Devtools
|
|
92
|
+
# The project devtools is active for
|
|
93
|
+
PROJECT = Project.new(PROJECT_ROOT)
|
|
94
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
describe Devtools::Rake::Flay, '#verify' do
|
|
2
|
+
let(:tempfile) { Tempfile.new(%w[file .rb], Dir.mktmpdir) }
|
|
3
|
+
let(:file) { Pathname(tempfile.path) }
|
|
4
|
+
let(:directories) { [file.dirname.to_s] }
|
|
5
|
+
|
|
6
|
+
let(:ruby) do
|
|
7
|
+
<<-ERUBY
|
|
8
|
+
def foo; end
|
|
9
|
+
def bar; end
|
|
10
|
+
ERUBY
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
around(:each) do |example|
|
|
14
|
+
begin
|
|
15
|
+
# silence other flay output
|
|
16
|
+
$stdout = $stderr = StringIO.new
|
|
17
|
+
|
|
18
|
+
tempfile.write(ruby)
|
|
19
|
+
tempfile.close
|
|
20
|
+
|
|
21
|
+
example.run
|
|
22
|
+
ensure
|
|
23
|
+
$stdout = STDOUT
|
|
24
|
+
$stderr = STDERR
|
|
25
|
+
|
|
26
|
+
file.unlink
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'reporting' do
|
|
31
|
+
let(:options) do
|
|
32
|
+
{ threshold: 3, total_score: 3, lib_dirs: directories, excludes: [] }.freeze
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
let(:instance) { described_class.new(options) }
|
|
36
|
+
|
|
37
|
+
it 'measures total mass' do
|
|
38
|
+
allow(::Flay).to receive(:new).and_call_original
|
|
39
|
+
|
|
40
|
+
instance.verify
|
|
41
|
+
|
|
42
|
+
expect(::Flay).to have_received(:new).with(hash_including(mass: 0))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'does not report the files it is processing' do
|
|
46
|
+
expect { instance.verify }.to_not output(/Processing #{file}/).to_stderr
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'when theshold is too low' do
|
|
51
|
+
let(:instance) do
|
|
52
|
+
described_class.new(threshold: 0, total_score: 0, lib_dirs: directories, excludes: [])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
specify do
|
|
56
|
+
expect { instance.verify }
|
|
57
|
+
.to raise_error(SystemExit)
|
|
58
|
+
.with_message('Flay total is now 3, but expected 0')
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context 'when threshold is too high' do
|
|
63
|
+
let(:instance) do
|
|
64
|
+
described_class.new(threshold: 1000, total_score: 0, lib_dirs: directories, excludes: [])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
specify do
|
|
68
|
+
expect { instance.verify }
|
|
69
|
+
.to raise_error(SystemExit)
|
|
70
|
+
.with_message('Adjust flay threshold down to 3')
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'when total is too high' do
|
|
75
|
+
let(:instance) do
|
|
76
|
+
described_class.new(threshold: 3, total_score: 50, lib_dirs: directories, excludes: [])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
specify do
|
|
80
|
+
expect { instance.verify }
|
|
81
|
+
.to raise_error(SystemExit)
|
|
82
|
+
.with_message('Flay total is now 3, but expected 50')
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context 'when duplicate mass is greater than 0' do
|
|
87
|
+
let(:ruby) do
|
|
88
|
+
<<-ERUBY
|
|
89
|
+
def foo
|
|
90
|
+
:hi if baz?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def bar
|
|
94
|
+
:hi if baz?
|
|
95
|
+
end
|
|
96
|
+
ERUBY
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
let(:report) do
|
|
100
|
+
<<-REPORT
|
|
101
|
+
Total score (lower is better) = 10
|
|
102
|
+
|
|
103
|
+
Similar code found in :defn (mass = 10)
|
|
104
|
+
#{file}:1
|
|
105
|
+
#{file}:5
|
|
106
|
+
REPORT
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
let(:instance) do
|
|
110
|
+
described_class.new(threshold: 3, total_score: 5, lib_dirs: directories, excludes: [])
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
specify do
|
|
114
|
+
expect { instance.verify }
|
|
115
|
+
.to raise_error(SystemExit)
|
|
116
|
+
.with_message('1 chunks have a duplicate mass > 3')
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
specify do
|
|
120
|
+
expect { instance.verify }
|
|
121
|
+
.to raise_error(SystemExit)
|
|
122
|
+
.and output(report).to_stdout
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
context 'when multiple duplicate masses' do
|
|
127
|
+
let(:ruby) do
|
|
128
|
+
<<-ERUBY
|
|
129
|
+
def foo; end
|
|
130
|
+
def bar; end
|
|
131
|
+
|
|
132
|
+
class Foo
|
|
133
|
+
def initialize
|
|
134
|
+
@a = 1
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
class Bar
|
|
138
|
+
def initialize
|
|
139
|
+
@a = 1
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
ERUBY
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
let(:instance) do
|
|
146
|
+
described_class.new(threshold: 5, total_score: 8, lib_dirs: directories, excludes: [])
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'sums masses for total' do
|
|
150
|
+
expect { instance.verify }.to_not raise_error
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'when no duplication masses' do
|
|
155
|
+
let(:ruby) { '' }
|
|
156
|
+
let(:instance) do
|
|
157
|
+
described_class.new(threshold: 0, total_score: 0, lib_dirs: directories, excludes: [])
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
specify do
|
|
161
|
+
expect { instance.verify }.to_not raise_error
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
1
|
require 'devtools/spec_helper'
|
|
2
|
+
require 'tempfile'
|
|
3
|
+
require 'tmpdir'
|
|
4
4
|
|
|
5
5
|
if ENV['COVERAGE'] == 'true'
|
|
6
|
-
require 'simplecov'
|
|
7
|
-
require 'coveralls'
|
|
8
|
-
|
|
9
6
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
|
10
7
|
SimpleCov::Formatter::HTMLFormatter,
|
|
11
|
-
Coveralls::SimpleCov::Formatter
|
|
12
8
|
]
|
|
13
9
|
|
|
14
10
|
SimpleCov.start do
|
|
@@ -22,8 +18,6 @@ if ENV['COVERAGE'] == 'true'
|
|
|
22
18
|
end
|
|
23
19
|
end
|
|
24
20
|
|
|
25
|
-
require 'devtools'
|
|
26
|
-
|
|
27
21
|
RSpec.configure do |config|
|
|
28
22
|
config.expect_with :rspec do |expect_with|
|
|
29
23
|
expect_with.syntax = :expect
|