dohtest 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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