tunit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
1
+ require 'tunit/reporter'
2
+
3
+ module Tunit
4
+ class CompoundReporter < Reporter
5
+ def initialize *reporters
6
+ super()
7
+ self.reporters = reporters
8
+ end
9
+ attr_accessor :reporters
10
+
11
+ def << reporter
12
+ self.reporters << reporter
13
+ end
14
+
15
+ def passed?
16
+ self.reporters.all?(&:passed?)
17
+ end
18
+
19
+ def start
20
+ self.reporters.each(&:start)
21
+ end
22
+
23
+ def record result
24
+ self.reporters.each do |reporter|
25
+ reporter.record result
26
+ end
27
+ end
28
+
29
+ def report
30
+ self.reporters.each(&:report)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ module Tunit
2
+ module Hooks
3
+ # Runs before each test
4
+ def setup
5
+ end
6
+
7
+ # Runs after each test
8
+ def teardown
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'tunit/reporter'
2
+
3
+ module Tunit
4
+ class ProgressReporter < Reporter
5
+ def record result
6
+ io.print result.code
7
+ io.print " = %s#%s (%.2f s)" % [result.class, result.name, result.time] if options[:verbose]
8
+ io.puts if options[:verbose]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ module Tunit
2
+ class Reporter
3
+ def initialize io = $stdout, options = {}
4
+ self.io = io
5
+ self.options = options
6
+ self.assertions = 0
7
+ self.count = 0
8
+ self.results = []
9
+ end
10
+ attr_accessor :io, :options, :assertions, :count, :results
11
+ attr_accessor :start_time, :total_time
12
+ attr_accessor :failures, :skips, :errors
13
+
14
+ def start
15
+ self.start_time = Time.now
16
+ end
17
+
18
+ def record result
19
+ self.count += 1
20
+ self.assertions += result.assertions
21
+
22
+ self.results << result if !result.passed? || result.skipped?
23
+ end
24
+
25
+ def passed?
26
+ results.all?(&:skipped?)
27
+ end
28
+
29
+ def report
30
+ total = results.group_by {|r| r.failure.class }
31
+ total.default = []
32
+
33
+ self.total_time = Time.now - start_time
34
+ self.failures = total[Assertion].size
35
+ self.failures += total[Empty].size
36
+ self.skips = total[Skip].size
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,51 @@
1
+ module Tunit
2
+ class Runnable
3
+ def self.runnable_methods
4
+ raise NotImplementedError, "subclass responsibility"
5
+ end
6
+
7
+ def self.runnables
8
+ @@runnables ||= []
9
+ end
10
+
11
+ def self.runnables= runnable
12
+ @@runnables = [runnable].flatten
13
+ end
14
+
15
+ def self.inherited klass
16
+ self.runnables << klass
17
+ super
18
+ end
19
+
20
+ def self.run reporter, options = {}
21
+ filter = options.fetch(:filter) { '/./' }
22
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
23
+
24
+ filtered_methods = self.runnable_methods.select { |m|
25
+ filter === m || filter === "#{self}##{m}"
26
+ }
27
+
28
+ filtered_methods.each { |test|
29
+ reporter.record self.new(test).run
30
+ }
31
+ end
32
+
33
+ def initialize name
34
+ self.name = name
35
+ self.assertions = 0
36
+ self.failures = []
37
+ end
38
+ attr_accessor :name, :assertions, :failures, :time
39
+
40
+
41
+ def run
42
+ fail NotImplementedError, "subclass responsibility"
43
+ end
44
+
45
+ private
46
+
47
+ def self.methods_matching re
48
+ public_instance_methods(true).grep(re).map(&:to_s)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,77 @@
1
+ require 'tunit/test'
2
+
3
+ module Kernel
4
+ # Override describe to avoid warnings and collisions with minitest/spec
5
+ alias_method :_old_describe, :describe if defined? Minitest
6
+ def describe desc, &blk
7
+ _old_describe desc, &blk if defined? Minitest
8
+
9
+ super_klass = if Class === self && is_a?(Tunit::Spec::DSL)
10
+ self
11
+ else
12
+ Tunit::Spec
13
+ end
14
+
15
+ klass = super_klass.create desc
16
+ klass.class_eval(&blk)
17
+ klass
18
+ end
19
+ end
20
+
21
+ module Tunit
22
+ class Spec < Test
23
+ module DSL
24
+ attr_reader :name
25
+
26
+ def before &block
27
+ define_method :setup do
28
+ self.instance_eval(&block)
29
+ end
30
+ end
31
+
32
+ def after &block
33
+ define_method :teardown do
34
+ self.instance_eval(&block)
35
+ end
36
+ end
37
+
38
+ def it desc, &block
39
+ block ||= -> { skip "(no tests defined)" }
40
+
41
+ @specs ||= 0
42
+ @specs += 1
43
+
44
+ test_name = desc.gsub " ", "_"
45
+ name = "test_%04d_%s" % [ @specs, test_name ]
46
+
47
+ define_method name, &block
48
+
49
+ name
50
+ end
51
+
52
+ def children
53
+ @children ||= []
54
+ end
55
+
56
+ def create name
57
+ klass = Class.new(self) {
58
+ @name = name
59
+
60
+ remove_test_methods!
61
+ }
62
+
63
+ children << klass
64
+
65
+ klass
66
+ end
67
+
68
+ def remove_test_methods!
69
+ self.runnable_methods.map { |test|
70
+ self.send :undef_method, test
71
+ }
72
+ end
73
+ end
74
+
75
+ extend DSL
76
+ end
77
+ end
@@ -0,0 +1,50 @@
1
+ require 'tunit/reporter'
2
+
3
+ module Tunit
4
+ class SummaryReporter < Reporter
5
+ SKIP_MSG = "\n\nYou have skipped tests. Run with --verbose for details."
6
+
7
+ def start
8
+ super
9
+
10
+ io.puts "Run options: #{options.inspect}"
11
+ io.puts
12
+ io.puts "# Running:"
13
+ io.puts
14
+ end
15
+
16
+ def report
17
+ super
18
+
19
+ io.puts unless options[:verbose]
20
+ io.puts
21
+ io.puts statistics
22
+ io.puts aggregated_results
23
+ io.puts summary
24
+ end
25
+
26
+ private
27
+
28
+ def statistics
29
+ "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
30
+ [total_time, count / total_time, assertions / total_time]
31
+ end
32
+
33
+ def aggregated_results
34
+ filtered_results = results.dup
35
+ filtered_results.reject!(&:skipped?) unless options[:verbose]
36
+
37
+ filtered_results.each_with_index.map do |result, index|
38
+ "\n%3d) %s" % [index + 1, result]
39
+ end.join + "\n"
40
+ end
41
+
42
+ def summary
43
+ extra = ""
44
+ extra << SKIP_MSG if results.any?(&:skipped?) && !options[:verbose]
45
+
46
+ "%d runs, %d assertions, %d failures, %d skips%s" %
47
+ [count, assertions, failures, skips, extra]
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,104 @@
1
+ require 'tunit/runnable'
2
+ require 'tunit/assertions'
3
+ require 'tunit/hooks'
4
+
5
+ module Tunit
6
+ class Test < Runnable
7
+ include Assertions
8
+ include Hooks
9
+ PREFIX = /^test_/
10
+
11
+ def self.runnable_methods
12
+ methods = methods_matching PREFIX
13
+ case self.test_order
14
+ when :random
15
+ max = methods.size
16
+ methods.sort.sort_by { rand max }
17
+ when :alpha
18
+ methods.sort
19
+ else
20
+ raise "Unknown test_order: #{self.test_order.inspect}"
21
+ end
22
+ end
23
+
24
+ # Randomize tests by default
25
+ def self.test_order
26
+ :random
27
+ end
28
+
29
+ def self.order!
30
+ class << self
31
+ undef_method :test_order if method_defined?(:test_order)
32
+ define_method(:test_order) { :alpha }
33
+ end
34
+ end
35
+
36
+ def run
37
+ capture_exceptions do
38
+ time_it do
39
+ setup
40
+ send name
41
+ end
42
+
43
+ if self.assertions.zero?
44
+ begin
45
+ fail ::Tunit::Empty, "Empty test, '#{self.to_s}'"
46
+ rescue ::Tunit::Empty => e
47
+ method_obj = self.method(name)
48
+ e.location = method_obj.source_location.join(":")
49
+ raise e
50
+ end
51
+ end
52
+ end
53
+
54
+ capture_exceptions do
55
+ teardown
56
+ end
57
+ self
58
+ end
59
+
60
+ def passed?
61
+ !failure
62
+ end
63
+
64
+ def skipped?
65
+ failure && Skip === failure
66
+ end
67
+
68
+ def failure
69
+ self.failures.first
70
+ end
71
+
72
+ def code
73
+ failure && failure.result_code || "."
74
+ end
75
+
76
+ def location
77
+ loc = " [#{self.failure.location}]" unless passed?
78
+ "#{self.class}##{self.name}#{loc}"
79
+ end
80
+
81
+ def to_s
82
+ return location if passed? && !skipped?
83
+
84
+ failures.map { |failure|
85
+ "#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n"
86
+ }.join "\n"
87
+ end
88
+
89
+ private
90
+
91
+ def time_it
92
+ t0 = Time.now
93
+ yield
94
+ ensure
95
+ self.time = Time.now - t0
96
+ end
97
+
98
+ def capture_exceptions
99
+ yield
100
+ rescue Assertion => e
101
+ self.failures << e
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,3 @@
1
+ module Tunit
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'tunit/test_case'
2
+ require 'tunit'
3
+
4
+ class TunitTest < Tunit::TestCase
5
+ def setup
6
+ Tunit.io = io
7
+ Tunit::Runnable.runnables = [PassingTest]
8
+ end
9
+
10
+ def test_run_gathers_reporters_under_compound_reporter
11
+ Tunit.run
12
+ assert_instance_of Tunit::CompoundReporter, Tunit.reporter
13
+ end
14
+
15
+ def test_run_dispatches_the_reporters_to_run
16
+ Tunit.run
17
+ assert Tunit.reporter.passed?
18
+ end
19
+ end
@@ -0,0 +1,95 @@
1
+ require_relative 'test_case'
2
+ require 'tunit/assertion_errors'
3
+ require 'tunit/test'
4
+
5
+ module Tunit
6
+ class AssertionErrotunit < TestCase
7
+ def setup
8
+ self.assertion = Assertion.new
9
+ end
10
+ attr_accessor :assertion
11
+
12
+ def test_error
13
+ assert_instance_of Assertion, assertion.error
14
+ end
15
+
16
+ def test_location
17
+ result = FailingTest.new.run
18
+ assertion = result.failure
19
+ exp_location = %r(.*/tunit/test/tunit/test_case.rb:\d{1,})
20
+
21
+ assert_match exp_location, assertion.location
22
+ end
23
+
24
+ def test_result_code
25
+ assert_equal "F", assertion.result_code
26
+ end
27
+
28
+ def test_result_label
29
+ assert_equal "Failure", assertion.result_label
30
+ end
31
+ end
32
+
33
+ class EmptyTest < TestCase
34
+ def setup
35
+ self.assertion = Empty.new
36
+ end
37
+ attr_accessor :assertion
38
+
39
+ def test_error
40
+ assert_instance_of Empty, assertion.error
41
+ end
42
+
43
+ def test_location
44
+ result = FailingTest.new(:test_empty).run
45
+ assertion = result.failure
46
+ exp_location = %r(.*/tunit/test/tunit/test_case.rb:\d{1,})
47
+
48
+ assert_match exp_location, assertion.location
49
+ end
50
+
51
+ def test_location_handles_unnamed_classes
52
+ result = Class.new(Test) {
53
+ def test_empty
54
+ end
55
+ }.new(:test_empty).run
56
+
57
+ refute_equal :not_set, result.failure.location
58
+ end
59
+
60
+ def test_result_code
61
+ assert_equal "_", assertion.result_code
62
+ end
63
+
64
+ def test_result_label
65
+ assert_equal "Empty", assertion.result_label
66
+ end
67
+ end
68
+
69
+ class SkipTest < TestCase
70
+ def setup
71
+ self.assertion = Skip.new
72
+ end
73
+ attr_accessor :assertion
74
+
75
+ def test_error
76
+ assert_instance_of Skip, assertion.error
77
+ end
78
+
79
+ def test_location
80
+ result = SkippedTest.new.run
81
+ assertion = result.failure
82
+ exp_location = %r(.*/tunit/test/tunit/test_case.rb:\d{1,})
83
+
84
+ assert_match exp_location, assertion.location
85
+ end
86
+
87
+ def test_result_code
88
+ assert_equal "S", assertion.result_code
89
+ end
90
+
91
+ def test_result_label
92
+ assert_equal "Skipped", assertion.result_label
93
+ end
94
+ end
95
+ end