ZenTest 3.4.3 → 3.5.1

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.
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