ZenTest 3.4.3 → 3.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +46 -3
- data/Manifest.txt +13 -0
- data/README.txt +1 -0
- data/Rakefile +20 -3
- data/bin/autotest +23 -37
- data/bin/multiruby +13 -7
- data/bin/unit_diff +1 -1
- data/example_dot_autotest.rb +14 -0
- data/lib/autotest.rb +77 -30
- data/lib/autotest/autoupdate.rb +26 -0
- data/lib/autotest/emacs.rb +29 -0
- data/lib/autotest/fixtures.rb +12 -0
- data/lib/autotest/growl.rb +7 -17
- data/lib/autotest/heckle.rb +14 -0
- data/lib/autotest/migrate.rb +7 -0
- data/lib/autotest/notify.rb +38 -0
- data/lib/autotest/redgreen.rb +7 -4
- data/lib/autotest/screen.rb +77 -0
- data/lib/autotest/shame.rb +45 -0
- data/lib/autotest/timestamp.rb +3 -1
- data/lib/camping_autotest.rb +37 -0
- data/lib/functional_test_matrix.rb +85 -0
- data/lib/rails_autotest.rb +49 -41
- data/lib/rspec_rails_autotest.rb +119 -0
- data/lib/test/rails.rb +28 -1
- data/lib/test/rails/controller_test_case.rb +27 -6
- data/lib/test/rails/functional_test_case.rb +3 -0
- data/lib/test/rails/helper_test_case.rb +3 -0
- data/lib/test/rails/view_test_case.rb +13 -5
- data/lib/test/zentest_assertions.rb +42 -23
- data/lib/unit_diff.rb +86 -69
- data/lib/zentest.rb +58 -87
- data/lib/zentest_mapping.rb +97 -0
- data/test/test_autotest.rb +23 -3
- data/test/test_help.rb +10 -4
- data/test/test_rails_autotest.rb +6 -4
- data/test/test_rails_controller_test_case.rb +10 -2
- data/test/test_ruby_fork.rb +12 -12
- data/test/test_unit_diff.rb +37 -33
- data/test/test_zentest.rb +15 -141
- data/test/test_zentest_assertions.rb +38 -18
- data/test/test_zentest_mapping.rb +213 -0
- metadata +18 -4
@@ -0,0 +1,26 @@
|
|
1
|
+
module Autotest::AutoUpdate
|
2
|
+
@@sleep_time, @@update_cmd, @@updater = 60, "svn up", nil
|
3
|
+
|
4
|
+
def self.sleep_time= o
|
5
|
+
@@sleep_time = o
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.update_cmd= o
|
9
|
+
@@update_cmd = o
|
10
|
+
end
|
11
|
+
|
12
|
+
Autotest.add_hook :run_command do |at|
|
13
|
+
@@updater.kill if @@updater
|
14
|
+
end
|
15
|
+
|
16
|
+
Autotest.add_hook :ran_command do |at|
|
17
|
+
@@updater = Thread.start do
|
18
|
+
loop do
|
19
|
+
puts "# Waiting for #{@@sleep_time} seconds before updating"
|
20
|
+
sleep @@sleep_time
|
21
|
+
puts "# Running #{@@update_cmd}"
|
22
|
+
system @@update_cmd
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
# Get autotest.el from http://www.emacswiki.org/cgi-bin/wiki/RyanDavis
|
3
|
+
#
|
4
|
+
|
5
|
+
module Autotest::Emacs
|
6
|
+
def self.emacs_autotest status
|
7
|
+
`emacsclient -e \"(autotest-update '#{status})\"`
|
8
|
+
end
|
9
|
+
|
10
|
+
Autotest.add_hook :run_command do |at|
|
11
|
+
emacs_autotest :running
|
12
|
+
end
|
13
|
+
|
14
|
+
Autotest.add_hook :green do |at|
|
15
|
+
emacs_autotest :passed
|
16
|
+
end
|
17
|
+
|
18
|
+
Autotest.add_hook :all_good do |at|
|
19
|
+
emacs_autotest :passed
|
20
|
+
end
|
21
|
+
|
22
|
+
Autotest.add_hook :red do |at|
|
23
|
+
emacs_autotest :failed
|
24
|
+
end
|
25
|
+
|
26
|
+
Autotest.add_hook :quit do |at|
|
27
|
+
emacs_autotest :quit
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
# This is an example of how to change the mappings of file that
|
4
|
+
# changed to tests to run for a project.
|
5
|
+
|
6
|
+
module Autotest::Fixtures
|
7
|
+
Autotest.add_hook :initialize do |at|
|
8
|
+
at.test_mappings['^test/fixtures/(.*)s.yml'] = proc { |filename, matches|
|
9
|
+
at.files_matching /test\/\w+\/#{matches[1]}(_\w+)?.*_test.rb$/
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
data/lib/autotest/growl.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
# -*-
|
1
|
+
# -*- ruby -*-
|
2
2
|
|
3
3
|
module Autotest::Growl
|
4
4
|
def self.growl title, msg, pri=0
|
5
|
+
title += " in #{Dir.pwd}"
|
6
|
+
msg += " at #{Time.now}"
|
5
7
|
system "growlnotify -n autotest --image /Applications/Mail.app/Contents/Resources/Caution.tiff -p #{pri} -m #{msg.inspect} #{title}"
|
6
8
|
end
|
7
9
|
|
8
10
|
Autotest.add_hook :run do |at|
|
9
|
-
growl "
|
11
|
+
growl "autotest running", "Started"
|
10
12
|
end
|
11
13
|
|
12
14
|
Autotest.add_hook :red do |at|
|
@@ -14,22 +16,10 @@ module Autotest::Growl
|
|
14
16
|
end
|
15
17
|
|
16
18
|
Autotest.add_hook :green do |at|
|
17
|
-
growl "Tests Passed", "
|
19
|
+
growl "Tests Passed", "Tests passed", -2 if at.tainted
|
18
20
|
end
|
19
21
|
|
20
|
-
Autotest.add_hook :
|
21
|
-
growl "
|
22
|
-
end
|
23
|
-
|
24
|
-
Autotest.add_hook :interrupt do |at|
|
25
|
-
growl "autotest", "autotest was reset" unless $TESTING
|
26
|
-
end
|
27
|
-
|
28
|
-
Autotest.add_hook :quit do |at|
|
29
|
-
growl "autotest", "autotest is exiting" unless $TESTING
|
30
|
-
end
|
31
|
-
|
32
|
-
Autotest.add_hook :all do |at|_hook
|
33
|
-
growl "autotest", "Tests have fully passed", -2 unless $TESTING
|
22
|
+
Autotest.add_hook :all_good do |at|
|
23
|
+
growl "Tests Passed", "All tests passed", -2 if at.tainted
|
34
24
|
end
|
35
25
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
module Autotest::Heckle
|
4
|
+
@@flags = []
|
5
|
+
@@klasses = []
|
6
|
+
def self.flags; @@flags; end
|
7
|
+
def self.klasses; @@klasses; end
|
8
|
+
|
9
|
+
Autotest.add_hook :all_good do |at|
|
10
|
+
heckle = "heckle" + (@@flags.empty? ? '' : " #{flags.join(' ')}")
|
11
|
+
cmd = @@klasses.map { |klass| "#{heckle} #{klass}" }.join(" && ")
|
12
|
+
system cmd
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# libnotify plugin for autotest
|
2
|
+
|
3
|
+
begin require 'rubygems'; rescue LoadError; end
|
4
|
+
require 'libnotify'
|
5
|
+
|
6
|
+
module Autotest::LibNotify
|
7
|
+
|
8
|
+
LibNotify.init("autotest")
|
9
|
+
|
10
|
+
def self.notify title, msg, ico = :info
|
11
|
+
LibNotify::Notification.new(title, msg, "gtk-#{ico}", nil).show
|
12
|
+
end
|
13
|
+
|
14
|
+
Autotest.add_hook :red do |at|
|
15
|
+
failed_tests = at.files_to_test.inject(0){ |s,a| k,v = a; s + v.size}
|
16
|
+
notify "Tests Failed", "#{failed_tests} tests failed", :no
|
17
|
+
end
|
18
|
+
|
19
|
+
Autotest.add_hook :green do |at|
|
20
|
+
notify "Tests Passed", "All tests passed", :yes
|
21
|
+
end
|
22
|
+
|
23
|
+
Autotest.add_hook :run do |at|
|
24
|
+
notify "autotest", "autotest was started" unless $TESTING
|
25
|
+
end
|
26
|
+
|
27
|
+
Autotest.add_hook :interrupt do |at|
|
28
|
+
notify "autotest", "autotest was reset" unless $TESTING
|
29
|
+
end
|
30
|
+
|
31
|
+
Autotest.add_hook :quit do |at|
|
32
|
+
notify "autotest", "autotest is exiting" unless $TESTING
|
33
|
+
end
|
34
|
+
|
35
|
+
Autotest.add_hook :all do |at|_hook
|
36
|
+
notify "autotest", "Tests have fully passed", :yes unless $TESTING
|
37
|
+
end
|
38
|
+
end
|
data/lib/autotest/redgreen.rb
CHANGED
@@ -5,9 +5,12 @@ module Autotest::RedGreen
|
|
5
5
|
BAR = "=" * 80
|
6
6
|
|
7
7
|
Autotest.add_hook :ran_command do |at|
|
8
|
-
at.results.
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
output = at.results.join
|
9
|
+
at.results.each do |line|
|
10
|
+
line.gsub!(/^.* (\d+) failures, (\d+) errors$/) { |match|
|
11
|
+
code = ($1 != "0" or $2 != "0") ? 31 : 32
|
12
|
+
"\e[#{code}m#{BAR}\n#{match}\e[0m\n\n"
|
13
|
+
}
|
14
|
+
end
|
12
15
|
end
|
13
16
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class Autotest::Screen
|
2
|
+
# Autotest::Screen is test result notify GUN Screen's statusline.
|
3
|
+
#
|
4
|
+
# === screenshots
|
5
|
+
# * <img src="http://f.hatena.ne.jp/images/fotolife/s/secondlife/20061109/20061109015543.png" />
|
6
|
+
# * <img src="http://f.hatena.ne.jp/images/fotolife/s/secondlife/20061109/20061109015522.png" />
|
7
|
+
#
|
8
|
+
# == SYNOPSIS
|
9
|
+
# require 'autotest/screen'
|
10
|
+
# # Autotest::Screen.statusline = '%H %`%-w%{=b bw}%n %t%{-}%+w (your statusline)'
|
11
|
+
#
|
12
|
+
|
13
|
+
DEFAULT_STATUSLINE = '%H %`%-w%{=b bw}%n %t%{-}%+w'
|
14
|
+
DEFAULT_SCREEN_CMD = 'screen'
|
15
|
+
|
16
|
+
SCREEN_COLOR = {
|
17
|
+
:black => 'dd',
|
18
|
+
:green => 'gk',
|
19
|
+
:red => 'rw',
|
20
|
+
}
|
21
|
+
|
22
|
+
def self.message(msg, color = :black)
|
23
|
+
col = SCREEN_COLOR[color]
|
24
|
+
msg = %Q[ %{=b #{col}} #{msg} %{-}]
|
25
|
+
send_cmd(msg)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.clear
|
29
|
+
send_cmd('')
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.run_screen_session?
|
33
|
+
str = `#{screen_cmd} -ls`
|
34
|
+
str.match(/(\d+) Socket/) && ($1.to_i > 0)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.execute?
|
38
|
+
!($TESTING || !run_screen_session?)
|
39
|
+
end
|
40
|
+
|
41
|
+
@statusline, @screen_cmd = nil
|
42
|
+
def self.statusline; @statusline || DEFAULT_STATUSLINE.dup; end
|
43
|
+
def self.statusline=(a); @statusline = a; end
|
44
|
+
def self.screen_cmd; @screen_cmd || DEFAULT_SCREEN_CMD.dup; end
|
45
|
+
def self.screen_cmd=(a); @screen_cmd = a; end
|
46
|
+
|
47
|
+
def self.send_cmd(msg)
|
48
|
+
cmd = %(#{screen_cmd} -X eval 'hardstatus alwayslastline "#{(statusline + msg).gsub('"', '\"')}"') #' stupid ruby-mode
|
49
|
+
system cmd
|
50
|
+
end
|
51
|
+
|
52
|
+
Autotest.add_hook :run do |at|
|
53
|
+
message 'Run Tests' if execute?
|
54
|
+
end
|
55
|
+
|
56
|
+
Autotest.add_hook :interrupt do |at|
|
57
|
+
message 'Run Tests' if execute?
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
Autotest.add_hook :quit do |at|
|
62
|
+
clear if execute?
|
63
|
+
end
|
64
|
+
|
65
|
+
Autotest.add_hook :ran_command do |at|
|
66
|
+
if execute? then
|
67
|
+
output = at.results.join
|
68
|
+
failed = output.scan(/^\s+\d+\) (?:Failure|Error):\n(.*?)\((.*?)\)/)
|
69
|
+
if failed.size == 0 then
|
70
|
+
message "All Green", :green
|
71
|
+
else
|
72
|
+
f,e = failed.partition { |s| s =~ /Failure/ }
|
73
|
+
message "Red F:#{f.size} E:#{e.size}", :red
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
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
|
data/lib/autotest/timestamp.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'autotest'
|
2
|
+
|
3
|
+
##
|
4
|
+
# CampingAutotest is an Autotest subclass designed for use with Camping projects.
|
5
|
+
#
|
6
|
+
# To use CampingAutotest pass the -camping flag to autotest.
|
7
|
+
#
|
8
|
+
# Contributed by Geoffrey Grosenbach http://nubyonrails.com
|
9
|
+
|
10
|
+
class CampingAutotest < Autotest
|
11
|
+
|
12
|
+
def initialize # :nodoc:
|
13
|
+
super
|
14
|
+
@exceptions = %r%\.(log|db)$%
|
15
|
+
|
16
|
+
@test_mappings = {
|
17
|
+
%r%^test/fixtures/([^_]+)_.*s\.yml% => proc { |_, m|
|
18
|
+
"test/#{m[1]}_test.rb"
|
19
|
+
},
|
20
|
+
%r%^test/.*rb$% => proc { |filename, m|
|
21
|
+
filename
|
22
|
+
},
|
23
|
+
%r%^public/([^\/]+)/(models|controllers|views)\.rb$% => proc { |_, m|
|
24
|
+
"test/#{m[1]}_test.rb"
|
25
|
+
},
|
26
|
+
%r%^public/(.*)\.rb$% => proc { |_, m|
|
27
|
+
"test/#{m[1]}_test.rb"
|
28
|
+
},
|
29
|
+
}
|
30
|
+
|
31
|
+
return functional_tests
|
32
|
+
end
|
33
|
+
|
34
|
+
def tests_for_file(filename)
|
35
|
+
super.select { |f| @files.has_key? f }
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
########################################################################
|
3
|
+
# The Idea:
|
4
|
+
#
|
5
|
+
# This is supposed to get us thinking about the various dimensions our
|
6
|
+
# testing should address. If there are states orthogonal to each other
|
7
|
+
# (eg. readable vs unreadable, logged in vs not logged in) each of
|
8
|
+
# those states should comprise a dimension in the matrix. By
|
9
|
+
# addressing it this way, we should be able to minimize the amount of
|
10
|
+
# setup/teardown code and get full coverage across our actions for all
|
11
|
+
# these edge cases and as a result have extremely clear tests.
|
12
|
+
#
|
13
|
+
########################################################################
|
14
|
+
# Example Test Matrix Specification:
|
15
|
+
#
|
16
|
+
# matrix :example, :edge1, edge2, :edge3, ...
|
17
|
+
# action :action1, :new, :err, :err, ...
|
18
|
+
# action :action2, :del, :err, :na, ...
|
19
|
+
# action ...
|
20
|
+
#
|
21
|
+
########################################################################
|
22
|
+
# Matrix:
|
23
|
+
#
|
24
|
+
# I envision the setups being a code that combines the different
|
25
|
+
# dimensions of edge case state.
|
26
|
+
#
|
27
|
+
# Something for a CMS might look like: `[df]_[ugo]_[rRwW]` where:
|
28
|
+
#
|
29
|
+
# + `[df]` for dir/file.
|
30
|
+
# + and the rest is in the style of symbolic args to chmod:
|
31
|
+
# + u/g/o = user, group, or other
|
32
|
+
# + lowercase `X` == `X`able, uppercase `X` == un`X`able, where `X`
|
33
|
+
# is read/write.
|
34
|
+
#
|
35
|
+
########################################################################
|
36
|
+
# Action:
|
37
|
+
#
|
38
|
+
# :new/:err/:del are just examples, they should have semantic info
|
39
|
+
# attached to them.
|
40
|
+
#
|
41
|
+
# Use :na to specify an inapplicable edge case for that action.
|
42
|
+
#
|
43
|
+
# Edge cases specific to an action that fall outside the matrix are
|
44
|
+
# regular tests.
|
45
|
+
#
|
46
|
+
########################################################################
|
47
|
+
# Matrix Methods (the legos):
|
48
|
+
#
|
49
|
+
# Everything else basically equates to lego pieces:
|
50
|
+
#
|
51
|
+
# + There is one "init" method per matrix: matrix_init_#{descr}(setup_args)
|
52
|
+
# + There is one "setup" method per action: matrix_setup_#{action}(setup, expect)
|
53
|
+
# + There is one "test" method per result: matrix_test_#{result}(setup)
|
54
|
+
#
|
55
|
+
# Thus, for the example above, the top left-most test will end up calling:
|
56
|
+
#
|
57
|
+
# matrix_init_example(:edge1)
|
58
|
+
# matrix_setup_action1(:edge1, :new)
|
59
|
+
# matrix_test_new(:edge1)
|
60
|
+
#
|
61
|
+
# Read the action method for exact details.
|
62
|
+
########################################################################
|
63
|
+
|
64
|
+
module FunctionalTestMatrix
|
65
|
+
def matrix(name, *setups)
|
66
|
+
@@matrix, @@setups = name, setups
|
67
|
+
end
|
68
|
+
|
69
|
+
def action(action, *results)
|
70
|
+
testcases = @@setups.zip(results).reject { |a,b| b == :na }
|
71
|
+
testcases = Hash[*testcases.flatten]
|
72
|
+
matrix = @@matrix # bind to local scope for define_method closure
|
73
|
+
|
74
|
+
testcases.each do |setup, expected|
|
75
|
+
define_method "test_#{action}_#{setup}" do
|
76
|
+
@action = action
|
77
|
+
send "matrix_init_#{matrix}", *setup.to_s.split(/_/).map {|c| c.intern }
|
78
|
+
send "matrix_setup_#{action}", setup, expected
|
79
|
+
send "matrix_test_#{expected}", setup
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
module_function :matrix, :action
|
85
|
+
end
|