sandi_meter 1.1.8 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/lib/sandi_meter/cli.rb +26 -12
- data/lib/sandi_meter/html_generator.rb +7 -7
- data/lib/sandi_meter/logger.rb +1 -1
- data/lib/sandi_meter/rules_checker.rb +8 -2
- data/lib/sandi_meter/version.rb +1 -1
- data/lib/sandi_meter/warning_scanner.rb +1 -1
- data/spec/analyzer_spec.rb +35 -35
- data/spec/calculator_spec.rb +4 -4
- data/spec/cli_spec.rb +76 -15
- data/spec/loc_checker_spec.rb +4 -4
- data/spec/method_arguments_counter_spec.rb +12 -12
- data/spec/rules_checker_spec.rb +2 -2
- data/spec/support/attr_matcher.rb +1 -1
- data/spec/support/terminate_matcher.rb +39 -0
- data/spec/test_helper.rb +19 -1
- data/spec/warning_scanner_spec.rb +3 -3
- metadata +20 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a83923b441f198ed909f5cc7e0b3933b4b0b2ad
|
4
|
+
data.tar.gz: 5f0d9b05649988b2c7e2094ee81490212be49444
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b35f03467396393d3ce937b5850c3cd1e6d1ac83becbc137feac43d7bb1b904e1fc21f3f195150b98dd7daa8c917406e30ad06bd7490bfc02a7fd71e51e69f5
|
7
|
+
data.tar.gz: 047facafdc3447ea5c37ed7e11260504fe6e7fb2e42f980b65e04f3a673d1bcaabc54328a9b33471cca1e4cabbbc14b7c5e095fccdd96da73cfcdbcfd6eced64
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ Static analysis tool for checking your Ruby code for [Sandi Metz' four rules](ht
|
|
7
7
|
* 100 lines per class
|
8
8
|
* 5 lines per method
|
9
9
|
* 4 params per method call (and don't even try cheating with hash params)
|
10
|
-
* 1 instance
|
10
|
+
* 1 instance variable per controller action
|
11
11
|
|
12
12
|
## CLI mode
|
13
13
|
|
@@ -19,8 +19,12 @@ sandi_meter --help
|
|
19
19
|
-g, --graph HTML mode. Create folder, log data and output stats to HTML file.
|
20
20
|
--json Output as JSON
|
21
21
|
-l, --log Show syntax error and indentation log output
|
22
|
-
-
|
22
|
+
-o, --output-path PATH Path for storing generated output files (default: ./sandi_meter/)
|
23
|
+
-p, --path PATH Path to folder or file to analyze
|
24
|
+
-q, --quiet Do not open HTML report for graph option in browser.
|
25
|
+
-t, --thresholds THRESHOLD Thresholds for each rule (default: "90,90,90,90" or in config.yml)
|
23
26
|
-r, --rules Show rules
|
27
|
+
-v, --version Gem version
|
24
28
|
-h, --help Help
|
25
29
|
|
26
30
|
cd ~/your/ruby/or/rails/project
|
data/lib/sandi_meter/cli.rb
CHANGED
@@ -21,6 +21,11 @@ module SandiMeter
|
|
21
21
|
description: "Path to folder or file to analyze",
|
22
22
|
default: "."
|
23
23
|
|
24
|
+
option :output_path,
|
25
|
+
short: "-o PATH",
|
26
|
+
long: "--output-path PATH",
|
27
|
+
description: "Path for storing generated output files (default: ./sandi_meter/)"
|
28
|
+
|
24
29
|
option :log,
|
25
30
|
short: "-l",
|
26
31
|
long: "--log",
|
@@ -70,6 +75,12 @@ module SandiMeter
|
|
70
75
|
long: "--json",
|
71
76
|
description: "Output as JSON",
|
72
77
|
boolean: false
|
78
|
+
|
79
|
+
option :rule_thresholds,
|
80
|
+
short: "-t THRESHOLD",
|
81
|
+
long: "--thresholds THRESHOLD",
|
82
|
+
description: "Thresholds for each rule (default: 90,90,90,90) or in config.yml",
|
83
|
+
default: "90,90,90,90"
|
73
84
|
end
|
74
85
|
|
75
86
|
class CLI
|
@@ -78,12 +89,15 @@ module SandiMeter
|
|
78
89
|
cli = CommandParser.new
|
79
90
|
cli.parse_options
|
80
91
|
|
92
|
+
cli.config[:output_path] ||= File.expand_path(File.join(cli.config[:path], 'sandi_meter'))
|
93
|
+
|
94
|
+
cli.config[:rule_thresholds] = cli.config[:rule_thresholds].split(",").map(&:to_i)
|
95
|
+
|
81
96
|
if cli.config[:graph]
|
82
|
-
|
83
|
-
FileUtils.mkdir(log_dir_path) unless Dir.exists?(log_dir_path)
|
97
|
+
FileUtils.mkdir_p(cli.config[:output_path]) unless Dir.exists?(cli.config[:output_path])
|
84
98
|
|
85
|
-
create_config_file(cli.config[:
|
86
|
-
create_config_file(cli.config[:
|
99
|
+
create_config_file(cli.config[:output_path], '.sandi_meter', %w(db vendor).join("\n"))
|
100
|
+
create_config_file(cli.config[:output_path], 'config.yml', YAML.dump({ thresholds: [90, 90, 90, 90] }))
|
87
101
|
end
|
88
102
|
|
89
103
|
if cli.config[:version]
|
@@ -108,16 +122,16 @@ module SandiMeter
|
|
108
122
|
formatter.print_data(data)
|
109
123
|
|
110
124
|
if cli.config[:graph]
|
111
|
-
if File.directory?(cli.config[:
|
125
|
+
if File.directory?(cli.config[:output_path])
|
112
126
|
logger = SandiMeter::Logger.new(data)
|
113
|
-
logger.log!(cli.config[:
|
127
|
+
logger.log!(cli.config[:output_path])
|
114
128
|
|
115
129
|
html_generator = SandiMeter::HtmlGenerator.new
|
116
|
-
html_generator.copy_assets!(cli.config[:
|
117
|
-
html_generator.generate_data!(cli.config[:
|
118
|
-
html_generator.generate_details!(cli.config[:
|
130
|
+
html_generator.copy_assets!(cli.config[:output_path])
|
131
|
+
html_generator.generate_data!(cli.config[:output_path])
|
132
|
+
html_generator.generate_details!(cli.config[:output_path], data)
|
119
133
|
|
120
|
-
index_html_path = File.join(cli.config[:
|
134
|
+
index_html_path = File.join(cli.config[:output_path], 'index.html')
|
121
135
|
unless cli.config[:quiet]
|
122
136
|
open_in_browser(index_html_path)
|
123
137
|
end
|
@@ -126,11 +140,11 @@ module SandiMeter
|
|
126
140
|
end
|
127
141
|
end
|
128
142
|
|
129
|
-
config_file_path = File.join(cli.config[:
|
143
|
+
config_file_path = File.join(cli.config[:output_path], 'config.yml')
|
130
144
|
config = if File.exists?(config_file_path)
|
131
145
|
YAML.load(File.read(config_file_path))
|
132
146
|
else
|
133
|
-
{
|
147
|
+
{ thresholds: cli.config[:rule_thresholds] }
|
134
148
|
end
|
135
149
|
|
136
150
|
if RulesChecker.new(data, config).ok?
|
@@ -4,19 +4,19 @@ require 'json'
|
|
4
4
|
module SandiMeter
|
5
5
|
class HtmlGenerator
|
6
6
|
def copy_assets!(path)
|
7
|
-
asset_dir_path = File.join(path, '
|
7
|
+
asset_dir_path = File.join(path, 'assets')
|
8
8
|
FileUtils.mkdir(asset_dir_path) unless Dir.exists?(asset_dir_path)
|
9
|
+
html_dir = File.expand_path('../../html', File.dirname(__FILE__))
|
9
10
|
|
10
|
-
|
11
|
-
Dir[File.join(File.dirname(__FILE__), "../../html/*.{js,css,png}")].each do |file|
|
11
|
+
Dir[File.join(html_dir, "*.{js,css,png}")].each do |file|
|
12
12
|
FileUtils.cp file, File.join(asset_dir_path, File.basename(file))
|
13
13
|
end
|
14
14
|
|
15
|
-
FileUtils.cp File.join(
|
15
|
+
FileUtils.cp File.join(html_dir, 'index.html'), File.join(path, 'index.html')
|
16
16
|
end
|
17
17
|
|
18
18
|
def generate_data!(path)
|
19
|
-
raw_data = File.read(File.join(path, 'sandi_meter
|
19
|
+
raw_data = File.read(File.join(path, 'sandi_meter.log')).split("\n")
|
20
20
|
raw_data.map! { |row| row.split(';').map(&:to_i) }
|
21
21
|
|
22
22
|
data = []
|
@@ -31,7 +31,7 @@ module SandiMeter
|
|
31
31
|
data << hash
|
32
32
|
end
|
33
33
|
|
34
|
-
index_file = File.join(path, '
|
34
|
+
index_file = File.join(path, 'index.html')
|
35
35
|
index = File.read(index_file)
|
36
36
|
index.gsub!('<% plot_data %>', data.to_json)
|
37
37
|
|
@@ -91,7 +91,7 @@ module SandiMeter
|
|
91
91
|
)
|
92
92
|
end
|
93
93
|
|
94
|
-
index_file = File.join(path, '
|
94
|
+
index_file = File.join(path, 'index.html')
|
95
95
|
index = File.read(index_file)
|
96
96
|
index.gsub!('<% details %>', details)
|
97
97
|
|
data/lib/sandi_meter/logger.rb
CHANGED
@@ -10,12 +10,18 @@ module SandiMeter
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def ok?
|
13
|
-
|
13
|
+
if @config[:threshold]
|
14
|
+
puts "DEPRECATION WARNING: sandi_meter threshold will be deprecated. Set thresholds for each rule in sandi_meter config.yml"
|
15
|
+
|
16
|
+
@rules.reduce(:+) / 4 > @config[:threshold]
|
17
|
+
elsif @config[:thresholds]
|
18
|
+
@rules.each_with_index.map { |percentage, index| percentage >= @config[:thresholds][index].to_f }.reduce(:&)
|
19
|
+
end
|
14
20
|
end
|
15
21
|
|
16
22
|
private
|
17
23
|
def percentage(amount, total)
|
18
|
-
total > 0 ? (amount / total.to_f)*100 : 100
|
24
|
+
total > 0 ? (amount / total.to_f) * 100 : 100
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
data/lib/sandi_meter/version.rb
CHANGED
data/spec/analyzer_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe SandiMeter::Analyzer do
|
|
14
14
|
it 'finds indentation warnings for method' do
|
15
15
|
klass = analyzer.classes.find { |c| c.name == "TestClass" }
|
16
16
|
|
17
|
-
klass.
|
17
|
+
expect(klass).to have_attributes(
|
18
18
|
first_line: 1,
|
19
19
|
last_line: 5,
|
20
20
|
path: test_file_path(3)
|
@@ -24,7 +24,7 @@ describe SandiMeter::Analyzer do
|
|
24
24
|
it 'finds methods' do
|
25
25
|
method = analyzer.methods["TestClass"].find { |m| m.name == "blah" }
|
26
26
|
|
27
|
-
method.
|
27
|
+
expect(method).to have_attributes(
|
28
28
|
first_line: 2,
|
29
29
|
last_line: 4,
|
30
30
|
number_of_arguments: 0,
|
@@ -35,7 +35,7 @@ describe SandiMeter::Analyzer do
|
|
35
35
|
it 'finds method calls that brakes third rule' do
|
36
36
|
method_call = analyzer.method_calls.first
|
37
37
|
|
38
|
-
method_call.
|
38
|
+
expect(method_call).to have_attributes(
|
39
39
|
first_line: 3,
|
40
40
|
number_of_arguments: 5,
|
41
41
|
path: test_file_path(3)
|
@@ -53,7 +53,7 @@ describe SandiMeter::Analyzer do
|
|
53
53
|
it 'finds indentation warnings for method' do
|
54
54
|
klass = analyzer.classes.find { |c| c.name == "MyApp::TestClass" }
|
55
55
|
|
56
|
-
klass.
|
56
|
+
expect(klass).to have_attributes(
|
57
57
|
first_line: 2,
|
58
58
|
last_line: nil,
|
59
59
|
path: test_file_path(1)
|
@@ -63,7 +63,7 @@ describe SandiMeter::Analyzer do
|
|
63
63
|
it 'finds methods' do
|
64
64
|
method = analyzer.methods["MyApp::TestClass"].find { |m| m.name == "blah" }
|
65
65
|
|
66
|
-
method.
|
66
|
+
expect(method).to have_attributes(
|
67
67
|
first_line: 3,
|
68
68
|
last_line: nil,
|
69
69
|
number_of_arguments: 0,
|
@@ -82,7 +82,7 @@ describe SandiMeter::Analyzer do
|
|
82
82
|
it 'finds classes' do
|
83
83
|
klass = analyzer.classes.find { |c| c.name == "FirstTestClass" }
|
84
84
|
|
85
|
-
klass.
|
85
|
+
expect(klass).to have_attributes(
|
86
86
|
first_line: 1,
|
87
87
|
last_line: 4,
|
88
88
|
path: test_file_path(4)
|
@@ -90,7 +90,7 @@ describe SandiMeter::Analyzer do
|
|
90
90
|
|
91
91
|
klass = analyzer.classes.find { |c| c.name == "SecondTestClass" }
|
92
92
|
|
93
|
-
klass.
|
93
|
+
expect(klass).to have_attributes(
|
94
94
|
first_line: 6,
|
95
95
|
last_line: 9,
|
96
96
|
path: test_file_path(4)
|
@@ -100,7 +100,7 @@ describe SandiMeter::Analyzer do
|
|
100
100
|
it 'finds methods' do
|
101
101
|
method = analyzer.methods["FirstTestClass"].find { |m| m.name == "first_meth" }
|
102
102
|
|
103
|
-
method.
|
103
|
+
expect(method).to have_attributes(
|
104
104
|
first_line: 2,
|
105
105
|
last_line: 3,
|
106
106
|
number_of_arguments: 1,
|
@@ -109,7 +109,7 @@ describe SandiMeter::Analyzer do
|
|
109
109
|
|
110
110
|
method = analyzer.methods["SecondTestClass"].find { |m| m.name == "second_meth" }
|
111
111
|
|
112
|
-
method.
|
112
|
+
expect(method).to have_attributes(
|
113
113
|
first_line: 7,
|
114
114
|
last_line: 8,
|
115
115
|
number_of_arguments: 1,
|
@@ -128,7 +128,7 @@ describe SandiMeter::Analyzer do
|
|
128
128
|
it 'finds classes' do
|
129
129
|
klass = analyzer.classes.find { |c| c.name == "OneLinerClass" }
|
130
130
|
|
131
|
-
klass.
|
131
|
+
expect(klass).to have_attributes(
|
132
132
|
first_line: 1,
|
133
133
|
last_line: nil,
|
134
134
|
path: test_file_path(5)
|
@@ -136,7 +136,7 @@ describe SandiMeter::Analyzer do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
it 'finds methods' do
|
139
|
-
analyzer.methods.
|
139
|
+
expect(analyzer.methods).to be_empty
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
@@ -149,14 +149,14 @@ describe SandiMeter::Analyzer do
|
|
149
149
|
|
150
150
|
it 'finds class and subclass' do
|
151
151
|
klass = analyzer.classes.find { |c| c.name == "MyApp::Blah::User" }
|
152
|
-
klass.
|
152
|
+
expect(klass).to have_attributes(
|
153
153
|
first_line: 5,
|
154
154
|
last_line: 13,
|
155
155
|
path: test_file_path(7)
|
156
156
|
)
|
157
157
|
|
158
158
|
klass = analyzer.classes.find { |c| c.name == "MyApp::Blah::User::SubUser" }
|
159
|
-
klass.
|
159
|
+
expect(klass).to have_attributes(
|
160
160
|
first_line: 9,
|
161
161
|
last_line: 12,
|
162
162
|
path: test_file_path(7)
|
@@ -165,7 +165,7 @@ describe SandiMeter::Analyzer do
|
|
165
165
|
|
166
166
|
it 'finds methods' do
|
167
167
|
method = analyzer.methods["MyApp::Blah"].find { |m| m.name == "module_meth" }
|
168
|
-
method.
|
168
|
+
expect(method).to have_attributes(
|
169
169
|
first_line: 2,
|
170
170
|
last_line: 3,
|
171
171
|
number_of_arguments: 0,
|
@@ -173,7 +173,7 @@ describe SandiMeter::Analyzer do
|
|
173
173
|
)
|
174
174
|
|
175
175
|
method = analyzer.methods["MyApp::Blah::User"].find { |m| m.name == "class_meth" }
|
176
|
-
method.
|
176
|
+
expect(method).to have_attributes(
|
177
177
|
first_line: 6,
|
178
178
|
last_line: 7,
|
179
179
|
number_of_arguments: 0,
|
@@ -181,7 +181,7 @@ describe SandiMeter::Analyzer do
|
|
181
181
|
)
|
182
182
|
|
183
183
|
method = analyzer.methods["MyApp::Blah::User::SubUser"].find { |m| m.name == "sub_meth" }
|
184
|
-
method.
|
184
|
+
expect(method).to have_attributes(
|
185
185
|
first_line: 10,
|
186
186
|
last_line: 11,
|
187
187
|
number_of_arguments: 0,
|
@@ -199,7 +199,7 @@ describe SandiMeter::Analyzer do
|
|
199
199
|
|
200
200
|
it 'finds class and subclass' do
|
201
201
|
klass = analyzer.classes.find { |c| c.name == "RailsController" }
|
202
|
-
klass.
|
202
|
+
expect(klass).to have_attributes(
|
203
203
|
first_line: 1,
|
204
204
|
last_line: 12,
|
205
205
|
path: test_file_path(8)
|
@@ -208,7 +208,7 @@ describe SandiMeter::Analyzer do
|
|
208
208
|
|
209
209
|
it 'finds methods' do
|
210
210
|
method = analyzer.methods["RailsController"].find { |m| m.name == "index" }
|
211
|
-
method.
|
211
|
+
expect(method).to have_attributes(
|
212
212
|
first_line: 2,
|
213
213
|
last_line: 3,
|
214
214
|
number_of_arguments: 0,
|
@@ -216,7 +216,7 @@ describe SandiMeter::Analyzer do
|
|
216
216
|
)
|
217
217
|
|
218
218
|
method = analyzer.methods["RailsController"].find { |m| m.name == "destroy" }
|
219
|
-
method.
|
219
|
+
expect(method).to have_attributes(
|
220
220
|
first_line: 5,
|
221
221
|
last_line: 6,
|
222
222
|
number_of_arguments: 0,
|
@@ -224,7 +224,7 @@ describe SandiMeter::Analyzer do
|
|
224
224
|
)
|
225
225
|
|
226
226
|
method = analyzer.methods["RailsController"].find { |m| m.name == "private_meth" }
|
227
|
-
method.
|
227
|
+
expect(method).to be_nil
|
228
228
|
end
|
229
229
|
end
|
230
230
|
|
@@ -238,7 +238,7 @@ describe SandiMeter::Analyzer do
|
|
238
238
|
|
239
239
|
it 'finds instance variable' do
|
240
240
|
method = analyzer.methods["UsersController"].find { |m| m.name == "index" }
|
241
|
-
method.ivars.
|
241
|
+
expect(method.ivars).to eq(["@users"])
|
242
242
|
end
|
243
243
|
end
|
244
244
|
|
@@ -251,7 +251,7 @@ describe SandiMeter::Analyzer do
|
|
251
251
|
|
252
252
|
it 'does not find instance variables' do
|
253
253
|
method = analyzer.methods["GuestController"].find { |m| m.name == "create_guest_user" }
|
254
|
-
method.ivars.
|
254
|
+
expect(method.ivars).to be_empty
|
255
255
|
end
|
256
256
|
end
|
257
257
|
|
@@ -264,10 +264,10 @@ describe SandiMeter::Analyzer do
|
|
264
264
|
|
265
265
|
it 'does not find instance variable' do
|
266
266
|
method = analyzer.methods["User"].find { |m| m.name == "initialize" }
|
267
|
-
method.ivars.
|
267
|
+
expect(method.ivars).to be_empty
|
268
268
|
|
269
269
|
method = analyzer.methods["User"].find { |m| m.name == "hi" }
|
270
|
-
method.ivars.
|
270
|
+
expect(method.ivars).to be_empty
|
271
271
|
end
|
272
272
|
end
|
273
273
|
|
@@ -280,22 +280,22 @@ describe SandiMeter::Analyzer do
|
|
280
280
|
|
281
281
|
it 'finds method defined after public keyword' do
|
282
282
|
method = analyzer.methods["UsersController"].find { |m| m.name == "create" }
|
283
|
-
method.ivars.
|
283
|
+
expect(method.ivars).to eq(["@user"])
|
284
284
|
end
|
285
285
|
|
286
286
|
it 'omits actions without instance variables' do
|
287
287
|
method = analyzer.methods["UsersController"].find { |m| m.name == "show" }
|
288
|
-
method.ivars.
|
288
|
+
expect(method.ivars).to be_empty
|
289
289
|
end
|
290
290
|
|
291
291
|
it 'omits private methods' do
|
292
292
|
method = analyzer.methods["UsersController"].find { |m| m.name == "find_user" }
|
293
|
-
method.
|
293
|
+
expect(method).to be_nil
|
294
294
|
end
|
295
295
|
|
296
296
|
it 'omits protected methods' do
|
297
297
|
method = analyzer.methods["UsersController"].find { |m| m.name == "protected_find_user" }
|
298
|
-
method.
|
298
|
+
expect(method).to be_nil
|
299
299
|
end
|
300
300
|
end
|
301
301
|
end
|
@@ -310,7 +310,7 @@ describe SandiMeter::Analyzer do
|
|
310
310
|
it 'counts arguments' do
|
311
311
|
method_call = analyzer.method_calls.first
|
312
312
|
|
313
|
-
method_call.
|
313
|
+
expect(method_call).to have_attributes(
|
314
314
|
first_line: 3,
|
315
315
|
number_of_arguments: 5,
|
316
316
|
path: test_file_path(11)
|
@@ -328,7 +328,7 @@ describe SandiMeter::Analyzer do
|
|
328
328
|
it 'are count for class definition' do
|
329
329
|
klass = analyzer.classes.find { |c| c.name == "Valera" }
|
330
330
|
|
331
|
-
klass.
|
331
|
+
expect(klass).to have_attributes(
|
332
332
|
first_line: 1,
|
333
333
|
last_line: 109,
|
334
334
|
path: test_file_path(12)
|
@@ -338,7 +338,7 @@ describe SandiMeter::Analyzer do
|
|
338
338
|
it 'are count for method definition' do
|
339
339
|
method = analyzer.methods["Valera"].find { |m| m.name == "doodle" }
|
340
340
|
|
341
|
-
method.
|
341
|
+
expect(method).to have_attributes(
|
342
342
|
first_line: 2,
|
343
343
|
last_line: 9,
|
344
344
|
number_of_arguments: 0,
|
@@ -355,7 +355,7 @@ describe SandiMeter::Analyzer do
|
|
355
355
|
end
|
356
356
|
|
357
357
|
it 'is not scanned' do
|
358
|
-
analyzer.method_calls.
|
358
|
+
expect(analyzer.method_calls).to be_empty
|
359
359
|
end
|
360
360
|
end
|
361
361
|
|
@@ -370,7 +370,7 @@ describe SandiMeter::Analyzer do
|
|
370
370
|
it 'mark 4line methods good' do
|
371
371
|
method = analyzer.methods["TestClass"].find { |m| m.name == "render4" }
|
372
372
|
|
373
|
-
method.
|
373
|
+
expect(method).to have_attributes(
|
374
374
|
first_line: 2,
|
375
375
|
last_line: 7,
|
376
376
|
number_of_arguments: 0,
|
@@ -381,7 +381,7 @@ describe SandiMeter::Analyzer do
|
|
381
381
|
it 'mark 5line methods good' do
|
382
382
|
method = analyzer.methods["TestClass"].find { |m| m.name == "render5" }
|
383
383
|
|
384
|
-
method.
|
384
|
+
expect(method).to have_attributes(
|
385
385
|
first_line: 9,
|
386
386
|
last_line: 15,
|
387
387
|
number_of_arguments: 0,
|
@@ -392,7 +392,7 @@ describe SandiMeter::Analyzer do
|
|
392
392
|
it 'mark 6line methods bad' do
|
393
393
|
method = analyzer.methods["TestClass"].find { |m| m.name == "render6" }
|
394
394
|
|
395
|
-
method.
|
395
|
+
expect(method).to have_attributes(
|
396
396
|
first_line: 17,
|
397
397
|
last_line: 24,
|
398
398
|
number_of_arguments: 0,
|
data/spec/calculator_spec.rb
CHANGED
@@ -17,13 +17,13 @@ describe SandiMeter::Calculator do
|
|
17
17
|
it 'counts class lines' do
|
18
18
|
output = calculator.calculate!(true)
|
19
19
|
klass = output[:first_rule][:log][:classes].find { |params| params.first == "User" }
|
20
|
-
klass[1].
|
20
|
+
expect(klass[1]).to eq(109)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'counts method lines' do
|
24
24
|
output = calculator.calculate!(true)
|
25
25
|
method_params = output[:second_rule][:log][:methods].find { |method| method[1] == "create" }
|
26
|
-
method_params[2].
|
26
|
+
expect(method_params[2]).to eq(6)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -69,12 +69,12 @@ describe SandiMeter::Calculator do
|
|
69
69
|
describe 'no matching ruby files found' do
|
70
70
|
it 'counts class lines' do
|
71
71
|
output = calculator.calculate!(false)
|
72
|
-
output[:first_rule][:total_classes_amount].
|
72
|
+
expect(output[:first_rule][:total_classes_amount]).to eql(0)
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'counts method lines' do
|
76
76
|
output = calculator.calculate!(true)
|
77
|
-
output[:second_rule][:total_methods_amount].
|
77
|
+
expect(output[:second_rule][:total_methods_amount]).to eq(0)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/spec/cli_spec.rb
CHANGED
@@ -2,25 +2,37 @@ require 'test_helper'
|
|
2
2
|
require_relative '../lib/sandi_meter/cli'
|
3
3
|
|
4
4
|
describe SandiMeter::CLI do
|
5
|
+
include FakeFS::SpecHelpers
|
6
|
+
|
5
7
|
let(:cli) { SandiMeter::CLI }
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
let(:gem_root) { File.expand_path('../', File.dirname(__FILE__)) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
FakeFS.activate!
|
12
|
+
|
13
|
+
FakeFS::FileSystem.clone(gem_root)
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
FakeFS.deactivate!
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#execute', silent_cli: true do
|
21
|
+
before do
|
9
22
|
@original_argv = ARGV
|
10
23
|
ARGV.clear
|
11
24
|
end
|
12
|
-
|
13
|
-
after do
|
25
|
+
|
26
|
+
after do
|
14
27
|
ARGV.clear
|
15
28
|
ARGV.concat(@original_argv)
|
16
29
|
end
|
17
|
-
|
30
|
+
|
18
31
|
context 'with the graph flag passed in' do
|
19
32
|
before { ARGV.push('-g') }
|
20
|
-
|
21
|
-
|
33
|
+
|
22
34
|
it 'opens the graph in a web browser' do
|
23
|
-
cli.
|
35
|
+
expect(cli).to receive(:open_in_browser)
|
24
36
|
expect { cli.execute }.to raise_error(SystemExit)
|
25
37
|
end
|
26
38
|
end
|
@@ -30,15 +42,64 @@ describe SandiMeter::CLI do
|
|
30
42
|
ARGV.push('-q')
|
31
43
|
ARGV.push('-g')
|
32
44
|
end
|
33
|
-
|
34
|
-
ARGV.pop
|
35
|
-
ARGV.pop
|
36
|
-
end
|
37
|
-
|
45
|
+
|
38
46
|
it 'does not open the browser' do
|
39
|
-
cli.
|
47
|
+
expect(cli).to_not receive(:open_in_browser)
|
40
48
|
expect { cli.execute }.to raise_error(SystemExit)
|
41
49
|
end
|
42
50
|
end
|
51
|
+
|
52
|
+
context 'output path passed in' do
|
53
|
+
let(:test_path) { '/test_out_dir/test2' }
|
54
|
+
before do
|
55
|
+
ARGV.push('-q')
|
56
|
+
ARGV.push('-g')
|
57
|
+
ARGV.push('-o')
|
58
|
+
ARGV.push(test_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'saves output files to specified output path' do
|
62
|
+
expect { cli.execute }.to raise_error(SystemExit)
|
63
|
+
expect(File.directory?(test_path)).to eq(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'output path not specified' do
|
68
|
+
before do
|
69
|
+
ARGV.push('-q')
|
70
|
+
ARGV.push('-g')
|
71
|
+
ARGV.push('-p')
|
72
|
+
ARGV.push('/')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'saves output files in sandi_meter folder relative to scanned path' do
|
76
|
+
expect { cli.execute }.to raise_error(SystemExit)
|
77
|
+
expect(File.directory?(File.expand_path('/sandi_meter'))).to eq(true)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'makes account for rules thresholds' do
|
82
|
+
context 'for low thresholds' do
|
83
|
+
before do
|
84
|
+
ARGV.push('-t')
|
85
|
+
ARGV.push("1,1,1,1")
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'terminates with 0 code' do
|
89
|
+
expect { cli.execute }.to terminate.with_code(0)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'for high thresholds' do
|
94
|
+
before do
|
95
|
+
ARGV.push('-t')
|
96
|
+
ARGV.push("99,99,99,99")
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'terminates with 1 code' do
|
100
|
+
expect { cli.execute }.to terminate.with_code(1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
43
104
|
end
|
44
105
|
end
|
data/spec/loc_checker_spec.rb
CHANGED
@@ -8,24 +8,24 @@ describe SandiMeter::LOCChecker do
|
|
8
8
|
context 'for short code' do
|
9
9
|
before do
|
10
10
|
stub_const('SandiMeter::LOCChecker::MAX_LOC', { 'blah' => 10 })
|
11
|
-
checker.
|
11
|
+
allow(checker).to receive(:locs_size).and_return(rand(0..10))
|
12
12
|
end
|
13
13
|
|
14
14
|
# REFACTOR
|
15
15
|
# avoid passing dumb arguments to tested methods
|
16
16
|
it 'passes the check' do
|
17
|
-
checker.check([1,2,3], 'blah').
|
17
|
+
expect(checker.check([1,2,3], 'blah')).to eq true
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'for large code' do
|
22
22
|
before do
|
23
23
|
stub_const('SandiMeter::LOCChecker::MAX_LOC', { 'blah' => 10 })
|
24
|
-
checker.
|
24
|
+
allow(checker).to receive(:locs_size).and_return(rand(11..100))
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'does not pass the check' do
|
28
|
-
checker.check([1,2,3], 'blah').
|
28
|
+
expect(checker.check([1,2,3], 'blah')).to eq false
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -10,8 +10,8 @@ describe SandiMeter::MethodArgumentsCounter do
|
|
10
10
|
let(:args_add_block_2) { load_args_block('blah(arg1, arg2)')}
|
11
11
|
|
12
12
|
it 'counts arguments' do
|
13
|
-
analyzer.count(args_add_block_1).
|
14
|
-
analyzer.count(args_add_block_2).
|
13
|
+
expect(analyzer.count(args_add_block_1)).to eq([2, 1])
|
14
|
+
expect(analyzer.count(args_add_block_2)).to eq([2, 1])
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -23,10 +23,10 @@ describe SandiMeter::MethodArgumentsCounter do
|
|
23
23
|
let(:args_add_block_4) { load_args_block('blah(k1: :v1, k2: :v2)') }
|
24
24
|
|
25
25
|
it 'counts arguments' do
|
26
|
-
analyzer.count(args_add_block_1).
|
27
|
-
analyzer.count(args_add_block_2).
|
28
|
-
analyzer.count(args_add_block_3).
|
29
|
-
analyzer.count(args_add_block_4).
|
26
|
+
expect(analyzer.count(args_add_block_1)).to eq([1, 1])
|
27
|
+
expect(analyzer.count(args_add_block_2)).to eq([1, 1])
|
28
|
+
expect(analyzer.count(args_add_block_3)).to eq([2, 1])
|
29
|
+
expect(analyzer.count(args_add_block_4)).to eq([2, 1])
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -37,13 +37,13 @@ describe SandiMeter::MethodArgumentsCounter do
|
|
37
37
|
let(:code_4) { load_args_block('blah(arg_1, arg_2, k1: :v1, k2: :v2)') }
|
38
38
|
|
39
39
|
it 'counts arguments' do
|
40
|
-
analyzer.count(code_1).
|
41
|
-
analyzer.count(code_2).
|
40
|
+
expect(analyzer.count(code_1)).to eq([3, 1])
|
41
|
+
expect(analyzer.count(code_2)).to eq([3, 1])
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'counts hash keys as argumets' do
|
45
|
-
analyzer.count(code_3).
|
46
|
-
analyzer.count(code_4).
|
45
|
+
expect(analyzer.count(code_3)).to eq([4, 1])
|
46
|
+
expect(analyzer.count(code_4)).to eq([4, 1])
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -52,8 +52,8 @@ describe SandiMeter::MethodArgumentsCounter do
|
|
52
52
|
let(:code_2) { load_args_block('blah(arg_1 = "blah")') }
|
53
53
|
|
54
54
|
it 'counts arguments' do
|
55
|
-
analyzer.count(code_1).
|
56
|
-
analyzer.count(code_2).
|
55
|
+
expect(analyzer.count(code_1)).to eq([1, 1])
|
56
|
+
expect(analyzer.count(code_2)).to eq([1, 1])
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
data/spec/rules_checker_spec.rb
CHANGED
@@ -13,11 +13,11 @@ describe SandiMeter::RulesChecker do
|
|
13
13
|
|
14
14
|
describe "#ok?" do
|
15
15
|
it "returns false with 100 threshold" do
|
16
|
-
expect(SandiMeter::RulesChecker.new(conditions, {
|
16
|
+
expect(SandiMeter::RulesChecker.new(conditions, {thresholds: [100, 100, 100, 100]})).to_not be_ok
|
17
17
|
end
|
18
18
|
|
19
19
|
it "returns true with threshold less than 100" do
|
20
|
-
expect(SandiMeter::RulesChecker.new(conditions, {
|
20
|
+
expect(SandiMeter::RulesChecker.new(conditions, {thresholds: [50, 100, 100, 100]})).to be_ok
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#https://gist.github.com/mmasashi/58bd7e2668836a387856
|
2
|
+
|
3
|
+
RSpec::Matchers.define :terminate do |code|
|
4
|
+
actual = nil
|
5
|
+
|
6
|
+
def supports_block_expectations?
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
match do |block|
|
11
|
+
begin
|
12
|
+
block.call
|
13
|
+
rescue SystemExit => e
|
14
|
+
actual = e.status
|
15
|
+
end
|
16
|
+
actual and actual == status_code
|
17
|
+
end
|
18
|
+
|
19
|
+
chain :with_code do |status_code|
|
20
|
+
@status_code = status_code
|
21
|
+
end
|
22
|
+
|
23
|
+
failure_message do |block|
|
24
|
+
"expected block to call exit(#{status_code}) but exit" +
|
25
|
+
(actual.nil? ? " not called" : "(#{actual}) was called")
|
26
|
+
end
|
27
|
+
|
28
|
+
failure_message_when_negated do |block|
|
29
|
+
"expected block not to call exit(#{status_code})"
|
30
|
+
end
|
31
|
+
|
32
|
+
description do
|
33
|
+
"expect block to call exit(#{status_code})"
|
34
|
+
end
|
35
|
+
|
36
|
+
def status_code
|
37
|
+
@status_code ||= 0
|
38
|
+
end
|
39
|
+
end
|
data/spec/test_helper.rb
CHANGED
@@ -1,4 +1,22 @@
|
|
1
|
-
require '
|
1
|
+
require 'pry'
|
2
2
|
require 'ripper'
|
3
|
+
require 'fakefs/spec_helpers'
|
4
|
+
|
5
|
+
# silence CLI output
|
6
|
+
RSpec.configure do |config|
|
7
|
+
original_stderr = $stderr
|
8
|
+
original_stdout = $stdout
|
9
|
+
|
10
|
+
config.before silent_cli: true do
|
11
|
+
# Redirect stderr and stdout
|
12
|
+
$stderr = File.open(File::NULL, "w")
|
13
|
+
$stdout = File.open(File::NULL, "w")
|
14
|
+
end
|
15
|
+
|
16
|
+
config.after silent_cli: true do
|
17
|
+
$stderr = original_stderr
|
18
|
+
$stdout = original_stdout
|
19
|
+
end
|
20
|
+
end
|
3
21
|
|
4
22
|
Dir["#{Dir.pwd}/spec/support/**/*.rb"].each { |f| require f }
|
@@ -12,15 +12,15 @@ describe SandiMeter::WarningScanner do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'finds indentation warnings for method' do
|
15
|
-
scanner.indentation_warnings['def'].
|
15
|
+
expect(scanner.indentation_warnings['def']).to eq([[3, 4]])
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'finds indentation warnings for class' do
|
19
|
-
scanner.indentation_warnings['class'].
|
19
|
+
expect(scanner.indentation_warnings['class']).to eq([[2, 5]])
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'finds indentation warnings for module' do
|
23
|
-
scanner.indentation_warnings['module'].
|
23
|
+
expect(scanner.indentation_warnings['module']).to eq([[1, 6]])
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sandi_meter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anatoli Makarevich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '2.13'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.13'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: mixlib-cli
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: json
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: launchy
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: Sandi Metz rules checker
|
@@ -105,7 +105,7 @@ files:
|
|
105
105
|
- LICENSE
|
106
106
|
- README.md
|
107
107
|
- Rakefile
|
108
|
-
- sandi_meter
|
108
|
+
- bin/sandi_meter
|
109
109
|
- html/_detail_block.html
|
110
110
|
- html/chart.js
|
111
111
|
- html/forkme.png
|
@@ -131,7 +131,7 @@ files:
|
|
131
131
|
- lib/sandi_meter/sandi_meter/method_call.rb
|
132
132
|
- lib/sandi_meter/version.rb
|
133
133
|
- lib/sandi_meter/warning_scanner.rb
|
134
|
-
-
|
134
|
+
- sandi_meter.gemspec
|
135
135
|
- spec/analyzer_spec.rb
|
136
136
|
- spec/calculator_spec.rb
|
137
137
|
- spec/cli_spec.rb
|
@@ -141,6 +141,7 @@ files:
|
|
141
141
|
- spec/support/args_loader.rb
|
142
142
|
- spec/support/attr_matcher.rb
|
143
143
|
- spec/support/helper_methods.rb
|
144
|
+
- spec/support/terminate_matcher.rb
|
144
145
|
- spec/test_classes/1.rb
|
145
146
|
- spec/test_classes/10.rb
|
146
147
|
- spec/test_classes/10_controller.rb
|
@@ -171,17 +172,17 @@ require_paths:
|
|
171
172
|
- lib
|
172
173
|
required_ruby_version: !ruby/object:Gem::Requirement
|
173
174
|
requirements:
|
174
|
-
- -
|
175
|
+
- - ">="
|
175
176
|
- !ruby/object:Gem::Version
|
176
177
|
version: 1.9.0
|
177
178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
179
|
requirements:
|
179
|
-
- -
|
180
|
+
- - ">="
|
180
181
|
- !ruby/object:Gem::Version
|
181
182
|
version: '0'
|
182
183
|
requirements: []
|
183
184
|
rubyforge_project:
|
184
|
-
rubygems_version: 2.
|
185
|
+
rubygems_version: 2.4.5
|
185
186
|
signing_key:
|
186
187
|
specification_version: 4
|
187
188
|
summary: Sandi Metz rules checker
|