zentest-without-autotest 4.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/.autotest +21 -0
- data/.gitignore +1 -0
- data/History.txt +631 -0
- data/README.markdown +96 -0
- data/Rakefile +70 -0
- data/VERSION +1 -0
- data/bin/multigem +4 -0
- data/bin/multiruby +50 -0
- data/bin/multiruby_setup +73 -0
- data/bin/zentest +28 -0
- data/example_dot_autotest.rb +12 -0
- data/lib/focus.rb +21 -0
- data/lib/functional_test_matrix.rb +92 -0
- data/lib/multiruby.rb +426 -0
- data/lib/zentest.rb +576 -0
- data/lib/zentest_mapping.rb +117 -0
- data/test/helper.rb +6 -0
- data/test/test_focus.rb +34 -0
- data/test/test_zentest.rb +560 -0
- data/test/test_zentest_mapping.rb +238 -0
- data/zentest-without-autotest.gemspec +62 -0
- metadata +81 -0
data/README.markdown
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
This is ZenTest without [AutoTest and UnitDiff](http://github.com/grosser/autotest)
|
2
|
+
|
3
|
+
ZenTest provides 2 different tools: zentest and multiruby.
|
4
|
+
|
5
|
+
ZenTest scans your target and unit-test code and writes your missing
|
6
|
+
code based on simple naming rules, enabling XP at a much quicker
|
7
|
+
pace. ZenTest only works with Ruby and Test::Unit. Nobody uses this
|
8
|
+
tool anymore but it is the package namesake, so it stays.
|
9
|
+
|
10
|
+
multiruby runs anything you want on multiple versions of ruby. Great
|
11
|
+
for compatibility checking! Use multiruby_setup to manage your
|
12
|
+
installed versions.
|
13
|
+
|
14
|
+
Install
|
15
|
+
=======
|
16
|
+
### Requirements
|
17
|
+
* Ruby 1.6+, JRuby 1.1.2+, or rubinius
|
18
|
+
* rubygems
|
19
|
+
|
20
|
+
###Setup
|
21
|
+
sudo gem install zentest-without-autotest
|
22
|
+
|
23
|
+
From Source:
|
24
|
+
git co git://github.com/grosser/zentest.git && cd zentest
|
25
|
+
rake install
|
26
|
+
|
27
|
+
Strategy
|
28
|
+
========
|
29
|
+
There are two strategies intended for ZenTest: test conformance
|
30
|
+
auditing and rapid XP.
|
31
|
+
|
32
|
+
For auditing, ZenTest provides an excellent means of finding methods
|
33
|
+
that have slipped through the testing process. I've run it against my
|
34
|
+
own software and found I missed a lot in a well tested
|
35
|
+
package. Writing those tests found 4 bugs I had no idea existed.
|
36
|
+
|
37
|
+
ZenTest can also be used to evaluate generated code and execute your
|
38
|
+
tests, allowing for very rapid development of both tests and
|
39
|
+
implementation.
|
40
|
+
|
41
|
+
Features
|
42
|
+
========
|
43
|
+
|
44
|
+
* Scans your ruby code and tests and generates missing methods for you.
|
45
|
+
* Test against multiple versions with multiruby.
|
46
|
+
* Enhance and automatically audit your rails tests using Test::Rails.
|
47
|
+
* Includes a LinuxJournal article on testing with ZenTest written by Pat Eyler.
|
48
|
+
* See also: http://blog.zenspider.com/archives/zentest/
|
49
|
+
* See also: http://blog.segment7.net/articles/category/zentest
|
50
|
+
|
51
|
+
Synopsis
|
52
|
+
========
|
53
|
+
ZenTest MyProject.rb TestMyProject.rb > missing.rb
|
54
|
+
|
55
|
+
multiruby_setup mri:svn:current
|
56
|
+
multiruby ./TestMyProject.rb
|
57
|
+
|
58
|
+
(and other stuff for Test::Rails)
|
59
|
+
|
60
|
+
TODO
|
61
|
+
====
|
62
|
+
- cleanup the readme: and insert useful examples + compact instructions + remove blabla
|
63
|
+
|
64
|
+
License
|
65
|
+
=======
|
66
|
+
###This is only ripped from ZenTest
|
67
|
+
Ripper: [Michael Grosser](http://pragmatig.wordpress.com)
|
68
|
+
|
69
|
+
### ZenTest Authors
|
70
|
+
- http://www.zenspider.com/ZSS/Products/ZenTest/
|
71
|
+
- http://rubyforge.org/projects/zentest/
|
72
|
+
- ryand-ruby@zenspider.com
|
73
|
+
|
74
|
+
(The MIT License)
|
75
|
+
|
76
|
+
Copyright (c) 2001-2006 Ryan Davis, Eric Hodel, Zen Spider Software
|
77
|
+
|
78
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
79
|
+
a copy of this software and associated documentation files (the
|
80
|
+
"Software"), to deal in the Software without restriction, including
|
81
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
82
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
83
|
+
permit persons to whom the Software is furnished to do so, subject to
|
84
|
+
the following conditions:
|
85
|
+
|
86
|
+
The above copyright notice and this permission notice shall be
|
87
|
+
included in all copies or substantial portions of the Software.
|
88
|
+
|
89
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
90
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
91
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
92
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
93
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
94
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
95
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
96
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
$LOAD_PATH << 'lib'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'zentest'
|
5
|
+
|
6
|
+
#rake test
|
7
|
+
require 'rake/testtask'
|
8
|
+
Rake::TestTask.new(:test) {|test| test.libs << "test"}
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc "run autotest on itself"
|
12
|
+
task :autotest do
|
13
|
+
ruby "-Ilib -w ./bin/autotest"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "update example_dot_autotest.rb with all possible constants"
|
17
|
+
task :update do
|
18
|
+
system "p4 edit example_dot_autotest.rb"
|
19
|
+
File.open "example_dot_autotest.rb", "w" do |f|
|
20
|
+
f.puts "# -*- ruby -*-"
|
21
|
+
f.puts
|
22
|
+
Dir.chdir "lib" do
|
23
|
+
Dir["autotest/*.rb"].sort.each do |s|
|
24
|
+
next if s =~ /rails|discover/
|
25
|
+
f.puts "# require '#{s[0..-4]}'"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
f.puts
|
30
|
+
|
31
|
+
Dir["lib/autotest/*.rb"].sort.each do |file|
|
32
|
+
file = File.read(file)
|
33
|
+
m = file[/module.*/].split(/ /).last rescue nil
|
34
|
+
next unless m
|
35
|
+
|
36
|
+
file.grep(/def[^(]+=/).each do |setter|
|
37
|
+
setter = setter.sub(/^ *def self\./, '').sub(/\s*=\s*/, ' = ')
|
38
|
+
f.puts "# #{m}.#{setter}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
system "p4 diff -du example_dot_autotest.rb"
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "show rcov report"
|
46
|
+
task :rcov_info do
|
47
|
+
ruby "-Ilib -S rcov --text-report --save coverage.info test/test_*.rb"
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
require 'jeweler'
|
52
|
+
Jeweler::Tasks.new do |gem|
|
53
|
+
gem.name = "zentest-without-autotest"
|
54
|
+
gem.summary = "ZenTest, without AutoTest and UnitDiff"
|
55
|
+
gem.homepage = "http://github.com/grosser/zentest"
|
56
|
+
gem.authors = ["Ryan Davis"]
|
57
|
+
end
|
58
|
+
Jeweler::GemcutterTasks.new
|
59
|
+
rescue LoadError
|
60
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
61
|
+
end
|
62
|
+
|
63
|
+
task :sort do
|
64
|
+
begin
|
65
|
+
sh 'for f in lib/*.rb; do echo $f; grep "^ *def " $f | grep -v sort=skip > x; sort x > y; echo $f; echo; diff x y; done'
|
66
|
+
sh 'for f in test/test_*.rb; do echo $f; grep "^ *def.test_" $f > x; sort x > y; echo $f; echo; diff x y; done'
|
67
|
+
ensure
|
68
|
+
sh 'rm x y'
|
69
|
+
end
|
70
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
4.1.4
|
data/bin/multigem
ADDED
data/bin/multiruby
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
|
3
|
+
require 'multiruby'
|
4
|
+
|
5
|
+
root_dir = Multiruby.root_dir
|
6
|
+
versions = Multiruby.build_and_install
|
7
|
+
versions = ENV['VERSIONS'].split(/:/) if ENV.has_key? 'VERSIONS'
|
8
|
+
|
9
|
+
if ENV.has_key? 'EXCLUDED_VERSIONS' then
|
10
|
+
excludes = Regexp.union(*ENV['EXCLUDED_VERSIONS'].split(/:/))
|
11
|
+
versions = versions.delete_if { |v| v =~ excludes }
|
12
|
+
end
|
13
|
+
|
14
|
+
# safekeep original PATH
|
15
|
+
original_path = ENV['PATH']
|
16
|
+
|
17
|
+
results = {}
|
18
|
+
versions.each do |version|
|
19
|
+
ruby = "#{root_dir}/install/#{version}/bin/ruby"
|
20
|
+
|
21
|
+
ruby.sub!(/bin.ruby/, 'bin/rbx') if version =~ /rubinius/
|
22
|
+
|
23
|
+
puts
|
24
|
+
puts "VERSION = #{version}"
|
25
|
+
cmd = [ruby, ARGV].flatten.map { |s| s =~ /\"/ ? "'#{s}'" : s }.join(' ')
|
26
|
+
cmd.sub!(/#{ENV['HOME']}/, '~')
|
27
|
+
puts "CMD = #{cmd}"
|
28
|
+
puts
|
29
|
+
|
30
|
+
# prepend ruby binary path prior execution
|
31
|
+
ENV['PATH'] = [File.dirname(ruby), original_path].join(File::PATH_SEPARATOR)
|
32
|
+
|
33
|
+
system ruby, *ARGV
|
34
|
+
puts
|
35
|
+
puts "RESULT = #{$?}"
|
36
|
+
results[version] = $?
|
37
|
+
|
38
|
+
# restore the path to original state
|
39
|
+
ENV['PATH'] = original_path
|
40
|
+
end
|
41
|
+
|
42
|
+
passed, failed = results.keys.partition { |v| results[v] == 0 }
|
43
|
+
|
44
|
+
puts
|
45
|
+
puts "TOTAL RESULT = #{failed.size} failures out of #{results.size}"
|
46
|
+
puts
|
47
|
+
puts "Passed: #{passed.join(", ")}"
|
48
|
+
puts "Failed: #{failed.join(", ")}"
|
49
|
+
|
50
|
+
exit failed.size
|
data/bin/multiruby_setup
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
|
3
|
+
require 'multiruby'
|
4
|
+
|
5
|
+
ENV.delete 'RUBYOPT'
|
6
|
+
|
7
|
+
ARGV << "help" if ARGV.empty?
|
8
|
+
|
9
|
+
Dir.chdir Multiruby.root_dir
|
10
|
+
Multiruby.setup_dirs(false)
|
11
|
+
|
12
|
+
ARGV.each do |spec|
|
13
|
+
case spec
|
14
|
+
when "-h", "--help", "help" then
|
15
|
+
Multiruby.help
|
16
|
+
exit 0
|
17
|
+
when "the_usual" then # TODO: update #help
|
18
|
+
ARGV.push(*Multiruby::TAGS.map { |v| "mri:tar:#{v.gsub(/_/, '.')}" })
|
19
|
+
ARGV << "build" << "update:rubygems"
|
20
|
+
system "multigem install --no-ri --no-rdoc rake minitest ZenTest"
|
21
|
+
when "build" then
|
22
|
+
Multiruby.build_and_install
|
23
|
+
when "clean" then
|
24
|
+
Multiruby.clean
|
25
|
+
when "list" then
|
26
|
+
Multiruby.list
|
27
|
+
when /rm:(.*)/ then
|
28
|
+
Multiruby.rm $1
|
29
|
+
when "rubygems:merge" then
|
30
|
+
Multiruby.merge_rubygems
|
31
|
+
when "rubygems:update", "update:rubygems" then
|
32
|
+
Multiruby.update_rubygems
|
33
|
+
when "update" then
|
34
|
+
Multiruby.update
|
35
|
+
when "tags" then
|
36
|
+
p Multiruby.tags
|
37
|
+
when "mri:svn:current" then
|
38
|
+
ARGV << "mri:svn:releases" << "mri:svn:branches" << "build"
|
39
|
+
when "mri:svn:releases" then
|
40
|
+
Multiruby::TAGS.each do |v|
|
41
|
+
latest = Multiruby.mri_latest_tag v
|
42
|
+
abort "Can't find tag #{v}" unless latest
|
43
|
+
ARGV << "mri:svn:tag:#{latest}:mri_rel_#{v}"
|
44
|
+
end
|
45
|
+
ARGV << "build"
|
46
|
+
when /mri:svn:branch:(.*)/ then
|
47
|
+
ver = "branches/ruby_#{$1}" unless ver == "trunk"
|
48
|
+
Multiruby.svn_co "#{Multiruby::MRI_SVN}/#{$1}", "mri_#{$1}"
|
49
|
+
ARGV << "build"
|
50
|
+
when "mri:svn:branches" then
|
51
|
+
Multiruby::BRANCHES.each do |v|
|
52
|
+
ARGV << "mri:svn:branch:#{v}"
|
53
|
+
end
|
54
|
+
ARGV << "build"
|
55
|
+
when /mri:svn:tag:(.*):(.*)/ then
|
56
|
+
Multiruby.svn_co "#{Multiruby::MRI_SVN}/tags/#{$1}", $2
|
57
|
+
ARGV << "build"
|
58
|
+
when /mri:svn:tag:(.*)/ then
|
59
|
+
ARGV << "mri:svn:tag:#{$1}:#{$1}" << "build"
|
60
|
+
when /mri:tar:(.*)/ then
|
61
|
+
Multiruby.fetch_tar $1
|
62
|
+
ARGV << "build"
|
63
|
+
when /rbx:git:current/ then
|
64
|
+
Multiruby.git_clone "#{Multiruby::RBX_GIT}", "rubinius"
|
65
|
+
ARGV << "build"
|
66
|
+
when /rbx:ln:(.*)/ then
|
67
|
+
Multiruby.rbx_ln $1
|
68
|
+
ARGV << "build"
|
69
|
+
else
|
70
|
+
warn "unknown spec #{spec}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
data/bin/zentest
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/local/bin/ruby -swI .
|
2
|
+
|
3
|
+
require 'zentest'
|
4
|
+
|
5
|
+
$TESTING = true # for ZenWeb and any other testing infrastructure code
|
6
|
+
|
7
|
+
if defined? $v then
|
8
|
+
puts "#{File.basename $0} v#{ZenTest::VERSION}"
|
9
|
+
exit 0
|
10
|
+
end
|
11
|
+
|
12
|
+
if defined? $h then
|
13
|
+
puts "usage: #{File.basename $0} [-h -v] test-and-implementation-files..."
|
14
|
+
puts " -h display this information"
|
15
|
+
puts " -v display version information"
|
16
|
+
puts " -r Reverse mapping (ClassTest instead of TestClass)"
|
17
|
+
puts " -e (Rapid XP) eval the code generated instead of printing it"
|
18
|
+
exit 0
|
19
|
+
end
|
20
|
+
|
21
|
+
code = ZenTest.fix(*ARGV)
|
22
|
+
if defined? $e then
|
23
|
+
require 'test/unit'
|
24
|
+
eval code
|
25
|
+
else
|
26
|
+
print code
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
# require 'autotest/autoupdate'
|
4
|
+
# require 'autotest/once'
|
5
|
+
# require 'autotest/rcov'
|
6
|
+
# require 'autotest/restart'
|
7
|
+
# require 'autotest/timestamp'
|
8
|
+
|
9
|
+
# Autotest::AutoUpdate.sleep_time = o
|
10
|
+
# Autotest::AutoUpdate.update_cmd = o
|
11
|
+
# Autotest::RCov.command = o
|
12
|
+
# Autotest::RCov.pattern = o
|
data/lib/focus.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class Module
|
2
|
+
def focus *wanteds
|
3
|
+
wanteds.map! { |m| m.to_s }
|
4
|
+
unwanteds = public_instance_methods(false).grep(/test_/) - wanteds
|
5
|
+
unwanteds.each do |unwanted|
|
6
|
+
remove_method unwanted
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def blur
|
11
|
+
parent = self.superclass
|
12
|
+
|
13
|
+
ObjectSpace.each_object Class do |klass|
|
14
|
+
next unless parent > klass
|
15
|
+
next if klass == self
|
16
|
+
|
17
|
+
klass.send :focus
|
18
|
+
klass.send :undef_method, :default_test
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,92 @@
|
|
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, :OK, :e_NF, :mod, ...
|
18
|
+
# action :action2, :OK, :e_RO, :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
|
+
# Use :OK to specify the standard positive state. It is equivalent to
|
44
|
+
# a result with the same name as the action. (eg
|
45
|
+
# matrix_test_index). This cleans up the matrix a lot and allows for
|
46
|
+
# narrower and more readable columns.
|
47
|
+
#
|
48
|
+
# Edge cases specific to an action that fall outside the matrix are
|
49
|
+
# regular tests.
|
50
|
+
#
|
51
|
+
########################################################################
|
52
|
+
# Matrix Methods (the legos):
|
53
|
+
#
|
54
|
+
# Everything else basically equates to lego pieces:
|
55
|
+
#
|
56
|
+
# + There is one "init" method per matrix: matrix_init_#{descr}(setup_args)
|
57
|
+
# + There is one "setup" method per action: matrix_setup_#{action}(setup, expect)
|
58
|
+
# + There is one "test" method per result: matrix_test_#{result}(setup)
|
59
|
+
#
|
60
|
+
# Thus, for the matrix "example" above, the top left-most test will
|
61
|
+
# end up calling:
|
62
|
+
#
|
63
|
+
# matrix_init_example(:edge1)
|
64
|
+
# matrix_setup_action1(:edge1, :new)
|
65
|
+
# matrix_test_new(:edge1)
|
66
|
+
#
|
67
|
+
# Read the action method for exact details.
|
68
|
+
########################################################################
|
69
|
+
|
70
|
+
module FunctionalTestMatrix
|
71
|
+
def matrix(name, *setups)
|
72
|
+
@@matrix, @@setups = name, setups
|
73
|
+
end
|
74
|
+
|
75
|
+
def action(action, *results)
|
76
|
+
testcases = @@setups.zip(results).reject { |a,b| b == :na }
|
77
|
+
testcases = Hash[*testcases.flatten]
|
78
|
+
matrix = @@matrix # bind to local scope for define_method closure
|
79
|
+
|
80
|
+
testcases.each do |setup, expected|
|
81
|
+
expected_action = expected == :OK ? action : expected
|
82
|
+
define_method "test_#{matrix}_#{action}_#{setup}" do
|
83
|
+
@action = action
|
84
|
+
send "matrix_init_#{matrix}", *setup.to_s.split(/_/).map {|c| c.intern }
|
85
|
+
send "matrix_setup_#{action}", setup, expected
|
86
|
+
send "matrix_test_#{expected_action}", setup
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module_function :matrix, :action
|
92
|
+
end
|