tunit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +113 -0
- data/Rakefile +9 -0
- data/example_spec.rb +35 -0
- data/example_test.rb +23 -0
- data/lib/tunit.rb +83 -0
- data/lib/tunit/assertion_errors.rb +43 -0
- data/lib/tunit/assertions.rb +68 -0
- data/lib/tunit/autorun.rb +8 -0
- data/lib/tunit/compound_reporter.rb +33 -0
- data/lib/tunit/hooks.rb +11 -0
- data/lib/tunit/progress_reporter.rb +11 -0
- data/lib/tunit/reporter.rb +39 -0
- data/lib/tunit/runnable.rb +51 -0
- data/lib/tunit/spec.rb +77 -0
- data/lib/tunit/summary_reporter.rb +50 -0
- data/lib/tunit/test.rb +104 -0
- data/lib/tunit/version.rb +3 -0
- data/test/rtest_test.rb +19 -0
- data/test/tunit/assertion_errors_test.rb +95 -0
- data/test/tunit/assertions_test.rb +68 -0
- data/test/tunit/progress_reporter_test.rb +45 -0
- data/test/tunit/reporter_test.rb +66 -0
- data/test/tunit/runnable_test.rb +69 -0
- data/test/tunit/spec_test.rb +57 -0
- data/test/tunit/summary_reporter_test.rb +116 -0
- data/test/tunit/test_case.rb +72 -0
- data/test/tunit/test_test.rb +181 -0
- data/tunit.gemspec +24 -0
- metadata +127 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative 'test_case'
|
2
|
+
require 'tunit/assertions'
|
3
|
+
require 'tunit/test'
|
4
|
+
|
5
|
+
module Tunit
|
6
|
+
class AssertionsTest < TestCase
|
7
|
+
def setup
|
8
|
+
self.tc = Class.new(Test).new "name"
|
9
|
+
self.assertion_count = 0
|
10
|
+
end
|
11
|
+
attr_accessor :tc, :assertion_count
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
assert_equal assertion_count, tc.assertions,
|
15
|
+
"Expected #{assertion_count} assertions to have been made to #{tc.inspect}, but was #{tc.assertions}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_assert
|
19
|
+
self.assertion_count = 1
|
20
|
+
tc.assert "truthy"
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_refute
|
24
|
+
self.assertion_count = 1
|
25
|
+
tc.refute false
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_assert_equal
|
29
|
+
self.assertion_count = 1
|
30
|
+
tc.assert_equal 1, 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_refute_equal
|
34
|
+
self.assertion_count = 1
|
35
|
+
tc.refute_equal 1, 2
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_assert_includes
|
39
|
+
self.assertion_count = 2
|
40
|
+
tc.assert_includes [2], 2
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_refute_includes
|
44
|
+
self.assertion_count = 2
|
45
|
+
tc.refute_includes [1], 2
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_assert_respond_to
|
49
|
+
self.assertion_count = 1
|
50
|
+
tc.assert_respond_to tc, :assert
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_refute_respond_to
|
54
|
+
self.assertion_count = 1
|
55
|
+
tc.refute_respond_to tc, :omg
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_assert_instance_of
|
59
|
+
self.assertion_count = 1
|
60
|
+
tc.assert_instance_of String, "omg"
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_refute_instance_of
|
64
|
+
self.assertion_count = 1
|
65
|
+
tc.refute_instance_of String, 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative 'test_case'
|
2
|
+
require 'tunit/progress_reporter'
|
3
|
+
|
4
|
+
module Tunit
|
5
|
+
class ProgressReporterTest < TestCase
|
6
|
+
def setup
|
7
|
+
self.reporter = ProgressReporter.new io
|
8
|
+
end
|
9
|
+
attr_accessor :reporter
|
10
|
+
|
11
|
+
def test_record_passing_tests
|
12
|
+
reporter.record PassingTest.new.run
|
13
|
+
|
14
|
+
assert_equal ".", io.string
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_record_skipped_tests
|
18
|
+
reporter.record SkippedTest.new.run
|
19
|
+
|
20
|
+
assert_equal "S", io.string
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_record_failing_tests
|
24
|
+
reporter.record FailingTest.new.run
|
25
|
+
|
26
|
+
assert_equal "F", io.string
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_record_empty_tests
|
30
|
+
reporter.record FailingTest.new(:test_empty).run
|
31
|
+
|
32
|
+
assert_equal "_", io.string
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_record_is_very_verbose
|
36
|
+
reporter = ProgressReporter.new io, verbose: true
|
37
|
+
reporter.record PassingTest.new(:test_pass).run
|
38
|
+
exp_verbosity = <<-EOS
|
39
|
+
. = Tunit::TestCase::PassingTest#test_pass (0.00 s)
|
40
|
+
EOS
|
41
|
+
|
42
|
+
assert_equal exp_verbosity, io.string
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative './test_case'
|
2
|
+
require 'tunit/reporter'
|
3
|
+
|
4
|
+
module Tunit
|
5
|
+
class ReporterTest < TestCase
|
6
|
+
def setup
|
7
|
+
self.reporter = Reporter.new
|
8
|
+
end
|
9
|
+
attr_accessor :reporter
|
10
|
+
|
11
|
+
def test_start_time
|
12
|
+
reporter.start
|
13
|
+
|
14
|
+
assert_instance_of Time, reporter.start_time
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_record_passing_test
|
18
|
+
reporter.record PassingTest.new.run
|
19
|
+
|
20
|
+
assert_equal 1, reporter.count
|
21
|
+
assert_equal 1, reporter.assertions
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_record_failing_test
|
25
|
+
reporter.record FailingTest.new.run
|
26
|
+
|
27
|
+
assert_equal 1, reporter.results.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_passed_eh
|
31
|
+
reporter.record PassingTest.new.run
|
32
|
+
|
33
|
+
assert reporter.passed?
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_passed_eh_is_only_for_passing_tests
|
37
|
+
reporter.record FailingTest.new.run
|
38
|
+
|
39
|
+
refute reporter.passed?
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_report_collects_total_time
|
43
|
+
reporter.start
|
44
|
+
reporter.record PassingTest.new.run
|
45
|
+
reporter.report
|
46
|
+
|
47
|
+
assert_instance_of Float, reporter.total_time
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_report_collects_failures
|
51
|
+
reporter.start
|
52
|
+
reporter.record FailingTest.new.run
|
53
|
+
reporter.report
|
54
|
+
|
55
|
+
assert_equal 1, reporter.failures
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_report_collects_skips
|
59
|
+
reporter.start
|
60
|
+
reporter.record SkippedTest.new.run
|
61
|
+
reporter.report
|
62
|
+
|
63
|
+
assert_equal 1, reporter.skips
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'test_case'
|
2
|
+
require 'tunit/runnable'
|
3
|
+
|
4
|
+
module Tunit
|
5
|
+
class RunnableTest < TestCase
|
6
|
+
def test_runnable_methods_is_a_subclass_responsibility
|
7
|
+
e = assert_raises NotImplementedError do
|
8
|
+
Runnable.runnable_methods
|
9
|
+
end
|
10
|
+
|
11
|
+
exp = "subclass responsibility"
|
12
|
+
assert_equal exp, e.message
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_runnables_list_all_runnables_that_inherit_from_runnable
|
16
|
+
assert_includes Runnable.runnables, PassingTest
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_runnables_custom
|
20
|
+
prev_runnables = Runnable.runnables
|
21
|
+
|
22
|
+
Runnable.runnables = "omg"
|
23
|
+
assert_includes Runnable.runnables, "omg"
|
24
|
+
|
25
|
+
# reset Runnable.runnables to avoid mishaps, teardown didn't pull through
|
26
|
+
ensure
|
27
|
+
Runnable.runnables = prev_runnables
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_run_runs_all_tests_with_a_given_reporter
|
31
|
+
PassingTest.run dummy_reporter, io: io
|
32
|
+
|
33
|
+
assert_equal dummy_reporter.report, PassingTest.runnable_methods.size
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_run_runs_all_tests_with_matching_pattern
|
37
|
+
filter = "test_pass_one_more"
|
38
|
+
matched_methods = PassingTest.runnable_methods.grep(/#{filter}/).size
|
39
|
+
|
40
|
+
PassingTest.run dummy_reporter, io: io, filter: filter
|
41
|
+
|
42
|
+
assert_equal dummy_reporter.report, matched_methods
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_runnable_methods_can_be_customized_to_find_your_tests
|
46
|
+
super_klass = Class.new(Runnable) {
|
47
|
+
def self.runnable_methods
|
48
|
+
methods_matching(/^spec_/)
|
49
|
+
end
|
50
|
+
}
|
51
|
+
|
52
|
+
klass = Class.new(super_klass) {
|
53
|
+
def spec_foo; end
|
54
|
+
def foo_test; end
|
55
|
+
}
|
56
|
+
|
57
|
+
assert_includes klass.runnable_methods, "spec_foo"
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_run_is_a_subclass_responsibility
|
61
|
+
e = assert_raises NotImplementedError do
|
62
|
+
Runnable.new("name").run
|
63
|
+
end
|
64
|
+
|
65
|
+
exp = "subclass responsibility"
|
66
|
+
assert_equal exp, e.message
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative 'test_case'
|
2
|
+
require 'tunit/spec'
|
3
|
+
|
4
|
+
MyThing = Class.new
|
5
|
+
MySecondThing = Class.new
|
6
|
+
|
7
|
+
module Tunit
|
8
|
+
class SpecTest < TestCase
|
9
|
+
def test_it_blocks_are_converted_to_test_methods
|
10
|
+
klass = Class.new(::Tunit::Spec) {
|
11
|
+
it "does the thing" do end
|
12
|
+
}
|
13
|
+
|
14
|
+
klass.new "blah"
|
15
|
+
|
16
|
+
assert_includes klass.runnable_methods, "test_0001_does_the_thing"
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_before_is_converted_to_setup
|
20
|
+
klass = Class.new(::Tunit::Spec)
|
21
|
+
klass.before { "here!" }
|
22
|
+
|
23
|
+
assert_respond_to klass.new(:test), :setup
|
24
|
+
assert_equal "here!", klass.new(:test).setup
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_after_is_converted_to_teardown
|
28
|
+
klass = Class.new(::Tunit::Spec)
|
29
|
+
klass.after { "there!" }
|
30
|
+
|
31
|
+
assert_respond_to klass.new(:test), :teardown
|
32
|
+
assert_equal "there!", klass.new(:test).teardown
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_describe_is_converted_to_a_test_klass_with_test_methods
|
36
|
+
my_thing = describe MyThing do
|
37
|
+
it 'dances all night long' do end
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_includes my_thing.ancestors, ::Tunit::Test
|
41
|
+
assert_includes my_thing.runnable_methods, "test_0001_dances_all_night_long"
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_describe_can_be_nested
|
45
|
+
my_second_thing = describe MySecondThing do
|
46
|
+
describe '#dance!' do
|
47
|
+
it 'busts the moves' do end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
child = my_second_thing.children.pop
|
52
|
+
|
53
|
+
assert_equal "#dance!", child.name
|
54
|
+
assert_includes child.runnable_methods, "test_0001_busts_the_moves"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require_relative 'test_case'
|
2
|
+
require 'tunit/summary_reporter'
|
3
|
+
|
4
|
+
module Tunit
|
5
|
+
class SummaryReporterTest < TestCase
|
6
|
+
def setup
|
7
|
+
self.reporter = SummaryReporter.new io
|
8
|
+
end
|
9
|
+
attr_accessor :reporter
|
10
|
+
|
11
|
+
def test_start_returns_run_msg
|
12
|
+
reporter.start
|
13
|
+
exp_msg = <<-EOS
|
14
|
+
Run options: {}
|
15
|
+
|
16
|
+
# Running:
|
17
|
+
|
18
|
+
EOS
|
19
|
+
|
20
|
+
assert_equal exp_msg, io.string
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_report_gives_test_run_statistics
|
24
|
+
reporter.start
|
25
|
+
reporter.record PassingTest.new.run
|
26
|
+
reporter.report
|
27
|
+
|
28
|
+
stats = reporter.send :statistics
|
29
|
+
exp_stats = %r(Finished in 0{1,}.0{1,}s, 0{1,}.0{1,} runs/s, 0{1,}.0{1,} assertions/s.)
|
30
|
+
|
31
|
+
assert_match exp_stats, zeroify_time(stats)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_report_returns_errors
|
35
|
+
reporter.start
|
36
|
+
reporter.record FailingTest.new.run
|
37
|
+
reporter.report
|
38
|
+
|
39
|
+
aggregated_results = reporter.send :aggregated_results
|
40
|
+
exp_aggregated_results = <<-EOS
|
41
|
+
|
42
|
+
1) Failure:
|
43
|
+
Tunit::TestCase::FailingTest#test_fail [test/tunit/test_case.rb:LINE]:
|
44
|
+
Failed assertion, no message given.
|
45
|
+
|
46
|
+
EOS
|
47
|
+
|
48
|
+
assert_equal exp_aggregated_results, remove_line_numbers(
|
49
|
+
truncate_absolut_path(aggregated_results)
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_report_returns_summary
|
54
|
+
reporter.start
|
55
|
+
reporter.record PassingTest.new.run
|
56
|
+
reporter.report
|
57
|
+
|
58
|
+
summary = reporter.send :summary
|
59
|
+
exp_summary = "1 runs, 1 assertions, 0 failures, 0 skips"
|
60
|
+
|
61
|
+
assert_equal exp_summary, summary
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_report_considers_empty_test_failures
|
65
|
+
reporter.start
|
66
|
+
reporter.record FailingTest.new(:test_empty).run
|
67
|
+
reporter.report
|
68
|
+
|
69
|
+
summary = reporter.send :summary
|
70
|
+
exp_summary = "1 runs, 0 assertions, 1 failures, 0 skips"
|
71
|
+
|
72
|
+
assert_equal exp_summary, summary
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_report_summay_does_not_show_skip_message_if_verbose
|
76
|
+
reporter = SummaryReporter.new io, verbose: true
|
77
|
+
reporter.start
|
78
|
+
reporter.record SkippedTest.new.run
|
79
|
+
reporter.report
|
80
|
+
|
81
|
+
summary = reporter.send :summary
|
82
|
+
summary_skip_msg = /#{SummaryReporter::SKIP_MSG}/
|
83
|
+
|
84
|
+
refute_match summary_skip_msg, summary
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_report_only_shows_skips_if_verbose
|
88
|
+
unverbose_reporter = self.reporter
|
89
|
+
unverbose_reporter.io = StringIO.new ""
|
90
|
+
verbose_reporter = SummaryReporter.new io, verbose: true
|
91
|
+
|
92
|
+
verbose_reporter.start
|
93
|
+
verbose_reporter.record SkippedTest.new(:test_skip).run
|
94
|
+
verbose_reporter.report
|
95
|
+
|
96
|
+
reporter.start
|
97
|
+
reporter.record SkippedTest.new(:test_skip).run
|
98
|
+
reporter.report
|
99
|
+
|
100
|
+
exp_report = /1\) Skipped:\nTunit::TestCase::SkippedTest#test_skip \[(.*)\]/
|
101
|
+
|
102
|
+
assert_match exp_report, io.string
|
103
|
+
refute_match exp_report, reporter.io.string
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def remove_line_numbers str
|
109
|
+
str.gsub(/:\d{1,}/, ':LINE')
|
110
|
+
end
|
111
|
+
|
112
|
+
def zeroify_time str
|
113
|
+
str.gsub(/\d/, '0')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "tunit/test"
|
3
|
+
require "stringio"
|
4
|
+
|
5
|
+
module Tunit
|
6
|
+
class TestCase < Minitest::Test
|
7
|
+
def io
|
8
|
+
@io ||= StringIO.new ""
|
9
|
+
end
|
10
|
+
|
11
|
+
def dummy_reporter
|
12
|
+
@dummy_reporter ||= Class.new {
|
13
|
+
def record(*)
|
14
|
+
@tests ||= 0
|
15
|
+
@tests += 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def report(*)
|
19
|
+
@tests ||= 0
|
20
|
+
@tests
|
21
|
+
end
|
22
|
+
}.new
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def truncate_absolut_path str
|
28
|
+
str.gsub(%r{\[.*(test/tunit/test_case.rb.*)\]}, '[\1]')
|
29
|
+
end
|
30
|
+
|
31
|
+
class PassingTest < Test
|
32
|
+
def initialize name = :test_pass
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_pass
|
37
|
+
assert 2.even?
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_pass_one_more
|
41
|
+
assert [1, 2].include?(2)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class FailingTest < Test
|
46
|
+
def initialize name = :test_fail
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_fail
|
51
|
+
assert false
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_empty
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class SkippedTest < Test
|
59
|
+
def initialize test = :test_skip
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_skip
|
64
|
+
skip
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_skip_with_msg
|
68
|
+
skip "implement me when IQ > 80"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|