rubytest 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,11 @@
1
+ Test.run(:default) do |run|
2
+ run.files << 'test/*_case.rb'
3
+ end
4
+
5
+ Test.run(:cov) do |run|
6
+ run.files << 'test/*_case.rb'
7
+ SimpleCov.start do |cov|
8
+ cov.coverage_dir = 'log/coverage'
9
+ end
10
+ end
11
+
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubytest'
3
+ Test::Runner.cli(*ARGV)
4
+
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,2 @@
1
+ require 'test/runner'
2
+
@@ -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
+
@@ -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
@@ -0,0 +1,8 @@
1
+ class Exception
2
+ def set_assertion(boolean)
3
+ @assertion = boolean
4
+ end
5
+ def assertion?
6
+ @assertion
7
+ end
8
+ end