summaryrefslogtreecommitdiffstats
path: root/autotest
diff options
context:
space:
mode:
authorLuke Kanies <luke@puppetlabs.com>2010-06-10 12:54:50 -0400
committertest branch <puppet-dev@googlegroups.com>2010-02-17 06:50:53 -0800
commit182c0033dcc1885a42bd0cbb429d278f53ae9480 (patch)
tree89151e30f8c39af556033dd9f0ea91f359562d1a /autotest
parent3a44f0e4826b8677323d3c1be55263dfa94f3305 (diff)
downloadpuppet-182c0033dcc1885a42bd0cbb429d278f53ae9480.tar.gz
puppet-182c0033dcc1885a42bd0cbb429d278f53ae9480.tar.xz
puppet-182c0033dcc1885a42bd0cbb429d278f53ae9480.zip
Fixing #3988 - adding support for watchr
Also added a readme file explaining a bit of how the continuous testing tools work. Signed-off-by: Luke Kanies <luke@puppetlabs.com>
Diffstat (limited to 'autotest')
-rw-r--r--autotest/README.markdown45
-rw-r--r--autotest/images/fail.pngbin0 -> 19978 bytes
-rw-r--r--autotest/images/pass.pngbin0 -> 21763 bytes
-rw-r--r--autotest/images/pending.pngbin0 -> 19745 bytes
-rw-r--r--autotest/watcher.rb138
5 files changed, 183 insertions, 0 deletions
diff --git a/autotest/README.markdown b/autotest/README.markdown
new file mode 100644
index 000000000..4cb3d8370
--- /dev/null
+++ b/autotest/README.markdown
@@ -0,0 +1,45 @@
+# Continuous Testing
+
+This directory contains configurations for continuous testing, using
+either autotest (part of the ZenTest gem) or watchr (in the watchr
+gem). The purpose of these tools is to automatically run the
+appropriate test when a file is changed or, if appropriate, all
+tests. In general, they do a straightforward mapping from a given
+code file to its unit and/or integration test.
+
+It is highly recommended that you have one of these running at all
+times during development, as they provide immediate and continuous
+feedback as to your development process. There are some general
+usability downsides as you have to track the running process, but
+those downsides are easily worth it.
+
+# How to use
+
+To use autotest, install ZenTest and run it with no arguments
+from the root of the puppet repository:
+
+ $ autotest
+
+It is currently only configured to run specs.
+
+To use watchr, run it with the watchr file specified as its argument:
+
+ $ watchr autotest/watcher.rb
+
+Both will use growl if installed on a Mac, but watchr assumes the
+presence of growl and will likely fail without it. Autotest is a bit
+more mature and should be resilient to either.
+
+The primary reason to use to use watchr over autotest is that it uses
+filesystem events to detect changes (theoretically portably although
+only tested on OS X), thus eliminating the need for polling for
+changes across all files being monitored.
+
+# Gotchas
+
+Autotest will start out by running all tests; if you don't want that,
+stick a syntax error in one of the tests to force a failure, then fix
+it and go on your merry way.
+
+Watchr, on the other hand, will default to only running the files you
+change.
diff --git a/autotest/images/fail.png b/autotest/images/fail.png
new file mode 100644
index 000000000..2d5539442
--- /dev/null
+++ b/autotest/images/fail.png
Binary files differ
diff --git a/autotest/images/pass.png b/autotest/images/pass.png
new file mode 100644
index 000000000..cbe537186
--- /dev/null
+++ b/autotest/images/pass.png
Binary files differ
diff --git a/autotest/images/pending.png b/autotest/images/pending.png
new file mode 100644
index 000000000..b8cf9a391
--- /dev/null
+++ b/autotest/images/pending.png
Binary files differ
diff --git a/autotest/watcher.rb b/autotest/watcher.rb
new file mode 100644
index 000000000..61baf49d0
--- /dev/null
+++ b/autotest/watcher.rb
@@ -0,0 +1,138 @@
+ENV["WATCHR"] = "1"
+ENV['AUTOTEST'] = 'true'
+
+def run_comp(cmd)
+ puts cmd
+ results = []
+ old_sync = $stdout.sync
+ $stdout.sync = true
+ line = []
+ begin
+ open("| #{cmd}", "r") do |f|
+ until f.eof? do
+ c = f.getc
+ putc c
+ line << c
+ if c == ?\n then
+ results << if RUBY_VERSION >= "1.9" then
+ line.join
+ else
+ line.pack "c*"
+ end
+ line.clear
+ end
+ end
+ end
+ ensure
+ $stdout.sync = old_sync
+ end
+ results.join
+end
+
+def clear
+ #system("clear")
+end
+
+def growl(message, status)
+ # Strip the color codes
+ message.gsub!(/\[\d+m/, '')
+
+ growlnotify = `which growlnotify`.chomp
+ return if growlnotify.empty?
+ title = "Watchr Test Results"
+ image = status == :pass ? "autotest/images/pass.png" : "autotest/images/fail.png"
+ options = "-w -n Watchr --image '#{File.expand_path(image)}' -m '#{message}' '#{title}'"
+ system %(#{growlnotify} #{options} &)
+end
+
+def file2specs(file)
+ %w{spec/unit spec/integration}.collect { |d|
+ file.sub('lib/puppet', d)
+ }.find_all { |f|
+ File.exist?(f)
+ }
+end
+
+def file2test(file)
+ result = file.sub('lib/puppet', 'test')
+ return nil unless File.exist?(result)
+ result
+end
+
+def run_spec(command)
+ clear
+ result = run_comp(command).split("\n").last
+ status = result.include?('0 failures') ? :pass : :fail
+ growl result, status
+end
+
+def run_test(command)
+ clear
+ result = run_comp(command).split("\n").last
+ status = result.include?('0 failures, 0 errors') ? :pass : :fail
+ growl result.split("\n").last rescue nil
+end
+
+def run_test_file(file)
+ run_test(%Q(#{file}))
+end
+
+def run_spec_files(files)
+ files = Array(files)
+ return if files.empty?
+ opts = File.readlines('spec/spec.opts').collect { |l| l.chomp }.join(" ")
+ run_spec("spec #{files.join(' ')}")
+end
+
+def run_all_tests
+ run_test("rake unit")
+end
+
+def run_all_specs
+ run_test("rake spec")
+end
+
+def run_suite
+ run_all_tests
+ run_all_specs
+end
+
+watch('spec/spec_helper.rb') { run_all_specs }
+watch(%r%^spec/(unit|integration)/.*\.rb$%) { |md| run_spec_files(md[0]) }
+watch(%r%^lib/puppet/(.*)\.rb$%) { |md|
+ run_spec_files(file2specs(md[0]))
+ if t = file2test(md[0])
+ run_test_file(t)
+ end
+}
+watch(%r!^spec/lib/spec.*!) { |md| run_all_specs }
+watch(%r!^spec/lib/monkey_patches/.*!) { |md| run_all_specs }
+watch(%r{test/.+\.rb}) { |md|
+ if md[0] =~ /\/lib\//
+ run_all_tests
+ else
+ run_test_file(md[0])
+ end
+}
+
+# Ctrl-\
+Signal.trap 'QUIT' do
+ puts " --- Running all tests ---\n\n"
+ run_suite
+end
+
+@interrupted = false
+
+# Ctrl-C
+Signal.trap 'INT' do
+ if @interrupted then
+ @wants_to_quit = true
+ abort("\n")
+ else
+ puts "Interrupt a second time to quit; wait for rerun of tests"
+ @interrupted = true
+ Kernel.sleep 1.5
+ # raise Interrupt, nil # let the run loop catch it
+ run_suite
+ end
+end