sandi_meter 1.1.8 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54a3a95954d2e42aaf57f24b88a0988b793015b2
4
- data.tar.gz: 0b71ff002bb37ceee3e65b2d70ba3ebd8ff1db35
3
+ metadata.gz: 9a83923b441f198ed909f5cc7e0b3933b4b0b2ad
4
+ data.tar.gz: 5f0d9b05649988b2c7e2094ee81490212be49444
5
5
  SHA512:
6
- metadata.gz: bfbf7a4c4374cdc0f78ef62faf90500fcf2e85895fb2f52d26da3ed66b6c9507b9fb8c0a72350fa1e50dfd54e3f1865a255217f4e2a99bbed43b871b45efcc7c
7
- data.tar.gz: 7e7158e10271549a4c5fad4004874bacb629e6dc77efd8d9db36c8f35f42dfbe9019c63ab459d9175843cb1c7ff9f98d249d0b1b83d8ea7d01974d50afb0dc3d
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 variables per controller' action
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
- -p, --path PATH Path to folder or file to analyze (default is ".")
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
@@ -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
- log_dir_path = File.join(cli.config[:path], 'sandi_meter')
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[:path], 'sandi_meter/.sandi_meter', %w(db vendor).join("\n"))
86
- create_config_file(cli.config[:path], 'sandi_meter/config.yml', YAML.dump({ threshold: 90 }))
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[:path])
125
+ if File.directory?(cli.config[:output_path])
112
126
  logger = SandiMeter::Logger.new(data)
113
- logger.log!(cli.config[:path])
127
+ logger.log!(cli.config[:output_path])
114
128
 
115
129
  html_generator = SandiMeter::HtmlGenerator.new
116
- html_generator.copy_assets!(cli.config[:path])
117
- html_generator.generate_data!(cli.config[:path])
118
- html_generator.generate_details!(cli.config[:path], data)
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[:path], 'sandi_meter/index.html')
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[:path], 'sandi_meter', 'config.yml')
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
- { threshold: 90 }
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, 'sandi_meter/assets')
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(File.dirname(__FILE__), "../../html", "index.html"), File.join(path, 'sandi_meter', 'index.html')
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', 'sandi_meter.log')).split("\n")
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, 'sandi_meter', 'index.html')
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, 'sandi_meter', 'index.html')
94
+ index_file = File.join(path, 'index.html')
95
95
  index = File.read(index_file)
96
96
  index.gsub!('<% details %>', details)
97
97
 
@@ -3,7 +3,7 @@ require 'fileutils'
3
3
  module SandiMeter
4
4
  class Logger < Struct.new(:data)
5
5
  def log!(path)
6
- File.open(File.join(path, 'sandi_meter', 'sandi_meter.log'), 'a') do |file|
6
+ File.open(File.join(path, 'sandi_meter.log'), 'a') do |file|
7
7
  file.puts(log_line)
8
8
  end
9
9
  end
@@ -10,12 +10,18 @@ module SandiMeter
10
10
  end
11
11
 
12
12
  def ok?
13
- @rules.reduce(:+) / 4 > @config[:threshold]
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
@@ -1,3 +1,3 @@
1
1
  module SandiMeter
2
- VERSION = "1.1.8"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -21,7 +21,7 @@ module SandiMeter
21
21
 
22
22
  private
23
23
  def validate(source)
24
- Open3.capture3('ruby -wc', stdin_data: source)
24
+ Open3.capture3("#{RUBY_ENGINE} -wc", stdin_data: source)
25
25
  end
26
26
 
27
27
  def check_syntax(status)
@@ -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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should be_empty
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should be_nil
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.should eq(["@users"])
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.should be_empty
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.should be_empty
267
+ expect(method.ivars).to be_empty
268
268
 
269
269
  method = analyzer.methods["User"].find { |m| m.name == "hi" }
270
- method.ivars.should be_empty
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.should eq(["@user"])
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.should be_empty
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.should be_nil
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.should be_nil
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
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.should be_empty
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.should have_attributes(
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.should have_attributes(
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.should have_attributes(
395
+ expect(method).to have_attributes(
396
396
  first_line: 17,
397
397
  last_line: 24,
398
398
  number_of_arguments: 0,
@@ -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].should eq(109)
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].should eq(6)
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].should eql(0)
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].should eql(0)
77
+ expect(output[:second_rule][:total_methods_amount]).to eq(0)
78
78
  end
79
79
  end
80
80
  end
@@ -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
- describe '#execute' do
8
- before do
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
- after { ARGV.pop }
21
-
33
+
22
34
  it 'opens the graph in a web browser' do
23
- cli.should_receive(:open_in_browser)
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
- after do
34
- ARGV.pop
35
- ARGV.pop
36
- end
37
-
45
+
38
46
  it 'does not open the browser' do
39
- cli.should_not_receive(:open_in_browser)
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
@@ -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.stub(:locs_size).and_return(rand(0..10))
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').should be_true
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.stub(:locs_size).and_return(rand(11..100))
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').should be_false
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).should eq([2, 1])
14
- analyzer.count(args_add_block_2).should eq([2, 1])
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).should eq([1, 1])
27
- analyzer.count(args_add_block_2).should eq([1, 1])
28
- analyzer.count(args_add_block_3).should eq([2, 1])
29
- analyzer.count(args_add_block_4).should eq([2, 1])
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).should eq([3, 1])
41
- analyzer.count(code_2).should eq([3, 1])
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).should eq([4, 1])
46
- analyzer.count(code_4).should eq([4, 1])
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).should eq([1, 1])
56
- analyzer.count(code_2).should eq([1, 1])
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
@@ -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, {threshold: 100})).to_not be_ok
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, {threshold: 50})).to be_ok
20
+ expect(SandiMeter::RulesChecker.new(conditions, {thresholds: [50, 100, 100, 100]})).to be_ok
21
21
  end
22
22
  end
23
23
  end
@@ -10,7 +10,7 @@ RSpec::Matchers.define :have_attributes do |expected|
10
10
  result
11
11
  end
12
12
 
13
- failure_message_for_should do |actual|
13
+ failure_message do |actual|
14
14
  wrong_fields = {}
15
15
  expected.each do |key, value|
16
16
  wrong_fields[key] = {
@@ -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
@@ -1,4 +1,22 @@
1
- require 'rspec/autorun'
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'].should eq([[3, 4]])
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'].should eq([[2, 5]])
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'].should eq([[1, 6]])
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.1.8
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: 2014-12-02 00:00:00.000000000 Z
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.gemspec
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
- - bin/sandi_meter
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.0.5
185
+ rubygems_version: 2.4.5
185
186
  signing_key:
186
187
  specification_version: 4
187
188
  summary: Sandi Metz rules checker