dohtest 0.1.0

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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Makani Mason, Kem Mason
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/dohtest ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ require 'doh/options'
3
+ require 'doh/test/master_runner'
4
+ require 'doh/test/stream_output'
5
+
6
+ opts = Doh::Options.new(
7
+ {'grep' => [nil, "-g", "--grep <name>", "only execute tests with name that include the given value"] \
8
+ ,'glob' => ['*.dt.rb', "-b", "--glob <string>", "glob string to find test files"] \
9
+ ,'seed' => [nil, "-v", "--seed <number>", "random seed"] \
10
+ }, true, 'Files or directories may be specified to run tests on. Directories will be treated recursively. Defaults to the current directory.')
11
+
12
+ config = {}
13
+ config[:grep] = opts.grep if opts.grep
14
+ config[:glob] = opts.glob
15
+ config[:seed] = opts.seed.to_i if opts.seed
16
+ config[:paths] = (if opts.varargs.empty? then ['.'] else opts.varargs end)
17
+
18
+ exit DohTest::MasterRunner.new(DohTest::StreamOutput.new, config).run
@@ -0,0 +1,55 @@
1
+ module DohTest
2
+
3
+ AssertionFailed = Class.new(StandardError)
4
+
5
+ class TestGroup
6
+ def assert(condition, msg = nil)
7
+ if condition
8
+ @runner.assertion_passed
9
+ else
10
+ raise DohTest::AssertionFailed, msg || "Assertion failed."
11
+ end
12
+ end
13
+
14
+ def build_equal_msg(expected, actual)
15
+ if (expected.to_s.size + actual.to_s.size) < 50
16
+ "expected: #{expected}; actual: #{actual}"
17
+ else
18
+ "\nexpected: #{expected}\n actual: #{actual}"
19
+ end
20
+ end
21
+
22
+ def assert_equal(expected, actual, msg = nil)
23
+ assert(expected == actual, msg || build_equal_msg(expected, actual))
24
+ end
25
+
26
+ def assert_raises(*args)
27
+ msg = args.pop if args.last.is_a?(String)
28
+
29
+ begin
30
+ yield
31
+ no_exception = true
32
+ rescue Exception => excpt
33
+ assert(args.include?(excpt.class), msg || "expected: #{args}; actual: #{excpt}")
34
+ return
35
+ end
36
+
37
+ if no_exception
38
+ raise DohTest::AssertionFailed, msg || "expected: #{args}, but no exception was raised"
39
+ end
40
+ end
41
+
42
+ def assert_instance_of(expected_class, actual_object, msg = nil)
43
+ assert(actual_object.instance_of?(expected_class), msg || "expected class: #{expected_class}; actual: #{actual_object.class}")
44
+ end
45
+
46
+ def assert_match(expected_regex, actual_str, msg = nil)
47
+ assert(actual_str.match(expected_regex), msg || "expected regex #{expected_regex} to match str: #{actual_str}")
48
+ end
49
+
50
+ def assert_not_equal(expected, actual, msg = nil)
51
+ assert(expected != actual, msg || "expected unequal values")
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,64 @@
1
+ module DohTest
2
+
3
+ class BacktraceParser
4
+ def initialize(backtrace)
5
+ @backtrace = backtrace
6
+ end
7
+
8
+ def relevant_stack
9
+ @relevant_stack ||= find_relevant_stack
10
+ end
11
+
12
+ def summary
13
+ @summary ||= build_summary
14
+ end
15
+
16
+ private
17
+ def find_relevant_stack
18
+ retval = []
19
+ found_start = false
20
+ @backtrace.each do |location|
21
+ has_doh_test = location.index('doh/test')
22
+ if found_start && has_doh_test
23
+ break
24
+ elsif has_doh_test
25
+ # just ignore it and continue
26
+ else
27
+ found_start = true
28
+ info = location.rpartition(':in').first
29
+ retval << info
30
+ end
31
+ end
32
+ retval
33
+ end
34
+
35
+ def build_summary
36
+ retval = ''
37
+ prev_filename = ''
38
+ prev_simplified = ''
39
+ relevant_stack.each do |location|
40
+ parts = location.partition(':')
41
+ filename = File.basename(parts.first)
42
+ simplified = "#{filename}:#{parts.last}"
43
+ raise "unexpected location format: #{location}" unless filename
44
+ if simplified == prev_simplified
45
+ # ignore it
46
+ elsif filename == prev_filename
47
+ retval += ",#{parts.last}"
48
+ elsif retval.empty?
49
+ retval = simplified
50
+ else
51
+ retval += ";#{simplified}"
52
+ end
53
+ prev_filename = filename
54
+ prev_simplified = simplified
55
+ end
56
+ retval
57
+ end
58
+ end
59
+
60
+ def self.backtrace_summary(excpt)
61
+ BacktraceParser.new(excpt.backtrace).summary
62
+ end
63
+
64
+ end
@@ -0,0 +1,18 @@
1
+ require 'doh/root'
2
+
3
+ module DohTest
4
+
5
+ def self.configure(start_path)
6
+ start_directory = File.dirname(start_path)
7
+
8
+ root_directory = Doh::find_root(start_directory)
9
+ if root_directory
10
+ root_filename = File.join(root_directory, 'config', 'dohtest.rb')
11
+ require(root_filename) if File.exist?(root_filename)
12
+ end
13
+
14
+ local_filename = Doh::findup(start_directory, 'configure_dohtest.rb')
15
+ require(local_filename) if local_filename && File.exist?(local_filename)
16
+ end
17
+
18
+ end
@@ -0,0 +1,79 @@
1
+ require 'doh/test/test_group'
2
+
3
+ module DohTest
4
+
5
+ class GroupRunner
6
+ def initialize(group_class, output, config = nil)
7
+ @group_class,@output = group_class,output
8
+ @config = config || {}
9
+ @group_name = @group_class.to_s
10
+ @group_failed = false
11
+ end
12
+
13
+ def run
14
+ @output.group_begin(@group_name)
15
+ create_group
16
+ run_before_all unless @group_failed
17
+ run_tests unless @group_failed
18
+ run_after_all unless @group_failed
19
+ @output.group_end(@group_name)
20
+ end
21
+
22
+ def create_group
23
+ @group = @group_class.new
24
+ rescue => error
25
+ @group_failed = true
26
+ @output.test_error(@group_name, 'initialize', error)
27
+ else
28
+ @group.runner = self
29
+ end
30
+
31
+ def run_before_all
32
+ @group.before_all if @group.respond_to?(:before_all)
33
+ rescue => error
34
+ @group_failed = true
35
+ @output.test_error(@group_name, 'before_all', error)
36
+ end
37
+
38
+ def run_after_all
39
+ @group.after_all if @group.respond_to?(:after_all)
40
+ rescue => error
41
+ @output.test_error(@group_name, 'after_all', error)
42
+ end
43
+
44
+ def run_tests
45
+ determine_test_methods
46
+ has_before_each = @group.respond_to?(:before_each)
47
+ has_after_each = @group.respond_to?(:after_each)
48
+
49
+ @test_methods.each do |method_name|
50
+ @test_name = method_name
51
+ begin
52
+ @group.send(:before_each) if has_before_each
53
+ @output.test_begin(@group_name, @test_name)
54
+ @group.send(@test_name)
55
+ @output.test_end(@group_name, @test_name)
56
+ @group.send(:after_each) if has_after_each
57
+ rescue DohTest::AssertionFailed => failure
58
+ @output.assertion_failed(@group_name, @test_name, failure)
59
+ rescue => error
60
+ @output.test_error(@group_name, @test_name, error)
61
+ end
62
+ end
63
+ end
64
+
65
+ def determine_test_methods
66
+ @test_methods = @group_class.public_instance_methods.grep(/^test/)
67
+ original_test_count = @test_methods.size
68
+ return unless @config.key?(:grep)
69
+ grep_filter = Regexp.new(@config[:grep])
70
+ @test_methods.select! { |method| name.to_s =~ grep_filter }
71
+ @output.tests_skipped(@group_name, original_test_count - @test_methods.size)
72
+ end
73
+
74
+ def assertion_passed
75
+ @output.assertion_passed(@group_name, @test_name)
76
+ end
77
+ end
78
+
79
+ end
@@ -0,0 +1,31 @@
1
+ require 'doh/test/configure'
2
+ require 'doh/test/group_runner'
3
+ require 'doh/test/require_paths'
4
+
5
+ module DohTest
6
+
7
+ class MasterRunner
8
+ def initialize(output, config)
9
+ @output, @config = output, config
10
+ add_missing_config
11
+ end
12
+
13
+ def run
14
+ paths = @config[:paths]
15
+ DohTest::configure(paths[0])
16
+ DohTest::require_paths(@config[:glob], paths)
17
+ srand(@config[:seed])
18
+ @output.run_begin(@config)
19
+ TestGroup.descendants.each { |group_class| GroupRunner.new(group_class, @output, @config).run }
20
+ @output.run_end
21
+ end
22
+
23
+ private
24
+ def add_missing_config
25
+ @config[:glob] ||= '*.dt.rb'
26
+ @config[:seed] ||= (Time.new.to_f * 1000).to_i
27
+ @config[:paths] ||= ['.']
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,13 @@
1
+ module DohTest
2
+
3
+ def self.require_paths(glob, paths)
4
+ paths.collect {|elem| File.expand_path(elem) }.each do |onepath|
5
+ if File.directory?(onepath)
6
+ Dir.glob(File.join(onepath, '**', glob)).each {|filename| require(filename)}
7
+ else
8
+ require(File.expand_path(onepath))
9
+ end
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,67 @@
1
+ require 'doh/test/backtrace_parser'
2
+ require 'set'
3
+
4
+ module DohTest
5
+
6
+ class StreamOutput
7
+ def initialize
8
+ @error_count = @group_cnt = @tests_ran = @tests_skipped = @assertions_failed = @assertions_passed = 0
9
+ @badness = Set.new
10
+ end
11
+
12
+ def run_begin(config)
13
+ puts "running tests with config: #{config}"
14
+ end
15
+
16
+ def run_end
17
+ total_assertions = @assertions_passed + @assertions_failed
18
+ puts "\n\n#@error_count errors, #@group_cnt groups, #@tests_ran tests, #{@tests_skipped} skipped, #{total_assertions} assertions, #@assertions_passed passed, #@assertions_failed failed"
19
+ puts "completed in 0.043702s, 22.8822 tests/s, 45.7645 assertions/s <TODO: put real values here>"
20
+ # this is to generate an exit code; true translates to 0, false to 1
21
+ @error_count == 0 && @assertions_failed == 0
22
+ end
23
+
24
+ def group_begin(group_name)
25
+ @group_cnt += 1
26
+ end
27
+
28
+ def group_end(group_name)
29
+ puts "success in #{group_name}" unless @badness.include?(group_name)
30
+ end
31
+
32
+ def tests_skipped(group_name, count)
33
+ @tests_skipped += count
34
+ end
35
+
36
+ def test_begin(group_name, test_name)
37
+ end
38
+
39
+ def test_end(group_name, test_name)
40
+ @tests_ran += 1
41
+ end
42
+
43
+ def test_error(group_name, test_name, error)
44
+ @badness.add(group_name)
45
+ @error_count += 1
46
+ display_badness('error', group_name, test_name, error, true)
47
+ end
48
+
49
+ def assertion_failed(group_name, test_name, failure)
50
+ @badness.add(group_name)
51
+ @assertions_failed += 1
52
+ display_badness('failure', group_name, test_name, failure, false)
53
+ end
54
+
55
+ def assertion_passed(group_name, test_name)
56
+ @assertions_passed += 1
57
+ end
58
+
59
+ private
60
+ def display_badness(title, group_name, test_name, excpt, display_name)
61
+ warn "#{title} in #{group_name}.#{test_name} at #{DohTest::backtrace_summary(excpt)}"
62
+ badname = if display_name then "#{excpt.class}: " else '' end
63
+ warn "=> #{badname}#{excpt}"
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,17 @@
1
+ require 'doh/test/assertions'
2
+
3
+ module DohTest
4
+
5
+ class TestGroup
6
+ def self.descendants
7
+ @@descendants ||= []
8
+ end
9
+
10
+ def self.inherited(descendant)
11
+ descendants << descendant
12
+ end
13
+
14
+ attr_writer :runner
15
+ end
16
+
17
+ end
@@ -0,0 +1,77 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/doh/test/backtrace_parser'
3
+
4
+ module DohTest
5
+
6
+ class TestBacktraceParser < MiniTest::Unit::TestCase
7
+ def create_single_stack
8
+ retval = []
9
+ retval << "/Users/somebody/dohtest/lib/doh/test/assertions.rb:10:in `assert'"
10
+ retval << "/Users/somebody/dohtest/lib/doh/test/assertions.rb:15:in `assert_equal'"
11
+ retval << "/Users/somebody/tinker/test/frog.rb:12:in `test_thing'"
12
+ retval << "/Users/somebody/dohtest/lib/doh/test/group_runner.rb:28:in `block in run_group'"
13
+ retval << "/Users/somebody/dohtest/lib/doh/test/group_runner.rb:12:in `each'"
14
+ retval << "/Users/somebody/dohtest/lib/doh/test/group_runner.rb:12:in `run'"
15
+ retval << "/Users/somebody/dohtest/bin/dohtest:24:in `<main>'"
16
+ retval
17
+ end
18
+
19
+ def test_single_stack
20
+ location = DohTest::BacktraceParser.new(create_single_stack).summary
21
+ assert_equal("frog.rb:12", location)
22
+ end
23
+
24
+ def create_double_stack
25
+ retval = []
26
+ retval << "/Users/somebody/dohtest/lib/doh/test/assertions.rb:10:in `assert'"
27
+ retval << "/Users/somebody/tinker/test/frog.rb:5:in `verify_sum'"
28
+ retval << "/Users/somebody/tinker/test/frog.rb:12:in `test_thing'"
29
+ retval << "/Users/somebody/dohtest/lib/doh/test/group_runner.rb:28:in `block in run_group'"
30
+ retval
31
+ end
32
+
33
+ def test_double_stack
34
+ location = DohTest::BacktraceParser.new(create_double_stack).summary
35
+ assert_equal("frog.rb:5,12", location)
36
+ end
37
+
38
+ def create_multifile_stack
39
+ retval = []
40
+ retval << "/Users/somebody/dohtest/lib/doh/test/assertions.rb:10:in `assert'"
41
+ retval << "/Users/somebody/tinker/helpers/toad.rb:8:in `verify_sum'"
42
+ retval << "/Users/somebody/tinker/test/frog.rb:11:in `test_thing'"
43
+ retval << "/Users/somebody/dohtest/lib/doh/test/group_runner.rb:28:in `block in run_group'"
44
+ retval
45
+ end
46
+
47
+ def test_multifile_stack
48
+ location = DohTest::BacktraceParser.new(create_multifile_stack).summary
49
+ assert_equal("toad.rb:8;frog.rb:11", location)
50
+ end
51
+
52
+ def create_duplicate_stack
53
+ retval = []
54
+ retval << "/Users/somebody/tinker/dtest/blee.rb:30:in `/'"
55
+ retval << "/Users/somebody/tinker/dtest/blee.rb:30:in `test_silly_error'"
56
+ retval << "/Users/somebody/dohtest/lib/doh/test/group_runner.rb:28:in `block in run_group'"
57
+ retval
58
+ end
59
+
60
+ def test_duplicate_stack
61
+ location = DohTest::BacktraceParser.new(create_duplicate_stack).summary
62
+ assert_equal("blee.rb:30", location)
63
+ end
64
+
65
+ def create_block_stack
66
+ retval = []
67
+ retval << "/Users/somebody/tinker/dtest/kblah.rb:3:in `block in <class:TestKblah>'"
68
+ retval
69
+ end
70
+
71
+ def test_block_stack
72
+ location = DohTest::BacktraceParser.new(create_block_stack).summary
73
+ assert_equal("kblah.rb:3", location)
74
+ end
75
+ end
76
+
77
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dohtest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Makani Mason
9
+ - Kem Mason
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-01-27 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dohutil
17
+ requirement: &70176037590840 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70176037590840
26
+ description: This is a fairly straight forward replacement for minitest, though some
27
+ changes to test code are required. Code is meant to be easy to understand and extend.
28
+ Includes dohtest to make execution convenient. Designed for speed, including running
29
+ tests concurrently (though as of this version that's not implemented).
30
+ email:
31
+ - gitauthor@pqmland.com
32
+ executables:
33
+ - dohtest
34
+ extensions: []
35
+ extra_rdoc_files:
36
+ - MIT-LICENSE
37
+ files:
38
+ - bin/dohtest
39
+ - lib/doh/test/assertions.rb
40
+ - lib/doh/test/backtrace_parser.rb
41
+ - lib/doh/test/configure.rb
42
+ - lib/doh/test/group_runner.rb
43
+ - lib/doh/test/master_runner.rb
44
+ - lib/doh/test/require_paths.rb
45
+ - lib/doh/test/stream_output.rb
46
+ - lib/doh/test/test_group.rb
47
+ - test/test_backtrace_parser.rb
48
+ - MIT-LICENSE
49
+ homepage: https://github.com/pquimo/dohtest
50
+ licenses:
51
+ - MIT
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.9.2
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.10
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Minimalist unit test framework.
74
+ test_files:
75
+ - test/test_backtrace_parser.rb