flog 2.1.0 → 2.1.1
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.tar.gz.sig +0 -0
- data/History.txt +7 -0
- data/Rakefile +8 -11
- data/bin/flog +0 -2
- data/lib/flog.rb +67 -73
- data/test/test_flog.rb +1361 -1013
- data/test/test_flog_command.rb +282 -282
- data/test/test_flog_integration.rb +904 -904
- metadata +12 -8
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
data/Rakefile
CHANGED
@@ -3,25 +3,22 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
5
|
|
6
|
-
Hoe.add_include_dirs("../../
|
6
|
+
Hoe.add_include_dirs("../../ruby_parser/dev/lib",
|
7
7
|
"../../RubyInline/dev/lib",
|
8
8
|
"../../sexp_processor/dev/lib",
|
9
9
|
"../../ZenTest/dev/lib",
|
10
10
|
"../../minitest/dev/lib",
|
11
11
|
"lib")
|
12
12
|
|
13
|
-
|
13
|
+
Hoe.plugin :seattlerb
|
14
14
|
|
15
|
-
Hoe.
|
16
|
-
|
15
|
+
Hoe.spec 'flog' do
|
16
|
+
developer 'Ryan Davis', 'ryand-ruby@zenspider.com'
|
17
17
|
|
18
|
-
|
18
|
+
self.rubyforge_name = 'seattlerb'
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
flog.testlib = :minitest
|
20
|
+
extra_deps << ['sexp_processor', '~> 3.0']
|
21
|
+
extra_deps << ['ruby_parser', '~> 1.1.0']
|
24
22
|
end
|
25
23
|
|
26
|
-
|
27
|
-
# vim: syntax=Ruby
|
24
|
+
# vim: syntax=ruby
|
data/bin/flog
CHANGED
data/lib/flog.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'parse_tree'
|
3
2
|
require 'sexp_processor'
|
4
|
-
require '
|
3
|
+
require 'ruby_parser'
|
4
|
+
require 'optparse'
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
# REFACTOR: push up to sexp_processor. also in flay
|
7
|
+
class Sexp
|
8
|
+
def mass
|
9
|
+
@mass ||= self.structure.flatten.size
|
10
|
+
end
|
11
|
+
end
|
8
12
|
|
9
|
-
|
13
|
+
class Flog < SexpProcessor
|
14
|
+
VERSION = '2.1.1'
|
10
15
|
|
11
16
|
THRESHOLD = 0.60
|
12
17
|
SCORES = Hash.new 1
|
@@ -71,27 +76,41 @@ class Flog < SexpProcessor
|
|
71
76
|
@@no_method = :none
|
72
77
|
|
73
78
|
attr_accessor :multiplier
|
74
|
-
attr_reader :calls, :options, :class_stack, :method_stack
|
79
|
+
attr_reader :calls, :options, :class_stack, :method_stack, :mass
|
75
80
|
|
76
81
|
def self.default_options
|
77
82
|
{
|
78
|
-
:quiet
|
83
|
+
:quiet => true,
|
84
|
+
:continue => false,
|
79
85
|
}
|
80
86
|
end
|
81
87
|
|
88
|
+
# REFACTOR: from flay
|
89
|
+
def self.expand_dirs_to_files *dirs
|
90
|
+
extensions = ['rb']
|
91
|
+
|
92
|
+
dirs.flatten.map { |p|
|
93
|
+
if File.directory? p then
|
94
|
+
Dir[File.join(p, '**', "*.{#{extensions.join(',')}}")]
|
95
|
+
else
|
96
|
+
p
|
97
|
+
end
|
98
|
+
}.flatten.sort
|
99
|
+
end
|
100
|
+
|
82
101
|
def self.parse_options
|
83
102
|
options = self.default_options
|
84
103
|
op = OptionParser.new do |opts|
|
85
|
-
opts.on("-a", "--all", "Display all flog results, not top 60%.") do
|
86
|
-
options[:all] =
|
104
|
+
opts.on("-a", "--all", "Display all flog results, not top 60%.") do
|
105
|
+
options[:all] = true
|
87
106
|
end
|
88
107
|
|
89
|
-
opts.on("-b", "--blame", "Include blame information for methods.") do
|
90
|
-
options[:blame] =
|
108
|
+
opts.on("-b", "--blame", "Include blame information for methods.") do
|
109
|
+
options[:blame] = true
|
91
110
|
end
|
92
111
|
|
93
|
-
opts.on("-c", "--continue", "Continue despite syntax errors.") do
|
94
|
-
options[:continue] =
|
112
|
+
opts.on("-c", "--continue", "Continue despite syntax errors.") do
|
113
|
+
options[:continue] = true
|
95
114
|
end
|
96
115
|
|
97
116
|
opts.on("-d", "--details", "Show method details.") do
|
@@ -107,8 +126,10 @@ class Flog < SexpProcessor
|
|
107
126
|
exit
|
108
127
|
end
|
109
128
|
|
110
|
-
opts.on("-I
|
111
|
-
|
129
|
+
opts.on("-I dir1,dir2,dir3", Array, "Add to LOAD_PATH.") do |dirs|
|
130
|
+
dirs.each do |dir|
|
131
|
+
$: << dir
|
132
|
+
end
|
112
133
|
end
|
113
134
|
|
114
135
|
opts.on("-m", "--methods-only", "Skip code outside of methods.") do |m|
|
@@ -139,6 +160,7 @@ class Flog < SexpProcessor
|
|
139
160
|
|
140
161
|
##
|
141
162
|
# Process each element of #exp in turn.
|
163
|
+
# TODO: rename, bleed wasn't good, but this is actually worse
|
142
164
|
|
143
165
|
def analyze_list exp
|
144
166
|
process exp.shift until exp.empty?
|
@@ -149,49 +171,28 @@ class Flog < SexpProcessor
|
|
149
171
|
total / calls.size
|
150
172
|
end
|
151
173
|
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
def flog_file file
|
176
|
-
return flog_directory(file) if File.directory? file
|
177
|
-
if file == '-'
|
178
|
-
raise "Cannot provide blame information for code provided on input stream." if options[:blame]
|
179
|
-
data = $stdin.read
|
180
|
-
end
|
181
|
-
data ||= File.read(file)
|
182
|
-
warn "** flogging #{file}" if options[:verbose]
|
183
|
-
flog(data, file)
|
184
|
-
end
|
185
|
-
|
186
|
-
##
|
187
|
-
# Process #files with flog, recursively descending directories.
|
188
|
-
#--
|
189
|
-
# There is no way to exclude directories at present (RCS, SCCS, .svn)
|
190
|
-
#++
|
191
|
-
|
192
|
-
def flog_files(*files)
|
193
|
-
files.flatten.each do |file|
|
194
|
-
flog_file(file)
|
174
|
+
def flog(*files_or_dirs)
|
175
|
+
files = Flog.expand_dirs_to_files(*files_or_dirs)
|
176
|
+
|
177
|
+
files.each do |file|
|
178
|
+
begin
|
179
|
+
# TODO: replace File.open to deal with "-"
|
180
|
+
ruby = file == '-' ? $stdin.read : File.read(file)
|
181
|
+
warn "** flogging #{file}" if options[:verbose]
|
182
|
+
|
183
|
+
ast = @parser.process(ruby, file)
|
184
|
+
mass[file] = ast.mass
|
185
|
+
process ast
|
186
|
+
rescue SyntaxError, Racc::ParseError => e
|
187
|
+
if e.inspect =~ /<%|%>/ then
|
188
|
+
warn "#{e.inspect} at #{e.backtrace.first(5).join(', ')}"
|
189
|
+
warn "\n...stupid lemmings and their bad erb templates... skipping"
|
190
|
+
else
|
191
|
+
raise e unless options[:continue]
|
192
|
+
warn file
|
193
|
+
warn "#{e.inspect} at #{e.backtrace.first(5).join(', ')}"
|
194
|
+
end
|
195
|
+
end
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
@@ -217,11 +218,13 @@ class Flog < SexpProcessor
|
|
217
218
|
|
218
219
|
def initialize options = {}
|
219
220
|
super()
|
220
|
-
@options
|
221
|
-
@class_stack
|
222
|
-
@method_stack
|
221
|
+
@options = options
|
222
|
+
@class_stack = []
|
223
|
+
@method_stack = []
|
224
|
+
@mass = {}
|
225
|
+
@parser = RubyParser.new
|
223
226
|
self.auto_shift_type = true
|
224
|
-
self.require_empty
|
227
|
+
self.require_empty = false # HACK
|
225
228
|
self.reset
|
226
229
|
end
|
227
230
|
|
@@ -306,10 +309,6 @@ class Flog < SexpProcessor
|
|
306
309
|
io.puts "%8.1f: %s" % [average, "flog/method average"]
|
307
310
|
end
|
308
311
|
|
309
|
-
def parse_tree
|
310
|
-
@parse_tree ||= ParseTree.new(false)
|
311
|
-
end
|
312
|
-
|
313
312
|
##
|
314
313
|
# For the duration of the block the complexity factor is increased
|
315
314
|
# by #bonus This allows the complexity of sub-expressions to be
|
@@ -322,11 +321,6 @@ class Flog < SexpProcessor
|
|
322
321
|
@multiplier -= bonus
|
323
322
|
end
|
324
323
|
|
325
|
-
def process_parse_tree(ruby, file) # TODO: rename away from process
|
326
|
-
sexp = parse_tree.parse_tree_for_string(ruby, file)
|
327
|
-
process Sexp.from_array(sexp).first
|
328
|
-
end
|
329
|
-
|
330
324
|
def record_method_score(method, score)
|
331
325
|
@totals ||= Hash.new(0)
|
332
326
|
@totals[method] = score
|
@@ -349,9 +343,9 @@ class Flog < SexpProcessor
|
|
349
343
|
end
|
350
344
|
|
351
345
|
def reset
|
352
|
-
@totals
|
346
|
+
@totals = @total_score = nil
|
353
347
|
@multiplier = 1.0
|
354
|
-
@calls
|
348
|
+
@calls = Hash.new { |h,k| h[k] = Hash.new 0 }
|
355
349
|
end
|
356
350
|
|
357
351
|
def score_method(tally)
|
data/test/test_flog.rb
CHANGED
@@ -6,269 +6,425 @@ class Flog
|
|
6
6
|
attr_writer :total_score
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@flog = Flog.new(@options)
|
9
|
+
class TestFlog < MiniTest::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@flog = Flog.new
|
13
12
|
end
|
14
13
|
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# def test_sanity
|
15
|
+
# # FIX: make this easy to pass in to Flog.new
|
16
|
+
# ARGV.push("-a")
|
17
|
+
# opts = Flog.parse_options
|
18
|
+
# ARGV.clear
|
19
|
+
# @flog.flog __FILE__
|
20
|
+
#
|
21
|
+
# test_methods = self.class.instance_methods(false).sort.map { |m|
|
22
|
+
# "#{self.class}##{m}"
|
23
|
+
# }
|
24
|
+
#
|
25
|
+
# expected_calls = ["Flog#none"] + test_methods + ["main#none"]
|
26
|
+
#
|
27
|
+
# assert_in_delta 1.0, @flog.multiplier, 0.001
|
28
|
+
# assert_equal expected_calls, @flog.calls.keys.sort
|
29
|
+
# assert_equal 1, @flog.mass.size
|
30
|
+
# assert_operator @flog.mass[__FILE__], :>, 100
|
31
|
+
# assert_equal [], @flog.class_stack
|
32
|
+
# assert_equal [], @flog.method_stack
|
33
|
+
#
|
34
|
+
# # FIX: this sucks, but it is a start.
|
35
|
+
# out = StringIO.new
|
36
|
+
# @flog.report out
|
37
|
+
# out = out.string
|
38
|
+
#
|
39
|
+
# assert_match(/[\d\.]+: flog total/, out)
|
40
|
+
# assert_match(/[\d\.]+: flog.method average/, out)
|
41
|
+
#
|
42
|
+
# test_methods.each do |m|
|
43
|
+
# assert_match(/[\d\.]+: #{m}/, out)
|
19
44
|
# end
|
20
45
|
# end
|
21
46
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
47
|
+
def test_class_expand_dirs_to_files
|
48
|
+
expected = %w(lib/flog.rb lib/flog_task.rb lib/gauntlet_flog.rb)
|
49
|
+
assert_equal expected, Flog.expand_dirs_to_files('lib')
|
50
|
+
expected = %w(Rakefile)
|
51
|
+
assert_equal expected, Flog.expand_dirs_to_files('Rakefile')
|
52
|
+
end
|
26
53
|
|
27
|
-
|
28
|
-
|
54
|
+
def test_class_parse_options
|
55
|
+
d = Flog.default_options
|
56
|
+
assert_equal d, Flog.parse_options
|
57
|
+
|
58
|
+
options = {
|
59
|
+
"-a" => :all,
|
60
|
+
"-b" => :blame,
|
61
|
+
"-c" => :continue,
|
62
|
+
"-d" => :details,
|
63
|
+
"-g" => :group,
|
64
|
+
"-m" => :methods,
|
65
|
+
"-q" => :quiet,
|
66
|
+
"-s" => :score,
|
67
|
+
"-v" => :verbose,
|
68
|
+
}
|
69
|
+
|
70
|
+
options.each do |arg, opt|
|
71
|
+
ARGV.replace [arg]
|
72
|
+
assert_equal d.merge(opt => true), Flog.parse_options
|
73
|
+
end
|
74
|
+
|
75
|
+
old_load_path = $:.dup
|
76
|
+
ARGV.replace ["-Iblah1,blah2"]
|
77
|
+
assert_equal d, Flog.parse_options
|
78
|
+
assert_equal old_load_path + %w(blah1 blah2), $:
|
79
|
+
|
80
|
+
def Flog.exit
|
81
|
+
raise "happy"
|
82
|
+
end
|
83
|
+
|
84
|
+
ex = nil
|
85
|
+
o, e = capture_io do
|
86
|
+
ex = assert_raises RuntimeError do
|
87
|
+
ARGV.replace ["-h"]
|
88
|
+
Flog.parse_options
|
89
|
+
end
|
29
90
|
end
|
91
|
+
assert_equal "happy", ex.message
|
92
|
+
assert_match(/methods-only/, o)
|
93
|
+
assert_equal "", e
|
94
|
+
ensure
|
95
|
+
ARGV.clear
|
96
|
+
end
|
30
97
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
98
|
+
def test_add_to_score
|
99
|
+
assert_empty @flog.calls
|
100
|
+
@flog.class_stack << "MyKlass"
|
101
|
+
@flog.method_stack << "mymethod"
|
102
|
+
@flog.add_to_score "blah", 42
|
35
103
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
104
|
+
expected = {"MyKlass#mymethod"=>{"blah"=>42.0}}
|
105
|
+
assert_equal expected, @flog.calls
|
39
106
|
|
40
|
-
|
41
|
-
@flog.method_name.must_equal :none
|
42
|
-
end
|
107
|
+
@flog.add_to_score "blah", 2
|
43
108
|
|
44
|
-
|
45
|
-
|
46
|
-
|
109
|
+
expected["MyKlass#mymethod"]["blah"] = 44.0
|
110
|
+
assert_equal expected, @flog.calls
|
111
|
+
end
|
47
112
|
|
48
|
-
|
49
|
-
|
50
|
-
|
113
|
+
# def test_analyze_list
|
114
|
+
# raise NotImplementedError, 'Need to write test_analyze_list'
|
115
|
+
# end
|
51
116
|
|
52
|
-
|
53
|
-
|
54
|
-
|
117
|
+
def test_average
|
118
|
+
assert_equal 0, Flog.new.average
|
119
|
+
# TODO: non-zero... but do total/totals first
|
120
|
+
end
|
55
121
|
|
56
|
-
|
57
|
-
|
58
|
-
|
122
|
+
def test_calls
|
123
|
+
expected = {}
|
124
|
+
assert_equal expected, Flog.new.calls
|
125
|
+
end
|
59
126
|
|
60
|
-
|
61
|
-
|
62
|
-
|
127
|
+
# def test_flog
|
128
|
+
# raise NotImplementedError, 'Need to write test_flog'
|
129
|
+
# end
|
63
130
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
131
|
+
def test_in_klass
|
132
|
+
assert_empty @flog.class_stack
|
67
133
|
|
68
|
-
|
69
|
-
@flog.
|
134
|
+
@flog.in_klass "xxx" do
|
135
|
+
assert_equal ["xxx"], @flog.class_stack
|
70
136
|
end
|
71
|
-
end
|
72
137
|
|
73
|
-
|
74
|
-
it 'should return the current options settings' do
|
75
|
-
@flog.must_respond_to(:options)
|
76
|
-
end
|
138
|
+
assert_empty @flog.class_stack
|
77
139
|
end
|
78
140
|
|
79
|
-
|
80
|
-
|
81
|
-
|
141
|
+
def test_in_method
|
142
|
+
assert_empty @flog.method_stack
|
143
|
+
|
144
|
+
@flog.in_method "xxx" do
|
145
|
+
assert_equal ["xxx"], @flog.method_stack
|
82
146
|
end
|
83
147
|
|
84
|
-
|
85
|
-
|
86
|
-
ParseTree.expects(:new)
|
87
|
-
@flog.parse_tree
|
88
|
-
end
|
148
|
+
assert_empty @flog.method_stack
|
149
|
+
end
|
89
150
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
151
|
+
# def test_increment_total_score_by
|
152
|
+
# raise NotImplementedError, 'Need to write test_increment_total_score_by'
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# def test_klass_name
|
156
|
+
# raise NotImplementedError, 'Need to write test_klass_name'
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# def test_mass
|
160
|
+
# raise NotImplementedError, 'Need to write test_mass'
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# def test_method_name
|
164
|
+
# raise NotImplementedError, 'Need to write test_method_name'
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# def test_method_stack
|
168
|
+
# raise NotImplementedError, 'Need to write test_method_stack'
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# def test_multiplier
|
172
|
+
# raise NotImplementedError, 'Need to write test_multiplier'
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
# def test_multiplier_equals
|
176
|
+
# raise NotImplementedError, 'Need to write test_multiplier_equals'
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# def test_options
|
180
|
+
# raise NotImplementedError, 'Need to write test_options'
|
181
|
+
# end
|
182
|
+
#
|
183
|
+
# def test_output_details
|
184
|
+
# raise NotImplementedError, 'Need to write test_output_details'
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# def test_output_method_details
|
188
|
+
# raise NotImplementedError, 'Need to write test_output_method_details'
|
189
|
+
# end
|
190
|
+
#
|
191
|
+
# def test_output_summary
|
192
|
+
# raise NotImplementedError, 'Need to write test_output_summary'
|
193
|
+
# end
|
194
|
+
#
|
195
|
+
# def test_parse_tree
|
196
|
+
# raise NotImplementedError, 'Need to write test_parse_tree'
|
197
|
+
# end
|
94
198
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
# end
|
199
|
+
def test_penalize_by
|
200
|
+
assert_equal 1, @flog.multiplier
|
201
|
+
@flog.penalize_by 2 do
|
202
|
+
assert_equal 3, @flog.multiplier
|
100
203
|
end
|
204
|
+
assert_equal 1, @flog.multiplier
|
205
|
+
end
|
101
206
|
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
# @flog.parse_tree
|
106
|
-
# ParseTree.expects(:new).never
|
107
|
-
# @flog.parse_tree
|
108
|
-
# end
|
207
|
+
# def test_record_method_score
|
208
|
+
# raise NotImplementedError, 'Need to write test_record_method_score'
|
209
|
+
# end
|
109
210
|
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
211
|
+
# def test_report
|
212
|
+
# raise NotImplementedError, 'Need to write test_report'
|
213
|
+
# end
|
214
|
+
#
|
215
|
+
# def test_reset
|
216
|
+
# raise NotImplementedError, 'Need to write test_reset'
|
217
|
+
# end
|
218
|
+
|
219
|
+
def test_score_method
|
220
|
+
expected = 3.742
|
221
|
+
assert_in_delta expected, @flog.score_method(:assignment => 1,
|
222
|
+
:branch => 2,
|
223
|
+
:other => 3)
|
116
224
|
end
|
117
225
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
226
|
+
# def test_summarize_method
|
227
|
+
# raise NotImplementedError, 'Need to write test_summarize_method'
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# def test_total
|
231
|
+
# raise NotImplementedError, 'Need to write test_total'
|
232
|
+
# end
|
233
|
+
#
|
234
|
+
# def test_totals
|
235
|
+
# raise NotImplementedError, 'Need to write test_totals'
|
236
|
+
# end
|
237
|
+
end
|
123
238
|
|
124
|
-
|
125
|
-
def @flog.flog_file(*args); raise "no"; end
|
126
|
-
@flog.flog_files
|
127
|
-
end
|
128
|
-
end
|
239
|
+
# Number of errors detected: 64
|
129
240
|
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
241
|
+
# describe Flog do
|
242
|
+
# before :each do
|
243
|
+
# @options = { }
|
244
|
+
# @flog = Flog.new(@options)
|
245
|
+
# end
|
246
|
+
#
|
247
|
+
# # describe 'when initializing' do
|
248
|
+
# # it 'should not reference the parse tree' do
|
249
|
+
# # ParseTree.expects(:new).never
|
250
|
+
# # Flog.new(@options)
|
251
|
+
# # end
|
252
|
+
# # end
|
253
|
+
#
|
254
|
+
# describe 'after initializing' do
|
255
|
+
# it 'should have options set' do
|
256
|
+
# @flog.options.must_equal @options
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# it 'should return an SexpProcessor' do
|
260
|
+
# @flog.must_be_kind_of(SexpProcessor)
|
261
|
+
# end
|
262
|
+
#
|
263
|
+
# it 'should be initialized like all SexpProcessors' do
|
264
|
+
# # less than ideal means of insuring the Flog instance was initialized properly, imo -RB
|
265
|
+
# @flog.context.must_equal []
|
266
|
+
# end
|
267
|
+
#
|
268
|
+
# it 'should have no current class' do
|
269
|
+
# @flog.klass_name.must_equal :main
|
270
|
+
# end
|
271
|
+
#
|
272
|
+
# it 'should have no current method' do
|
273
|
+
# @flog.method_name.must_equal :none
|
274
|
+
# end
|
275
|
+
#
|
276
|
+
# it 'should not have any calls yet' do
|
277
|
+
# @flog.calls.must_equal({})
|
278
|
+
# end
|
279
|
+
#
|
280
|
+
# it 'should have a means of accessing its parse tree' do
|
281
|
+
# @flog.must_respond_to(:parse_tree)
|
282
|
+
# end
|
283
|
+
#
|
284
|
+
# it 'should not have any totals yet' do
|
285
|
+
# @flog.totals.must_equal({})
|
286
|
+
# end
|
287
|
+
#
|
288
|
+
# it 'should have a 0 total score' do
|
289
|
+
# @flog.total.must_equal 0.0
|
290
|
+
# end
|
291
|
+
#
|
292
|
+
# it 'should have a multiplier of 1' do
|
293
|
+
# @flog.multiplier.must_equal 1.0
|
294
|
+
# end
|
295
|
+
#
|
296
|
+
# currently "should have 'auto shift type' set to true" do
|
297
|
+
# @flog.auto_shift_type.must_equal true
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
# currently "should have 'require empty' set to false" do
|
301
|
+
# @flog.require_empty.must_equal false
|
302
|
+
# end
|
303
|
+
# end
|
304
|
+
#
|
305
|
+
# describe 'options' do
|
306
|
+
# it 'should return the current options settings' do
|
307
|
+
# @flog.must_respond_to(:options)
|
308
|
+
# end
|
309
|
+
# end
|
310
|
+
#
|
311
|
+
# describe 'when accessing the parse tree' do
|
312
|
+
# before :each do
|
313
|
+
# @parse_tree = stub('parse tree')
|
314
|
+
# end
|
315
|
+
#
|
316
|
+
# describe 'for the first time' do
|
317
|
+
# it 'should create a new ParseTree' do
|
318
|
+
# RubyParser.expects(:new)
|
319
|
+
# @flog.parse_tree
|
135
320
|
# end
|
136
321
|
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
322
|
+
# # HACK: most tarded spec ever
|
323
|
+
# # it 'should return a ParseTree instance' do
|
324
|
+
# # ParseTree.stubs(:new).returns(@parse_tree)
|
325
|
+
# # @flog.parse_tree.must_equal @parse_tree
|
326
|
+
# # end
|
327
|
+
# end
|
328
|
+
#
|
329
|
+
# # HACK Jesus... this is useless.
|
330
|
+
# # describe 'after the parse tree has been initialized' do
|
331
|
+
# # it 'should not attempt to create a new ParseTree instance' do
|
332
|
+
# # @flog.parse_tree
|
333
|
+
# # ParseTree.expects(:new).never
|
334
|
+
# # @flog.parse_tree
|
335
|
+
# # end
|
336
|
+
# #
|
337
|
+
# # it 'should return a ParseTree instance' do
|
338
|
+
# # ParseTree.stubs(:new).returns(@parse_tree)
|
339
|
+
# # @flog.parse_tree
|
340
|
+
# # @flog.parse_tree.must_equal @parse_tree
|
341
|
+
# # end
|
342
|
+
# # end
|
343
|
+
# end
|
344
|
+
#
|
345
|
+
# describe "when flogging a list of files" do
|
346
|
+
# describe 'when no files are specified' do
|
347
|
+
# currently 'should not raise an exception' do
|
348
|
+
# lambda { @flog.flog_files }.wont_raise_error
|
140
349
|
# end
|
141
350
|
#
|
142
|
-
# it 'should
|
143
|
-
# @
|
144
|
-
#
|
145
|
-
# end
|
146
|
-
# @flog.flog_files(@files)
|
351
|
+
# it 'should never call flog_file' do
|
352
|
+
# def @flog.flog_file(*args); raise "no"; end
|
353
|
+
# @flog.flog_files
|
147
354
|
# end
|
148
355
|
# end
|
149
|
-
|
150
|
-
describe 'when flogging a single file' do
|
151
|
-
before :each do
|
152
|
-
@flog.stubs(:flog)
|
153
|
-
end
|
154
|
-
|
155
|
-
describe 'when the filename is "-"' do
|
156
|
-
before :each do
|
157
|
-
@stdin = $stdin # HERE: working through the fact that zenspider is using $stdin in the middle of the system
|
158
|
-
$stdin = stub('stdin', :read => 'data')
|
159
|
-
end
|
160
|
-
|
161
|
-
after :each do
|
162
|
-
$stdin = @stdin
|
163
|
-
end
|
164
|
-
|
165
|
-
# describe 'when reporting blame information' do
|
166
|
-
# before :each do
|
167
|
-
# @flog = Flog.new(:blame => true)
|
168
|
-
# @flog.stubs(:flog)
|
169
|
-
# end
|
170
356
|
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
|
176
|
-
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
#
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
# it 'should note which file is being flogged' do
|
198
|
-
# @flog.expects(:warn)
|
199
|
-
# @flog.flog_file('-')
|
200
|
-
# end
|
201
|
-
end
|
202
|
-
|
203
|
-
describe 'when the verbose flag is off' do
|
204
|
-
before :each do
|
205
|
-
@flog = Flog.new({})
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'should not note which file is being flogged' do
|
209
|
-
def @flog.warn(*args); raise "no"; end
|
210
|
-
@flog.flog_file('-')
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
describe 'when the filename points to a directory' do
|
216
|
-
before :each do
|
217
|
-
def @flog.flog_directory(*args); end
|
218
|
-
@file = File.dirname(__FILE__)
|
219
|
-
end
|
220
|
-
|
221
|
-
it 'should expand the files under the directory' do
|
222
|
-
@flog.expects(:flog_directory)
|
223
|
-
@flog.flog_file(@file)
|
224
|
-
end
|
225
|
-
|
226
|
-
it 'should not read data from stdin' do
|
227
|
-
def $stdin.read(*args); raise "no"; end
|
228
|
-
@flog.flog_file(@file)
|
229
|
-
end
|
230
|
-
|
231
|
-
it 'should not flog any data' do
|
232
|
-
def @flog.flog(*args); raise "no"; end
|
233
|
-
@flog.flog_file(@file)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe 'when the filename points to a non-existant file' do
|
238
|
-
before :each do
|
239
|
-
@file = '/adfasdfasfas/fasdfaf-#{rand(1000000).to_s}'
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'should raise an exception' do
|
243
|
-
lambda { @flog.flog_file(@file) }.must_raise(Errno::ENOENT)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
# describe 'when the filename points to an existing file' do
|
357
|
+
# # HACK
|
358
|
+
# # describe 'when files are specified' do
|
359
|
+
# # before :each do
|
360
|
+
# # @files = [1, 2, 3, 4]
|
361
|
+
# # @flog.stubs(:flog_file)
|
362
|
+
# # end
|
363
|
+
# #
|
364
|
+
# # it 'should do a flog for each individual file' do
|
365
|
+
# # @flog.expects(:flog_file).times(@files.size)
|
366
|
+
# # @flog.flog_files(@files)
|
367
|
+
# # end
|
368
|
+
# #
|
369
|
+
# # it 'should provide the filename when flogging a file' do
|
370
|
+
# # @files.each do |file|
|
371
|
+
# # @flog.expects(:flog_file).with(file)
|
372
|
+
# # end
|
373
|
+
# # @flog.flog_files(@files)
|
374
|
+
# # end
|
375
|
+
# # end
|
376
|
+
#
|
377
|
+
# describe 'when flogging a single file' do
|
378
|
+
# before :each do
|
379
|
+
# @flog.stubs(:flog)
|
380
|
+
# end
|
381
|
+
#
|
382
|
+
# describe 'when the filename is "-"' do
|
248
383
|
# before :each do
|
249
|
-
# @
|
250
|
-
#
|
384
|
+
# @stdin = $stdin # HERE: working through the fact that zenspider is using $stdin in the middle of the system
|
385
|
+
# $stdin = stub('stdin', :read => 'data')
|
251
386
|
# end
|
252
387
|
#
|
253
|
-
#
|
254
|
-
#
|
255
|
-
# @flog.flog_file(@file)
|
388
|
+
# after :each do
|
389
|
+
# $stdin = @stdin
|
256
390
|
# end
|
257
391
|
#
|
258
|
-
#
|
259
|
-
#
|
260
|
-
#
|
261
|
-
#
|
392
|
+
# # describe 'when reporting blame information' do
|
393
|
+
# # before :each do
|
394
|
+
# # @flog = Flog.new(:blame => true)
|
395
|
+
# # @flog.stubs(:flog)
|
396
|
+
# # end
|
397
|
+
# #
|
398
|
+
# # it 'should fail' do
|
399
|
+
# # lambda { @flog.flog_file('-') }.must_raise(RuntimeError)
|
400
|
+
# # end
|
401
|
+
# # end
|
402
|
+
#
|
403
|
+
# # HACK: need to figure out how to do nested setup w/o inherited tests
|
404
|
+
# # it 'should not raise an exception' do
|
405
|
+
# # lambda { @flog.flog_file('-') }.wont_raise_error
|
406
|
+
# # end
|
407
|
+
#
|
408
|
+
# # HACK: need to figure out how to do nested setup w/o inherited tests
|
409
|
+
# # it 'should read the data from stdin' do
|
410
|
+
# # $stdin.expects(:read).returns('data')
|
411
|
+
# # @flog.flog_file('-')
|
412
|
+
# # end
|
413
|
+
#
|
414
|
+
# # it 'should flog the read data' do
|
415
|
+
# # @flog.expects(:flog).with('data', '-')
|
416
|
+
# # @flog.flog_file('-')
|
417
|
+
# # end
|
262
418
|
#
|
263
419
|
# describe 'when the verbose flag is on' do
|
264
420
|
# before :each do
|
265
421
|
# @flog = Flog.new(:verbose => true)
|
266
422
|
# end
|
267
423
|
#
|
268
|
-
# it 'should note which file is being flogged' do
|
269
|
-
# @flog.expects(:warn)
|
270
|
-
# @flog.flog_file(
|
271
|
-
# end
|
424
|
+
# # it 'should note which file is being flogged' do
|
425
|
+
# # @flog.expects(:warn)
|
426
|
+
# # @flog.flog_file('-')
|
427
|
+
# # end
|
272
428
|
# end
|
273
429
|
#
|
274
430
|
# describe 'when the verbose flag is off' do
|
@@ -278,861 +434,1053 @@ describe Flog do
|
|
278
434
|
#
|
279
435
|
# it 'should not note which file is being flogged' do
|
280
436
|
# def @flog.warn(*args); raise "no"; end
|
281
|
-
# @flog.flog_file(
|
437
|
+
# @flog.flog_file('-')
|
282
438
|
# end
|
283
439
|
# end
|
284
440
|
# end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
# describe 'when flogging a directory' do
|
289
|
-
# before :each do
|
290
|
-
# @files = ['a.rb', '/foo/b.rb', '/foo/bar/c.rb', '/foo/bar/baz/d.rb']
|
291
|
-
# @dir = File.dirname(__FILE__)
|
292
|
-
# Dir.stubs(:[]).returns(@files)
|
293
|
-
# end
|
294
441
|
#
|
295
|
-
#
|
296
|
-
#
|
297
|
-
#
|
298
|
-
#
|
299
|
-
#
|
442
|
+
# describe 'when the filename points to a directory' do
|
443
|
+
# before :each do
|
444
|
+
# def @flog.flog_directory(*args); end
|
445
|
+
# @file = File.dirname(__FILE__)
|
446
|
+
# end
|
447
|
+
#
|
448
|
+
# it 'should expand the files under the directory' do
|
449
|
+
# @flog.expects(:flog_directory)
|
450
|
+
# @flog.flog_file(@file)
|
451
|
+
# end
|
452
|
+
#
|
453
|
+
# it 'should not read data from stdin' do
|
454
|
+
# def $stdin.read(*args); raise "no"; end
|
455
|
+
# @flog.flog_file(@file)
|
456
|
+
# end
|
457
|
+
#
|
458
|
+
# it 'should not flog any data' do
|
459
|
+
# def @flog.flog(*args); raise "no"; end
|
460
|
+
# @flog.flog_file(@file)
|
461
|
+
# end
|
462
|
+
# end
|
463
|
+
#
|
464
|
+
# describe 'when the filename points to a non-existant file' do
|
465
|
+
# before :each do
|
466
|
+
# @file = '/adfasdfasfas/fasdfaf-#{rand(1000000).to_s}'
|
467
|
+
# end
|
468
|
+
#
|
469
|
+
# it 'should raise an exception' do
|
470
|
+
# lambda { @flog.flog_file(@file) }.must_raise(Errno::ENOENT)
|
471
|
+
# end
|
472
|
+
# end
|
300
473
|
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
#
|
474
|
+
# # describe 'when the filename points to an existing file' do
|
475
|
+
# # before :each do
|
476
|
+
# # @file = __FILE__
|
477
|
+
# # File.stubs(:read).returns('data')
|
478
|
+
# # end
|
479
|
+
# #
|
480
|
+
# # it 'should read the contents of the file' do
|
481
|
+
# # File.expects(:read).with(@file).returns('data')
|
482
|
+
# # @flog.flog_file(@file)
|
483
|
+
# # end
|
484
|
+
# #
|
485
|
+
# # it 'should flog the contents of the file' do
|
486
|
+
# # @flog.expects(:flog).with('data', @file)
|
487
|
+
# # @flog.flog_file(@file)
|
488
|
+
# # end
|
489
|
+
# #
|
490
|
+
# # describe 'when the verbose flag is on' do
|
491
|
+
# # before :each do
|
492
|
+
# # @flog = Flog.new(:verbose => true)
|
493
|
+
# # end
|
494
|
+
# #
|
495
|
+
# # it 'should note which file is being flogged' do
|
496
|
+
# # @flog.expects(:warn)
|
497
|
+
# # @flog.flog_file(@file)
|
498
|
+
# # end
|
499
|
+
# # end
|
500
|
+
# #
|
501
|
+
# # describe 'when the verbose flag is off' do
|
502
|
+
# # before :each do
|
503
|
+
# # @flog = Flog.new({})
|
504
|
+
# # end
|
505
|
+
# #
|
506
|
+
# # it 'should not note which file is being flogged' do
|
507
|
+
# # def @flog.warn(*args); raise "no"; end
|
508
|
+
# # @flog.flog_file(@file)
|
509
|
+
# # end
|
510
|
+
# # end
|
511
|
+
# # end
|
304
512
|
# end
|
305
513
|
# end
|
306
|
-
|
307
|
-
describe 'when flogging a Ruby string' do
|
308
|
-
it 'should require both a Ruby string and a filename' do
|
309
|
-
lambda { @flog.flog('string') }.must_raise(ArgumentError)
|
310
|
-
end
|
311
|
-
|
312
|
-
describe 'when reporting blame information' do
|
313
|
-
before :each do
|
314
|
-
@flog = Flog.new(:blame => true)
|
315
|
-
end
|
316
|
-
|
317
|
-
it 'should gather blame information for the file' do
|
318
|
-
@flog.expects(:collect_blame).with('filename')
|
319
|
-
@flog.flog('string', 'filename')
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
describe 'when not reporting blame information' do
|
324
|
-
it 'should not gather blame information for the file' do
|
325
|
-
def @flog.collect_blame(*args); raise "no"; end
|
326
|
-
@flog.flog('string', 'filename')
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
describe 'when the string has a syntax error' do
|
331
|
-
before :each do
|
332
|
-
def @flog.warn(*args); end
|
333
|
-
def @flog.process_parse_tree(*args); raise SyntaxError, "<% foo %>"; end
|
334
|
-
end
|
335
|
-
|
336
|
-
describe 'when the string has erb snippets' do
|
337
|
-
currently 'should warn about skipping' do
|
338
|
-
@flog.expects(:warn)
|
339
|
-
@flog.flog('string', 'filename')
|
340
|
-
end
|
341
|
-
|
342
|
-
it 'should not raise an exception' do
|
343
|
-
lambda { @flog.flog('string', 'filename') }.wont_raise_error
|
344
|
-
end
|
345
|
-
|
346
|
-
it 'should not process the failing code' do
|
347
|
-
def @flog.process(*args); raise "no"; end
|
348
|
-
@flog.flog('string', 'filename')
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
describe 'when the string has no erb snippets' do
|
353
|
-
before :each do
|
354
|
-
def @flog.process_parse_tree(*args); raise SyntaxError; end
|
355
|
-
end
|
356
|
-
|
357
|
-
it 'should raise a SyntaxError exception' do
|
358
|
-
# TODO: what the fuck?!? how does this test ANYTHING?
|
359
|
-
# it checks that #flog calls #process_parse_tree?? AND?!?!
|
360
|
-
lambda { @flog.flog('string', 'filename') }.must_raise(SyntaxError)
|
361
|
-
end
|
362
|
-
|
363
|
-
it 'should not process the failing code' do
|
364
|
-
def @flog.process(*args); raise "no"; end
|
365
|
-
lambda { @flog.flog('string', 'filename') }
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
describe 'when the string contains valid Ruby' do
|
371
|
-
before :each do
|
372
|
-
@flog.stubs(:process_parse_tree)
|
373
|
-
end
|
374
|
-
|
375
|
-
it 'should process the parse tree for the string' do
|
376
|
-
@flog.expects(:process_parse_tree)
|
377
|
-
@flog.flog('string', 'filename')
|
378
|
-
end
|
379
|
-
|
380
|
-
it 'should provide the string and the filename to the parse tree processor' do
|
381
|
-
@flog.expects(:process_parse_tree).with('string', 'filename')
|
382
|
-
@flog.flog('string', 'filename')
|
383
|
-
end
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
# describe 'when processing a ruby parse tree' do
|
388
|
-
# before :each do
|
389
|
-
# @flog.stubs(:process)
|
390
|
-
# @sexp = stub('s-expressions')
|
391
|
-
# @parse_tree = stub('parse tree', :parse_tree_for_string => @sexp)
|
392
|
-
# ParseTree.stubs(:new).returns(@parse_tree)
|
393
|
-
# end
|
394
514
|
#
|
395
|
-
#
|
396
|
-
#
|
515
|
+
# # describe 'when flogging a directory' do
|
516
|
+
# # before :each do
|
517
|
+
# # @files = ['a.rb', '/foo/b.rb', '/foo/bar/c.rb', '/foo/bar/baz/d.rb']
|
518
|
+
# # @dir = File.dirname(__FILE__)
|
519
|
+
# # Dir.stubs(:[]).returns(@files)
|
520
|
+
# # end
|
521
|
+
# #
|
522
|
+
# # it 'should get the list of ruby files under the directory' do
|
523
|
+
# # @flog.stubs(:flog_file)
|
524
|
+
# # Dir.expects(:[]).returns(@files)
|
525
|
+
# # @flog.flog_directory(@dir)
|
526
|
+
# # end
|
527
|
+
# #
|
528
|
+
# # it "should call flog_file once for each file in the directory" do
|
529
|
+
# # @files.each {|f| @flog.expects(:flog_file).with(f) }
|
530
|
+
# # @flog.flog_directory(@dir)
|
531
|
+
# # end
|
532
|
+
# # end
|
533
|
+
#
|
534
|
+
# describe 'when flogging a Ruby string' do
|
535
|
+
# it 'should require both a Ruby string and a filename' do
|
536
|
+
# lambda { @flog.flog('string') }.must_raise(ArgumentError)
|
397
537
|
# end
|
398
538
|
#
|
399
|
-
#
|
400
|
-
#
|
401
|
-
#
|
402
|
-
#
|
539
|
+
# describe 'when reporting blame information' do
|
540
|
+
# before :each do
|
541
|
+
# @flog = Flog.new(:blame => true)
|
542
|
+
# end
|
543
|
+
#
|
544
|
+
# it 'should gather blame information for the file' do
|
545
|
+
# @flog.expects(:collect_blame).with('filename')
|
546
|
+
# @flog.flog('string', 'filename')
|
547
|
+
# end
|
403
548
|
# end
|
404
549
|
#
|
405
|
-
#
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
550
|
+
# describe 'when not reporting blame information' do
|
551
|
+
# it 'should not gather blame information for the file' do
|
552
|
+
# def @flog.collect_blame(*args); raise "no"; end
|
553
|
+
# @flog.flog('string', 'filename')
|
554
|
+
# end
|
409
555
|
# end
|
410
556
|
#
|
411
|
-
# describe '
|
557
|
+
# describe 'when the string has a syntax error' do
|
412
558
|
# before :each do
|
413
|
-
#
|
414
|
-
# def @flog.
|
415
|
-
# def @flog.parse_tree; return $pt; end
|
559
|
+
# def @flog.warn(*args); end
|
560
|
+
# def @flog.process_parse_tree(*args); raise SyntaxError, "<% foo %>"; end
|
416
561
|
# end
|
417
562
|
#
|
418
|
-
#
|
419
|
-
#
|
420
|
-
#
|
421
|
-
#
|
563
|
+
# describe 'when the string has erb snippets' do
|
564
|
+
# currently 'should warn about skipping' do
|
565
|
+
# @flog.expects(:warn)
|
566
|
+
# @flog.flog('string', 'filename')
|
567
|
+
# end
|
422
568
|
#
|
423
|
-
#
|
424
|
-
#
|
425
|
-
#
|
569
|
+
# it 'should not raise an exception' do
|
570
|
+
# lambda { @flog.flog('string', 'filename') }.wont_raise_error
|
571
|
+
# end
|
572
|
+
#
|
573
|
+
# it 'should not process the failing code' do
|
574
|
+
# def @flog.process(*args); raise "no"; end
|
575
|
+
# @flog.flog('string', 'filename')
|
576
|
+
# end
|
426
577
|
# end
|
427
578
|
#
|
428
|
-
#
|
429
|
-
#
|
430
|
-
#
|
431
|
-
#
|
579
|
+
# describe 'when the string has no erb snippets' do
|
580
|
+
# before :each do
|
581
|
+
# def @flog.process_parse_tree(*args); raise SyntaxError; end
|
582
|
+
# end
|
583
|
+
#
|
584
|
+
# it 'should raise a SyntaxError exception' do
|
585
|
+
# # TODO: what the fuck?!? how does this test ANYTHING?
|
586
|
+
# # it checks that #flog calls #process_parse_tree?? AND?!?!
|
587
|
+
# lambda { @flog.flog('string', 'filename') }.must_raise(SyntaxError)
|
588
|
+
# end
|
589
|
+
#
|
590
|
+
# it 'should not process the failing code' do
|
591
|
+
# def @flog.process(*args); raise "no"; end
|
592
|
+
# lambda { @flog.flog('string', 'filename') }
|
593
|
+
# end
|
432
594
|
# end
|
433
595
|
# end
|
434
596
|
#
|
435
|
-
# describe '
|
597
|
+
# describe 'when the string contains valid Ruby' do
|
436
598
|
# before :each do
|
437
|
-
#
|
438
|
-
# def @flog.parse_tree; return $parse_tree; end
|
439
|
-
# def $parse_tree.parse_tree_for_string(*args); raise SyntaxError; end
|
599
|
+
# @flog.stubs(:process_parse_tree)
|
440
600
|
# end
|
441
601
|
#
|
442
|
-
# it 'should
|
443
|
-
#
|
602
|
+
# it 'should process the parse tree for the string' do
|
603
|
+
# @flog.expects(:process_parse_tree)
|
604
|
+
# @flog.flog('string', 'filename')
|
444
605
|
# end
|
445
606
|
#
|
446
|
-
# it 'should
|
447
|
-
#
|
448
|
-
#
|
607
|
+
# it 'should provide the string and the filename to the parse tree processor' do
|
608
|
+
# @flog.expects(:process_parse_tree).with('string', 'filename')
|
609
|
+
# @flog.flog('string', 'filename')
|
449
610
|
# end
|
450
611
|
# end
|
451
612
|
# end
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
describe 'when looking up the name of the class currently under analysis' do
|
617
|
-
it 'should not take any arguments' do
|
618
|
-
lambda { @flog.klass_name('foo') }.must_raise(ArgumentError)
|
619
|
-
end
|
620
|
-
|
621
|
-
it 'should return the most recent class entered' do
|
622
|
-
@flog.class_stack << :foo << :bar << :baz
|
623
|
-
@flog.klass_name.must_equal :foo
|
624
|
-
end
|
625
|
-
|
626
|
-
it 'should return the default class if no classes entered' do
|
627
|
-
@flog.class_stack.clear
|
628
|
-
@flog.klass_name.must_equal :main
|
629
|
-
end
|
630
|
-
end
|
631
|
-
|
632
|
-
describe 'when recording the current method being analyzed' do
|
633
|
-
it 'should require a method name' do
|
634
|
-
lambda { @flog.in_method }.must_raise(ArgumentError)
|
635
|
-
end
|
636
|
-
|
637
|
-
it 'should require a block during which the class name is in effect' do
|
638
|
-
lambda { @flog.in_method('name') }.must_raise(LocalJumpError)
|
639
|
-
end
|
640
|
-
|
641
|
-
it 'should recursively analyze the provided code block' do
|
642
|
-
@flog.in_method 'name' do
|
643
|
-
@foo = true
|
644
|
-
end
|
645
|
-
|
646
|
-
@foo.must_equal true
|
647
|
-
end
|
648
|
-
|
649
|
-
it 'should update the class stack when recursing' do
|
650
|
-
@flog.method_stack.clear
|
651
|
-
@flog.in_method 'name' do
|
652
|
-
@flog.method_stack.must_equal ['name']
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
it 'when it is done it should restore the class stack to its original value' do
|
657
|
-
@flog.method_stack.clear
|
658
|
-
@flog.in_method 'name' do
|
659
|
-
end
|
660
|
-
@flog.method_stack.must_equal []
|
661
|
-
end
|
662
|
-
end
|
663
|
-
|
664
|
-
describe 'when looking up the name of the method currently under analysis' do
|
665
|
-
it 'should not take any arguments' do
|
666
|
-
lambda { @flog.method_name('foo') }.must_raise(ArgumentError)
|
667
|
-
end
|
668
|
-
|
669
|
-
it 'should return the most recent method entered' do
|
670
|
-
@flog.method_stack << :foo << :bar << :baz
|
671
|
-
@flog.method_name.must_equal :foo
|
672
|
-
end
|
673
|
-
|
674
|
-
it 'should return the default method if no methods entered' do
|
675
|
-
@flog.method_stack.clear
|
676
|
-
@flog.method_name.must_equal :none
|
677
|
-
end
|
678
|
-
end
|
679
|
-
|
680
|
-
describe 'when resetting state' do
|
681
|
-
it 'should not take any arguments' do
|
682
|
-
lambda { @flog.reset('foo') }.must_raise(ArgumentError)
|
683
|
-
end
|
684
|
-
|
685
|
-
it 'should clear any recorded totals data' do
|
686
|
-
@flog.totals['foo'] = 'bar'
|
687
|
-
@flog.reset
|
688
|
-
@flog.totals.must_equal({})
|
689
|
-
end
|
690
|
-
|
691
|
-
it 'should clear the total score' do
|
692
|
-
# the only way I know to do this is to force the total score to be computed for actual code, then reset it
|
693
|
-
@flog.flog_files(fixture_files('/simple/simple.rb'))
|
694
|
-
@flog.reset
|
695
|
-
@flog.total.must_equal 0
|
696
|
-
end
|
697
|
-
|
698
|
-
it 'should set the multiplier to 1.0' do
|
699
|
-
@flog.multiplier = 20.0
|
700
|
-
@flog.reset
|
701
|
-
@flog.multiplier.must_equal 1.0
|
702
|
-
end
|
703
|
-
|
704
|
-
it 'should set clear any calls data' do
|
705
|
-
@flog.calls['foobar'] = 'yoda'
|
706
|
-
@flog.reset
|
707
|
-
@flog.calls.must_equal({})
|
708
|
-
end
|
709
|
-
|
710
|
-
it 'should ensure that new recorded calls will get 0 counts without explicit initialization' do
|
711
|
-
@flog.reset
|
712
|
-
@flog.calls['foobar']['baz'] += 20
|
713
|
-
@flog.calls['foobar']['baz'].must_equal 20
|
714
|
-
end
|
715
|
-
end
|
716
|
-
|
717
|
-
describe 'when retrieving the total score' do
|
718
|
-
it 'should take no arguments' do
|
719
|
-
lambda { @flog.total('foo') }.must_raise(ArgumentError)
|
720
|
-
end
|
721
|
-
|
722
|
-
it 'should return 0 if nothing has been analyzed' do
|
723
|
-
@flog.total.must_equal 0
|
724
|
-
end
|
725
|
-
|
726
|
-
it 'should compute totals data when called the first time' do
|
727
|
-
@flog.expects(:totals)
|
728
|
-
@flog.total
|
729
|
-
end
|
730
|
-
|
731
|
-
it 'should not recompute totals data when called after the first time' do
|
732
|
-
@flog.total
|
733
|
-
def @flog.totals(*args); raise "no"; end
|
734
|
-
@flog.total
|
735
|
-
end
|
736
|
-
|
737
|
-
it 'should return the score from the analysis once files have been analyzed' do
|
738
|
-
@flog.flog_files(fixture_files('/simple/simple.rb'))
|
739
|
-
@flog.total.wont_equal 0
|
740
|
-
end
|
741
|
-
end
|
742
|
-
|
743
|
-
describe 'when computing a score for a method' do
|
744
|
-
it 'should require a hash of call tallies' do
|
745
|
-
lambda { @flog.score_method }.must_raise(ArgumentError)
|
746
|
-
end
|
747
|
-
|
748
|
-
it 'should return a score of 0 if no tallies are provided' do
|
749
|
-
@flog.score_method({}).must_equal 0.0
|
750
|
-
end
|
751
|
-
|
752
|
-
it 'should compute the sqrt of summed squares for assignments, branches, and other tallies' do
|
753
|
-
@flog.score_method({
|
754
|
-
:assignment => 7,
|
755
|
-
:branch => 23,
|
756
|
-
:crap => 37
|
757
|
-
}).must_be_close_to Math.sqrt(7*7 + 23*23 + 37*37)
|
758
|
-
end
|
759
|
-
end
|
760
|
-
|
761
|
-
describe 'when recording a total for a method' do
|
762
|
-
# guess what, @totals and @calls could be refactored to be first-class objects
|
763
|
-
it 'should require a method and a score' do
|
764
|
-
lambda { @flog.record_method_score('foo') }.must_raise(ArgumentError)
|
765
|
-
end
|
766
|
-
|
767
|
-
it 'should set the total score for the provided method' do
|
768
|
-
@flog.record_method_score('foo', 20)
|
769
|
-
@flog.totals['foo'].must_equal 20
|
770
|
-
end
|
771
|
-
end
|
772
|
-
|
773
|
-
describe 'when updating the total flog score' do
|
774
|
-
it 'should require an amount to update by' do
|
775
|
-
lambda { @flog.increment_total_score_by }.must_raise(ArgumentError)
|
776
|
-
end
|
777
|
-
|
778
|
-
it 'should update the total flog score' do
|
779
|
-
@flog.total_score = 0
|
780
|
-
@flog.increment_total_score_by 42
|
781
|
-
@flog.total.must_equal 42
|
782
|
-
end
|
783
|
-
end
|
784
|
-
|
785
|
-
describe 'when compiling summaries for a method' do
|
786
|
-
before :each do
|
787
|
-
@tally = { :foo => 0.0 }
|
788
|
-
@method = 'foo'
|
789
|
-
$score = @score = 42.0
|
790
|
-
|
791
|
-
@flog.total_score = 0
|
792
|
-
|
793
|
-
def @flog.score_method(*args); return $score; end
|
794
|
-
def @flog.record_method_score(*args); end
|
795
|
-
def @flog.increment_total_score_by(*args); end
|
796
|
-
end
|
797
|
-
|
798
|
-
it 'should require a method name and a tally' do
|
799
|
-
lambda { @flog.summarize_method('foo') }.must_raise(ArgumentError)
|
800
|
-
end
|
801
|
-
|
802
|
-
it 'should compute a score for the method, based on the tally' do
|
803
|
-
@flog.expects(:score_method).with(@tally)
|
804
|
-
@flog.summarize_method(@method, @tally)
|
805
|
-
end
|
806
|
-
|
807
|
-
it 'should record the score for the method' do
|
808
|
-
@flog.expects(:record_method_score).with(@method, @score)
|
809
|
-
@flog.summarize_method(@method, @tally)
|
810
|
-
end
|
811
|
-
|
812
|
-
it 'should update the overall flog score' do
|
813
|
-
@flog.expects(:increment_total_score_by).with(@score)
|
814
|
-
@flog.summarize_method(@method, @tally)
|
815
|
-
end
|
816
|
-
|
817
|
-
# HACK: I don't see how these ever worked if the above passes... *shrug*
|
818
|
-
# describe 'ignoring non-method code and given a non-method tally' do
|
819
|
-
# it 'should not compute a score for the tally' do
|
820
|
-
# def @flog.score_method(*args); raise "no"; end
|
821
|
-
# @flog.summarize_method(@method, @tally)
|
613
|
+
#
|
614
|
+
# # describe 'when processing a ruby parse tree' do
|
615
|
+
# # before :each do
|
616
|
+
# # @flog.stubs(:process)
|
617
|
+
# # @sexp = stub('s-expressions')
|
618
|
+
# # @parse_tree = stub('parse tree', :parse_tree_for_string => @sexp)
|
619
|
+
# # ParseTree.stubs(:new).returns(@parse_tree)
|
620
|
+
# # end
|
621
|
+
# #
|
622
|
+
# # it 'should require both a ruby string and a filename' do
|
623
|
+
# # lambda { @flog.process_parse_tree('string') }.must_raise(ArgumentError)
|
624
|
+
# # end
|
625
|
+
# #
|
626
|
+
# # it 'should compute the parse tree for the ruby string' do
|
627
|
+
# # Sexp.stubs(:from_array).returns(['1', '2'])
|
628
|
+
# # @parse_tree.expects(:parse_tree_for_string).returns(@sexp)
|
629
|
+
# # @flog.process_parse_tree('string', 'file')
|
630
|
+
# # end
|
631
|
+
# #
|
632
|
+
# # it 'should use both the ruby string and the filename when computing the parse tree' do
|
633
|
+
# # Sexp.stubs(:from_array).returns(['1', '2'])
|
634
|
+
# # @parse_tree.expects(:parse_tree_for_string).with('string', 'file').returns(@sexp)
|
635
|
+
# # @flog.process_parse_tree('string', 'file')
|
636
|
+
# # end
|
637
|
+
# #
|
638
|
+
# # describe 'if the ruby string is valid' do
|
639
|
+
# # before :each do
|
640
|
+
# # $pt = @parse_tree = stub('parse tree', :parse_tree_for_string => @sexp)
|
641
|
+
# # def @flog.process; end
|
642
|
+
# # def @flog.parse_tree; return $pt; end
|
643
|
+
# # end
|
644
|
+
# #
|
645
|
+
# # it 'should convert the parse tree into a list of S-expressions' do
|
646
|
+
# # Sexp.expects(:from_array).with(@sexp).returns(['1', '2'])
|
647
|
+
# # @flog.process_parse_tree('string', 'file')
|
648
|
+
# # end
|
649
|
+
# #
|
650
|
+
# # it 'should process the list of S-expressions' do
|
651
|
+
# # @flog.expects(:process)
|
652
|
+
# # @flog.process_parse_tree('string', 'file')
|
653
|
+
# # end
|
654
|
+
# #
|
655
|
+
# # it 'should start processing at the first S-expression' do
|
656
|
+
# # Sexp.stubs(:from_array).returns(['1', '2'])
|
657
|
+
# # @flog.expects(:process).with('1')
|
658
|
+
# # @flog.process_parse_tree('string', 'file')
|
659
|
+
# # end
|
660
|
+
# # end
|
661
|
+
# #
|
662
|
+
# # describe 'if the ruby string is invalid' do
|
663
|
+
# # before :each do
|
664
|
+
# # $parse_tree = stub('parse tree')
|
665
|
+
# # def @flog.parse_tree; return $parse_tree; end
|
666
|
+
# # def $parse_tree.parse_tree_for_string(*args); raise SyntaxError; end
|
667
|
+
# # end
|
668
|
+
# #
|
669
|
+
# # it 'should fail' do
|
670
|
+
# # lambda { @flog.process_parse_tree('string', 'file') }.must_raise(SyntaxError)
|
671
|
+
# # end
|
672
|
+
# #
|
673
|
+
# # it 'should not attempt to process the parse tree' do
|
674
|
+
# # def @flog.process(*args); raise "no"; end
|
675
|
+
# # lambda { @flog.process_parse_tree('string', 'file') }
|
676
|
+
# # end
|
677
|
+
# # end
|
678
|
+
# # end
|
679
|
+
#
|
680
|
+
# describe 'when collecting blame information from a file' do
|
681
|
+
# it 'should require a filename' do
|
682
|
+
# lambda { @flog.collect_blame }.must_raise(ArgumentError)
|
683
|
+
# end
|
684
|
+
#
|
685
|
+
# it 'should not fail when given a filename' do
|
686
|
+
# @flog.collect_blame('filename')
|
687
|
+
# end
|
688
|
+
#
|
689
|
+
# # TODO: talk to Rick and see what he was planning for
|
690
|
+
# # this... otherwise I'm thinking it should be ripped out
|
691
|
+
#
|
692
|
+
# # it 'should have more specs'
|
693
|
+
# end
|
694
|
+
#
|
695
|
+
# describe 'multiplier' do
|
696
|
+
# it 'should be possible to determine the current value of the multiplier' do
|
697
|
+
# @flog.must_respond_to(:multiplier)
|
698
|
+
# end
|
699
|
+
#
|
700
|
+
# currently 'should be possible to set the current value of the multiplier' do
|
701
|
+
# @flog.multiplier = 10
|
702
|
+
# @flog.multiplier.must_equal 10
|
703
|
+
# end
|
704
|
+
# end
|
705
|
+
#
|
706
|
+
# describe 'class_stack' do
|
707
|
+
# it 'should be possible to determine the current value of the class stack' do
|
708
|
+
# @flog.must_respond_to(:class_stack)
|
709
|
+
# end
|
710
|
+
#
|
711
|
+
# currently 'should be possible to set the current value of the class stack' do
|
712
|
+
# @flog.class_stack << 'name'
|
713
|
+
# @flog.class_stack.must_equal [ 'name' ]
|
714
|
+
# end
|
715
|
+
# end
|
716
|
+
#
|
717
|
+
# describe 'method_stack' do
|
718
|
+
# it 'should be possible to determine the current value of the method stack' do
|
719
|
+
# @flog.must_respond_to(:method_stack)
|
720
|
+
# end
|
721
|
+
#
|
722
|
+
# currently 'should be possible to set the current value of the method stack' do
|
723
|
+
# @flog.method_stack << 'name'
|
724
|
+
# @flog.method_stack.must_equal [ 'name' ]
|
725
|
+
# end
|
726
|
+
# end
|
727
|
+
#
|
728
|
+
# describe 'when adding to the current flog score' do
|
729
|
+
# before :each do
|
730
|
+
# @flog.multiplier = 1
|
731
|
+
# def @flog.klass_name; return 'foo'; end
|
732
|
+
# def @flog.method_name; return 'bar'; end
|
733
|
+
# @flog.calls['foo#bar'] = { :alias => 0 }
|
734
|
+
# end
|
735
|
+
#
|
736
|
+
# it 'should require an operation name' do
|
737
|
+
# lambda { @flog.add_to_score() }.must_raise(ArgumentError)
|
738
|
+
# end
|
739
|
+
#
|
740
|
+
# it 'should update the score for the current class, method, and operation' do
|
741
|
+
# @flog.add_to_score(:alias)
|
742
|
+
# @flog.calls['foo#bar'][:alias].wont_equal 0
|
743
|
+
# end
|
744
|
+
#
|
745
|
+
# it 'should use the multiplier when updating the current call score' do
|
746
|
+
# @flog.multiplier = 10
|
747
|
+
# @flog.add_to_score(:alias)
|
748
|
+
# @flog.calls['foo#bar'][:alias].must_equal 10*Flog::OTHER_SCORES[:alias]
|
749
|
+
# end
|
750
|
+
# end
|
751
|
+
#
|
752
|
+
# describe 'when computing the average per-call flog score' do
|
753
|
+
# it 'should not allow arguments' do
|
754
|
+
# lambda { @flog.average('foo') }.must_raise(ArgumentError)
|
755
|
+
# end
|
756
|
+
#
|
757
|
+
# it 'should return the total flog score divided by the number of calls' do
|
758
|
+
# def @flog.total; return 100; end
|
759
|
+
# def @flog.calls; return :bar => {}, :foo => {} ; end
|
760
|
+
# @flog.average.must_be_close_to 50.0
|
761
|
+
# end
|
762
|
+
# end
|
763
|
+
#
|
764
|
+
# describe 'when recursively analyzing the complexity of code' do
|
765
|
+
# it 'should require a complexity modifier value' do
|
766
|
+
# lambda { @flog.penalize_by }.must_raise(ArgumentError)
|
767
|
+
# end
|
768
|
+
#
|
769
|
+
# it 'should require a block, for code to recursively analyze' do
|
770
|
+
# lambda { @flog.penalize_by(42) }.must_raise(LocalJumpError)
|
771
|
+
# end
|
772
|
+
#
|
773
|
+
# it 'should recursively analyze the provided code block' do
|
774
|
+
# @flog.penalize_by(42) do
|
775
|
+
# @foo = true
|
822
776
|
# end
|
823
777
|
#
|
824
|
-
#
|
825
|
-
#
|
826
|
-
#
|
827
|
-
#
|
778
|
+
# @foo.must_equal true
|
779
|
+
# end
|
780
|
+
#
|
781
|
+
# it 'should update the complexity multiplier when recursing' do
|
782
|
+
# @flog.multiplier = 1
|
783
|
+
# @flog.penalize_by(42) do
|
784
|
+
# @flog.multiplier.must_equal 43
|
785
|
+
# end
|
786
|
+
# end
|
787
|
+
#
|
788
|
+
# it 'when it is done it should restore the complexity multiplier to its original value' do
|
789
|
+
# @flog.multiplier = 1
|
790
|
+
# @flog.penalize_by(42) do
|
791
|
+
# end
|
792
|
+
# @flog.multiplier.must_equal 1
|
793
|
+
# end
|
794
|
+
# end
|
795
|
+
#
|
796
|
+
# describe 'when computing complexity of all remaining opcodes' do
|
797
|
+
# it 'should require a list of opcodes' do
|
798
|
+
# lambda { @flog.analyze_list }.must_raise(ArgumentError)
|
799
|
+
# end
|
800
|
+
#
|
801
|
+
# # HACK: nope. this is just poorly written.
|
802
|
+
# # it 'should process each opcode' do
|
803
|
+
# # @opcodes = [ :foo, :bar, :baz ]
|
804
|
+
# # @opcodes.each do |opcode|
|
805
|
+
# # @flog.expects(:process).with(opcode)
|
806
|
+
# # end
|
807
|
+
# #
|
808
|
+
# # @flog.analyze_list @opcodes
|
809
|
+
# # end
|
810
|
+
# end
|
811
|
+
#
|
812
|
+
# describe 'when recording the current class being analyzed' do
|
813
|
+
# it 'should require a class name' do
|
814
|
+
# lambda { @flog.in_klass }.must_raise(ArgumentError)
|
815
|
+
# end
|
816
|
+
#
|
817
|
+
# it 'should require a block during which the class name is in effect' do
|
818
|
+
# lambda { @flog.in_klass('name') }.must_raise(LocalJumpError)
|
819
|
+
# end
|
820
|
+
#
|
821
|
+
# it 'should recursively analyze the provided code block' do
|
822
|
+
# @flog.in_klass 'name' do
|
823
|
+
# @foo = true
|
824
|
+
# end
|
825
|
+
#
|
826
|
+
# @foo.must_equal true
|
827
|
+
# end
|
828
|
+
#
|
829
|
+
# it 'should update the class stack when recursing' do
|
830
|
+
# @flog.class_stack.clear
|
831
|
+
# @flog.in_klass 'name' do
|
832
|
+
# @flog.class_stack.must_equal ['name']
|
833
|
+
# end
|
834
|
+
# end
|
835
|
+
#
|
836
|
+
# it 'when it is done it should restore the class stack to its original value' do
|
837
|
+
# @flog.class_stack.clear
|
838
|
+
# @flog.in_klass 'name' do
|
839
|
+
# end
|
840
|
+
# @flog.class_stack.must_equal []
|
841
|
+
# end
|
842
|
+
# end
|
843
|
+
#
|
844
|
+
# describe 'when looking up the name of the class currently under analysis' do
|
845
|
+
# it 'should not take any arguments' do
|
846
|
+
# lambda { @flog.klass_name('foo') }.must_raise(ArgumentError)
|
847
|
+
# end
|
848
|
+
#
|
849
|
+
# it 'should return the most recent class entered' do
|
850
|
+
# @flog.class_stack << :foo << :bar << :baz
|
851
|
+
# @flog.klass_name.must_equal :foo
|
852
|
+
# end
|
853
|
+
#
|
854
|
+
# it 'should return the default class if no classes entered' do
|
855
|
+
# @flog.class_stack.clear
|
856
|
+
# @flog.klass_name.must_equal :main
|
857
|
+
# end
|
858
|
+
# end
|
859
|
+
#
|
860
|
+
# describe 'when recording the current method being analyzed' do
|
861
|
+
# it 'should require a method name' do
|
862
|
+
# lambda { @flog.in_method }.must_raise(ArgumentError)
|
863
|
+
# end
|
864
|
+
#
|
865
|
+
# it 'should require a block during which the class name is in effect' do
|
866
|
+
# lambda { @flog.in_method('name') }.must_raise(LocalJumpError)
|
867
|
+
# end
|
868
|
+
#
|
869
|
+
# it 'should recursively analyze the provided code block' do
|
870
|
+
# @flog.in_method 'name' do
|
871
|
+
# @foo = true
|
872
|
+
# end
|
873
|
+
#
|
874
|
+
# @foo.must_equal true
|
875
|
+
# end
|
876
|
+
#
|
877
|
+
# it 'should update the class stack when recursing' do
|
878
|
+
# @flog.method_stack.clear
|
879
|
+
# @flog.in_method 'name' do
|
880
|
+
# @flog.method_stack.must_equal ['name']
|
881
|
+
# end
|
882
|
+
# end
|
883
|
+
#
|
884
|
+
# it 'when it is done it should restore the class stack to its original value' do
|
885
|
+
# @flog.method_stack.clear
|
886
|
+
# @flog.in_method 'name' do
|
887
|
+
# end
|
888
|
+
# @flog.method_stack.must_equal []
|
889
|
+
# end
|
890
|
+
# end
|
891
|
+
#
|
892
|
+
# describe 'when looking up the name of the method currently under analysis' do
|
893
|
+
# it 'should not take any arguments' do
|
894
|
+
# lambda { @flog.method_name('foo') }.must_raise(ArgumentError)
|
895
|
+
# end
|
896
|
+
#
|
897
|
+
# it 'should return the most recent method entered' do
|
898
|
+
# @flog.method_stack << :foo << :bar << :baz
|
899
|
+
# @flog.method_name.must_equal :foo
|
900
|
+
# end
|
901
|
+
#
|
902
|
+
# it 'should return the default method if no methods entered' do
|
903
|
+
# @flog.method_stack.clear
|
904
|
+
# @flog.method_name.must_equal :none
|
905
|
+
# end
|
906
|
+
# end
|
907
|
+
#
|
908
|
+
# describe 'when resetting state' do
|
909
|
+
# it 'should not take any arguments' do
|
910
|
+
# lambda { @flog.reset('foo') }.must_raise(ArgumentError)
|
911
|
+
# end
|
912
|
+
#
|
913
|
+
# it 'should clear any recorded totals data' do
|
914
|
+
# @flog.totals['foo'] = 'bar'
|
915
|
+
# @flog.reset
|
916
|
+
# @flog.totals.must_equal({})
|
917
|
+
# end
|
918
|
+
#
|
919
|
+
# it 'should clear the total score' do
|
920
|
+
# # the only way I know to do this is to force the total score to be computed for actual code, then reset it
|
921
|
+
# @flog.flog_files(fixture_files('/simple/simple.rb'))
|
922
|
+
# @flog.reset
|
923
|
+
# @flog.total.must_equal 0
|
924
|
+
# end
|
925
|
+
#
|
926
|
+
# it 'should set the multiplier to 1.0' do
|
927
|
+
# @flog.multiplier = 20.0
|
928
|
+
# @flog.reset
|
929
|
+
# @flog.multiplier.must_equal 1.0
|
930
|
+
# end
|
931
|
+
#
|
932
|
+
# it 'should set clear any calls data' do
|
933
|
+
# @flog.calls['foobar'] = 'yoda'
|
934
|
+
# @flog.reset
|
935
|
+
# @flog.calls.must_equal({})
|
936
|
+
# end
|
937
|
+
#
|
938
|
+
# it 'should ensure that new recorded calls will get 0 counts without explicit initialization' do
|
939
|
+
# @flog.reset
|
940
|
+
# @flog.calls['foobar']['baz'] += 20
|
941
|
+
# @flog.calls['foobar']['baz'].must_equal 20
|
942
|
+
# end
|
943
|
+
# end
|
944
|
+
#
|
945
|
+
# describe 'when retrieving the total score' do
|
946
|
+
# it 'should take no arguments' do
|
947
|
+
# lambda { @flog.total('foo') }.must_raise(ArgumentError)
|
948
|
+
# end
|
949
|
+
#
|
950
|
+
# it 'should return 0 if nothing has been analyzed' do
|
951
|
+
# @flog.total.must_equal 0
|
952
|
+
# end
|
953
|
+
#
|
954
|
+
# it 'should compute totals data when called the first time' do
|
955
|
+
# @flog.expects(:totals)
|
956
|
+
# @flog.total
|
957
|
+
# end
|
958
|
+
#
|
959
|
+
# it 'should not recompute totals data when called after the first time' do
|
960
|
+
# @flog.total
|
961
|
+
# def @flog.totals(*args); raise "no"; end
|
962
|
+
# @flog.total
|
963
|
+
# end
|
964
|
+
#
|
965
|
+
# it 'should return the score from the analysis once files have been analyzed' do
|
966
|
+
# @flog.flog_files(fixture_files('/simple/simple.rb'))
|
967
|
+
# @flog.total.wont_equal 0
|
968
|
+
# end
|
969
|
+
# end
|
970
|
+
#
|
971
|
+
# describe 'when computing a score for a method' do
|
972
|
+
# it 'should require a hash of call tallies' do
|
973
|
+
# lambda { @flog.score_method }.must_raise(ArgumentError)
|
974
|
+
# end
|
975
|
+
#
|
976
|
+
# it 'should return a score of 0 if no tallies are provided' do
|
977
|
+
# @flog.score_method({}).must_equal 0.0
|
978
|
+
# end
|
979
|
+
#
|
980
|
+
# it 'should compute the sqrt of summed squares for assignments, branches, and other tallies' do
|
981
|
+
# @flog.score_method({
|
982
|
+
# :assignment => 7,
|
983
|
+
# :branch => 23,
|
984
|
+
# :crap => 37
|
985
|
+
# }).must_be_close_to Math.sqrt(7*7 + 23*23 + 37*37)
|
986
|
+
# end
|
987
|
+
# end
|
988
|
+
#
|
989
|
+
# describe 'when recording a total for a method' do
|
990
|
+
# # guess what, @totals and @calls could be refactored to be first-class objects
|
991
|
+
# it 'should require a method and a score' do
|
992
|
+
# lambda { @flog.record_method_score('foo') }.must_raise(ArgumentError)
|
993
|
+
# end
|
994
|
+
#
|
995
|
+
# it 'should set the total score for the provided method' do
|
996
|
+
# @flog.record_method_score('foo', 20)
|
997
|
+
# @flog.totals['foo'].must_equal 20
|
998
|
+
# end
|
999
|
+
# end
|
1000
|
+
#
|
1001
|
+
# describe 'when updating the total flog score' do
|
1002
|
+
# it 'should require an amount to update by' do
|
1003
|
+
# lambda { @flog.increment_total_score_by }.must_raise(ArgumentError)
|
1004
|
+
# end
|
1005
|
+
#
|
1006
|
+
# it 'should update the total flog score' do
|
1007
|
+
# @flog.total_score = 0
|
1008
|
+
# @flog.increment_total_score_by 42
|
1009
|
+
# @flog.total.must_equal 42
|
1010
|
+
# end
|
1011
|
+
# end
|
1012
|
+
#
|
1013
|
+
# describe 'when compiling summaries for a method' do
|
1014
|
+
# before :each do
|
1015
|
+
# @tally = { :foo => 0.0 }
|
1016
|
+
# @method = 'foo'
|
1017
|
+
# $score = @score = 42.0
|
1018
|
+
#
|
1019
|
+
# @flog.total_score = 0
|
1020
|
+
#
|
1021
|
+
# def @flog.score_method(*args); return $score; end
|
1022
|
+
# def @flog.record_method_score(*args); end
|
1023
|
+
# def @flog.increment_total_score_by(*args); end
|
1024
|
+
# end
|
1025
|
+
#
|
1026
|
+
# it 'should require a method name and a tally' do
|
1027
|
+
# lambda { @flog.summarize_method('foo') }.must_raise(ArgumentError)
|
1028
|
+
# end
|
1029
|
+
#
|
1030
|
+
# it 'should compute a score for the method, based on the tally' do
|
1031
|
+
# @flog.expects(:score_method).with(@tally)
|
1032
|
+
# @flog.summarize_method(@method, @tally)
|
1033
|
+
# end
|
1034
|
+
#
|
1035
|
+
# it 'should record the score for the method' do
|
1036
|
+
# @flog.expects(:record_method_score).with(@method, @score)
|
1037
|
+
# @flog.summarize_method(@method, @tally)
|
1038
|
+
# end
|
1039
|
+
#
|
1040
|
+
# it 'should update the overall flog score' do
|
1041
|
+
# @flog.expects(:increment_total_score_by).with(@score)
|
1042
|
+
# @flog.summarize_method(@method, @tally)
|
1043
|
+
# end
|
1044
|
+
#
|
1045
|
+
# # HACK: I don't see how these ever worked if the above passes... *shrug*
|
1046
|
+
# # describe 'ignoring non-method code and given a non-method tally' do
|
1047
|
+
# # it 'should not compute a score for the tally' do
|
1048
|
+
# # def @flog.score_method(*args); raise "no"; end
|
1049
|
+
# # @flog.summarize_method(@method, @tally)
|
1050
|
+
# # end
|
1051
|
+
# #
|
1052
|
+
# # it 'should not record a score based on the tally' do
|
1053
|
+
# # def @flog.record_method_score(*args); raise "no"; end
|
1054
|
+
# # @flog.summarize_method(@method, @tally)
|
1055
|
+
# # end
|
1056
|
+
# #
|
1057
|
+
# # it 'should not update the overall flog score' do
|
1058
|
+
# # def @flog.increment_total_score_by(*args); raise "no"; end
|
1059
|
+
# # @flog.summarize_method(@method, @tally)
|
1060
|
+
# # end
|
1061
|
+
# # end
|
1062
|
+
# end
|
1063
|
+
#
|
1064
|
+
# describe 'when requesting totals' do
|
1065
|
+
# it 'should not accept any arguments' do
|
1066
|
+
# lambda { @flog.totals('foo') }.must_raise(ArgumentError)
|
1067
|
+
# end
|
1068
|
+
#
|
1069
|
+
# describe 'when called the first time' do
|
1070
|
+
# # it 'should access calls data' do
|
1071
|
+
# # @flog.expects(:calls).returns({})
|
1072
|
+
# # @flog.totals
|
1073
|
+
# # end
|
828
1074
|
#
|
829
|
-
# it
|
830
|
-
#
|
831
|
-
# @flog.
|
1075
|
+
# # it "will compile a summary for each method from the method's tally" do
|
1076
|
+
# # $calls = @calls = { :foo => 1.0, :bar => 2.0, :baz => 3.0 }
|
1077
|
+
# # def @flog.calls; return $calls; end
|
1078
|
+
# #
|
1079
|
+
# # @calls.each do |meth, tally|
|
1080
|
+
# # @flog.expects(:summarize_method).with(meth, tally)
|
1081
|
+
# # end
|
1082
|
+
# #
|
1083
|
+
# # @flog.totals
|
1084
|
+
# # end
|
1085
|
+
#
|
1086
|
+
# it 'should return the totals data' do
|
1087
|
+
# @flog.totals.must_equal({})
|
832
1088
|
# end
|
833
1089
|
# end
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
it 'should not accept any arguments' do
|
838
|
-
lambda { @flog.totals('foo') }.must_raise(ArgumentError)
|
839
|
-
end
|
840
|
-
|
841
|
-
describe 'when called the first time' do
|
842
|
-
# it 'should access calls data' do
|
843
|
-
# @flog.expects(:calls).returns({})
|
1090
|
+
#
|
1091
|
+
# describe 'when called after the first time' do
|
1092
|
+
# before :each do
|
844
1093
|
# @flog.totals
|
845
1094
|
# end
|
846
|
-
|
847
|
-
# it "will compile a summary for each method from the method's tally" do
|
848
|
-
# $calls = @calls = { :foo => 1.0, :bar => 2.0, :baz => 3.0 }
|
849
|
-
# def @flog.calls; return $calls; end
|
850
1095
|
#
|
851
|
-
#
|
852
|
-
#
|
853
|
-
#
|
1096
|
+
# it 'should not access calls data' do
|
1097
|
+
# def @flog.calls(*args); raise "no"; end
|
1098
|
+
# @flog.totals
|
1099
|
+
# end
|
854
1100
|
#
|
1101
|
+
# it 'should not compile method summaries' do
|
1102
|
+
# def @flog.summarize_method(*args); raise "no"; end
|
855
1103
|
# @flog.totals
|
856
1104
|
# end
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
end
|
862
|
-
|
863
|
-
describe 'when called after the first time' do
|
864
|
-
before :each do
|
865
|
-
@flog.totals
|
866
|
-
end
|
867
|
-
|
868
|
-
it 'should not access calls data' do
|
869
|
-
def @flog.calls(*args); raise "no"; end
|
870
|
-
@flog.totals
|
871
|
-
end
|
872
|
-
|
873
|
-
it 'should not compile method summaries' do
|
874
|
-
def @flog.summarize_method(*args); raise "no"; end
|
875
|
-
@flog.totals
|
876
|
-
end
|
877
|
-
|
878
|
-
it 'should return the totals data' do
|
879
|
-
@flog.totals.must_equal({})
|
880
|
-
end
|
881
|
-
end
|
882
|
-
end
|
883
|
-
|
884
|
-
describe 'when producing a report summary' do
|
885
|
-
before :each do
|
886
|
-
@handle = stub('io handle)', :puts => nil)
|
887
|
-
@total_score = 42.0
|
888
|
-
@average_score = 1.0
|
889
|
-
def @flog.total; return 42.0; end
|
890
|
-
def @flog.average; return 1.0; end
|
891
|
-
end
|
892
|
-
|
893
|
-
it 'should require an io handle' do
|
894
|
-
lambda { @flog.output_summary }.must_raise(ArgumentError)
|
895
|
-
end
|
896
|
-
|
897
|
-
it 'computes the total flog score' do
|
898
|
-
# HACK @flog.expects(:total).returns 42.0
|
899
|
-
@flog.output_summary(@handle)
|
900
|
-
end
|
901
|
-
|
902
|
-
it 'computes the average flog score' do
|
903
|
-
# HACK @flog.expects(:average).returns 1.0
|
904
|
-
@flog.output_summary(@handle)
|
905
|
-
end
|
906
|
-
|
907
|
-
it 'outputs the total flog score to the handle' do
|
908
|
-
@handle.expects(:puts).with do |string|
|
909
|
-
string =~ Regexp.new(Regexp.escape("%.1f" % @total_score))
|
910
|
-
end
|
911
|
-
@flog.output_summary(@handle)
|
912
|
-
end
|
913
|
-
|
914
|
-
it 'outputs the average flog score to the handle' do
|
915
|
-
@handle.expects(:puts).with do |string|
|
916
|
-
string =~ Regexp.new(Regexp.escape("%.1f" % @average_score))
|
917
|
-
end
|
918
|
-
@flog.output_summary(@handle)
|
919
|
-
end
|
920
|
-
end
|
921
|
-
|
922
|
-
describe 'when producing a detailed call summary report' do
|
923
|
-
before :each do
|
924
|
-
@handle = stub('io handle)', :puts => nil)
|
925
|
-
$calls = @calls = { :foo => {}, :bar => {}, :baz => {} }
|
926
|
-
$totals = @totals = { :foo => 1, :bar => 2, :baz => 3 }
|
927
|
-
|
928
|
-
def @flog.calls; return $calls; end
|
929
|
-
def @flog.totals; return $totals; end
|
930
|
-
def @flog.output_method_details(*args); return 5; end
|
931
|
-
end
|
932
|
-
|
933
|
-
it 'should require an i/o handle' do
|
934
|
-
lambda { @flog.output_details }.must_raise(ArgumentError)
|
935
|
-
end
|
936
|
-
|
937
|
-
it 'should allow a threshold on the amount of detail to report' do
|
938
|
-
lambda { @flog.output_details(@handle, 300) }.wont_raise_error(ArgumentError)
|
939
|
-
end
|
940
|
-
|
941
|
-
# it 'retrieves the set of total statistics' do
|
942
|
-
# @flog.expects(:totals).returns(@totals)
|
943
|
-
# @flog.output_details(@handle)
|
1105
|
+
#
|
1106
|
+
# it 'should return the totals data' do
|
1107
|
+
# @flog.totals.must_equal({})
|
1108
|
+
# end
|
944
1109
|
# end
|
945
|
-
|
946
|
-
#
|
947
|
-
#
|
948
|
-
#
|
1110
|
+
# end
|
1111
|
+
#
|
1112
|
+
# describe 'when producing a report summary' do
|
1113
|
+
# before :each do
|
1114
|
+
# @handle = stub('io handle)', :puts => nil)
|
1115
|
+
# @total_score = 42.0
|
1116
|
+
# @average_score = 1.0
|
1117
|
+
# def @flog.total; return 42.0; end
|
1118
|
+
# def @flog.average; return 1.0; end
|
949
1119
|
# end
|
950
|
-
|
951
|
-
# it 'should
|
952
|
-
# @
|
953
|
-
#
|
1120
|
+
#
|
1121
|
+
# it 'should require an io handle' do
|
1122
|
+
# lambda { @flog.output_summary }.must_raise(ArgumentError)
|
1123
|
+
# end
|
1124
|
+
#
|
1125
|
+
# it 'computes the total flog score' do
|
1126
|
+
# # HACK @flog.expects(:total).returns 42.0
|
1127
|
+
# @flog.output_summary(@handle)
|
1128
|
+
# end
|
1129
|
+
#
|
1130
|
+
# it 'computes the average flog score' do
|
1131
|
+
# # HACK @flog.expects(:average).returns 1.0
|
1132
|
+
# @flog.output_summary(@handle)
|
1133
|
+
# end
|
1134
|
+
#
|
1135
|
+
# it 'outputs the total flog score to the handle' do
|
1136
|
+
# @handle.expects(:puts).with do |string|
|
1137
|
+
# string =~ Regexp.new(Regexp.escape("%.1f" % @total_score))
|
954
1138
|
# end
|
955
|
-
# @flog.
|
1139
|
+
# @flog.output_summary(@handle)
|
956
1140
|
# end
|
957
1141
|
#
|
958
|
-
#
|
959
|
-
#
|
960
|
-
#
|
961
|
-
# @flog.expects(:output_method_details).with(@handle, :bar, {}).returns(5)
|
962
|
-
# # HACK @flog.expects(:output_method_details).with(@handle, :foo, {}).never
|
963
|
-
# @flog.output_details(@handle, 10)
|
1142
|
+
# it 'outputs the average flog score to the handle' do
|
1143
|
+
# @handle.expects(:puts).with do |string|
|
1144
|
+
# string =~ Regexp.new(Regexp.escape("%.1f" % @average_score))
|
964
1145
|
# end
|
1146
|
+
# @flog.output_summary(@handle)
|
965
1147
|
# end
|
966
|
-
|
967
|
-
#
|
968
|
-
#
|
969
|
-
#
|
970
|
-
#
|
1148
|
+
# end
|
1149
|
+
#
|
1150
|
+
# describe 'when producing a detailed call summary report' do
|
1151
|
+
# before :each do
|
1152
|
+
# @handle = stub('io handle)', :puts => nil)
|
1153
|
+
# $calls = @calls = { :foo => {}, :bar => {}, :baz => {} }
|
1154
|
+
# $totals = @totals = { :foo => 1, :bar => 2, :baz => 3 }
|
1155
|
+
#
|
1156
|
+
# def @flog.calls; return $calls; end
|
1157
|
+
# def @flog.totals; return $totals; end
|
1158
|
+
# def @flog.output_method_details(*args); return 5; end
|
1159
|
+
# end
|
1160
|
+
#
|
1161
|
+
# it 'should require an i/o handle' do
|
1162
|
+
# lambda { @flog.output_details }.must_raise(ArgumentError)
|
1163
|
+
# end
|
1164
|
+
#
|
1165
|
+
# it 'should allow a threshold on the amount of detail to report' do
|
1166
|
+
# lambda { @flog.output_details(@handle, 300) }.wont_raise_error(ArgumentError)
|
1167
|
+
# end
|
1168
|
+
#
|
1169
|
+
# # it 'retrieves the set of total statistics' do
|
1170
|
+
# # @flog.expects(:totals).returns(@totals)
|
1171
|
+
# # @flog.output_details(@handle)
|
1172
|
+
# # end
|
1173
|
+
#
|
1174
|
+
# # it 'retrieves the set of call statistics' do
|
1175
|
+
# # @flog.expects(:calls).returns({})
|
1176
|
+
# # @flog.output_details(@handle)
|
1177
|
+
# # end
|
1178
|
+
#
|
1179
|
+
# # it 'should output a method summary for each located method' do
|
1180
|
+
# # @calls.each do |meth, list|
|
1181
|
+
# # @flog.expects(:output_method_details).with(@handle, meth, list).returns(5)
|
1182
|
+
# # end
|
1183
|
+
# # @flog.output_details(@handle)
|
1184
|
+
# # end
|
1185
|
+
# #
|
1186
|
+
# # describe 'if a threshold is provided' do
|
1187
|
+
# # it 'should only output details for methods until the threshold is reached' do
|
1188
|
+
# # @flog.expects(:output_method_details).with(@handle, :baz, {}).returns(5)
|
1189
|
+
# # @flog.expects(:output_method_details).with(@handle, :bar, {}).returns(5)
|
1190
|
+
# # # HACK @flog.expects(:output_method_details).with(@handle, :foo, {}).never
|
1191
|
+
# # @flog.output_details(@handle, 10)
|
1192
|
+
# # end
|
1193
|
+
# # end
|
1194
|
+
#
|
1195
|
+
# # describe 'if no threshold is provided' do
|
1196
|
+
# # it 'should output details for all methods' do
|
1197
|
+
# # @calls.each do |class_method, call_list|
|
1198
|
+
# # @flog.expects(:output_method_details).with(@handle, class_method, call_list).returns(5)
|
1199
|
+
# # end
|
1200
|
+
# # @flog.output_details(@handle)
|
1201
|
+
# # end
|
1202
|
+
# # end
|
1203
|
+
# end
|
1204
|
+
#
|
1205
|
+
# describe 'when reporting the details for a specific method' do
|
1206
|
+
# before :each do
|
1207
|
+
# @handle = stub('i/o handle', :puts => nil)
|
1208
|
+
# $totals = { 'foo#foo' => 42.0, 'foo#none' => 12.0 }
|
1209
|
+
# @data = { :assign => 10, :branch => 5, :case => 3 }
|
1210
|
+
# def @flog.totals; return $totals; end
|
1211
|
+
# end
|
1212
|
+
#
|
1213
|
+
# it 'should require an i/o handle, a method name, and method details' do
|
1214
|
+
# lambda { @flog.output_method_details('foo', 'bar') }.must_raise(ArgumentError)
|
1215
|
+
# end
|
1216
|
+
#
|
1217
|
+
# describe 'and ignoring non-method code' do
|
1218
|
+
# before :each do
|
1219
|
+
# @flog = Flog.new(:methods => true)
|
1220
|
+
# def @flog.totals; return $totals; end
|
1221
|
+
# end
|
1222
|
+
#
|
1223
|
+
# describe 'and given non-method data to summarize' do
|
1224
|
+
# it 'should not generate any output on the i/o handle' do
|
1225
|
+
# def @handle.puts(*args); raise "no"; end
|
1226
|
+
# @flog.output_method_details(@handle, 'foo#none', @data)
|
1227
|
+
# end
|
1228
|
+
#
|
1229
|
+
# it 'should return 0' do
|
1230
|
+
# @flog.output_method_details(@handle, 'foo#none', @data).must_equal 0.0
|
1231
|
+
# end
|
1232
|
+
# end
|
1233
|
+
#
|
1234
|
+
# describe 'and given method data to summarize' do
|
1235
|
+
# it 'should return the total complexity for the method' do
|
1236
|
+
# @flog.output_method_details(@handle, 'foo#foo', @data).must_equal 42.0
|
1237
|
+
# end
|
1238
|
+
#
|
1239
|
+
# it 'should output the overall total for the method' do
|
1240
|
+
# @handle.expects(:puts).with do |string|
|
1241
|
+
# string =~ Regexp.new(Regexp.escape("%.1f" % 42.0))
|
1242
|
+
# end
|
1243
|
+
# @flog.output_method_details(@handle, 'foo#foo', @data)
|
1244
|
+
# end
|
1245
|
+
#
|
1246
|
+
# it 'should output call details for each call for the method' do
|
1247
|
+
# @data.each do |call, count|
|
1248
|
+
# @handle.expects(:puts).with do |string|
|
1249
|
+
# string =~ Regexp.new(Regexp.escape("%6.1f: %s" % [ count, call ]))
|
1250
|
+
# end
|
1251
|
+
# end
|
1252
|
+
# @flog.output_method_details(@handle, 'foo#foo', @data)
|
971
1253
|
# end
|
972
|
-
# @flog.output_details(@handle)
|
973
1254
|
# end
|
974
1255
|
# end
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
it 'should not generate any output on the i/o handle' do
|
997
|
-
def @handle.puts(*args); raise "no"; end
|
998
|
-
@flog.output_method_details(@handle, 'foo#none', @data)
|
999
|
-
end
|
1000
|
-
|
1001
|
-
it 'should return 0' do
|
1002
|
-
@flog.output_method_details(@handle, 'foo#none', @data).must_equal 0.0
|
1003
|
-
end
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
describe 'and given method data to summarize' do
|
1007
|
-
it 'should return the total complexity for the method' do
|
1008
|
-
@flog.output_method_details(@handle, 'foo#foo', @data).must_equal 42.0
|
1009
|
-
end
|
1010
|
-
|
1011
|
-
it 'should output the overall total for the method' do
|
1012
|
-
@handle.expects(:puts).with do |string|
|
1013
|
-
string =~ Regexp.new(Regexp.escape("%.1f" % 42.0))
|
1014
|
-
end
|
1015
|
-
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1016
|
-
end
|
1017
|
-
|
1018
|
-
it 'should output call details for each call for the method' do
|
1019
|
-
@data.each do |call, count|
|
1020
|
-
@handle.expects(:puts).with do |string|
|
1021
|
-
string =~ Regexp.new(Regexp.escape("%6.1f: %s" % [ count, call ]))
|
1022
|
-
end
|
1023
|
-
end
|
1024
|
-
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1025
|
-
end
|
1026
|
-
end
|
1027
|
-
end
|
1028
|
-
|
1029
|
-
describe 'and not excluding non-method code' do
|
1030
|
-
it 'should return the total complexity for the method' do
|
1031
|
-
@flog.output_method_details(@handle, 'foo#foo', @data).must_equal 42.0
|
1032
|
-
end
|
1033
|
-
|
1034
|
-
it 'should output the overall total for the method' do
|
1035
|
-
@handle.expects(:puts).with do |string|
|
1036
|
-
string =~ Regexp.new(Regexp.escape("%.1f" % 42.0))
|
1037
|
-
end
|
1038
|
-
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
it 'should output call details for each call for the method' do
|
1042
|
-
@data.each do |call, count|
|
1043
|
-
@handle.expects(:puts).with do |string|
|
1044
|
-
string =~ Regexp.new(Regexp.escape("%6.1f: %s" % [ count, call ]))
|
1045
|
-
end
|
1046
|
-
end
|
1047
|
-
@flog.output_method_details(@handle, 'foo#foo', @data)
|
1048
|
-
end
|
1049
|
-
end
|
1050
|
-
end
|
1051
|
-
|
1052
|
-
describe 'when generating a report' do
|
1053
|
-
before :each do
|
1054
|
-
@flog.stubs(:output_summary)
|
1055
|
-
@handle = stub('io handle)', :puts => nil)
|
1056
|
-
end
|
1057
|
-
|
1058
|
-
# it 'allows specifying an i/o handle' do
|
1059
|
-
# lambda { @flog.report @handle }.wont_raise_error(ArgumentError)
|
1256
|
+
#
|
1257
|
+
# describe 'and not excluding non-method code' do
|
1258
|
+
# it 'should return the total complexity for the method' do
|
1259
|
+
# @flog.output_method_details(@handle, 'foo#foo', @data).must_equal 42.0
|
1260
|
+
# end
|
1261
|
+
#
|
1262
|
+
# it 'should output the overall total for the method' do
|
1263
|
+
# @handle.expects(:puts).with do |string|
|
1264
|
+
# string =~ Regexp.new(Regexp.escape("%.1f" % 42.0))
|
1265
|
+
# end
|
1266
|
+
# @flog.output_method_details(@handle, 'foo#foo', @data)
|
1267
|
+
# end
|
1268
|
+
#
|
1269
|
+
# it 'should output call details for each call for the method' do
|
1270
|
+
# @data.each do |call, count|
|
1271
|
+
# @handle.expects(:puts).with do |string|
|
1272
|
+
# string =~ Regexp.new(Regexp.escape("%6.1f: %s" % [ count, call ]))
|
1273
|
+
# end
|
1274
|
+
# end
|
1275
|
+
# @flog.output_method_details(@handle, 'foo#foo', @data)
|
1276
|
+
# end
|
1060
1277
|
# end
|
1061
|
-
#
|
1062
|
-
#
|
1063
|
-
#
|
1278
|
+
# end
|
1279
|
+
#
|
1280
|
+
# describe 'when generating a report' do
|
1281
|
+
# before :each do
|
1282
|
+
# @flog.stubs(:output_summary)
|
1283
|
+
# @handle = stub('io handle)', :puts => nil)
|
1064
1284
|
# end
|
1065
|
-
|
1066
|
-
#
|
1067
|
-
#
|
1068
|
-
#
|
1069
|
-
#
|
1285
|
+
#
|
1286
|
+
# # it 'allows specifying an i/o handle' do
|
1287
|
+
# # lambda { @flog.report @handle }.wont_raise_error(ArgumentError)
|
1288
|
+
# # end
|
1289
|
+
# #
|
1290
|
+
# # it 'allows running the report without a specified i/o handle' do
|
1291
|
+
# # lambda { @flog.report }.wont_raise_error(ArgumentError)
|
1292
|
+
# # end
|
1293
|
+
#
|
1294
|
+
# # describe 'and no i/o handle is specified' do
|
1295
|
+
# # it 'defaults the io handle to stdout' do
|
1296
|
+
# # @flog.expects(:output_summary).with($stdout)
|
1297
|
+
# # @flog.report
|
1298
|
+
# # end
|
1299
|
+
# # end
|
1300
|
+
#
|
1301
|
+
# describe 'and producing a summary report' do
|
1302
|
+
# before :each do
|
1303
|
+
# @flog = Flog.new(:score => true)
|
1304
|
+
# @flog.stubs(:output_summary)
|
1305
|
+
# end
|
1306
|
+
#
|
1307
|
+
# it 'produces an output summary on the i/o handle' do
|
1308
|
+
# @flog.expects(:output_summary).with(@handle)
|
1309
|
+
# @flog.report(@handle)
|
1310
|
+
# end
|
1311
|
+
#
|
1312
|
+
# it 'does not output a detailed report' do
|
1313
|
+
# def @flog.output_details(*args); raise "no"; end
|
1314
|
+
# @flog.report(@handle)
|
1315
|
+
# end
|
1316
|
+
#
|
1317
|
+
# it 'should reset statistics when finished' do
|
1318
|
+
# @flog.expects(:reset)
|
1319
|
+
# @flog.report(@handle)
|
1070
1320
|
# end
|
1071
1321
|
# end
|
1322
|
+
#
|
1323
|
+
# describe 'and producing a full report' do
|
1324
|
+
# before :each do
|
1325
|
+
# @flog.stubs(:output_summary)
|
1326
|
+
# @flog.stubs(:output_details)
|
1327
|
+
# end
|
1328
|
+
#
|
1329
|
+
# it 'produces an output summary on the i/o handle' do
|
1330
|
+
# @flog.expects(:output_summary).with(@handle)
|
1331
|
+
# @flog.report(@handle)
|
1332
|
+
# end
|
1333
|
+
#
|
1334
|
+
# it 'should generate a detailed report of method complexity on the i/o handle' do
|
1335
|
+
# @flog.expects(:output_details).with {|handle, max| handle == @handle }
|
1336
|
+
# @flog.report(@handle)
|
1337
|
+
# end
|
1338
|
+
#
|
1339
|
+
# describe 'when flogging all methods in the system' do
|
1340
|
+
# before :each do
|
1341
|
+
# @flog = Flog.new(:all => true)
|
1342
|
+
# @flog.stubs(:output_summary)
|
1343
|
+
# @flog.stubs(:output_details)
|
1344
|
+
# end
|
1345
|
+
#
|
1346
|
+
# it 'should not limit the detailed report' do
|
1347
|
+
# @flog.expects(:output_details).with(@handle)
|
1348
|
+
# @flog.report(@handle)
|
1349
|
+
# end
|
1350
|
+
# end
|
1351
|
+
#
|
1352
|
+
# describe 'when flogging only the most expensive methods in the system' do
|
1353
|
+
# it 'should limit the detailed report to the Flog threshold' do
|
1354
|
+
# def @flog.total; return 3.45; end
|
1355
|
+
# @flog.expects(:output_details).with(@handle, 3.45 * 0.60)
|
1356
|
+
# @flog.report(@handle)
|
1357
|
+
# end
|
1358
|
+
# end
|
1359
|
+
#
|
1360
|
+
# it 'should reset statistics when finished' do
|
1361
|
+
# @flog.expects(:reset)
|
1362
|
+
# @flog.report(@handle)
|
1363
|
+
# end
|
1364
|
+
# end
|
1365
|
+
# end
|
1366
|
+
# end
|
1072
1367
|
|
1073
|
-
|
1074
|
-
|
1075
|
-
@flog = Flog.new(:score => true)
|
1076
|
-
@flog.stubs(:output_summary)
|
1077
|
-
end
|
1078
|
-
|
1079
|
-
it 'produces an output summary on the i/o handle' do
|
1080
|
-
@flog.expects(:output_summary).with(@handle)
|
1081
|
-
@flog.report(@handle)
|
1082
|
-
end
|
1083
|
-
|
1084
|
-
it 'does not output a detailed report' do
|
1085
|
-
def @flog.output_details(*args); raise "no"; end
|
1086
|
-
@flog.report(@handle)
|
1087
|
-
end
|
1088
|
-
|
1089
|
-
it 'should reset statistics when finished' do
|
1090
|
-
@flog.expects(:reset)
|
1091
|
-
@flog.report(@handle)
|
1092
|
-
end
|
1093
|
-
end
|
1094
|
-
|
1095
|
-
describe 'and producing a full report' do
|
1096
|
-
before :each do
|
1097
|
-
@flog.stubs(:output_summary)
|
1098
|
-
@flog.stubs(:output_details)
|
1099
|
-
end
|
1100
|
-
|
1101
|
-
it 'produces an output summary on the i/o handle' do
|
1102
|
-
@flog.expects(:output_summary).with(@handle)
|
1103
|
-
@flog.report(@handle)
|
1104
|
-
end
|
1105
|
-
|
1106
|
-
it 'should generate a detailed report of method complexity on the i/o handle' do
|
1107
|
-
@flog.expects(:output_details).with {|handle, max| handle == @handle }
|
1108
|
-
@flog.report(@handle)
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
describe 'when flogging all methods in the system' do
|
1112
|
-
before :each do
|
1113
|
-
@flog = Flog.new(:all => true)
|
1114
|
-
@flog.stubs(:output_summary)
|
1115
|
-
@flog.stubs(:output_details)
|
1116
|
-
end
|
1117
|
-
|
1118
|
-
it 'should not limit the detailed report' do
|
1119
|
-
@flog.expects(:output_details).with(@handle)
|
1120
|
-
@flog.report(@handle)
|
1121
|
-
end
|
1122
|
-
end
|
1123
|
-
|
1124
|
-
describe 'when flogging only the most expensive methods in the system' do
|
1125
|
-
it 'should limit the detailed report to the Flog threshold' do
|
1126
|
-
def @flog.total; return 3.45; end
|
1127
|
-
@flog.expects(:output_details).with(@handle, 3.45 * 0.60)
|
1128
|
-
@flog.report(@handle)
|
1129
|
-
end
|
1130
|
-
end
|
1368
|
+
############################################################
|
1369
|
+
# TODO after driver code is covered
|
1131
1370
|
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
end
|
1371
|
+
# def test_process_alias
|
1372
|
+
# raise NotImplementedError, 'Need to write test_process_alias'
|
1373
|
+
# end
|
1374
|
+
#
|
1375
|
+
# def test_process_and
|
1376
|
+
# raise NotImplementedError, 'Need to write test_process_and'
|
1377
|
+
# end
|
1378
|
+
#
|
1379
|
+
# def test_process_attrasgn
|
1380
|
+
# raise NotImplementedError, 'Need to write test_process_attrasgn'
|
1381
|
+
# end
|
1382
|
+
#
|
1383
|
+
# def test_process_attrset
|
1384
|
+
# raise NotImplementedError, 'Need to write test_process_attrset'
|
1385
|
+
# end
|
1386
|
+
#
|
1387
|
+
# def test_process_block
|
1388
|
+
# raise NotImplementedError, 'Need to write test_process_block'
|
1389
|
+
# end
|
1390
|
+
#
|
1391
|
+
# def test_process_block_pass
|
1392
|
+
# raise NotImplementedError, 'Need to write test_process_block_pass'
|
1393
|
+
# end
|
1394
|
+
#
|
1395
|
+
# def test_process_call
|
1396
|
+
# raise NotImplementedError, 'Need to write test_process_call'
|
1397
|
+
# end
|
1398
|
+
#
|
1399
|
+
# def test_process_case
|
1400
|
+
# raise NotImplementedError, 'Need to write test_process_case'
|
1401
|
+
# end
|
1402
|
+
#
|
1403
|
+
# def test_process_class
|
1404
|
+
# raise NotImplementedError, 'Need to write test_process_class'
|
1405
|
+
# end
|
1406
|
+
#
|
1407
|
+
# def test_process_dasgn_curr
|
1408
|
+
# raise NotImplementedError, 'Need to write test_process_dasgn_curr'
|
1409
|
+
# end
|
1410
|
+
#
|
1411
|
+
# def test_process_defn
|
1412
|
+
# raise NotImplementedError, 'Need to write test_process_defn'
|
1413
|
+
# end
|
1414
|
+
#
|
1415
|
+
# def test_process_defs
|
1416
|
+
# raise NotImplementedError, 'Need to write test_process_defs'
|
1417
|
+
# end
|
1418
|
+
#
|
1419
|
+
# def test_process_else
|
1420
|
+
# raise NotImplementedError, 'Need to write test_process_else'
|
1421
|
+
# end
|
1422
|
+
#
|
1423
|
+
# def test_process_iasgn
|
1424
|
+
# raise NotImplementedError, 'Need to write test_process_iasgn'
|
1425
|
+
# end
|
1426
|
+
#
|
1427
|
+
# def test_process_if
|
1428
|
+
# raise NotImplementedError, 'Need to write test_process_if'
|
1429
|
+
# end
|
1430
|
+
#
|
1431
|
+
# def test_process_iter
|
1432
|
+
# raise NotImplementedError, 'Need to write test_process_iter'
|
1433
|
+
# end
|
1434
|
+
#
|
1435
|
+
# def test_process_lasgn
|
1436
|
+
# raise NotImplementedError, 'Need to write test_process_lasgn'
|
1437
|
+
# end
|
1438
|
+
#
|
1439
|
+
# def test_process_lit
|
1440
|
+
# raise NotImplementedError, 'Need to write test_process_lit'
|
1441
|
+
# end
|
1442
|
+
#
|
1443
|
+
# def test_process_masgn
|
1444
|
+
# raise NotImplementedError, 'Need to write test_process_masgn'
|
1445
|
+
# end
|
1446
|
+
#
|
1447
|
+
# def test_process_module
|
1448
|
+
# raise NotImplementedError, 'Need to write test_process_module'
|
1449
|
+
# end
|
1450
|
+
#
|
1451
|
+
# def test_process_or
|
1452
|
+
# raise NotImplementedError, 'Need to write test_process_or'
|
1453
|
+
# end
|
1454
|
+
#
|
1455
|
+
# def test_process_parse_tree
|
1456
|
+
# raise NotImplementedError, 'Need to write test_process_parse_tree'
|
1457
|
+
# end
|
1458
|
+
#
|
1459
|
+
# def test_process_rescue
|
1460
|
+
# raise NotImplementedError, 'Need to write test_process_rescue'
|
1461
|
+
# end
|
1462
|
+
#
|
1463
|
+
# def test_process_sclass
|
1464
|
+
# raise NotImplementedError, 'Need to write test_process_sclass'
|
1465
|
+
# end
|
1466
|
+
#
|
1467
|
+
# def test_process_super
|
1468
|
+
# raise NotImplementedError, 'Need to write test_process_super'
|
1469
|
+
# end
|
1470
|
+
#
|
1471
|
+
# def test_process_until
|
1472
|
+
# raise NotImplementedError, 'Need to write test_process_until'
|
1473
|
+
# end
|
1474
|
+
#
|
1475
|
+
# def test_process_when
|
1476
|
+
# raise NotImplementedError, 'Need to write test_process_when'
|
1477
|
+
# end
|
1478
|
+
#
|
1479
|
+
# def test_process_while
|
1480
|
+
# raise NotImplementedError, 'Need to write test_process_while'
|
1481
|
+
# end
|
1482
|
+
#
|
1483
|
+
# def test_process_yield
|
1484
|
+
# raise NotImplementedError, 'Need to write test_process_yield'
|
1485
|
+
# end
|
1486
|
+
#
|