tunit 0.0.1
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.
- 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
|