grosser-autotest 4.0.3

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.
@@ -0,0 +1,51 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ module Autotest::Menu
4
+ WINDOZE = /win32/ =~ RUBY_PLATFORM unless defined? WINDOZE
5
+
6
+ if WINDOZE then
7
+ require "Win32API"
8
+ def self.getchar
9
+ Win32API.new("crtdll", "_getch", [], "L").Call
10
+ end
11
+ else
12
+ STTY_SAVE_STATE=`stty -g`
13
+ def self.getchar
14
+ system 'stty raw echo'
15
+ STDIN.getc
16
+ ensure
17
+ system "stty '#{STTY_SAVE_STATE}'"
18
+ end
19
+ end
20
+
21
+ def self.menu(choices)
22
+ result = nil
23
+ choices.sort.each do |c, desc|
24
+ puts "#{c.chr}: #{desc}"
25
+ end
26
+ until choices[result]
27
+ print "menu> "
28
+ result = getchar
29
+ print " invalid input" unless choices[result]
30
+ puts
31
+ end
32
+ result
33
+ end
34
+
35
+ Autotest.add_hook(:interrupt) do |at|
36
+ $stderr.puts "menu"
37
+ case menu ?q => "quit", ?c => "continue", ?r => "restart"
38
+ when ?c
39
+ true
40
+ when ?r
41
+ at.reset
42
+ true
43
+ when ?q
44
+ at.wants_to_quit = true
45
+ true
46
+ else
47
+ false
48
+ end
49
+ # puts "you chose #{c.chr}"
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Migrate
4
+ Autotest.add_hook(:run) do |autotest|
5
+ system "rake db:migrate" if autotest.class.to_s == "RailsAutotest"
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ module Autotest::Notify
2
+ def self.notify(title, message, priority='critical')
3
+ icon = if priority == 'critical'
4
+ 'dialog-error'
5
+ else
6
+ 'dialog-information'
7
+ end
8
+ system "notify-send -u #{priority} -t 10000 -i #{icon} '#{title}' '#{message.inspect}'"
9
+ end
10
+
11
+ Autotest.add_hook :red do |at|
12
+ tests = 0
13
+ assertions = 0
14
+ failures = 0
15
+ errors = 0
16
+ at.results.scan(/(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/) do |t, a, f, e|
17
+ tests += t.to_i
18
+ assertions += a.to_i
19
+ failures += f.to_i
20
+ errors += e.to_i
21
+ end
22
+ message = "%d tests, %d assertions, %d failures, %d errors" %
23
+ [tests, assertions, failures, errors]
24
+ notify("Tests Failed", message)
25
+ end
26
+
27
+ Autotest.add_hook :green do |at|
28
+ notify("Tests Passed", "Outstanding tests passed", 'low') if at.tainted
29
+ end
30
+
31
+ Autotest.add_hook :all do |at|_hook
32
+ notify("autotest", "Tests have fully passed", 'low')
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ ##
2
+ # this is for autotest plugin developers only...
3
+
4
+ module Autotest::Once
5
+ Autotest.add_hook :ran_command do |at|
6
+ exit 0
7
+ end
8
+ end
9
+
@@ -0,0 +1,83 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'osx/cocoa'
4
+ include Math
5
+ include OSX
6
+
7
+ OSX::NSBundle.bundleWithPath(File.expand_path("~/Library/Frameworks/Aquaterm.framework")).load
8
+ OSX.ns_import :AQTAdapter
9
+
10
+ class Autotest::Pretty
11
+ BLACK = 0
12
+ WHITE = 1
13
+ RED = 2
14
+ GREEN = 3
15
+ GRAY = 4
16
+
17
+ def initialize
18
+ @past = []
19
+
20
+ @adapter = AQTAdapter.alloc.init
21
+ @adapter.openPlotWithIndex 1
22
+ @adapter.setPlotSize([122,122])
23
+ @adapter.setPlotTitle("Autotest Status")
24
+
25
+ @adapter.setColormapEntry_red_green_blue(0, 0.0, 0.0, 0.0) # black
26
+ @adapter.setColormapEntry_red_green_blue(1, 1.0, 1.0, 1.0) # white
27
+ @adapter.setColormapEntry_red_green_blue(2, 1.0, 0.0, 0.0) # red
28
+ @adapter.setColormapEntry_red_green_blue(3, 0.0, 1.0, 0.0) # green
29
+ @adapter.setColormapEntry_red_green_blue(4, 0.7, 0.7, 0.7) # gray
30
+
31
+ draw
32
+ end
33
+
34
+ def draw
35
+ @past.shift if @past.size > 100
36
+
37
+ @adapter.takeColorFromColormapEntry(@past.last ? GREEN : RED)
38
+ @adapter.addFilledRect([0, 0, 122, 122])
39
+
40
+ @adapter.takeColorFromColormapEntry(BLACK)
41
+ @adapter.addFilledRect([10, 10, 102, 102])
42
+
43
+ @adapter.takeColorFromColormapEntry(GRAY)
44
+ @adapter.addFilledRect([11, 11, 100, 100])
45
+
46
+ @adapter.takeColorFromColormapEntry(0)
47
+
48
+ @past.each_with_index do |passed,i|
49
+ x = i % 10
50
+ y = i / 10
51
+
52
+ @adapter.takeColorFromColormapEntry(passed ? GREEN : RED)
53
+ @adapter.addFilledRect([x*10+11, y*10+11, 10, 10])
54
+ end
55
+ @adapter.renderPlot
56
+ end
57
+
58
+ def pass
59
+ @past.push true
60
+ draw
61
+ end
62
+
63
+ def fail
64
+ @past.push false
65
+ draw
66
+ end
67
+
68
+ def close
69
+ @adapter.closePlot
70
+ end
71
+ end
72
+
73
+ unless $TESTING then
74
+ board = Autotest::Pretty.new
75
+
76
+ Autotest.add_hook :red do |at|
77
+ board.fail unless $TESTING
78
+ end
79
+
80
+ Autotest.add_hook :green do |at|
81
+ board.pass unless $TESTING
82
+ end
83
+ end
@@ -0,0 +1,81 @@
1
+ require 'autotest'
2
+
3
+ class Autotest::Rails < Autotest
4
+
5
+ def initialize # :nodoc:
6
+ super
7
+
8
+ add_exception %r%^\./(?:db|doc|log|public|script|tmp|vendor)%
9
+
10
+ clear_mappings
11
+
12
+ self.add_mapping(/^lib\/.*\.rb$/) do |filename, _|
13
+ impl = File.basename(filename, '.rb')
14
+ files_matching %r%^test/unit/#{impl}_test.rb$%
15
+ # TODO: (unit|functional|integration) maybe?
16
+ end
17
+
18
+ add_mapping %r%^test/fixtures/(.*)s.yml% do |_, m|
19
+ ["test/unit/#{m[1]}_test.rb",
20
+ "test/controllers/#{m[1]}_controller_test.rb",
21
+ "test/views/#{m[1]}_view_test.rb",
22
+ "test/functional/#{m[1]}_controller_test.rb"]
23
+ end
24
+
25
+ add_mapping %r%^test/(unit|integration|controllers|views|functional)/.*rb$% do |filename, _|
26
+ filename
27
+ end
28
+
29
+ add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
30
+ "test/unit/#{m[1]}_test.rb"
31
+ end
32
+
33
+ add_mapping %r%^app/helpers/application_helper.rb% do
34
+ files_matching %r%^test/(views|functional)/.*_test\.rb$%
35
+ end
36
+
37
+ add_mapping %r%^app/helpers/(.*)_helper.rb% do |_, m|
38
+ if m[1] == "application" then
39
+ files_matching %r%^test/(views|functional)/.*_test\.rb$%
40
+ else
41
+ ["test/views/#{m[1]}_view_test.rb",
42
+ "test/functional/#{m[1]}_controller_test.rb"]
43
+ end
44
+ end
45
+
46
+ add_mapping %r%^app/views/(.*)/% do |_, m|
47
+ ["test/views/#{m[1]}_view_test.rb",
48
+ "test/functional/#{m[1]}_controller_test.rb"]
49
+ end
50
+
51
+ add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
52
+ if m[1] == "application" then
53
+ files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
54
+ else
55
+ ["test/controllers/#{m[1]}_test.rb",
56
+ "test/functional/#{m[1]}_test.rb"]
57
+ end
58
+ end
59
+
60
+ add_mapping %r%^app/views/layouts/% do
61
+ "test/views/layouts_view_test.rb"
62
+ end
63
+
64
+ add_mapping %r%^config/routes.rb$% do # FIX:
65
+ files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
66
+ end
67
+
68
+ add_mapping %r%^test/test_helper.rb|config/((boot|environment(s/test)?).rb|database.yml)% do
69
+ files_matching %r%^test/(unit|controllers|views|functional)/.*_test\.rb$%
70
+ end
71
+ end
72
+
73
+ # Convert the pathname s to the name of class.
74
+ def path_to_classname(s)
75
+ sep = File::SEPARATOR
76
+ f = s.sub(/^test#{sep}((unit|functional|integration|views|controllers|helpers)#{sep})?/, '').sub(/\.rb$/, '').split(sep)
77
+ f = f.map { |path| path.split(/_/).map { |seg| seg.capitalize }.join }
78
+ f = f.map { |path| path =~ /Test$/ ? path : "#{path}Test" }
79
+ f.join('::')
80
+ end
81
+ end
@@ -0,0 +1,22 @@
1
+ module Autotest::RCov
2
+ @@command, @@pattern = "rcov", "test/*.rb"
3
+
4
+ def self.command= o
5
+ @@command = o
6
+ end
7
+
8
+ def self.pattern= o
9
+ @@pattern = o
10
+ end
11
+
12
+ Autotest.add_hook :all_good do |at|
13
+ system "rake #{@@command} PATTERN=#{@@pattern}"
14
+ end
15
+
16
+ Autotest.add_hook :initialize do |at|
17
+ at.add_exception 'coverage'
18
+ at.add_exception 'coverage.info'
19
+ false
20
+ end
21
+ end
22
+
@@ -0,0 +1,21 @@
1
+ # -*- ruby -*-
2
+
3
+ # special thanks to Pat Eyler, Sean Carley, and Rob Sanheim
4
+ # and to Peter Havens for rspec patches
5
+ module Autotest::RedGreen
6
+ BAR = "=" * 78
7
+ REDCODE = 31
8
+ GREENCODE = 32
9
+
10
+ Autotest.add_hook :ran_command do |at|
11
+ green = case at.results.last
12
+ when /^.* (\d+) failures, (\d+) errors$/ # Test::Unit
13
+ ($1 == "0" and $2 == "0")
14
+ when /^\d+\s+examples?,\s+(\d+)\s+failure/ # RSpec
15
+ ($1 == "0")
16
+ end
17
+
18
+ code = green ? GREENCODE : REDCODE
19
+ puts "\e[#{ code }m#{ BAR }\e[0m\n\n" unless green.nil?
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Autotest::Restart
2
+ Autotest.add_hook :updated do |at, *args|
3
+ if args.flatten.include? ".autotest" then
4
+ warn "Detected change to .autotest, restarting"
5
+ cmd = "autotest"
6
+ cmd << " -v" if $v
7
+
8
+ exec cmd
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ require 'code_statistics'
2
+ require 'rbosa'
3
+
4
+ module Autotest::Shame
5
+ @@chat_app = :adium
6
+
7
+ def self.chat_app= o
8
+ @@chat_app = o
9
+ end
10
+
11
+ # Until the rails team learns how to write modular code... I must steal :/
12
+ STATS_DIRECTORIES = [
13
+ %w(Controllers app/controllers),
14
+ %w(Helpers app/helpers),
15
+ %w(Models app/models),
16
+ %w(Libraries lib/),
17
+ %w(APIs app/apis),
18
+ %w(Components components),
19
+ %w(Integration\ tests test/integration),
20
+ %w(Functional\ tests test/functional),
21
+ %w(Unit\ tests test/unit),
22
+ ].select { |name, dir| File.directory?(dir) }
23
+
24
+ def self.shame
25
+ stats = CodeStatistics.new(*STATS_DIRECTORIES)
26
+ code = stats.send :calculate_code
27
+ tests = stats.send :calculate_tests
28
+ msg = "Code To Test Ratio: 1:#{sprintf("%.2f", tests.to_f/code)}"
29
+ $-w = ! $-w
30
+ case @@chat_app
31
+ when :adium then
32
+ OSA.app('Adium').adium_controller.my_status_message = msg
33
+ when :ichat then
34
+ OSA.app('ichat').status_message = msg
35
+ else
36
+ raise "huh?"
37
+ end
38
+ $-w = ! $-w
39
+ $stderr.puts "Status set to: #{msg.inspect}"
40
+ end
41
+
42
+ Autotest.add_hook(:all_good) do |autotest|
43
+ shame
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ # special thanks to: Patrick Hurley <phurley@gmail.com>
2
+ # requires the ruby-snarl gem.
3
+
4
+ begin require 'rubygems'; rescue LoadError; end
5
+ require 'snarl'
6
+
7
+ module Autotest::Snarl
8
+ def self.icon
9
+ # icons from http://www.famfamfam.com/lab/icons/silk/
10
+ path = File.join(File.dirname(__FILE__), "/../icons")
11
+ {
12
+ :green => "#{path}/accept.png",
13
+ :red => "#{path}/exclamation.png",
14
+ :info => "#{path}/information.png"
15
+ }
16
+ end
17
+
18
+ def self.snarl title, msg, ico = nil
19
+ Snarl.show_message(title, msg, icon[ico])
20
+ end
21
+
22
+ Autotest.add_hook :run do |at|
23
+ snarl "Run", "Run" unless $TESTING
24
+ end
25
+
26
+ Autotest.add_hook :red do |at|
27
+ failed_tests = at.files_to_test.inject(0){ |s,a| k,v = a; s + v.size}
28
+ snarl "Tests Failed", "#{failed_tests} tests failed", :red
29
+ end
30
+
31
+ Autotest.add_hook :green do |at|
32
+ snarl "Tests Passed", "All tests passed", :green #if at.tainted
33
+ end
34
+
35
+ Autotest.add_hook :run do |at|
36
+ snarl "autotest", "autotest was started", :info unless $TESTING
37
+ end
38
+
39
+ Autotest.add_hook :interrupt do |at|
40
+ snarl "autotest", "autotest was reset", :info unless $TESTING
41
+ end
42
+
43
+ Autotest.add_hook :quit do |at|
44
+ snarl "autotest", "autotest is exiting", :info unless $TESTING
45
+ end
46
+
47
+ Autotest.add_hook :all do |at|_hook
48
+ snarl "autotest", "Tests have fully passed", :green unless $TESTING
49
+ end
50
+
51
+ end
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::Timestamp
4
+ Autotest.add_hook :waiting do
5
+ puts
6
+ puts "# Waiting since #{Time.now.strftime "%Y-%m-%d %H:%M:%S"}"
7
+ puts
8
+ end
9
+ end
data/lib/unit_diff.rb ADDED
@@ -0,0 +1,258 @@
1
+ require 'tempfile'
2
+
3
+ ##
4
+ # UnitDiff makes reading Test::Unit output easy and fun. Instead of a
5
+ # confusing jumble of text with nearly unnoticable changes like this:
6
+ #
7
+ # 1) Failure:
8
+ # test_to_gpoints(RouteTest) [test/unit/route_test.rb:29]:
9
+ # <"new GPolyline([\n new GPoint( 47.00000, -122.00000),\n new GPoint( 46.5000
10
+ # 0, -122.50000),\n new GPoint( 46.75000, -122.75000),\n new GPoint( 46.00000,
11
+ # -123.00000)])"> expected but was
12
+ # <"new Gpolyline([\n new GPoint( 47.00000, -122.00000),\n new GPoint( 46.5000
13
+ # 0, -122.50000),\n new GPoint( 46.75000, -122.75000),\n new GPoint( 46.00000,
14
+ # -123.00000)])">.
15
+ #
16
+ #
17
+ # You get an easy-to-read diff output like this:
18
+ #
19
+ # 1) Failure:
20
+ # test_to_gpoints(RouteTest) [test/unit/route_test.rb:29]:
21
+ # 1c1
22
+ # < new GPolyline([
23
+ # ---
24
+ # > new Gpolyline([
25
+ #
26
+ # == Usage
27
+ #
28
+ # test.rb | unit_diff [options]
29
+ # options:
30
+ # -b ignore whitespace differences
31
+ # -c contextual diff
32
+ # -h show usage
33
+ # -k keep temp diff files around
34
+ # -l prefix line numbers on the diffs
35
+ # -u unified diff
36
+ # -v display version
37
+
38
+ class UnitDiff
39
+
40
+ WINDOZE = /win32/ =~ RUBY_PLATFORM unless defined? WINDOZE
41
+ DIFF = if WINDOZE
42
+ 'diff.exe'
43
+ else
44
+ if system("gdiff", __FILE__, __FILE__)
45
+ 'gdiff' # solaris and kin suck
46
+ else
47
+ 'diff'
48
+ end
49
+ end unless defined? DIFF
50
+
51
+ ##
52
+ # Handy wrapper for UnitDiff#unit_diff.
53
+
54
+ def self.unit_diff
55
+ trap 'INT' do exit 1 end
56
+ puts UnitDiff.new.unit_diff
57
+ end
58
+
59
+ def parse_input(input, output)
60
+ current = []
61
+ data = []
62
+ data << current
63
+ print_lines = true
64
+
65
+ term = "\nFinished".split(//).map { |c| c[0] }
66
+ term_length = term.size
67
+
68
+ old_sync = output.sync
69
+ output.sync = true
70
+ while line = input.gets
71
+ case line
72
+ when /^(Loaded suite|Started)/ then
73
+ print_lines = true
74
+ output.puts line
75
+ chars = []
76
+ while c = input.getc do
77
+ output.putc c
78
+ chars << c
79
+ tail = chars[-term_length..-1]
80
+ break if chars.size >= term_length and tail == term
81
+ end
82
+ output.puts input.gets # the rest of "Finished in..."
83
+ output.puts
84
+ next
85
+ when /^\s*$/, /^\(?\s*\d+\) (Failure|Error):/, /^\d+\)/ then
86
+ print_lines = false
87
+ current = []
88
+ data << current
89
+ when /^Finished in \d/ then
90
+ print_lines = false
91
+ end
92
+ output.puts line if print_lines
93
+ current << line
94
+ end
95
+ output.sync = old_sync
96
+ data = data.reject { |o| o == ["\n"] or o.empty? }
97
+ footer = data.pop
98
+
99
+ return data, footer
100
+ end
101
+
102
+ # Parses a single diff recording the header and what
103
+ # was expected, and what was actually obtained.
104
+ def parse_diff(result)
105
+ header = []
106
+ expect = []
107
+ butwas = []
108
+ footer = []
109
+ found = false
110
+ state = :header
111
+
112
+ until result.empty? do
113
+ case state
114
+ when :header then
115
+ header << result.shift
116
+ state = :expect if result.first =~ /^<|^Expected/
117
+ when :expect then
118
+ case result.first
119
+ when /^Expected (.*?) to equal (.*?):$/ then
120
+ expect << $1
121
+ butwas << $2
122
+ state = :footer
123
+ result.shift
124
+ when /^Expected (.*?), not (.*)$/m then
125
+ expect << $1
126
+ butwas << $2
127
+ state = :footer
128
+ result.shift
129
+ when /^Expected (.*?)$/ then
130
+ expect << "#{$1}\n"
131
+ result.shift
132
+ when /^to equal / then
133
+ state = :spec_butwas
134
+ bw = result.shift.sub(/^to equal (.*):?$/, '\1')
135
+ butwas << bw
136
+ else
137
+ state = :butwas if result.first.sub!(/ expected( but was|, not)/, '')
138
+ expect << result.shift
139
+ end
140
+ when :butwas then
141
+ butwas = result[0..-1]
142
+ result.clear
143
+ when :spec_butwas then
144
+ if result.first =~ /^\s+\S+ at |^:\s*$/
145
+ state = :footer
146
+ else
147
+ butwas << result.shift
148
+ end
149
+ when :footer then
150
+ butwas.last.sub!(/:$/, '')
151
+ footer = result.map {|l| l.chomp }
152
+ result.clear
153
+ else
154
+ raise "unknown state #{state}"
155
+ end
156
+ end
157
+
158
+ return header, expect, nil, footer if butwas.empty?
159
+
160
+ expect.last.chomp!
161
+ expect.first.sub!(/^<\"/, '')
162
+ expect.last.sub!(/\">$/, '')
163
+
164
+ butwas.last.chomp!
165
+ butwas.last.chop! if butwas.last =~ /\.$/
166
+ butwas.first.sub!( /^<\"/, '')
167
+ butwas.last.sub!(/\">$/, '')
168
+
169
+ return header, expect, butwas, footer
170
+ end
171
+
172
+ ##
173
+ # Scans Test::Unit output +input+ looking for comparison failures and makes
174
+ # them easily readable by passing them through diff.
175
+
176
+ def unit_diff(input=ARGF, output=$stdout)
177
+ $b = false unless defined? $b
178
+ $c = false unless defined? $c
179
+ $k = false unless defined? $k
180
+ $u = false unless defined? $u
181
+
182
+ data, footer = self.parse_input(input, output)
183
+
184
+ output = []
185
+
186
+ # Output
187
+ data.each do |result|
188
+ first = []
189
+ second = []
190
+
191
+ if result.first =~ /Error/ then
192
+ output.push result.join('')
193
+ next
194
+ end
195
+
196
+ prefix, expect, butwas, result_footer = parse_diff(result)
197
+
198
+ output.push prefix.compact.map {|line| line.strip}.join("\n")
199
+
200
+ if butwas then
201
+ output.push self.diff(expect, butwas)
202
+
203
+ output.push result_footer
204
+ output.push ''
205
+ else
206
+ output.push expect.join('')
207
+ end
208
+ end
209
+
210
+ if footer then
211
+ footer.shift if footer.first.strip.empty?# unless footer.first.nil?
212
+ output.push footer.compact.map {|line| line.strip}.join("\n")
213
+ end
214
+
215
+ return output.flatten.join("\n")
216
+ end
217
+
218
+ def diff expect, butwas
219
+ output = nil
220
+
221
+ Tempfile.open("expect") do |a|
222
+ a.write(massage(expect))
223
+ a.rewind
224
+ Tempfile.open("butwas") do |b|
225
+ b.write(massage(butwas))
226
+ b.rewind
227
+
228
+ diff_flags = $u ? "-u" : $c ? "-c" : ""
229
+ diff_flags += " -b" if $b
230
+
231
+ result = `#{DIFF} #{diff_flags} #{a.path} #{b.path}`
232
+ output = if result.empty? then
233
+ "[no difference--suspect ==]"
234
+ else
235
+ result.split(/\n/)
236
+ end
237
+
238
+ if $k then
239
+ warn "moving #{a.path} to #{a.path}.keep"
240
+ File.rename a.path, a.path + ".keep"
241
+ warn "moving #{b.path} to #{b.path}.keep"
242
+ File.rename b.path, b.path + ".keep"
243
+ end
244
+ end
245
+ end
246
+
247
+ output
248
+ end
249
+
250
+ def massage(data)
251
+ count = 0
252
+ # unescape newlines, strip <> from entire string
253
+ data = data.join
254
+ data = data.gsub(/\\n/, "\n").gsub(/0x[a-f0-9]+/m, '0xXXXXXX') + "\n"
255
+ data += "\n" unless data[-1] == ?\n
256
+ data
257
+ end
258
+ end