test 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemspec +152 -0
- data/.gitignore +7 -0
- data/.ruby +43 -0
- data/.test +11 -0
- data/.yardopts +7 -0
- data/Assembly +46 -0
- data/COPYING.rdoc +31 -0
- data/HISTORY.md +29 -0
- data/LICENSE.txt +25 -0
- data/MANIFEST +38 -0
- data/PROFILE +31 -0
- data/README.md +110 -0
- data/VERSION +1 -0
- data/bin/ruby-test +4 -0
- data/lib/test.rb +3 -0
- data/lib/test/autorun.rb +18 -0
- data/lib/test/cli.rb +110 -0
- data/lib/test/code_snippet.rb +93 -0
- data/lib/test/config.rb +72 -0
- data/lib/test/core_ext.rb +9 -0
- data/lib/test/core_ext/assertion.rb +30 -0
- data/lib/test/core_ext/exception.rb +8 -0
- data/lib/test/core_ext/string.rb +30 -0
- data/lib/test/rake.rb +120 -0
- data/lib/test/recorder.rb +53 -0
- data/lib/test/reporters/abstract.rb +238 -0
- data/lib/test/reporters/abstract_hash.rb +224 -0
- data/lib/test/reporters/dotprogress.rb +89 -0
- data/lib/test/reporters/html.rb +155 -0
- data/lib/test/reporters/outline.rb +211 -0
- data/lib/test/reporters/progress.rb +197 -0
- data/lib/test/reporters/summary.rb +145 -0
- data/lib/test/reporters/tap.rb +61 -0
- data/lib/test/reporters/tapj.rb +53 -0
- data/lib/test/reporters/tapy.rb +53 -0
- data/lib/test/reporters/test.rb +51 -0
- data/lib/test/runner.rb +342 -0
- data/site/assets/images/test_pattern.jpg +0 -0
- data/site/index.html +31 -0
- data/spec/01_test.md +29 -0
- data/spec/02_case.md +34 -0
- data/spec/applique/ruby-test.rb +2 -0
- data/test/basic_case.rb +11 -0
- data/try/raw_example.rb +41 -0
- data/work/NOTES.md +17 -0
- metadata +129 -0
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/bin/ruby-test
ADDED
data/lib/test.rb
ADDED
data/lib/test/autorun.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$TEST_SUITE = [] unless defined?($TEST_SUITE)
|
2
|
+
|
3
|
+
at_exit {
|
4
|
+
if RUBY_VERSION < '1.9'
|
5
|
+
require 'test/runner'
|
6
|
+
else
|
7
|
+
require_relative 'runner'
|
8
|
+
end
|
9
|
+
|
10
|
+
suite = $TEST_SUITE
|
11
|
+
options = {
|
12
|
+
:format => ENV['ruby-test-format'] # TODO: better name?
|
13
|
+
}
|
14
|
+
|
15
|
+
runner = Test::Runner.new(suite, options)
|
16
|
+
success = runner.run
|
17
|
+
exit -1 unless success
|
18
|
+
}
|
data/lib/test/cli.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
module Test
|
2
|
+
|
3
|
+
require 'test/config'
|
4
|
+
require 'test/runner'
|
5
|
+
|
6
|
+
# Command line interface.
|
7
|
+
class Runner
|
8
|
+
|
9
|
+
# Test runner command line interface.
|
10
|
+
#
|
11
|
+
def self.cli(*argv)
|
12
|
+
runner = new
|
13
|
+
|
14
|
+
Test::Config.load
|
15
|
+
|
16
|
+
cli_options(runner, argv)
|
17
|
+
|
18
|
+
begin
|
19
|
+
# Add standard location if it exists.
|
20
|
+
$LOAD_PATH.unshift(File.expand_path('lib')) if File.directory?('lib')
|
21
|
+
|
22
|
+
success = runner.run
|
23
|
+
exit -1 unless success
|
24
|
+
rescue => error
|
25
|
+
raise error if $DEBUG
|
26
|
+
$stderr.puts('ERROR: ' + error.to_s)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
def self.cli_options(runner, argv)
|
32
|
+
require 'optparse'
|
33
|
+
|
34
|
+
config = Test.config.dup
|
35
|
+
config_loaded = false
|
36
|
+
|
37
|
+
common = config.delete('common')
|
38
|
+
default = config.delete('default')
|
39
|
+
|
40
|
+
common.call(runner) if common
|
41
|
+
|
42
|
+
OptionParser.new do |opt|
|
43
|
+
opt.banner = "Usage: #{$0} [options] [files ...]"
|
44
|
+
|
45
|
+
unless config.empty?
|
46
|
+
opt.separator "PRESET OPTIONS:"
|
47
|
+
config.each do |name, block|
|
48
|
+
opt.on("--#{name}") do
|
49
|
+
block.call(runner)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
opt.separator "CONFIG OPTIONS:"
|
55
|
+
|
56
|
+
opt.on '-f', '--format NAME', 'report format' do |name|
|
57
|
+
runner.format = name
|
58
|
+
end
|
59
|
+
opt.on '-y', '--tapy', 'shortcut for -f tapy' do
|
60
|
+
runner.format = 'tapy'
|
61
|
+
end
|
62
|
+
opt.on '-j', '--tapj', 'shortcut for -f tapj' do
|
63
|
+
runner.format = 'tapj'
|
64
|
+
end
|
65
|
+
|
66
|
+
opt.on '-t', '--tag TAG', 'select tests by tag' do |tag|
|
67
|
+
runner.tags << tag
|
68
|
+
end
|
69
|
+
opt.on '-u', '--unit TAG', 'select tests by software unit' do |unit|
|
70
|
+
runner.units << unit
|
71
|
+
end
|
72
|
+
opt.on '-m', '--match TEXT', 'select tests by description' do |text|
|
73
|
+
runner.match << text
|
74
|
+
end
|
75
|
+
|
76
|
+
opt.on '-I', '--loadpath PATH', 'add to $LOAD_PATH' do |paths|
|
77
|
+
paths.split(/[:;]/).reverse_each do |path|
|
78
|
+
$LOAD_PATH.unshift path
|
79
|
+
end
|
80
|
+
end
|
81
|
+
opt.on '-r', '--require FILE', 'require file' do |file|
|
82
|
+
require file
|
83
|
+
end
|
84
|
+
opt.on '-v' , '--verbose', 'provide extra detailed report' do
|
85
|
+
runner.verbose = true
|
86
|
+
end
|
87
|
+
#opt.on('--log DIRECTORY', 'log directory'){ |dir|
|
88
|
+
# options[:log] = dir
|
89
|
+
#}
|
90
|
+
opt.on_tail("--[no-]ansi" , 'turn on/off ANSI colors'){ |v| $ansi = v }
|
91
|
+
opt.on_tail("--debug" , 'turn on debugging mode'){ $DEBUG = true }
|
92
|
+
#opt.on_tail("--about" , 'display information about lemon'){
|
93
|
+
# puts "Ruby Test v#{VERSION}"
|
94
|
+
# puts "#{COPYRIGHT}"
|
95
|
+
# exit
|
96
|
+
#}
|
97
|
+
opt.on_tail('-h', '--help', 'display this help message'){
|
98
|
+
puts opt
|
99
|
+
exit
|
100
|
+
}
|
101
|
+
end.parse!(argv)
|
102
|
+
|
103
|
+
default.call(runner) if default && !config_loaded
|
104
|
+
|
105
|
+
runner.files.replace(argv) unless argv.empty?
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Test
|
2
|
+
|
3
|
+
# Thanks goes to Suraj N. Kurapati for the origins of this code.
|
4
|
+
#
|
5
|
+
class CodeSnippet
|
6
|
+
|
7
|
+
def self.cache(file)
|
8
|
+
@cache ||= {}
|
9
|
+
@cache[file] ||= File.readlines(file)
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
def self.from_backtrace(backtrace)
|
14
|
+
backtrace.first =~ /(.+?):(\d+(?=:|\z))/ or return ""
|
15
|
+
file, line = $1, $2.to_i
|
16
|
+
new(file, line)
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
def self.from_error(exception)
|
21
|
+
backtrace = exception.backtrace
|
22
|
+
from_backtrace(backtrace)
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
def initialize(file, line)
|
27
|
+
@file = file
|
28
|
+
@line = line || 1
|
29
|
+
@code = CodeSnippet.cache(file)
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
attr :file
|
34
|
+
|
35
|
+
#
|
36
|
+
attr :line
|
37
|
+
|
38
|
+
#
|
39
|
+
attr :code
|
40
|
+
|
41
|
+
#
|
42
|
+
alias :source :code
|
43
|
+
|
44
|
+
#
|
45
|
+
def to_str
|
46
|
+
code[line-1].strip
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
#--
|
51
|
+
# TODO: ensure proper alignment by zero-padding line numbers
|
52
|
+
#++
|
53
|
+
def to_s(radius=2)
|
54
|
+
r = range(radius)
|
55
|
+
f = " %2s %0#{r.last.to_s.length}d %s"
|
56
|
+
r.map do |n|
|
57
|
+
f % [('=>' if n == line), n, code[n-1].chomp]
|
58
|
+
end.join("\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
def to_a(radius=2)
|
63
|
+
r = range(radius)
|
64
|
+
r.map do |n|
|
65
|
+
code[n-1].chomp
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
def to_omap(radius=2)
|
71
|
+
a = []
|
72
|
+
r = range(radius)
|
73
|
+
r.each do |n|
|
74
|
+
a << {n => code[n-1].chomp}
|
75
|
+
end
|
76
|
+
a
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
def succ
|
81
|
+
line += 1
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
#
|
87
|
+
def range(radius)
|
88
|
+
[line - radius, 1].max..[line + radius, source.length].min
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
data/lib/test/config.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Test
|
2
|
+
|
3
|
+
#
|
4
|
+
def self.run(name=:default, &block)
|
5
|
+
@config ||= {}
|
6
|
+
@config[name.to_s] = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.config
|
10
|
+
@config ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
class Config
|
15
|
+
|
16
|
+
# Test configuration file.
|
17
|
+
#
|
18
|
+
# The name of the file is an ode to the original Ruby cli test tool.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# .test
|
22
|
+
# .testrb
|
23
|
+
# .test.rb
|
24
|
+
# .config/test.rb
|
25
|
+
#
|
26
|
+
GLOB_RC = '{.testrb,.test.rb,.test,.config/test.rb,config/test.rb}'
|
27
|
+
|
28
|
+
#
|
29
|
+
GLOB_ROOT = '{.ruby,.git,.hg}'
|
30
|
+
|
31
|
+
#
|
32
|
+
def self.load
|
33
|
+
super(rc_file) if rc_file
|
34
|
+
end
|
35
|
+
|
36
|
+
# Find rc file.
|
37
|
+
def self.rc_file
|
38
|
+
@rc_file ||= (
|
39
|
+
glob = GLOB_RC
|
40
|
+
stop = root
|
41
|
+
default = nil
|
42
|
+
dir = Dir.pwd
|
43
|
+
file = nil
|
44
|
+
loop do
|
45
|
+
file = Dir[File.join(dir, glob)].first
|
46
|
+
break file if file
|
47
|
+
break if dir == stop
|
48
|
+
dir = File.dirname(dir)
|
49
|
+
break if dir == '/'
|
50
|
+
end
|
51
|
+
file ? file : default
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Find project root.
|
56
|
+
def self.root
|
57
|
+
@root ||= (
|
58
|
+
glob = GLOB_ROOT
|
59
|
+
stop = '/'
|
60
|
+
default = Dir.pwd
|
61
|
+
dir = Dir.pwd
|
62
|
+
until dir == stop
|
63
|
+
break dir if Dir[File.join(dir, glob)].first
|
64
|
+
dir = File.dirname(dir)
|
65
|
+
end
|
66
|
+
dir == stop ? default : dir
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Assertion < Exception
|
2
|
+
|
3
|
+
# New assertion (failure).
|
4
|
+
#
|
5
|
+
# @param message [String] the failure message
|
6
|
+
# @param options [Hash] options such as :backtrace
|
7
|
+
#
|
8
|
+
def initialize(message=nil, options={})
|
9
|
+
super(message)
|
10
|
+
backtrace = options[:backtrace]
|
11
|
+
set_backtrace(backtrace) if backtrace
|
12
|
+
@assertion = true
|
13
|
+
end
|
14
|
+
|
15
|
+
# Technically any object that affirmatively responds to #assertion?
|
16
|
+
# can be taken to be an Assertion. This makes it easier for various
|
17
|
+
# libraries to work together without having to depend upon a common
|
18
|
+
# Assertion base class.
|
19
|
+
def assertion?
|
20
|
+
true # @assertion
|
21
|
+
end
|
22
|
+
|
23
|
+
# Parents error message prefixed with "(assertion)".
|
24
|
+
#
|
25
|
+
# @return [String] error message
|
26
|
+
def to_s
|
27
|
+
'(assertion) ' + super
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Preserves relative tabbing.
|
4
|
+
# The first non-empty line ends up with n spaces before nonspace.
|
5
|
+
#
|
6
|
+
# This is a Ruby Facet (http://rubyworks.github.com/facets).
|
7
|
+
|
8
|
+
def tabto(n)
|
9
|
+
if self =~ /^( *)\S/
|
10
|
+
indent(n - $1.length)
|
11
|
+
else
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end unless method_defined?(:tabto)
|
15
|
+
|
16
|
+
# Indent left or right by n spaces.
|
17
|
+
# (This used to be called #tab and aliased as #indent.)
|
18
|
+
#
|
19
|
+
# This is a Ruby Facet (http://rubyworks.github.com/facets).
|
20
|
+
|
21
|
+
def indent(n, c=' ')
|
22
|
+
if n >= 0
|
23
|
+
gsub(/^/, c * n)
|
24
|
+
else
|
25
|
+
gsub(/^#{Regexp.escape(c)}{0,#{-n}}/, "")
|
26
|
+
end
|
27
|
+
end unless method_defined?(:indent)
|
28
|
+
|
29
|
+
end
|
30
|
+
|
data/lib/test/rake.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'rake/tasklib'
|
2
|
+
|
3
|
+
module Test
|
4
|
+
|
5
|
+
module Rake
|
6
|
+
|
7
|
+
# Define a test rake task.
|
8
|
+
#
|
9
|
+
# The `TEST` environment variable can be used to select tests
|
10
|
+
# when using the task.
|
11
|
+
#
|
12
|
+
#--
|
13
|
+
# TODO: The test task uses #fork. Maybe it should shell out instead?
|
14
|
+
# Or provide the option for either?
|
15
|
+
#++
|
16
|
+
class TestTask < ::Rake::TaskLib
|
17
|
+
|
18
|
+
# Glob patterns are used by default to select test scripts.
|
19
|
+
DEFAULT_TESTS = [
|
20
|
+
'test/**/case_*.rb',
|
21
|
+
'test/**/*_case.rb',
|
22
|
+
'test/**/test_*.rb',
|
23
|
+
'test/**/*_test.rb'
|
24
|
+
]
|
25
|
+
|
26
|
+
# Test scripts to load. Can be a file glob.
|
27
|
+
attr_accessor :tests
|
28
|
+
|
29
|
+
# Paths to add to $LOAD_PATH.
|
30
|
+
attr_accessor :loadpath
|
31
|
+
|
32
|
+
# Scripts to load prior to loading tests.
|
33
|
+
attr_accessor :requires
|
34
|
+
|
35
|
+
# Report format to use.
|
36
|
+
attr_accessor :format
|
37
|
+
|
38
|
+
# Filter tests based by tags.
|
39
|
+
attr_accessor :tags
|
40
|
+
|
41
|
+
# Filter tests by matching description.
|
42
|
+
attr_accessor :match
|
43
|
+
|
44
|
+
#
|
45
|
+
def initialize(name='test', desc="run tests", &block)
|
46
|
+
@name = name
|
47
|
+
@desc = desc
|
48
|
+
|
49
|
+
@loadpath = ['lib']
|
50
|
+
@requires = []
|
51
|
+
@tests = [ENV['TEST'] || DEFAULT_TESTS].flatten
|
52
|
+
@format = nil
|
53
|
+
@match = nil
|
54
|
+
@tags = []
|
55
|
+
|
56
|
+
block.call(self)
|
57
|
+
|
58
|
+
define_task
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
def define_task
|
63
|
+
desc @desc
|
64
|
+
task @name do
|
65
|
+
@tests ||= default_tests
|
66
|
+
run
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
def run
|
72
|
+
fork {
|
73
|
+
#require 'test'
|
74
|
+
require 'test/runner'
|
75
|
+
|
76
|
+
loadpath.each { |d| $LOAD_PATH.unshift(d) }
|
77
|
+
requires.each { |f| require f }
|
78
|
+
test_files.each { |f| require f }
|
79
|
+
|
80
|
+
suite = $TEST_SUITE || []
|
81
|
+
runner = new(suite, :format=>format, :tags=>tags, :match=>match)
|
82
|
+
success = runner.run
|
83
|
+
|
84
|
+
exit -1 unless success
|
85
|
+
}
|
86
|
+
Process.wait
|
87
|
+
end
|
88
|
+
|
89
|
+
# Resolve test globs.
|
90
|
+
#--
|
91
|
+
# TODO: simplify?
|
92
|
+
#++
|
93
|
+
def test_files
|
94
|
+
files = tests
|
95
|
+
files = files.map{ |f| Dir[f] }.flatten
|
96
|
+
files = files.map{ |f| File.directory?(f) ? Dir[File.join(f, '**/*.rb')] : f }
|
97
|
+
files = files.flatten.uniq
|
98
|
+
files = files.map{ |f| File.expand_path(f) }
|
99
|
+
files
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
def default_tests
|
104
|
+
if ENV['tests']
|
105
|
+
ENV['tests'].split(/[:;]/)
|
106
|
+
else
|
107
|
+
DEFAULT_TESTS
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
#def ruby_command
|
113
|
+
# File.join(RbConfig::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
114
|
+
#end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|