flog 1.2.0 → 2.0.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.
- data/History.txt +15 -1
- data/Manifest.txt +17 -0
- data/bin/flog +52 -23
- data/lib/flog.rb +230 -179
- data/lib/gauntlet_flog.rb +193 -0
- data/spec/flog_command_spec.rb +352 -0
- data/spec/flog_integration_spec.rb +944 -0
- data/spec/flog_spec.rb +1123 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +36 -0
- data/spec_fixtures/collection/bigger_example/acts/date_range.rb +199 -0
- data/spec_fixtures/collection/bigger_example/acts/range.rb +391 -0
- data/spec_fixtures/collection/bigger_example/association_extensions/date_ranged.rb +11 -0
- data/spec_fixtures/collection/bigger_example/association_extensions/ranged.rb +13 -0
- data/spec_fixtures/collection/bigger_example/reflection_extensions/ranged.rb +50 -0
- data/spec_fixtures/directory/bot_filter.rb +70 -0
- data/spec_fixtures/directory/bot_parser.rb +79 -0
- data/spec_fixtures/directory/bot_parser_format.rb +23 -0
- data/spec_fixtures/directory/bot_sender.rb +46 -0
- data/spec_fixtures/empty/empty.rb +0 -0
- data/spec_fixtures/simple/simple.rb +191 -0
- metadata +21 -4
data/spec/flog_spec.rb
ADDED
@@ -0,0 +1,1123 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require 'flog'
|
3
|
+
require 'sexp_processor'
|
4
|
+
|
5
|
+
class Flog
|
6
|
+
attr_writer :total_score
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Flog do
|
10
|
+
before :each do
|
11
|
+
@options = { }
|
12
|
+
@flog = Flog.new(@options)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'when initializing' do
|
16
|
+
it 'should not reference the parse tree' do
|
17
|
+
ParseTree.expects(:new).never
|
18
|
+
Flog.new(@options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'after initializing' do
|
23
|
+
it 'should have options set' do
|
24
|
+
@flog.options.should == @options
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should return an SexpProcessor' do
|
28
|
+
@flog.should be_a_kind_of(SexpProcessor)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should be initialized like all SexpProcessors' do
|
32
|
+
# less than ideal means of insuring the Flog instance was initialized properly, imo -RB
|
33
|
+
@flog.context.should == []
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should have no current class' do
|
37
|
+
@flog.klass_name.should == :main
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should have no current method' do
|
41
|
+
@flog.method_name.should == :none
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should not have any calls yet' do
|
45
|
+
@flog.calls.should == {}
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have a means of accessing its parse tree' do
|
49
|
+
@flog.should respond_to(:parse_tree)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should not have any totals yet' do
|
53
|
+
@flog.totals.should == {}
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should have a 0 total score' do
|
57
|
+
@flog.total.should == 0.0
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should have a multiplier of 1' do
|
61
|
+
@flog.multiplier.should == 1.0
|
62
|
+
end
|
63
|
+
|
64
|
+
currently "should have 'auto shift type' set to true" do
|
65
|
+
@flog.auto_shift_type.should be_true
|
66
|
+
end
|
67
|
+
|
68
|
+
currently "should have 'require empty' set to false" do
|
69
|
+
@flog.require_empty.should be_false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'options' do
|
74
|
+
it 'should return the current options settings' do
|
75
|
+
@flog.should respond_to(:options)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'when accessing the parse tree' do
|
80
|
+
before :each do
|
81
|
+
@parse_tree = stub('parse tree')
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'for the first time' do
|
85
|
+
it 'should create a new ParseTree' do
|
86
|
+
ParseTree.expects(:new)
|
87
|
+
@flog.parse_tree
|
88
|
+
end
|
89
|
+
|
90
|
+
currently 'should leave newlines off when creating the ParseTree instance' do
|
91
|
+
ParseTree.expects(:new).with(false)
|
92
|
+
@flog.parse_tree
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should return a ParseTree instance' do
|
96
|
+
ParseTree.stubs(:new).returns(@parse_tree)
|
97
|
+
@flog.parse_tree.should == @parse_tree
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'after the parse tree has been initialized' do
|
102
|
+
it 'should not attempt to create a new ParseTree instance' do
|
103
|
+
@flog.parse_tree
|
104
|
+
ParseTree.expects(:new).never
|
105
|
+
@flog.parse_tree
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should return a ParseTree instance' do
|
109
|
+
ParseTree.stubs(:new).returns(@parse_tree)
|
110
|
+
@flog.parse_tree
|
111
|
+
@flog.parse_tree.should == @parse_tree
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "when flogging a list of files" do
|
117
|
+
describe 'when no files are specified' do
|
118
|
+
currently 'should not raise an exception' do
|
119
|
+
lambda { @flog.flog_files }.should_not raise_error
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should never call flog_file' do
|
123
|
+
@flog.expects(:flog_file).never
|
124
|
+
@flog.flog_files
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'when files are specified' do
|
129
|
+
before :each do
|
130
|
+
@files = [1, 2, 3, 4]
|
131
|
+
@flog.stubs(:flog_file)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should do a flog for each individual file' do
|
135
|
+
@flog.expects(:flog_file).times(@files.size)
|
136
|
+
@flog.flog_files(@files)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should provide the filename when flogging a file' do
|
140
|
+
@files.each do |file|
|
141
|
+
@flog.expects(:flog_file).with(file)
|
142
|
+
end
|
143
|
+
@flog.flog_files(@files)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'when flogging a single file' do
|
148
|
+
before :each do
|
149
|
+
@flog.stubs(:flog)
|
150
|
+
end
|
151
|
+
|
152
|
+
describe 'when the filename is "-"' do
|
153
|
+
before :each do
|
154
|
+
@stdin = $stdin # HERE: working through the fact that zenspider is using $stdin in the middle of the system
|
155
|
+
$stdin = stub('stdin', :read => 'data')
|
156
|
+
end
|
157
|
+
|
158
|
+
after :each do
|
159
|
+
$stdin = @stdin
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'when reporting blame information' do
|
163
|
+
before :each do
|
164
|
+
@flog = Flog.new(:blame => true)
|
165
|
+
@flog.stubs(:flog)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'should fail' do
|
169
|
+
lambda { @flog.flog_file('-') }.should raise_error(RuntimeError)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should not raise an exception' do
|
174
|
+
lambda { @flog.flog_file('-') }.should_not raise_error
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should read the data from stdin' do
|
178
|
+
$stdin.expects(:read).returns('data')
|
179
|
+
@flog.flog_file('-')
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should flog the read data' do
|
183
|
+
@flog.expects(:flog).with('data', '-')
|
184
|
+
@flog.flog_file('-')
|
185
|
+
end
|
186
|
+
|
187
|
+
describe 'when the verbose flag is on' do
|
188
|
+
before :each do
|
189
|
+
@flog = Flog.new(:verbose => true)
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should note which file is being flogged' do
|
193
|
+
@flog.expects(:warn)
|
194
|
+
@flog.flog_file('-')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe 'when the verbose flag is off' do
|
199
|
+
before :each do
|
200
|
+
@flog = Flog.new({})
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should not note which file is being flogged' do
|
204
|
+
@flog.expects(:warn).never
|
205
|
+
@flog.flog_file('-')
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe 'when the filename points to a directory' do
|
211
|
+
before :each do
|
212
|
+
@flog.stubs(:flog_directory)
|
213
|
+
@file = File.dirname(__FILE__)
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'should expand the files under the directory' do
|
217
|
+
@flog.expects(:flog_directory)
|
218
|
+
@flog.flog_file(@file)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should not read data from stdin' do
|
222
|
+
$stdin.expects(:read).never
|
223
|
+
@flog.flog_file(@file)
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'should not flog any data' do
|
227
|
+
@flog.expects(:flog).never
|
228
|
+
@flog.flog_file(@file)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe 'when the filename points to a non-existant file' do
|
233
|
+
before :each do
|
234
|
+
@file = '/adfasdfasfas/fasdfaf-#{rand(1000000).to_s}'
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'should raise an exception' do
|
238
|
+
lambda { @flog.flog_file(@file) }.should raise_error(Errno::ENOENT)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe 'when the filename points to an existing file' do
|
243
|
+
before :each do
|
244
|
+
@file = __FILE__
|
245
|
+
File.stubs(:read).returns('data')
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should read the contents of the file' do
|
249
|
+
File.expects(:read).with(@file).returns('data')
|
250
|
+
@flog.flog_file(@file)
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should flog the contents of the file' do
|
254
|
+
@flog.expects(:flog).with('data', @file)
|
255
|
+
@flog.flog_file(@file)
|
256
|
+
end
|
257
|
+
|
258
|
+
describe 'when the verbose flag is on' do
|
259
|
+
before :each do
|
260
|
+
@flog = Flog.new(:verbose => true)
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'should note which file is being flogged' do
|
264
|
+
@flog.expects(:warn)
|
265
|
+
@flog.flog_file(@file)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe 'when the verbose flag is off' do
|
270
|
+
before :each do
|
271
|
+
@flog = Flog.new({})
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'should not note which file is being flogged' do
|
275
|
+
@flog.expects(:warn).never
|
276
|
+
@flog.flog_file(@file)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe 'when flogging a directory' do
|
284
|
+
before :each do
|
285
|
+
@files = ['a.rb', '/foo/b.rb', '/foo/bar/c.rb', '/foo/bar/baz/d.rb']
|
286
|
+
@dir = File.dirname(__FILE__)
|
287
|
+
Dir.stubs(:[]).returns(@files)
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'should get the list of ruby files under the directory' do
|
291
|
+
@flog.stubs(:flog_file)
|
292
|
+
Dir.expects(:[]).returns(@files)
|
293
|
+
@flog.flog_directory(@dir)
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should call flog_file once for each file in the directory" do
|
297
|
+
@files.each {|f| @flog.expects(:flog_file).with(f) }
|
298
|
+
@flog.flog_directory(@dir)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe 'when flogging a Ruby string' do
|
303
|
+
it 'should require both a Ruby string and a filename' do
|
304
|
+
lambda { @flog.flog('string') }.should raise_error(ArgumentError)
|
305
|
+
end
|
306
|
+
|
307
|
+
describe 'when reporting blame information' do
|
308
|
+
before :each do
|
309
|
+
@flog = Flog.new(:blame => true)
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'should gather blame information for the file' do
|
313
|
+
@flog.expects(:collect_blame).with('filename')
|
314
|
+
@flog.flog('string', 'filename')
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe 'when not reporting blame information' do
|
319
|
+
it 'should not gather blame information for the file' do
|
320
|
+
@flog.expects(:collect_blame).never
|
321
|
+
@flog.flog('string', 'filename')
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
describe 'when the string has a syntax error' do
|
326
|
+
before :each do
|
327
|
+
@flog.stubs(:warn)
|
328
|
+
@flog.stubs(:process_parse_tree).raises(SyntaxError.new("<% foo %>"))
|
329
|
+
end
|
330
|
+
|
331
|
+
describe 'when the string has erb snippets' do
|
332
|
+
currently 'should warn about skipping' do
|
333
|
+
@flog.expects(:warn)
|
334
|
+
@flog.flog('string', 'filename')
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'should not raise an exception' do
|
338
|
+
lambda { @flog.flog('string', 'filename') }.should_not raise_error
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'should not process the failing code' do
|
342
|
+
@flog.expects(:process).never
|
343
|
+
@flog.flog('string', 'filename')
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe 'when the string has no erb snippets' do
|
348
|
+
before :each do
|
349
|
+
@flog.stubs(:process_parse_tree).raises(SyntaxError)
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'should raise a SyntaxError exception' do
|
353
|
+
lambda { @flog.flog('string', 'filename') }.should raise_error(SyntaxError)
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'should not process the failing code' do
|
357
|
+
@flog.expects(:process).never
|
358
|
+
lambda { @flog.flog('string', 'filename') }
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
describe 'when the string contains valid Ruby' do
|
364
|
+
before :each do
|
365
|
+
@flog.stubs(:process_parse_tree)
|
366
|
+
end
|
367
|
+
|
368
|
+
it 'should process the parse tree for the string' do
|
369
|
+
@flog.expects(:process_parse_tree)
|
370
|
+
@flog.flog('string', 'filename')
|
371
|
+
end
|
372
|
+
|
373
|
+
it 'should provide the string and the filename to the parse tree processor' do
|
374
|
+
@flog.expects(:process_parse_tree).with('string', 'filename')
|
375
|
+
@flog.flog('string', 'filename')
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
describe 'when processing a ruby parse tree' do
|
381
|
+
before :each do
|
382
|
+
@flog.stubs(:process)
|
383
|
+
@sexp = stub('s-expressions')
|
384
|
+
@parse_tree = stub('parse tree', :parse_tree_for_string => @sexp)
|
385
|
+
ParseTree.stubs(:new).returns(@parse_tree)
|
386
|
+
end
|
387
|
+
|
388
|
+
it 'should require both a ruby string and a filename' do
|
389
|
+
lambda { @flog.process_parse_tree('string') }.should raise_error(ArgumentError)
|
390
|
+
end
|
391
|
+
|
392
|
+
it 'should compute the parse tree for the ruby string' do
|
393
|
+
Sexp.stubs(:from_array).returns(['1', '2'])
|
394
|
+
@parse_tree.expects(:parse_tree_for_string).returns(@sexp)
|
395
|
+
@flog.process_parse_tree('string', 'file')
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'should use both the ruby string and the filename when computing the parse tree' do
|
399
|
+
Sexp.stubs(:from_array).returns(['1', '2'])
|
400
|
+
@parse_tree.expects(:parse_tree_for_string).with('string', 'file').returns(@sexp)
|
401
|
+
@flog.process_parse_tree('string', 'file')
|
402
|
+
end
|
403
|
+
|
404
|
+
describe 'if the ruby string is valid' do
|
405
|
+
before :each do
|
406
|
+
@parse_tree = stub('parse tree', :parse_tree_for_string => @sexp)
|
407
|
+
@flog.stubs(:process)
|
408
|
+
@flog.stubs(:parse_tree).returns(@parse_tree)
|
409
|
+
end
|
410
|
+
|
411
|
+
it 'should convert the parse tree into a list of S-expressions' do
|
412
|
+
Sexp.expects(:from_array).with(@sexp).returns(['1', '2'])
|
413
|
+
@flog.process_parse_tree('string', 'file')
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'should process the list of S-expressions' do
|
417
|
+
@flog.expects(:process)
|
418
|
+
@flog.process_parse_tree('string', 'file')
|
419
|
+
end
|
420
|
+
|
421
|
+
it 'should start processing at the first S-expression' do
|
422
|
+
Sexp.stubs(:from_array).returns(['1', '2'])
|
423
|
+
@flog.expects(:process).with('1')
|
424
|
+
@flog.process_parse_tree('string', 'file')
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
describe 'if the ruby string is invalid' do
|
429
|
+
before :each do
|
430
|
+
@parse_tree = stub('parse tree')
|
431
|
+
@flog.stubs(:parse_tree).returns(@parse_tree)
|
432
|
+
@parse_tree.stubs(:parse_tree_for_string).raises(SyntaxError)
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'should fail' do
|
436
|
+
lambda { @flog.process_parse_tree('string', 'file') }.should raise_error(SyntaxError)
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'should not attempt to process the parse tree' do
|
440
|
+
@flog.expects(:process).never
|
441
|
+
lambda { @flog.process_parse_tree('string', 'file') }
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
describe 'when collecting blame information from a file' do
|
447
|
+
it 'should require a filename' do
|
448
|
+
lambda { @flog.collect_blame }.should raise_error(ArgumentError)
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'should not fail when given a filename' do
|
452
|
+
@flog.collect_blame('filename')
|
453
|
+
end
|
454
|
+
|
455
|
+
# TODO: talk to Rick and see what he was planning for
|
456
|
+
# this... otherwise I'm thinking it should be ripped out
|
457
|
+
|
458
|
+
# it 'should have more specs'
|
459
|
+
end
|
460
|
+
|
461
|
+
describe 'multiplier' do
|
462
|
+
it 'should be possible to determine the current value of the multiplier' do
|
463
|
+
@flog.should respond_to(:multiplier)
|
464
|
+
end
|
465
|
+
|
466
|
+
currently 'should be possible to set the current value of the multiplier' do
|
467
|
+
@flog.multiplier = 10
|
468
|
+
@flog.multiplier.should == 10
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
describe 'class_stack' do
|
473
|
+
it 'should be possible to determine the current value of the class stack' do
|
474
|
+
@flog.should respond_to(:class_stack)
|
475
|
+
end
|
476
|
+
|
477
|
+
currently 'should be possible to set the current value of the class stack' do
|
478
|
+
@flog.class_stack << 'name'
|
479
|
+
@flog.class_stack.should == [ 'name' ]
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
describe 'method_stack' do
|
484
|
+
it 'should be possible to determine the current value of the method stack' do
|
485
|
+
@flog.should respond_to(:method_stack)
|
486
|
+
end
|
487
|
+
|
488
|
+
currently 'should be possible to set the current value of the method stack' do
|
489
|
+
@flog.method_stack << 'name'
|
490
|
+
@flog.method_stack.should == [ 'name' ]
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
describe 'when adding to the current flog score' do
|
495
|
+
before :each do
|
496
|
+
@flog.multiplier = 1
|
497
|
+
@flog.stubs(:klass_name).returns('foo')
|
498
|
+
@flog.stubs(:method_name).returns('bar')
|
499
|
+
@flog.calls['foo#bar'] = { :alias => 0 }
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'should require an operation name' do
|
503
|
+
lambda { @flog.add_to_score() }.should raise_error(ArgumentError)
|
504
|
+
end
|
505
|
+
|
506
|
+
it 'should update the score for the current class, method, and operation' do
|
507
|
+
@flog.add_to_score(:alias)
|
508
|
+
@flog.calls['foo#bar'][:alias].should_not == 0
|
509
|
+
end
|
510
|
+
|
511
|
+
it 'should use the multiplier when updating the current call score' do
|
512
|
+
@flog.multiplier = 10
|
513
|
+
@flog.add_to_score(:alias)
|
514
|
+
@flog.calls['foo#bar'][:alias].should == 10*Flog::OTHER_SCORES[:alias]
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
describe 'when computing the average per-call flog score' do
|
519
|
+
it 'should not allow arguments' do
|
520
|
+
lambda { @flog.average('foo') }.should raise_error(ArgumentError)
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'should return the total flog score divided by the number of calls' do
|
524
|
+
@flog.stubs(:total).returns(100.0)
|
525
|
+
@flog.stubs(:calls).returns({ :bar => {}, :foo => {} })
|
526
|
+
@flog.average.should be_close(100.0/2, 0.00000000001)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
describe 'when recursively analyzing the complexity of code' do
|
531
|
+
it 'should require a complexity modifier value' do
|
532
|
+
lambda { @flog.penalize_by }.should raise_error(ArgumentError)
|
533
|
+
end
|
534
|
+
|
535
|
+
it 'should require a block, for code to recursively analyze' do
|
536
|
+
lambda { @flog.penalize_by(42) }.should raise_error(LocalJumpError)
|
537
|
+
end
|
538
|
+
|
539
|
+
it 'should recursively analyze the provided code block' do
|
540
|
+
@flog.penalize_by(42) do
|
541
|
+
@foo = true
|
542
|
+
end
|
543
|
+
|
544
|
+
@foo.should be_true
|
545
|
+
end
|
546
|
+
|
547
|
+
it 'should update the complexity multiplier when recursing' do
|
548
|
+
@flog.multiplier = 1
|
549
|
+
@flog.penalize_by(42) do
|
550
|
+
@flog.multiplier.should == 43
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
it 'when it is done it should restore the complexity multiplier to its original value' do
|
555
|
+
@flog.multiplier = 1
|
556
|
+
@flog.penalize_by(42) do
|
557
|
+
end
|
558
|
+
@flog.multiplier.should == 1
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
describe 'when computing complexity of all remaining opcodes' do
|
563
|
+
it 'should require a list of opcodes' do
|
564
|
+
lambda { @flog.analyze_list }.should raise_error(ArgumentError)
|
565
|
+
end
|
566
|
+
|
567
|
+
it 'should process each opcode' do
|
568
|
+
@opcodes = [ :foo, :bar, :baz ]
|
569
|
+
@opcodes.each do |opcode|
|
570
|
+
@flog.expects(:process).with(opcode)
|
571
|
+
end
|
572
|
+
|
573
|
+
@flog.analyze_list @opcodes
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
describe 'when recording the current class being analyzed' do
|
578
|
+
it 'should require a class name' do
|
579
|
+
lambda { @flog.in_klass }.should raise_error(ArgumentError)
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'should require a block during which the class name is in effect' do
|
583
|
+
lambda { @flog.in_klass('name') }.should raise_error(LocalJumpError)
|
584
|
+
end
|
585
|
+
|
586
|
+
it 'should recursively analyze the provided code block' do
|
587
|
+
@flog.in_klass 'name' do
|
588
|
+
@foo = true
|
589
|
+
end
|
590
|
+
|
591
|
+
@foo.should be_true
|
592
|
+
end
|
593
|
+
|
594
|
+
it 'should update the class stack when recursing' do
|
595
|
+
@flog.class_stack.clear
|
596
|
+
@flog.in_klass 'name' do
|
597
|
+
@flog.class_stack.should == ['name']
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
it 'when it is done it should restore the class stack to its original value' do
|
602
|
+
@flog.class_stack.clear
|
603
|
+
@flog.in_klass 'name' do
|
604
|
+
end
|
605
|
+
@flog.class_stack.should == []
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
describe 'when looking up the name of the class currently under analysis' do
|
610
|
+
it 'should not take any arguments' do
|
611
|
+
lambda { @flog.klass_name('foo') }.should raise_error(ArgumentError)
|
612
|
+
end
|
613
|
+
|
614
|
+
it 'should return the most recent class entered' do
|
615
|
+
@flog.class_stack << :foo << :bar << :baz
|
616
|
+
@flog.klass_name.should == :foo
|
617
|
+
end
|
618
|
+
|
619
|
+
it 'should return the default class if no classes entered' do
|
620
|
+
@flog.class_stack.clear
|
621
|
+
@flog.klass_name.should == :main
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
describe 'when recording the current method being analyzed' do
|
626
|
+
it 'should require a method name' do
|
627
|
+
lambda { @flog.in_method }.should raise_error(ArgumentError)
|
628
|
+
end
|
629
|
+
|
630
|
+
it 'should require a block during which the class name is in effect' do
|
631
|
+
lambda { @flog.in_method('name') }.should raise_error(LocalJumpError)
|
632
|
+
end
|
633
|
+
|
634
|
+
it 'should recursively analyze the provided code block' do
|
635
|
+
@flog.in_method 'name' do
|
636
|
+
@foo = true
|
637
|
+
end
|
638
|
+
|
639
|
+
@foo.should be_true
|
640
|
+
end
|
641
|
+
|
642
|
+
it 'should update the class stack when recursing' do
|
643
|
+
@flog.method_stack.clear
|
644
|
+
@flog.in_method 'name' do
|
645
|
+
@flog.method_stack.should == ['name']
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
it 'when it is done it should restore the class stack to its original value' do
|
650
|
+
@flog.method_stack.clear
|
651
|
+
@flog.in_method 'name' do
|
652
|
+
end
|
653
|
+
@flog.method_stack.should == []
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
657
|
+
describe 'when looking up the name of the method currently under analysis' do
|
658
|
+
it 'should not take any arguments' do
|
659
|
+
lambda { @flog.method_name('foo') }.should raise_error(ArgumentError)
|
660
|
+
end
|
661
|
+
|
662
|
+
it 'should return the most recent method entered' do
|
663
|
+
@flog.method_stack << :foo << :bar << :baz
|
664
|
+
@flog.method_name.should == :foo
|
665
|
+
end
|
666
|
+
|
667
|
+
it 'should return the default method if no methods entered' do
|
668
|
+
@flog.method_stack.clear
|
669
|
+
@flog.method_name.should == :none
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
describe 'when resetting state' do
|
674
|
+
it 'should not take any arguments' do
|
675
|
+
lambda { @flog.reset('foo') }.should raise_error(ArgumentError)
|
676
|
+
end
|
677
|
+
|
678
|
+
it 'should clear any recorded totals data' do
|
679
|
+
@flog.totals['foo'] = 'bar'
|
680
|
+
@flog.reset
|
681
|
+
@flog.totals.should == {}
|
682
|
+
end
|
683
|
+
|
684
|
+
it 'should clear the total score' do
|
685
|
+
# the only way I know to do this is to force the total score to be computed for actual code, then reset it
|
686
|
+
@flog.flog_files(fixture_files('/simple/simple.rb'))
|
687
|
+
@flog.reset
|
688
|
+
@flog.total.should == 0
|
689
|
+
end
|
690
|
+
|
691
|
+
it 'should set the multiplier to 1.0' do
|
692
|
+
@flog.multiplier = 20.0
|
693
|
+
@flog.reset
|
694
|
+
@flog.multiplier.should == 1.0
|
695
|
+
end
|
696
|
+
|
697
|
+
it 'should set clear any calls data' do
|
698
|
+
@flog.calls['foobar'] = 'yoda'
|
699
|
+
@flog.reset
|
700
|
+
@flog.calls.should == {}
|
701
|
+
end
|
702
|
+
|
703
|
+
it 'should ensure that new recorded calls will get 0 counts without explicit initialization' do
|
704
|
+
@flog.reset
|
705
|
+
@flog.calls['foobar']['baz'] += 20
|
706
|
+
@flog.calls['foobar']['baz'].should == 20
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
describe 'when retrieving the total score' do
|
711
|
+
it 'should take no arguments' do
|
712
|
+
lambda { @flog.total('foo') }.should raise_error(ArgumentError)
|
713
|
+
end
|
714
|
+
|
715
|
+
it 'should return 0 if nothing has been analyzed' do
|
716
|
+
@flog.total.should == 0
|
717
|
+
end
|
718
|
+
|
719
|
+
it 'should compute totals data when called the first time' do
|
720
|
+
@flog.expects(:totals)
|
721
|
+
@flog.total
|
722
|
+
end
|
723
|
+
|
724
|
+
it 'should not recompute totals data when called after the first time' do
|
725
|
+
@flog.total
|
726
|
+
@flog.expects(:totals).never
|
727
|
+
@flog.total
|
728
|
+
end
|
729
|
+
|
730
|
+
it 'should return the score from the analysis once files have been analyzed' do
|
731
|
+
@flog.flog_files(fixture_files('/simple/simple.rb'))
|
732
|
+
@flog.total.should_not == 0
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
736
|
+
describe 'when computing a score for a method' do
|
737
|
+
it 'should require a hash of call tallies' do
|
738
|
+
lambda { @flog.score_method }.should raise_error(ArgumentError)
|
739
|
+
end
|
740
|
+
|
741
|
+
it 'should return a score of 0 if no tallies are provided' do
|
742
|
+
@flog.score_method({}).should == 0.0
|
743
|
+
end
|
744
|
+
|
745
|
+
it 'should compute the sqrt of summed squares for assignments, branches, and other tallies' do
|
746
|
+
@flog.score_method({
|
747
|
+
:assignment => 7,
|
748
|
+
:branch => 23,
|
749
|
+
:crap => 37
|
750
|
+
}).should be_close(Math.sqrt(7*7 + 23*23 + 37*37), 0.0000000001)
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
describe 'when recording a total for a method' do
|
755
|
+
# guess what, @totals and @calls could be refactored to be first-class objects
|
756
|
+
it 'should require a method and a score' do
|
757
|
+
lambda { @flog.record_method_score('foo') }.should raise_error(ArgumentError)
|
758
|
+
end
|
759
|
+
|
760
|
+
it 'should set the total score for the provided method' do
|
761
|
+
@flog.record_method_score('foo', 20)
|
762
|
+
@flog.totals['foo'].should == 20
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
describe 'when updating the total flog score' do
|
767
|
+
it 'should require an amount to update by' do
|
768
|
+
lambda { @flog.increment_total_score_by }.should raise_error(ArgumentError)
|
769
|
+
end
|
770
|
+
|
771
|
+
it 'should update the total flog score' do
|
772
|
+
@flog.total_score = 0
|
773
|
+
@flog.increment_total_score_by 42
|
774
|
+
@flog.total.should == 42
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
778
|
+
describe 'when compiling summaries for a method' do
|
779
|
+
before :each do
|
780
|
+
@tally = { :foo => 0.0 }
|
781
|
+
@method = 'foo'
|
782
|
+
@score = 42.0
|
783
|
+
|
784
|
+
@flog.stubs(:score_method).returns(@score)
|
785
|
+
@flog.stubs(:record_method_score)
|
786
|
+
@flog.stubs(:increment_total_score_by)
|
787
|
+
end
|
788
|
+
|
789
|
+
it 'should require a method name and a tally' do
|
790
|
+
lambda { @flog.summarize_method('foo') }.should raise_error(ArgumentError)
|
791
|
+
end
|
792
|
+
|
793
|
+
it 'should compute a score for the method, based on the tally' do
|
794
|
+
@flog.expects(:score_method).with(@tally)
|
795
|
+
@flog.summarize_method(@method, @tally)
|
796
|
+
end
|
797
|
+
|
798
|
+
it 'should record the score for the method' do
|
799
|
+
@flog.expects(:record_method_score).with(@method, @score)
|
800
|
+
@flog.summarize_method(@method, @tally)
|
801
|
+
end
|
802
|
+
|
803
|
+
it 'should update the overall flog score' do
|
804
|
+
@flog.expects(:increment_total_score_by).with(@score)
|
805
|
+
@flog.summarize_method(@method, @tally)
|
806
|
+
end
|
807
|
+
|
808
|
+
describe 'ignoring non-method code and given a non-method tally' do
|
809
|
+
it 'should not compute a score for the tally' do
|
810
|
+
@flog.expects(:score_method).never
|
811
|
+
@flog.summarize_method(@method, @tally)
|
812
|
+
end
|
813
|
+
|
814
|
+
it 'should not record a score based on the tally' do
|
815
|
+
@flog.expects(:record_method_score).never
|
816
|
+
@flog.summarize_method(@method, @tally)
|
817
|
+
end
|
818
|
+
|
819
|
+
it 'should not update the overall flog score' do
|
820
|
+
@flog.expects(:increment_total_score_by).never
|
821
|
+
@flog.summarize_method(@method, @tally)
|
822
|
+
end
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
describe 'when requesting totals' do
|
827
|
+
it 'should not accept any arguments' do
|
828
|
+
lambda { @flog.totals('foo') }.should raise_error(ArgumentError)
|
829
|
+
end
|
830
|
+
|
831
|
+
describe 'when called the first time' do
|
832
|
+
it 'should access calls data' do
|
833
|
+
@flog.expects(:calls).returns({})
|
834
|
+
@flog.totals
|
835
|
+
end
|
836
|
+
|
837
|
+
it "will compile a summary for each method from the method's tally" do
|
838
|
+
@calls = { :foo => 1.0, :bar => 2.0, :baz => 3.0 }
|
839
|
+
@flog.stubs(:calls).returns(@calls)
|
840
|
+
@calls.each do |meth, tally|
|
841
|
+
@flog.expects(:summarize_method).with(meth, tally)
|
842
|
+
end
|
843
|
+
@flog.totals
|
844
|
+
end
|
845
|
+
|
846
|
+
it 'should return the totals data' do
|
847
|
+
@flog.totals.should == {}
|
848
|
+
end
|
849
|
+
end
|
850
|
+
|
851
|
+
describe 'when called after the first time' do
|
852
|
+
before :each do
|
853
|
+
@flog.totals
|
854
|
+
end
|
855
|
+
|
856
|
+
it 'should not access calls data' do
|
857
|
+
@flog.expects(:calls).never
|
858
|
+
@flog.totals
|
859
|
+
end
|
860
|
+
|
861
|
+
it 'should not compile method summaries' do
|
862
|
+
@flog.expects(:summarize_method).never
|
863
|
+
@flog.totals
|
864
|
+
end
|
865
|
+
|
866
|
+
it 'should return the totals data' do
|
867
|
+
@flog.totals.should == {}
|
868
|
+
end
|
869
|
+
end
|
870
|
+
end
|
871
|
+
|
872
|
+
describe 'when producing a report summary' do
|
873
|
+
before :each do
|
874
|
+
@handle = stub('io handle)', :puts => nil)
|
875
|
+
@flog.stubs(:total).returns(@total_score = 42.0)
|
876
|
+
@flog.stubs(:average).returns(@average_score = 1.0)
|
877
|
+
end
|
878
|
+
|
879
|
+
it 'should require an io handle' do
|
880
|
+
lambda { @flog.output_summary }.should raise_error(ArgumentError)
|
881
|
+
end
|
882
|
+
|
883
|
+
it 'computes the total flog score' do
|
884
|
+
@flog.expects(:total).returns 42.0
|
885
|
+
@flog.output_summary(@handle)
|
886
|
+
end
|
887
|
+
|
888
|
+
it 'computes the average flog score' do
|
889
|
+
@flog.expects(:average).returns 1.0
|
890
|
+
@flog.output_summary(@handle)
|
891
|
+
end
|
892
|
+
|
893
|
+
it 'outputs the total flog score to the handle' do
|
894
|
+
@handle.expects(:puts).with do |string|
|
895
|
+
string =~ Regexp.new(Regexp.escape("%.1f" % @total_score))
|
896
|
+
end
|
897
|
+
@flog.output_summary(@handle)
|
898
|
+
end
|
899
|
+
|
900
|
+
it 'outputs the average flog score to the handle' do
|
901
|
+
@handle.expects(:puts).with do |string|
|
902
|
+
string =~ Regexp.new(Regexp.escape("%.1f" % @average_score))
|
903
|
+
end
|
904
|
+
@flog.output_summary(@handle)
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
describe 'when producing a detailed call summary report' do
|
909
|
+
before :each do
|
910
|
+
@handle = stub('io handle)', :puts => nil)
|
911
|
+
@calls = { :foo => {}, :bar => {}, :baz => {} }
|
912
|
+
@totals = { :foo => 1, :bar => 2, :baz => 3 }
|
913
|
+
|
914
|
+
@flog.stubs(:calls).returns(@calls)
|
915
|
+
@flog.stubs(:totals).returns(@totals)
|
916
|
+
@flog.stubs(:output_method_details).returns(5)
|
917
|
+
end
|
918
|
+
|
919
|
+
it 'should require an i/o handle' do
|
920
|
+
lambda { @flog.output_details }.should raise_error(ArgumentError)
|
921
|
+
end
|
922
|
+
|
923
|
+
it 'should allow a threshold on the amount of detail to report' do
|
924
|
+
lambda { @flog.output_details(@handle, 300) }.should_not raise_error(ArgumentError)
|
925
|
+
end
|
926
|
+
|
927
|
+
it 'retrieves the set of total statistics' do
|
928
|
+
@flog.expects(:totals).returns(@totals)
|
929
|
+
@flog.output_details(@handle)
|
930
|
+
end
|
931
|
+
|
932
|
+
it 'retrieves the set of call statistics' do
|
933
|
+
@flog.expects(:calls).returns({})
|
934
|
+
@flog.output_details(@handle)
|
935
|
+
end
|
936
|
+
|
937
|
+
it 'should output a method summary for each located method' do
|
938
|
+
@calls.each do |meth, list|
|
939
|
+
@flog.expects(:output_method_details).with(@handle, meth, list).returns(5)
|
940
|
+
end
|
941
|
+
@flog.output_details(@handle)
|
942
|
+
end
|
943
|
+
|
944
|
+
describe 'if a threshold is provided' do
|
945
|
+
it 'should only output details for methods until the threshold is reached' do
|
946
|
+
@flog.expects(:output_method_details).with(@handle, :baz, {}).returns(5)
|
947
|
+
@flog.expects(:output_method_details).with(@handle, :bar, {}).returns(5)
|
948
|
+
@flog.expects(:output_method_details).with(@handle, :foo, {}).never
|
949
|
+
@flog.output_details(@handle, 10)
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
953
|
+
describe 'if no threshold is provided' do
|
954
|
+
it 'should output details for all methods' do
|
955
|
+
@calls.each do |class_method, call_list|
|
956
|
+
@flog.expects(:output_method_details).with(@handle, class_method, call_list).returns(5)
|
957
|
+
end
|
958
|
+
@flog.output_details(@handle)
|
959
|
+
end
|
960
|
+
end
|
961
|
+
end
|
962
|
+
|
963
|
+
describe 'when reporting the details for a specific method' do
|
964
|
+
before :each do
|
965
|
+
@handle = stub('i/o handle', :puts => nil)
|
966
|
+
@totals = { 'foo#foo' => 42.0, 'foo#none' => 12.0 }
|
967
|
+
@data = { :assign => 10, :branch => 5, :case => 3 }
|
968
|
+
@flog.stubs(:totals).returns(@totals)
|
969
|
+
end
|
970
|
+
|
971
|
+
it 'should require an i/o handle, a method name, and method details' do
|
972
|
+
lambda { @flog.output_method_details('foo', 'bar') }.should raise_error(ArgumentError)
|
973
|
+
end
|
974
|
+
|
975
|
+
describe 'and ignoring non-method code' do
|
976
|
+
before :each do
|
977
|
+
@flog = Flog.new(:methods => true)
|
978
|
+
@flog.stubs(:totals).returns(@totals)
|
979
|
+
end
|
980
|
+
|
981
|
+
describe 'and given non-method data to summarize' do
|
982
|
+
it 'should not generate any output on the i/o handle' do
|
983
|
+
@handle.expects(:puts).never
|
984
|
+
@flog.output_method_details(@handle, 'foo#none', @data)
|
985
|
+
end
|
986
|
+
|
987
|
+
it 'should return 0' do
|
988
|
+
@flog.output_method_details(@handle, 'foo#none', @data).should == 0.0
|
989
|
+
end
|
990
|
+
end
|
991
|
+
|
992
|
+
describe 'and given method data to summarize' do
|
993
|
+
it 'should return the total complexity for the method' do
|
994
|
+
@flog.output_method_details(@handle, 'foo#foo', @data).should == 42.0
|
995
|
+
end
|
996
|
+
|
997
|
+
it 'should output the overall total for the method' do
|
998
|
+
@handle.expects(:puts).with do |string|
|
999
|
+
string =~ Regexp.new(Regexp.escape("%.1f" % 42.0))
|
1000
|
+
end
|
1001
|
+
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it 'should output call details for each call for the method' do
|
1005
|
+
@data.each do |call, count|
|
1006
|
+
@handle.expects(:puts).with do |string|
|
1007
|
+
string =~ Regexp.new(Regexp.escape("%6.1f: %s" % [ count, call ]))
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1011
|
+
end
|
1012
|
+
end
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
describe 'and not excluding non-method code' do
|
1016
|
+
it 'should return the total complexity for the method' do
|
1017
|
+
@flog.output_method_details(@handle, 'foo#foo', @data).should == 42.0
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
it 'should output the overall total for the method' do
|
1021
|
+
@handle.expects(:puts).with do |string|
|
1022
|
+
string =~ Regexp.new(Regexp.escape("%.1f" % 42.0))
|
1023
|
+
end
|
1024
|
+
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
it 'should output call details for each call for the method' do
|
1028
|
+
@data.each do |call, count|
|
1029
|
+
@handle.expects(:puts).with do |string|
|
1030
|
+
string =~ Regexp.new(Regexp.escape("%6.1f: %s" % [ count, call ]))
|
1031
|
+
end
|
1032
|
+
end
|
1033
|
+
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
describe 'when generating a report' do
|
1039
|
+
before :each do
|
1040
|
+
@flog.stubs(:output_summary)
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
it 'allows specifying an i/o handle' do
|
1044
|
+
lambda { @flog.report 'handle' }.should_not raise_error(ArgumentError)
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
it 'allows running the report without a specified i/o handle' do
|
1048
|
+
lambda { @flog.report }.should_not raise_error(ArgumentError)
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
describe 'and no i/o handle is specified' do
|
1052
|
+
it 'defaults the io handle to stdout' do
|
1053
|
+
@flog.expects(:output_summary).with($stdout)
|
1054
|
+
@flog.report
|
1055
|
+
end
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
describe 'and producing a summary report' do
|
1059
|
+
before :each do
|
1060
|
+
@flog = Flog.new(:score => true)
|
1061
|
+
@flog.stubs(:output_summary)
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
it 'produces an output summary on the i/o handle' do
|
1065
|
+
@flog.expects(:output_summary).with('handle')
|
1066
|
+
@flog.report('handle')
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
it 'does not output a detailed report' do
|
1070
|
+
@flog.expects(:output_details).never
|
1071
|
+
@flog.report('handle')
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
it 'should reset statistics when finished' do
|
1075
|
+
@flog.expects(:reset)
|
1076
|
+
@flog.report('handle')
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
describe 'and producing a full report' do
|
1081
|
+
before :each do
|
1082
|
+
@flog.stubs(:output_summary)
|
1083
|
+
@flog.stubs(:output_details)
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
it 'produces an output summary on the i/o handle' do
|
1087
|
+
@flog.expects(:output_summary).with('handle')
|
1088
|
+
@flog.report('handle')
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
it 'should generate a detailed report of method complexity on the i/o handle' do
|
1092
|
+
@flog.expects(:output_details).with {|handle, max| handle == 'handle' }
|
1093
|
+
@flog.report('handle')
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
describe 'when flogging all methods in the system' do
|
1097
|
+
before :each do
|
1098
|
+
@flog = Flog.new(:all => true)
|
1099
|
+
@flog.stubs(:output_summary)
|
1100
|
+
@flog.stubs(:output_details)
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
it 'should not limit the detailed report' do
|
1104
|
+
@flog.expects(:output_details).with('handle')
|
1105
|
+
@flog.report('handle')
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
describe 'when flogging only the most expensive methods in the system' do
|
1110
|
+
it 'should limit the detailed report to the Flog threshold' do
|
1111
|
+
@flog.stubs(:total).returns(3.45)
|
1112
|
+
@flog.expects(:output_details).with('handle', 3.45 * 0.60)
|
1113
|
+
@flog.report('handle')
|
1114
|
+
end
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
it 'should reset statistics when finished' do
|
1118
|
+
@flog.expects(:reset)
|
1119
|
+
@flog.report(@handle)
|
1120
|
+
end
|
1121
|
+
end
|
1122
|
+
end
|
1123
|
+
end
|