duck_test 0.1.4
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/bin/ducktest +29 -0
- data/lib/duck_test/autoload_config.rb +103 -0
- data/lib/duck_test/base.rb +41 -0
- data/lib/duck_test/commands.rb +208 -0
- data/lib/duck_test/config.rb +675 -0
- data/lib/duck_test/config_helper.rb +99 -0
- data/lib/duck_test/console.rb +18 -0
- data/lib/duck_test/default_config.rb +48 -0
- data/lib/duck_test/frame_work/base.rb +587 -0
- data/lib/duck_test/frame_work/file_manager.rb +511 -0
- data/lib/duck_test/frame_work/filter_set.rb +233 -0
- data/lib/duck_test/frame_work/map.rb +331 -0
- data/lib/duck_test/frame_work/queue.rb +221 -0
- data/lib/duck_test/frame_work/queue_event.rb +29 -0
- data/lib/duck_test/frame_work/rspec/base.rb +17 -0
- data/lib/duck_test/frame_work/rspec/frame_work.rb +30 -0
- data/lib/duck_test/frame_work/test_unit/base.rb +14 -0
- data/lib/duck_test/frame_work/test_unit/frame_work.rb +33 -0
- data/lib/duck_test/frame_work/watch_config.rb +69 -0
- data/lib/duck_test/gem/helper.rb +107 -0
- data/lib/duck_test/logger.rb +127 -0
- data/lib/duck_test/option_parser.rb +30 -0
- data/lib/duck_test/platforms/base.rb +18 -0
- data/lib/duck_test/platforms/dependencies.rb +18 -0
- data/lib/duck_test/platforms/generic/base.rb +15 -0
- data/lib/duck_test/platforms/generic/listener.rb +104 -0
- data/lib/duck_test/platforms/linux/base.rb +15 -0
- data/lib/duck_test/platforms/linux/listener.rb +76 -0
- data/lib/duck_test/platforms/listener.rb +303 -0
- data/lib/duck_test/platforms/mac/base.rb +15 -0
- data/lib/duck_test/platforms/mac/listener.rb +79 -0
- data/lib/duck_test/platforms/mac/listener.rb.orig +147 -0
- data/lib/duck_test/platforms/os_helper.rb +102 -0
- data/lib/duck_test/platforms/watch_event.rb +47 -0
- data/lib/duck_test/platforms/windows/base.rb +15 -0
- data/lib/duck_test/platforms/windows/listener.rb +123 -0
- data/lib/duck_test/railtie.rb +29 -0
- data/lib/duck_test/usage.rb +34 -0
- data/lib/duck_test/usage.yml +112 -0
- data/lib/duck_test/version.rb +3 -0
- data/lib/duck_test.rb +6 -0
- data/lib/notes.txt +215 -0
- data/lib/tasks/duck_tests.rake +35 -0
- data/lib/tasks/gem_tasks.rake +18 -0
- metadata +92 -0
@@ -0,0 +1,587 @@
|
|
1
|
+
require 'thor/shell/basic'
|
2
|
+
|
3
|
+
module DuckTest
|
4
|
+
module FrameWork
|
5
|
+
|
6
|
+
autoload :FileManager, 'duck_test/frame_work/file_manager'
|
7
|
+
autoload :FilterSet, 'duck_test/frame_work/filter_set'
|
8
|
+
autoload :Map, 'duck_test/frame_work/map'
|
9
|
+
autoload :Queue, 'duck_test/frame_work/queue'
|
10
|
+
autoload :QueueEvent, 'duck_test/frame_work/queue_event'
|
11
|
+
autoload :RSpec, 'duck_test/frame_work/rspec/base'
|
12
|
+
autoload :Runner, 'duck_test/frame_work/runner'
|
13
|
+
autoload :TestUnit, 'duck_test/frame_work/test_unit/base'
|
14
|
+
autoload :WatchConfig, 'duck_test/frame_work/watch_config'
|
15
|
+
autoload :WatchEvent, 'duck_test/frame_work/watch_event'
|
16
|
+
|
17
|
+
##################################################################################
|
18
|
+
# Base class for all FrameWork implementations testunit, minitest, rpsec, etc.
|
19
|
+
class Base
|
20
|
+
include DuckTest::ConfigHelper
|
21
|
+
include FileManager
|
22
|
+
include LoggerHelper
|
23
|
+
#include Thor::Actions
|
24
|
+
|
25
|
+
attr_accessor :name
|
26
|
+
attr_accessor :listener
|
27
|
+
attr_accessor :queue
|
28
|
+
attr_accessor :pre_load
|
29
|
+
attr_accessor :pre_run
|
30
|
+
attr_accessor :post_load
|
31
|
+
attr_accessor :post_run
|
32
|
+
|
33
|
+
##################################################################################
|
34
|
+
# Initializes a testing framework object.
|
35
|
+
# @param [String, Symbol] name The name of the testing framwork: :testunit, :rspec, etc.
|
36
|
+
# @return [Base] Instance of {Base}
|
37
|
+
def initialize(name)
|
38
|
+
super()
|
39
|
+
self.name = name
|
40
|
+
end
|
41
|
+
|
42
|
+
##################################################################################
|
43
|
+
# Clears all of the currently queue test suites. The intention is to allow a developer to override this method
|
44
|
+
# within a custom framework class to modify the behavior without having to alter {Base}
|
45
|
+
def clear_tests
|
46
|
+
::Test::Unit::TestCase.reset
|
47
|
+
end
|
48
|
+
|
49
|
+
##################################################################################
|
50
|
+
# Displays information about the current loaded testing framework.
|
51
|
+
# @return [String] The output message
|
52
|
+
def info
|
53
|
+
pad = 25
|
54
|
+
stats_black = self.list_stats(:black)
|
55
|
+
stats_white = self.list_stats(:white)
|
56
|
+
|
57
|
+
buffer = %(\r\n#{"DuckTest version:".rjust(pad)} #{DuckTest::VERSION})
|
58
|
+
buffer << %(\r\n#{"Ruby:".rjust(pad)} #{RUBY_VERSION})
|
59
|
+
buffer << %(\r\n#{"Rails:".rjust(pad)} #{Rails.version})
|
60
|
+
buffer << %(\r\n#{"Gem:".rjust(pad)} #{Gem::VERSION})
|
61
|
+
buffer << %(\r\n#{"Testing framework:".rjust(pad)} #{self.name})
|
62
|
+
buffer << %(\r\n#{"Autorun:".rjust(pad)} #{self.autorun ? "ON" : "OFF"})
|
63
|
+
buffer << %(\r\n#{"Blacklisted:".rjust(pad)} Directories: (#{stats_black[:dirs]}) Files: (#{stats_black[:files]}))
|
64
|
+
buffer << %(\r\n#{"Whitelisted:".rjust(pad)} Directories: (#{stats_white[:dirs]}) Files: (#{stats_white[:files]}))
|
65
|
+
buffer << %(\r\n#{"Listener Speed:".rjust(pad)} #{self.listener.speed})
|
66
|
+
buffer << %(\r\n#{"ActiveRecord Log Level:".rjust(pad)} #{DuckTest::Logger.to_severity(ActiveRecord::Base.logger.level)})
|
67
|
+
buffer << %(\r\n#{"Log Level:".rjust(pad)} #{DuckTest::Logger.to_severity(DuckTest::Logger.ducklog.level)})
|
68
|
+
buffer << %(\r\n#{"Queue Latency:".rjust(pad)} #{self.queue.latency})
|
69
|
+
buffer << %(\r\n#{"Queue Speed:".rjust(pad)} #{self.queue.speed})
|
70
|
+
|
71
|
+
return buffer
|
72
|
+
end
|
73
|
+
|
74
|
+
##################################################################################
|
75
|
+
# ...
|
76
|
+
def listener_event(event)
|
77
|
+
# TODO add support for all of the events.
|
78
|
+
|
79
|
+
ducklog.system "listener_event: #{event.flag}"
|
80
|
+
|
81
|
+
begin
|
82
|
+
case event.flag
|
83
|
+
when :destroy
|
84
|
+
when :update
|
85
|
+
self.queue.push(event.file_spec)
|
86
|
+
|
87
|
+
when :create
|
88
|
+
file_object_parent = self.find_file_object_parent(:white, event.file_spec)
|
89
|
+
if file_object_parent
|
90
|
+
if self.watch_file_spec(event.file_spec, file_object_parent[:watch_config])
|
91
|
+
self.queue.push(event.file_spec)
|
92
|
+
else
|
93
|
+
self.add_to_list(:black, event.file_spec, file_object_parent[:watch_config])
|
94
|
+
end
|
95
|
+
else
|
96
|
+
self.add_to_list(:black, event.file_spec, file_object_parent[:watch_config])
|
97
|
+
end
|
98
|
+
|
99
|
+
when :moved
|
100
|
+
#self.queue.push(event.file_spec)
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
rescue Exception => e
|
105
|
+
ducklog.exception e
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
##################################################################################
|
111
|
+
# Physically loads files from disk.
|
112
|
+
def load_files_from_disk(event)
|
113
|
+
|
114
|
+
ducklog.console "load_files_from_disk: #{event.files.length}"
|
115
|
+
|
116
|
+
event.files.each do |file|
|
117
|
+
|
118
|
+
begin
|
119
|
+
|
120
|
+
ducklog.console "==> #{File.basename(file)}"
|
121
|
+
load file
|
122
|
+
|
123
|
+
rescue Exception => e
|
124
|
+
ducklog.exception e
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
##################################################################################
|
132
|
+
# Processes a list of file specifications and prepares them to be run
|
133
|
+
def queue_event(event)
|
134
|
+
|
135
|
+
non_runnable_files = []
|
136
|
+
runnable_files = []
|
137
|
+
|
138
|
+
begin
|
139
|
+
|
140
|
+
if self.autorun?
|
141
|
+
|
142
|
+
ducklog.console "\r\n==> preparing tests: #{event.files.length}"
|
143
|
+
|
144
|
+
event.files.each do |file_spec|
|
145
|
+
|
146
|
+
ducklog.system "\r\n ==> file_spec: #{file_spec}"
|
147
|
+
|
148
|
+
# is the file black listed?
|
149
|
+
if self.black_listed?(file_spec)
|
150
|
+
ducklog.system " black_listed? true"
|
151
|
+
|
152
|
+
else
|
153
|
+
|
154
|
+
file_object = self.white_listed?(file_spec)
|
155
|
+
ducklog.system " white_listed? #{!file_object.blank?}"
|
156
|
+
|
157
|
+
# is the file white listed and runnable?
|
158
|
+
if file_object && file_object[:watch_config].runnable?
|
159
|
+
if file_object[:is_dir]
|
160
|
+
ducklog.system " --> SHOULD HAVE RUN THE FILE, BUT, IT IS A DIRECTORY !!!! white_listed? true runnable? #{file_object[:watch_config].runnable?} is_dir: #{file_object[:is_dir]}"
|
161
|
+
else
|
162
|
+
ducklog.system " --> SHOULD RUN THE FILE !!!! white_listed? true runnable? #{file_object[:watch_config].runnable?} is_dir: #{file_object[:is_dir]}"
|
163
|
+
runnable_files.push(file_spec)
|
164
|
+
end
|
165
|
+
|
166
|
+
# is the file white listed and NON-runnable?
|
167
|
+
elsif file_object && !file_object[:watch_config].runnable?
|
168
|
+
|
169
|
+
ducklog.system " --> Need to resolve if file is associated with runnable files"
|
170
|
+
non_runnable_files.push(file_spec)
|
171
|
+
runnable_files.concat(find_runnable_files(file_spec, file_object[:watch_config]))
|
172
|
+
|
173
|
+
else
|
174
|
+
|
175
|
+
if self.white_listed?(file_spec)
|
176
|
+
ducklog.system "i don't know what to do"
|
177
|
+
|
178
|
+
else
|
179
|
+
|
180
|
+
# if we have a file that has changed and was not previously on the whitelist, then, the event must have been triggered due to some
|
181
|
+
# other action such as after being created or being moved to the containing directory.
|
182
|
+
file_object_parent = self.find_file_object_parent(:white, file_spec)
|
183
|
+
|
184
|
+
# is the file watchable?
|
185
|
+
if file_object_parent && self.watchable?(file_spec, file_object_parent[:watch_config])
|
186
|
+
ducklog.system " YES - file_object_parent true AND watchable - the file should be whitelisted"
|
187
|
+
ducklog.system " need to resolve if file is associated with runnable files"
|
188
|
+
non_runnable_files.push(file_spec)
|
189
|
+
runnable_files.concat(find_runnable_files(file_spec, file_object_parent[:watch_config]))
|
190
|
+
else
|
191
|
+
ducklog.system " NO - file_object_parent false - the file should be blacklisted"
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
ducklog.console " ==> running tests: #{runnable_files.length}"
|
201
|
+
|
202
|
+
run_fork(non_runnable_files, runnable_files, true)
|
203
|
+
|
204
|
+
else
|
205
|
+
|
206
|
+
ducklog.console self.autorun_status
|
207
|
+
self.queue.reset
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
rescue Exception => e
|
212
|
+
ducklog.exception e
|
213
|
+
end
|
214
|
+
|
215
|
+
return runnable_files
|
216
|
+
end
|
217
|
+
|
218
|
+
##################################################################################
|
219
|
+
# Loads all runnable test files from disk and executes the run_tests method.
|
220
|
+
# @return [String] A message indicating the status of the run.
|
221
|
+
def run_all
|
222
|
+
msg = nil
|
223
|
+
|
224
|
+
non_runnable_files = []
|
225
|
+
runnable_files = []
|
226
|
+
|
227
|
+
self.white_list.each do |file_object|
|
228
|
+
unless file_object.last[:is_dir]
|
229
|
+
if file_object.last[:watch_config].runnable?
|
230
|
+
runnable_files.push(file_object.first)
|
231
|
+
else
|
232
|
+
non_runnable_files.push(file_object.first)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
run_fork(non_runnable_files, runnable_files, true)
|
238
|
+
|
239
|
+
return msg
|
240
|
+
end
|
241
|
+
|
242
|
+
##################################################################################
|
243
|
+
def loadable?(file_spec)
|
244
|
+
value = false
|
245
|
+
|
246
|
+
file_object = self.white_listed?(file_spec)
|
247
|
+
if file_object
|
248
|
+
value = !file_object[:watch_config].filter_set.non_loadable?(file_spec, nil)
|
249
|
+
end
|
250
|
+
|
251
|
+
return value
|
252
|
+
end
|
253
|
+
|
254
|
+
##################################################################################
|
255
|
+
# Loads all of the runnable tests contained in the runnable_files argument and executes the run_tests method.
|
256
|
+
# @param [Array] non_runnable_files A array of non-runnable files to load.
|
257
|
+
# @param [Array] runnable_files A array of runnable files load and execute.
|
258
|
+
# @param [Boolean] force_run Forces the tests to run regardless of the current state of autorun.
|
259
|
+
# @return [NilClass]
|
260
|
+
def run_fork(non_runnable_files, runnable_files, force_run = false)
|
261
|
+
|
262
|
+
buffer = []
|
263
|
+
non_runnable_files.each do |file_spec|
|
264
|
+
if self.loadable?(file_spec)
|
265
|
+
buffer.push(file_spec)
|
266
|
+
else
|
267
|
+
self.non_loadable_history = self.non_loadable_history.concat([file_spec])
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
self.non_runnable_history = self.non_runnable_history.concat(buffer)
|
272
|
+
non_runnable_files = self.non_runnable_history
|
273
|
+
|
274
|
+
self.runnable_history = self.runnable_history.concat(runnable_files)
|
275
|
+
|
276
|
+
ducklog.console self.autorun_status
|
277
|
+
|
278
|
+
if runnable_files.length > 0
|
279
|
+
|
280
|
+
pid = fork do
|
281
|
+
|
282
|
+
if non_runnable_files.length > 0
|
283
|
+
|
284
|
+
clear_constants(non_runnable_files)
|
285
|
+
|
286
|
+
self.pre_load.call self, :non_runnable unless self.pre_load.blank?
|
287
|
+
|
288
|
+
load_files_from_disk(QueueEvent.new(self, non_runnable_files))
|
289
|
+
|
290
|
+
self.post_load.call self, :non_runnable unless self.post_load.blank?
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
self.pre_load.call self, :runnable unless self.pre_load.blank?
|
295
|
+
|
296
|
+
clear_tests
|
297
|
+
|
298
|
+
load_files_from_disk(QueueEvent.new(self, runnable_files))
|
299
|
+
|
300
|
+
self.post_load.call self, :runnable unless self.post_load.blank?
|
301
|
+
|
302
|
+
if self.autorun || force_run
|
303
|
+
|
304
|
+
self.pre_run.call self unless self.pre_run.blank?
|
305
|
+
|
306
|
+
run_tests
|
307
|
+
|
308
|
+
self.post_run.call self unless self.post_run.blank?
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
Process.wait pid
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
ActiveRecord::Base.connection_pool.verify_active_connections! if defined?(ActiveRecord::Base)
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
##################################################################################
|
323
|
+
# Manually runs any tests pending in the queue.
|
324
|
+
# @return [String] A message indicating the status of the run.
|
325
|
+
def run_manually(expressions = nil)
|
326
|
+
msg = nil
|
327
|
+
list = []
|
328
|
+
expressions = expressions.kind_of?(Symbol) ? expressions.to_s : expressions
|
329
|
+
if expressions.kind_of?(String)
|
330
|
+
if expressions.include?(",")
|
331
|
+
expressions = expressions.split(",")
|
332
|
+
|
333
|
+
elsif expressions.include?(" ")
|
334
|
+
expressions = expressions.split(" ")
|
335
|
+
|
336
|
+
else
|
337
|
+
expressions = [expressions]
|
338
|
+
|
339
|
+
end
|
340
|
+
end
|
341
|
+
expressions = expressions.kind_of?(Regexp) ? [expressions] : expressions
|
342
|
+
expressions = expressions.kind_of?(Array) ? expressions : [expressions]
|
343
|
+
|
344
|
+
self.queue.reset
|
345
|
+
|
346
|
+
self.white_list.each do |file_object|
|
347
|
+
|
348
|
+
if !file_object.last[:is_dir] && file_object.last[:watch_config].runnable?
|
349
|
+
|
350
|
+
file_spec = file_object.first
|
351
|
+
file_name = File.basename(file_spec, ".rb")
|
352
|
+
|
353
|
+
expressions.each do |expression|
|
354
|
+
|
355
|
+
expression = expression.kind_of?(Symbol) ? expression.to_s : expression
|
356
|
+
|
357
|
+
if expression.kind_of?(String)
|
358
|
+
|
359
|
+
if file_name =~ /^#{expression}/
|
360
|
+
list.push(file_spec)
|
361
|
+
end
|
362
|
+
|
363
|
+
elsif expression.kind_of?(Regexp)
|
364
|
+
|
365
|
+
if file_name =~ expression
|
366
|
+
list.push(file_spec)
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
|
376
|
+
if list.length > 1
|
377
|
+
list.each_with_index {|item, index| STDOUT.puts "#{(index + 1).to_s.rjust(3)} - #{item.gsub(self.root, "")}"}
|
378
|
+
action = Thor::Shell::Basic.new.ask("Which file would you like to run (ENTER for all) ?")
|
379
|
+
unless action.blank?
|
380
|
+
buffer = []
|
381
|
+
index = action.to_i - 1
|
382
|
+
if (index >= 0 && index < list.length)
|
383
|
+
buffer.push(list[index])
|
384
|
+
list = buffer
|
385
|
+
else
|
386
|
+
list = []
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
if list.length > 0
|
393
|
+
self.run_fork([], list, true)
|
394
|
+
end
|
395
|
+
|
396
|
+
return msg
|
397
|
+
end
|
398
|
+
|
399
|
+
##################################################################################
|
400
|
+
# See {Platforms::Listener#speed}
|
401
|
+
# @return [NilClass]
|
402
|
+
def set_listener_speed(value)
|
403
|
+
self.listener.speed = value
|
404
|
+
return nil
|
405
|
+
end
|
406
|
+
|
407
|
+
##################################################################################
|
408
|
+
# See {Queue#speed}
|
409
|
+
# @return [NilClass]
|
410
|
+
def set_queue_speed(value)
|
411
|
+
self.queue.set_speed(value)
|
412
|
+
return nil
|
413
|
+
end
|
414
|
+
|
415
|
+
##################################################################################
|
416
|
+
# See {Queue#latency}
|
417
|
+
# @return [NilClass]
|
418
|
+
def set_latency(value)
|
419
|
+
self.queue.set_latency(value)
|
420
|
+
return nil
|
421
|
+
end
|
422
|
+
|
423
|
+
##################################################################################
|
424
|
+
# Configures and starts a testing framework.
|
425
|
+
# @param [Hash] config Hash containing all configuration values for the framework: paths, autorun, watch configurations, etc.
|
426
|
+
# @return [Base] Returns self.
|
427
|
+
def startup(config)
|
428
|
+
|
429
|
+
begin
|
430
|
+
|
431
|
+
ducklog.system "Starting framework: #{self.name}"
|
432
|
+
|
433
|
+
self.root = config[:root]
|
434
|
+
self.autorun = config[:autorun]
|
435
|
+
|
436
|
+
self.pre_load = config[:pre_load]
|
437
|
+
self.pre_run = config[:pre_run]
|
438
|
+
self.post_load = config[:post_load]
|
439
|
+
self.post_run = config[:post_run]
|
440
|
+
|
441
|
+
ducklog.console self.autorun_status
|
442
|
+
|
443
|
+
unless config[:watch_configs].blank?
|
444
|
+
config[:watch_configs].each do |watch_config|
|
445
|
+
self.watch_configs.push(watch_config)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
self.build_watch_lists
|
450
|
+
|
451
|
+
self.start
|
452
|
+
|
453
|
+
rescue Exception => e
|
454
|
+
ducklog.exception e
|
455
|
+
end
|
456
|
+
|
457
|
+
return self
|
458
|
+
end
|
459
|
+
|
460
|
+
##################################################################################
|
461
|
+
# TODO implement a shutdown. future version might implement the ability to shutdown a framework
|
462
|
+
# and switch to another on the fly. at this point, i haven't even tried any test code to verify each of the native
|
463
|
+
# notifiers will fully stop watching files. I would not want to switch framework and have an orphan notifier trigger
|
464
|
+
# an unwanted event.
|
465
|
+
def shutdown
|
466
|
+
end
|
467
|
+
|
468
|
+
##################################################################################
|
469
|
+
# Starts a FileManager session. start will instantiate a file watcher / listener for the current platform and begin watching
|
470
|
+
# files based on configuration specified in config/environments. Also, an event queue is created to listen for and act upon
|
471
|
+
# changes to watched files.
|
472
|
+
# @return [NilClass]
|
473
|
+
def start
|
474
|
+
self.queue = Queue.new
|
475
|
+
self.queue.autorun = self.autorun
|
476
|
+
self.queue.queue_event {|event| queue_event(event)}
|
477
|
+
self.queue.start
|
478
|
+
|
479
|
+
if self.is_linux? && self.available?
|
480
|
+
self.listener = Platforms::Linux::Listener.new
|
481
|
+
|
482
|
+
elsif self.is_mac? && self.available?
|
483
|
+
self.listener = Platforms::Mac::Listener.new
|
484
|
+
|
485
|
+
elsif self.is_windows? && self.available?
|
486
|
+
self.listener = Platforms::Windows::Listener.new
|
487
|
+
|
488
|
+
else
|
489
|
+
self.listener = Platforms::Generic::Listener.new
|
490
|
+
|
491
|
+
end
|
492
|
+
|
493
|
+
unless self.listener.blank?
|
494
|
+
|
495
|
+
self.listener.listener_event {|event| listener_event(event)}
|
496
|
+
|
497
|
+
ducklog.console "Loading watchlist for: #{self.name}"
|
498
|
+
ducklog.system "========================================================="
|
499
|
+
|
500
|
+
self.white_list.each do |file|
|
501
|
+
file_spec = file.first
|
502
|
+
ducklog.system "watch: #{file_spec}"
|
503
|
+
self.listener.watch(file_spec)
|
504
|
+
end
|
505
|
+
|
506
|
+
if self.white_list.length > 0
|
507
|
+
stats = self.list_stats(:white)
|
508
|
+
ducklog.console "Watching (#{stats[:dirs]}) directories (#{stats[:files]}) files..."
|
509
|
+
else
|
510
|
+
ducklog.console "You are not watching any files. Add DuckTest.config block to config/environments/test.rb to watch files..."
|
511
|
+
end
|
512
|
+
|
513
|
+
self.listener.start
|
514
|
+
|
515
|
+
ducklog.console "For help, type: 'duck' at the command prompt"
|
516
|
+
|
517
|
+
end
|
518
|
+
|
519
|
+
return nil
|
520
|
+
end
|
521
|
+
|
522
|
+
##################################################################################
|
523
|
+
# Stops the current instance of FileManager
|
524
|
+
# @return [NilClass]
|
525
|
+
def stop
|
526
|
+
# need to stop the queue as well.
|
527
|
+
self.queue.stop
|
528
|
+
self.listener.stop
|
529
|
+
return nil
|
530
|
+
end
|
531
|
+
|
532
|
+
##################################################################################
|
533
|
+
# Toggles the current state of autorun for the current FrameWork instance including it's queue.
|
534
|
+
# @return [String] Returns a message indicating the current autorun status.
|
535
|
+
def toggle_autorun
|
536
|
+
self.autorun = self.autorun ? false : true
|
537
|
+
self.queue.autorun = self.autorun
|
538
|
+
return self.autorun_status
|
539
|
+
end
|
540
|
+
|
541
|
+
##################################################################################
|
542
|
+
# Returns the current total number of directories and files for the black or white list.
|
543
|
+
# @return [Hash] Returns the stats for a list.
|
544
|
+
def list_stats(target)
|
545
|
+
stats = {dirs: 0, files: 0}
|
546
|
+
list = target.eql?(:black) ? self.black_list : self.white_list
|
547
|
+
|
548
|
+
if list.length > 0
|
549
|
+
list.each do |file_object|
|
550
|
+
if file_object.last[:is_dir]
|
551
|
+
stats[:dirs] += 1
|
552
|
+
else
|
553
|
+
stats[:files] += 1
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
return stats
|
559
|
+
end
|
560
|
+
|
561
|
+
##################################################################################
|
562
|
+
# I'm pretty sure I will be able to deprecate this method since now I am running the tests
|
563
|
+
# within a fork. keeping it in case I need it later
|
564
|
+
def clear_constants(file_list)
|
565
|
+
|
566
|
+
#ActiveRecord::Base.s.verify_active_connections! if defined?(ActiveRecord::Base)
|
567
|
+
|
568
|
+
file_list.each do |file_spec|
|
569
|
+
|
570
|
+
begin
|
571
|
+
|
572
|
+
file_name = File.basename(file_spec, ".*")
|
573
|
+
ducklog.console "removing constant: #{file_name} ==> #{file_name.classify}"
|
574
|
+
Object.send(:remove_const, file_name.classify.to_sym)
|
575
|
+
|
576
|
+
rescue Exception => e
|
577
|
+
# for now, I have decided not to warn the developer about constants that probably won't be there most of the time
|
578
|
+
# ducklog.exception e
|
579
|
+
end
|
580
|
+
|
581
|
+
end
|
582
|
+
|
583
|
+
end
|
584
|
+
|
585
|
+
end
|
586
|
+
end
|
587
|
+
end
|