ZenTest 3.4.3 → 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/History.txt +46 -3
  2. data/Manifest.txt +13 -0
  3. data/README.txt +1 -0
  4. data/Rakefile +20 -3
  5. data/bin/autotest +23 -37
  6. data/bin/multiruby +13 -7
  7. data/bin/unit_diff +1 -1
  8. data/example_dot_autotest.rb +14 -0
  9. data/lib/autotest.rb +77 -30
  10. data/lib/autotest/autoupdate.rb +26 -0
  11. data/lib/autotest/emacs.rb +29 -0
  12. data/lib/autotest/fixtures.rb +12 -0
  13. data/lib/autotest/growl.rb +7 -17
  14. data/lib/autotest/heckle.rb +14 -0
  15. data/lib/autotest/migrate.rb +7 -0
  16. data/lib/autotest/notify.rb +38 -0
  17. data/lib/autotest/redgreen.rb +7 -4
  18. data/lib/autotest/screen.rb +77 -0
  19. data/lib/autotest/shame.rb +45 -0
  20. data/lib/autotest/timestamp.rb +3 -1
  21. data/lib/camping_autotest.rb +37 -0
  22. data/lib/functional_test_matrix.rb +85 -0
  23. data/lib/rails_autotest.rb +49 -41
  24. data/lib/rspec_rails_autotest.rb +119 -0
  25. data/lib/test/rails.rb +28 -1
  26. data/lib/test/rails/controller_test_case.rb +27 -6
  27. data/lib/test/rails/functional_test_case.rb +3 -0
  28. data/lib/test/rails/helper_test_case.rb +3 -0
  29. data/lib/test/rails/view_test_case.rb +13 -5
  30. data/lib/test/zentest_assertions.rb +42 -23
  31. data/lib/unit_diff.rb +86 -69
  32. data/lib/zentest.rb +58 -87
  33. data/lib/zentest_mapping.rb +97 -0
  34. data/test/test_autotest.rb +23 -3
  35. data/test/test_help.rb +10 -4
  36. data/test/test_rails_autotest.rb +6 -4
  37. data/test/test_rails_controller_test_case.rb +10 -2
  38. data/test/test_ruby_fork.rb +12 -12
  39. data/test/test_unit_diff.rb +37 -33
  40. data/test/test_zentest.rb +15 -141
  41. data/test/test_zentest_assertions.rb +38 -18
  42. data/test/test_zentest_mapping.rb +213 -0
  43. 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
@@ -1,12 +1,14 @@
1
- # -*- mode -*-
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 "Run", "Run" unless $TESTING
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", "All tests passed", -2 if at.tainted
19
+ growl "Tests Passed", "Tests passed", -2 if at.tainted
18
20
  end
19
21
 
20
- Autotest.add_hook :init do |at|
21
- growl "autotest", "autotest was started" unless $TESTING
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,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,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
@@ -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.gsub!(/^.* (\d+) failures, (\d+) errors$/) { |match|
9
- code = ($1 != "0" or $2 != "0") ? 31 : 32
10
- "\e[#{code}m#{BAR}\n#{match}\e[0m\n\n"
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
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Autotest::Timestamp
4
4
  Autotest.add_hook :waiting do |at|
5
- puts "# waiting... #{Time.now}"
5
+ puts
6
+ puts "# Waiting at #{Time.now.strftime "%Y-%m-%d %H:%M:%S"}"
7
+ puts
6
8
  end
7
9
  end
@@ -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