rubytest 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby +45 -0
- data/.test +11 -0
- data/HISTORY.md +43 -0
- data/NOTICE.md +33 -0
- data/README.md +112 -0
- data/bin/rubytest +4 -0
- data/demo/01_test.md +29 -0
- data/demo/02_case.md +34 -0
- data/demo/applique/ruby-test.rb +2 -0
- data/lib/rubytest/autorun.rb +19 -0
- data/lib/rubytest/cli.rb +106 -0
- data/lib/rubytest/code_snippet.rb +93 -0
- data/lib/rubytest/config.rb +106 -0
- data/lib/rubytest/core_ext/assertion.rb +30 -0
- data/lib/rubytest/core_ext/exception.rb +8 -0
- data/lib/rubytest/core_ext/string.rb +30 -0
- data/lib/rubytest/core_ext.rb +9 -0
- data/lib/rubytest/rake.rb +124 -0
- data/lib/rubytest/recorder.rb +53 -0
- data/lib/rubytest/reporters/abstract.rb +261 -0
- data/lib/rubytest/reporters/abstract_hash.rb +224 -0
- data/lib/rubytest/reporters/dotprogress.rb +89 -0
- data/lib/rubytest/reporters/html.rb +155 -0
- data/lib/rubytest/reporters/outline.rb +211 -0
- data/lib/rubytest/reporters/progress.rb +195 -0
- data/lib/rubytest/reporters/summary.rb +145 -0
- data/lib/rubytest/reporters/tap.rb +61 -0
- data/lib/rubytest/reporters/tapj.rb +53 -0
- data/lib/rubytest/reporters/tapy.rb +58 -0
- data/lib/rubytest/reporters/test.rb +51 -0
- data/lib/rubytest/runner.rb +349 -0
- data/lib/rubytest.rb +28 -0
- data/lib/test.rb +8 -0
- data/test/basic_case.rb +11 -0
- metadata +119 -0
data/.ruby
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
---
|
2
|
+
source:
|
3
|
+
- var
|
4
|
+
authors:
|
5
|
+
- name: trans
|
6
|
+
email: transfire@gmail.com
|
7
|
+
copyrights:
|
8
|
+
- holder: RubyWorks
|
9
|
+
year: '2011'
|
10
|
+
license: BSD-2-Clause
|
11
|
+
replacements: []
|
12
|
+
alternatives: []
|
13
|
+
requirements:
|
14
|
+
- name: ansi
|
15
|
+
- name: detroit
|
16
|
+
groups:
|
17
|
+
- build
|
18
|
+
development: true
|
19
|
+
- name: qed
|
20
|
+
groups:
|
21
|
+
- test
|
22
|
+
development: true
|
23
|
+
dependencies: []
|
24
|
+
conflicts: []
|
25
|
+
repositories:
|
26
|
+
- uri: git@github.com:rubyworks/ruby-test.git
|
27
|
+
scm: git
|
28
|
+
name: upstream
|
29
|
+
resources:
|
30
|
+
home: http://rubyworks.github.com/ruby-test
|
31
|
+
code: http://github.com/rubyworks/ruby-test
|
32
|
+
mail: http://groups.google.com/group/rubyworks-mailinglist
|
33
|
+
extra: {}
|
34
|
+
load_path:
|
35
|
+
- lib
|
36
|
+
revision: 0
|
37
|
+
created: '2011-07-23'
|
38
|
+
summary: Ruby Universal Test Harness
|
39
|
+
title: Ruby Test
|
40
|
+
version: 0.3.0
|
41
|
+
name: rubytest
|
42
|
+
description: ! "Ruby Test is a universal test harness for Ruby. It can handle any
|
43
|
+
compliant \ntest framework, even running tests from multiple frameworks in a single
|
44
|
+
pass."
|
45
|
+
date: '2011-12-23'
|
data/.test
ADDED
data/HISTORY.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# RELEASE HISTORY
|
2
|
+
|
3
|
+
## 0.3.0 / 2011-12-22
|
4
|
+
|
5
|
+
Technically this is a fairly minor release that improves backtrace output
|
6
|
+
and prepares the `LOAD_PATH` automtically if a `.ruby` file is present.
|
7
|
+
However, it is significant in that the name of the gem has been changed
|
8
|
+
from `test` to `rubytest`.
|
9
|
+
|
10
|
+
Changes:
|
11
|
+
|
12
|
+
* Change gem name to `rubytest`.
|
13
|
+
* Improve backtrace filtering in reporters.
|
14
|
+
* Setup `LOAD_PATH` based on .ruby file if present.
|
15
|
+
|
16
|
+
|
17
|
+
## 0.2.0 / 2011-08-10
|
18
|
+
|
19
|
+
With this release Ruby Test is essentially feature complete. Of course there
|
20
|
+
are plenty of tweaks and improvements yet to come, but Ruby Test is fully usable
|
21
|
+
at this point. Only one major aspect of the design remains in question --the
|
22
|
+
way per-testcase "before and after all" advice is handled. Other than that
|
23
|
+
the API fairly solid, even as this early state of development. Always helps
|
24
|
+
when you have a spec to go by!
|
25
|
+
|
26
|
+
Changes:
|
27
|
+
|
28
|
+
* Use Config class to look-up .test file.
|
29
|
+
* Support hard testing, topic and pre-case setup.
|
30
|
+
* Add autorun.rb runner script.
|
31
|
+
* Add a test reporter to use for testing Ruby Test itself.
|
32
|
+
* Improved dotprogess reporter's handling of omissions.
|
33
|
+
* Add unit selection to test runner.
|
34
|
+
|
35
|
+
|
36
|
+
## 0.1.0 / 2011-07-30
|
37
|
+
|
38
|
+
First release of Ruby Test.
|
39
|
+
|
40
|
+
Changes:
|
41
|
+
|
42
|
+
* It's Your Birthday!
|
43
|
+
|
data/NOTICE.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# COPYRIGHT NOTICES
|
2
|
+
|
3
|
+
## Ruby Test
|
4
|
+
|
5
|
+
**Project** | Ruby Test
|
6
|
+
--------------|------------------------------------------
|
7
|
+
**Website** | http://rubyworks.github.com/ruby-test
|
8
|
+
**License** | BSD-2-Clause
|
9
|
+
**Copyright** | (c) 2011 Rubyworks
|
10
|
+
|
11
|
+
Copyright 2011 Rubyworks. All rights reserved.
|
12
|
+
|
13
|
+
Redistribution and use in source and binary forms, with or without
|
14
|
+
modification, are permitted provided that the following conditions are met:
|
15
|
+
|
16
|
+
1. Redistributions of source code must retain the above copyright notice,
|
17
|
+
this list of conditions and the following disclaimer.
|
18
|
+
|
19
|
+
2. Redistributions in binary form must reproduce the above copyright
|
20
|
+
notice, this list of conditions and the following disclaimer in the
|
21
|
+
documentation and/or other materials provided with the distribution.
|
22
|
+
|
23
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
24
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
26
|
+
COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
27
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
28
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
29
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
30
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
31
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
32
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
|
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# Ruby Test
|
2
|
+
|
3
|
+
[Homepage](http://rubyworks.github.com/rubytest) /
|
4
|
+
[User Guide](http://wiki.github.com/rubyworks/rubytest) /
|
5
|
+
[Development](http://github.com/rubyworks/rubytest) /
|
6
|
+
[Issues](http://github.com/rubyworks/rubytest/issues)
|
7
|
+
|
8
|
+
## Description
|
9
|
+
|
10
|
+
Ruby Test is a universal test harness for Ruby that can be used by any Ruby
|
11
|
+
test framework. Ruby Test defines a simple specification for compliance, which
|
12
|
+
allows tests from various frameworks to all run
|
13
|
+
|
14
|
+
Ruby Test defines a straight-forward specification that any test framework can
|
15
|
+
easily support which allows Ruby Test to run the frameworks tests through a
|
16
|
+
single uniform user interface in a single pass.
|
17
|
+
|
18
|
+
## Specification
|
19
|
+
|
20
|
+
The universal access point for testing is the `$TEST_SUITE` global array. A test
|
21
|
+
framework need only add compliant test objects to `$TEST_SUITE`.
|
22
|
+
Ruby Test will iterate through these objects. If a test object responds to
|
23
|
+
`#call`, it is run as a test procedure. If it responds to `#each` it is iterated
|
24
|
+
over as a test case with each entry handled in the same manner. All test
|
25
|
+
objects must respond to `#to_s` so their description can be used in test
|
26
|
+
reports.
|
27
|
+
|
28
|
+
Any raised exception that responds to `#assertion?` in the affirmative is taken
|
29
|
+
to be a failed assertion rather than simply an error. Ruby Test extends the
|
30
|
+
Exception class to support this method for all exceptions.
|
31
|
+
|
32
|
+
A test framework may raise a `NotImplementedError` to have a test recorded
|
33
|
+
as "pending" --a _todo_ item to remind the developer of tests that still
|
34
|
+
need to be written. The `NotImplementedError` is a standard Ruby exception
|
35
|
+
and a subclass of `ScriptError`.
|
36
|
+
|
37
|
+
If the `NotImplmentedError` responds in the affirmative to `#assertion?` then
|
38
|
+
the test is taken to be a purposeful _omission_, rather than simply pending.
|
39
|
+
|
40
|
+
That is the crux of Ruby Test specification. Ruby Test supports some
|
41
|
+
additional features that can makes its usage even more convenient.
|
42
|
+
See the [Wiki](http://github.com/rubyworks/test/wiki) for further details.
|
43
|
+
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
There are a few ways to run tests. First, there is a command line tool:
|
48
|
+
|
49
|
+
$ rubytest
|
50
|
+
|
51
|
+
The command line tool takes various options, use `--help` to see them.
|
52
|
+
Be sure to load in your test framework or framework's Ruby Test adapter.
|
53
|
+
|
54
|
+
Preconfigurations can be defined in a `.test` file, e.g.
|
55
|
+
|
56
|
+
Test.run 'default' do |r|
|
57
|
+
r.format = 'progress'
|
58
|
+
r.requires << 'lemon'
|
59
|
+
r.files << 'test/*_case.rb'
|
60
|
+
end
|
61
|
+
|
62
|
+
There is also a 'rubytest/autorun.rb' library script that can be loaded which
|
63
|
+
creates an `at_exit` runner, for which `test.rb` provides a nice shortcut:
|
64
|
+
|
65
|
+
$ ruby -r test
|
66
|
+
|
67
|
+
There is also a Rake task.
|
68
|
+
|
69
|
+
require 'rubytest/rake'
|
70
|
+
|
71
|
+
Test::Rake::TestTask.new
|
72
|
+
|
73
|
+
A Detroit plugin is in the works and should be available soon.
|
74
|
+
|
75
|
+
|
76
|
+
## Installation
|
77
|
+
|
78
|
+
Ruby Test is available as Gem package.
|
79
|
+
|
80
|
+
$ gem install rubytest
|
81
|
+
|
82
|
+
|
83
|
+
## Requirements
|
84
|
+
|
85
|
+
Ruby Test uses the [ANSI](http://rubyworks.github.com/ansi) gem for color output.
|
86
|
+
|
87
|
+
Because of the "foundational" nature of this library we will look at removing
|
88
|
+
this dependencies for future versions, but for early development the
|
89
|
+
requirements does the job and does it well.
|
90
|
+
|
91
|
+
|
92
|
+
## Development
|
93
|
+
|
94
|
+
Ruby Test is still a "nuby" gem. Please feel OBLIGATED to help improve it ;-)
|
95
|
+
|
96
|
+
Ruby Test is a [RubyWorks](http://rubyworks.github.com) project. If you can't
|
97
|
+
contribue code, you can still help out by contributing to our development fund.
|
98
|
+
|
99
|
+
|
100
|
+
## Reference Material
|
101
|
+
|
102
|
+
[1] [Standard Definition Of Unit Test](http://c2.com/cgi/wiki?StandardDefinitionOfUnitTest)
|
103
|
+
|
104
|
+
|
105
|
+
## Copyrights
|
106
|
+
|
107
|
+
Copyright (c) 2011 Rubyworks
|
108
|
+
|
109
|
+
Made available according to the terms of the <b>FreeBSD license</b>.
|
110
|
+
|
111
|
+
See NOTICE.md for details.
|
112
|
+
|
data/bin/rubytest
ADDED
data/demo/01_test.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
## Defining a Test
|
2
|
+
|
3
|
+
Any object in a test suite that responds to #call, will be executed as
|
4
|
+
a test. For instance, given an abtriray object defined as follows.
|
5
|
+
|
6
|
+
test = Object.new
|
7
|
+
|
8
|
+
def test.okay
|
9
|
+
@okay
|
10
|
+
end
|
11
|
+
|
12
|
+
def test.call
|
13
|
+
@okay = true
|
14
|
+
end
|
15
|
+
|
16
|
+
If we pass this to a test runner as part of a test suite,
|
17
|
+
|
18
|
+
runner = Test::Runner.new(:suite=>[test], :format=>'test')
|
19
|
+
|
20
|
+
success = runner.run
|
21
|
+
|
22
|
+
We will see that the test was called.
|
23
|
+
|
24
|
+
test.assert.okay
|
25
|
+
|
26
|
+
And testing was successful.
|
27
|
+
|
28
|
+
success.assert == true
|
29
|
+
|
data/demo/02_case.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
## Defining a Test Case
|
2
|
+
|
3
|
+
Any object in a test suite that responds to #each, will be iterated over
|
4
|
+
and each entry run a test or another sub-case. For instance, given an abitrary
|
5
|
+
object defined as follows.
|
6
|
+
|
7
|
+
test = Object.new
|
8
|
+
|
9
|
+
def test.okay
|
10
|
+
@okay
|
11
|
+
end
|
12
|
+
|
13
|
+
def test.call
|
14
|
+
@okay = true
|
15
|
+
end
|
16
|
+
|
17
|
+
And placed into an array.
|
18
|
+
|
19
|
+
tests = [test]
|
20
|
+
|
21
|
+
If we pass this to a test runner as part of a test suite,
|
22
|
+
|
23
|
+
runner = Test::Runner.new(:suite=>[tests], :format=>'test')
|
24
|
+
|
25
|
+
success = runner.run
|
26
|
+
|
27
|
+
We will see that the test was called.
|
28
|
+
|
29
|
+
test.assert.okay
|
30
|
+
|
31
|
+
And testing was successful.
|
32
|
+
|
33
|
+
success.assert == true
|
34
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#$TEST_SUITE = [] unless defined?($TEST_SUITE)
|
2
|
+
|
3
|
+
if RUBY_VERSION < '1.9'
|
4
|
+
require 'ruth'
|
5
|
+
else
|
6
|
+
require_relative '../ruth'
|
7
|
+
end
|
8
|
+
|
9
|
+
at_exit {
|
10
|
+
suite = $TEST_SUITE
|
11
|
+
options = {
|
12
|
+
:format => ENV['rubytest-format'] # TODO: better name?
|
13
|
+
}
|
14
|
+
|
15
|
+
runner = Ruth::Test::Runner.new(suite, options)
|
16
|
+
success = runner.run
|
17
|
+
exit -1 unless success
|
18
|
+
}
|
19
|
+
|
data/lib/rubytest/cli.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
module Test
|
2
|
+
|
3
|
+
# Command line interface.
|
4
|
+
class Runner
|
5
|
+
|
6
|
+
# Test runner command line interface.
|
7
|
+
#
|
8
|
+
def self.cli(*argv)
|
9
|
+
runner = Runner.new
|
10
|
+
|
11
|
+
Test::Config.load
|
12
|
+
|
13
|
+
cli_options(runner, argv)
|
14
|
+
|
15
|
+
Test::Config.load_path_setup #unless runner.autopath == false
|
16
|
+
|
17
|
+
begin
|
18
|
+
success = runner.run
|
19
|
+
exit -1 unless success
|
20
|
+
rescue => error
|
21
|
+
raise error if $DEBUG
|
22
|
+
$stderr.puts('ERROR: ' + error.to_s)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
def self.cli_options(runner, argv)
|
28
|
+
require 'optparse'
|
29
|
+
|
30
|
+
config = Test.config.dup
|
31
|
+
config_loaded = false
|
32
|
+
|
33
|
+
common = config.delete('common')
|
34
|
+
default = config.delete('default')
|
35
|
+
|
36
|
+
common.call(runner) if common
|
37
|
+
|
38
|
+
OptionParser.new do |opt|
|
39
|
+
opt.banner = "Usage: #{$0} [options] [files ...]"
|
40
|
+
|
41
|
+
unless config.empty?
|
42
|
+
opt.separator "PRESET OPTIONS:"
|
43
|
+
config.each do |name, block|
|
44
|
+
opt.on("--#{name}") do
|
45
|
+
block.call(runner)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
opt.separator "CONFIG OPTIONS:"
|
51
|
+
|
52
|
+
opt.on '-f', '--format NAME', 'report format' do |name|
|
53
|
+
runner.format = name
|
54
|
+
end
|
55
|
+
opt.on '-y', '--tapy', 'shortcut for -f tapy' do
|
56
|
+
runner.format = 'tapy'
|
57
|
+
end
|
58
|
+
opt.on '-j', '--tapj', 'shortcut for -f tapj' do
|
59
|
+
runner.format = 'tapj'
|
60
|
+
end
|
61
|
+
|
62
|
+
opt.on '-t', '--tag TAG', 'select tests by tag' do |tag|
|
63
|
+
runner.tags << tag
|
64
|
+
end
|
65
|
+
opt.on '-u', '--unit TAG', 'select tests by software unit' do |unit|
|
66
|
+
runner.units << unit
|
67
|
+
end
|
68
|
+
opt.on '-m', '--match TEXT', 'select tests by description' do |text|
|
69
|
+
runner.match << text
|
70
|
+
end
|
71
|
+
|
72
|
+
opt.on '-I', '--loadpath PATH', 'add to $LOAD_PATH' do |paths|
|
73
|
+
paths.split(/[:;]/).reverse_each do |path|
|
74
|
+
$LOAD_PATH.unshift path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
opt.on '-r', '--require FILE', 'require file' do |file|
|
78
|
+
require file
|
79
|
+
end
|
80
|
+
opt.on '-v' , '--verbose', 'provide extra detailed report' do
|
81
|
+
runner.verbose = true
|
82
|
+
end
|
83
|
+
#opt.on('--log DIRECTORY', 'log directory'){ |dir|
|
84
|
+
# options[:log] = dir
|
85
|
+
#}
|
86
|
+
opt.on_tail("--[no-]ansi" , 'turn on/off ANSI colors'){ |v| $ansi = v }
|
87
|
+
opt.on_tail("--debug" , 'turn on debugging mode'){ $DEBUG = true }
|
88
|
+
#opt.on_tail("--about" , 'display information about lemon'){
|
89
|
+
# puts "Ruby Test v#{VERSION}"
|
90
|
+
# puts "#{COPYRIGHT}"
|
91
|
+
# exit
|
92
|
+
#}
|
93
|
+
opt.on_tail('-h', '--help', 'display this help message'){
|
94
|
+
puts opt
|
95
|
+
exit
|
96
|
+
}
|
97
|
+
end.parse!(argv)
|
98
|
+
|
99
|
+
default.call(runner) if default && !config_loaded
|
100
|
+
|
101
|
+
runner.files.replace(argv) unless argv.empty?
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
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.exist?(file) ? File.readlines(file) : ['(N/A)']
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
def self.from_backtrace(backtrace)
|
14
|
+
backtrace.first =~ /(.+?):(\d+(?=:|\z))/ or return nil
|
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
|
@@ -0,0 +1,106 @@
|
|
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
|
+
# @todo Too many options for ruby-test configuration file.
|
27
|
+
GLOB_RC = '{.testrb,.test.rb,.test,.config/test.rb,config/test.rb}'
|
28
|
+
|
29
|
+
#
|
30
|
+
GLOB_ROOT = '{.ruby,.git,.hg}'
|
31
|
+
|
32
|
+
#
|
33
|
+
def self.load
|
34
|
+
super(rc_file) if rc_file
|
35
|
+
#Ruth.module_eval(File.read(rc_file)) if rc_file
|
36
|
+
end
|
37
|
+
|
38
|
+
# Find rc file.
|
39
|
+
def self.rc_file
|
40
|
+
@rc_file ||= (
|
41
|
+
glob = GLOB_RC
|
42
|
+
stop = root
|
43
|
+
default = nil
|
44
|
+
dir = Dir.pwd
|
45
|
+
file = nil
|
46
|
+
loop do
|
47
|
+
file = Dir[File.join(dir, glob)].first
|
48
|
+
break file if file
|
49
|
+
break if dir == stop
|
50
|
+
dir = File.dirname(dir)
|
51
|
+
break if dir == '/'
|
52
|
+
end
|
53
|
+
file ? file : default
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Find and cache project root directory.
|
58
|
+
#
|
59
|
+
# @return [String] Project's root path.
|
60
|
+
def self.root
|
61
|
+
@root ||= (
|
62
|
+
glob = GLOB_ROOT
|
63
|
+
stop = '/'
|
64
|
+
default = Dir.pwd
|
65
|
+
dir = Dir.pwd
|
66
|
+
until dir == stop
|
67
|
+
break dir if Dir[File.join(dir, glob)].first
|
68
|
+
dir = File.dirname(dir)
|
69
|
+
end
|
70
|
+
dir == stop ? default : dir
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Load and cache a project's `.ruby` file.
|
75
|
+
#
|
76
|
+
# @return [Hash] Project's loaded `.ruby` file, if it has one.
|
77
|
+
def self.dotruby
|
78
|
+
@dotruby ||= (
|
79
|
+
drfile = File.join(root, '.ruby')
|
80
|
+
if File.exist?(drfile)
|
81
|
+
YAML.load_file(drfile)
|
82
|
+
else
|
83
|
+
{}
|
84
|
+
end
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Setup $LOAD_PATH based on .ruby file.
|
89
|
+
#
|
90
|
+
# @todo Maybe we should not fallback to typical load path?
|
91
|
+
def self.load_path_setup
|
92
|
+
if load_paths = dotruby['load_path']
|
93
|
+
load_paths.each do |path|
|
94
|
+
$LOAD_PATH.unshift(File.join(root, path))
|
95
|
+
end
|
96
|
+
else
|
97
|
+
typical_load_path = File.join(root, 'lib')
|
98
|
+
if File.directory?(typical_load_path)
|
99
|
+
$LOAD_PATH.unshift(typical_load_path)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
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
|