kintama 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +247 -0
- data/lib/kintama.rb +100 -0
- data/lib/kintama/assertions.rb +38 -0
- data/lib/kintama/context.rb +187 -0
- data/lib/kintama/runnable.rb +33 -0
- data/lib/kintama/runner.rb +153 -0
- data/lib/kintama/test.rb +68 -0
- data/test/aliases_test.rb +26 -0
- data/test/assertions_test.rb +42 -0
- data/test/automatic_running_test.rb +45 -0
- data/test/exceptions_test.rb +40 -0
- data/test/kintama_test.rb +114 -0
- data/test/matcher_test.rb +65 -0
- data/test/method_behaviour_test.rb +176 -0
- data/test/pending_test.rb +13 -0
- data/test/runners/base_runner_test.rb +153 -0
- data/test/runners/inline_runner_test.rb +64 -0
- data/test/runners/verbose_runner_test.rb +129 -0
- data/test/setup_test.rb +107 -0
- data/test/teardown_test.rb +92 -0
- data/test/test_and_subcontext_access_test.rb +110 -0
- data/test/test_helper.rb +36 -0
- metadata +89 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module Kintama
|
2
|
+
class Runnable
|
3
|
+
class << self
|
4
|
+
attr_accessor :name
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
"<#{name} #{super}/#{is_a_test? ? 'Test' : 'Context'}>"
|
8
|
+
end
|
9
|
+
|
10
|
+
def is_a_test?
|
11
|
+
ancestors.index(Kintama::Test) &&
|
12
|
+
ancestors.index(Kintama::Test) < ancestors.index(Kintama::Context)
|
13
|
+
end
|
14
|
+
|
15
|
+
def is_a_context?
|
16
|
+
!is_a_test?
|
17
|
+
end
|
18
|
+
|
19
|
+
def parent
|
20
|
+
superclass.ancestors.include?(Kintama::Context) ? superclass : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the full name of this context, taking any parent contexts into account
|
24
|
+
def full_name
|
25
|
+
if @name
|
26
|
+
[parent ? parent.full_name : nil, @name].compact.join(" ")
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Kintama
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
def self.default
|
5
|
+
Verbose.new(*Kintama.default_context.subcontexts)
|
6
|
+
end
|
7
|
+
|
8
|
+
class Base
|
9
|
+
def initialize(*contexts)
|
10
|
+
@contexts = contexts
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(colour=$stdin.tty?)
|
14
|
+
@colour = colour
|
15
|
+
@test_count = 0
|
16
|
+
start = Time.now
|
17
|
+
@contexts.each do |c|
|
18
|
+
@current_indent = -1
|
19
|
+
c.run(self)
|
20
|
+
puts if c != @contexts.last
|
21
|
+
end
|
22
|
+
@duration = Time.now - start
|
23
|
+
show_results
|
24
|
+
passed?
|
25
|
+
end
|
26
|
+
|
27
|
+
def context_started(context); end
|
28
|
+
def context_finished(context); end
|
29
|
+
def test_started(test)
|
30
|
+
@test_count += 1
|
31
|
+
end
|
32
|
+
def test_finished(test); end
|
33
|
+
|
34
|
+
def passed?
|
35
|
+
failures.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def failures
|
39
|
+
@contexts.map { |c| c.failures }.flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def pending
|
43
|
+
@contexts.map { |c| c.pending }.flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_summary
|
47
|
+
output = ["#{@test_count} tests", "#{failures.length} failures"]
|
48
|
+
output << "#{pending.length} pending" if pending.any?
|
49
|
+
output.join(", ") + " (#{format("%.4f", @duration)} seconds)"
|
50
|
+
end
|
51
|
+
|
52
|
+
def show_results
|
53
|
+
puts
|
54
|
+
puts test_summary
|
55
|
+
puts "\n" + failure_messages.join("\n\n") if failures.any?
|
56
|
+
end
|
57
|
+
|
58
|
+
def failure_messages
|
59
|
+
x = 0
|
60
|
+
failures.map do |test|
|
61
|
+
x += 1
|
62
|
+
"#{x}) #{test.full_name}:\n #{test.failure_message}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def character_status_of(test)
|
67
|
+
character = if test.pending?
|
68
|
+
'P'
|
69
|
+
elsif test.passed?
|
70
|
+
'.'
|
71
|
+
else
|
72
|
+
'F'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Inline < Base
|
78
|
+
def test_finished(test)
|
79
|
+
print character_status_of(test)
|
80
|
+
end
|
81
|
+
|
82
|
+
def show_results
|
83
|
+
puts
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Verbose < Base
|
89
|
+
INDENT = " "
|
90
|
+
|
91
|
+
def initialize(*contexts)
|
92
|
+
super
|
93
|
+
@current_indent = -1
|
94
|
+
end
|
95
|
+
|
96
|
+
def indent
|
97
|
+
INDENT * @current_indent
|
98
|
+
end
|
99
|
+
|
100
|
+
def context_started(context)
|
101
|
+
@current_indent += 1
|
102
|
+
print indent + context.name + "\n" if context.name
|
103
|
+
end
|
104
|
+
|
105
|
+
def context_finished(context)
|
106
|
+
@current_indent -= 1
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_started(test)
|
110
|
+
super
|
111
|
+
print indent + INDENT + test.name + ": " unless @colour
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_finished(test)
|
115
|
+
if @colour
|
116
|
+
puts coloured_name(test)
|
117
|
+
else
|
118
|
+
puts character_status_of(test)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def coloured_name(test)
|
125
|
+
test_name = indent + INDENT + test.name
|
126
|
+
if test.pending?
|
127
|
+
yellow(test_name)
|
128
|
+
elsif test.passed?
|
129
|
+
green(test_name)
|
130
|
+
else
|
131
|
+
red(test_name)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def color(text, color_code)
|
136
|
+
"#{color_code}#{text}\e[0m"
|
137
|
+
end
|
138
|
+
|
139
|
+
def green(text)
|
140
|
+
color(text, "\e[32m")
|
141
|
+
end
|
142
|
+
|
143
|
+
def red(text)
|
144
|
+
color(text, "\e[31m")
|
145
|
+
end
|
146
|
+
|
147
|
+
def yellow(text)
|
148
|
+
color(text, "\e[33m")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
data/lib/kintama/test.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Kintama
|
2
|
+
class TestFailure < StandardError; end
|
3
|
+
|
4
|
+
module Test
|
5
|
+
include Kintama::Assertions
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
class << base
|
9
|
+
attr_accessor :block
|
10
|
+
|
11
|
+
def pending?
|
12
|
+
@block.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
new.run
|
17
|
+
end
|
18
|
+
end
|
19
|
+
base.send :attr_reader, :failure
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(runner=nil)
|
23
|
+
@failure = nil
|
24
|
+
runner.test_started(self) if runner
|
25
|
+
unless pending?
|
26
|
+
begin
|
27
|
+
setup
|
28
|
+
instance_eval(&self.class.block)
|
29
|
+
rescue Exception => e
|
30
|
+
@failure = e
|
31
|
+
ensure
|
32
|
+
begin
|
33
|
+
teardown
|
34
|
+
rescue Exception => e
|
35
|
+
@failure = e
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
runner.test_finished(self) if runner
|
40
|
+
passed?
|
41
|
+
end
|
42
|
+
|
43
|
+
def pending?
|
44
|
+
self.class.pending?
|
45
|
+
end
|
46
|
+
|
47
|
+
def passed?
|
48
|
+
@failure.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def name
|
52
|
+
self.class.name
|
53
|
+
end
|
54
|
+
|
55
|
+
def full_name
|
56
|
+
self.class.full_name
|
57
|
+
end
|
58
|
+
|
59
|
+
def failure_message
|
60
|
+
"#{@failure.message} (at #{failure_line})"
|
61
|
+
end
|
62
|
+
|
63
|
+
def failure_line
|
64
|
+
base_dir = File.expand_path("../..", __FILE__)
|
65
|
+
@failure.backtrace.find { |line| File.expand_path(line).index(base_dir).nil? }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AliasesTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_should_provide_given_and_it_aliases_for_context_and_should
|
6
|
+
x = context "In a world without hope" do
|
7
|
+
given "a massive gun" do
|
8
|
+
it "should work out well in the end" do
|
9
|
+
assert true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
x.run
|
14
|
+
assert x.passed?
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_provide_testcase_alias_for_context
|
18
|
+
x = testcase "In a world without hope" do
|
19
|
+
should "work out well in the end" do
|
20
|
+
assert true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
x.run
|
24
|
+
assert x.passed?
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AssertionsTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
class PseudoTest
|
6
|
+
include Kintama::Assertions
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@test = PseudoTest.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_provide_assert_nil
|
14
|
+
assert_assertion_fails { @test.assert_nil Object.new }
|
15
|
+
assert_assertion_passes { @test.assert_nil nil }
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_provide_assert_not_nil
|
19
|
+
assert_assertion_passes { @test.assert_not_nil Object.new }
|
20
|
+
assert_assertion_fails { @test.assert_not_nil nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_provide_assert_kind_of
|
24
|
+
assert_assertion_passes { @test.assert_kind_of Fixnum, 1 }
|
25
|
+
assert_assertion_passes { @test.assert_kind_of Object, 1 }
|
26
|
+
assert_assertion_passes { @test.assert_kind_of String, "hello" }
|
27
|
+
assert_assertion_fails { @test.assert_kind_of String, 1 }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def assert_assertion_passes
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
|
36
|
+
def assert_assertion_fails
|
37
|
+
yield
|
38
|
+
raise "assertion did not fail!"
|
39
|
+
rescue Kintama::TestFailure
|
40
|
+
# nothing
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AutomaticRunningTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_should_be_able_to_run_tests_automatically_when_file_is_loaded
|
6
|
+
assert_passes write_test %{
|
7
|
+
context "given a thing" do
|
8
|
+
should "work" do
|
9
|
+
assert true
|
10
|
+
end
|
11
|
+
end}
|
12
|
+
assert_fails write_test %{
|
13
|
+
context "given a thing" do
|
14
|
+
should "not work" do
|
15
|
+
flunk
|
16
|
+
end
|
17
|
+
end}
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def write_test(string)
|
23
|
+
f = File.open("/tmp/kintama_tmp_test.rb", "w") do |f|
|
24
|
+
f.puts %|$LOAD_PATH.unshift "#{File.expand_path("../../lib", __FILE__)}"; require "kintama"|
|
25
|
+
f.puts string
|
26
|
+
end
|
27
|
+
"/tmp/kintama_tmp_test.rb"
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_test(path)
|
31
|
+
prev = ENV["KINTAMA_EXPLICITLY_DONT_RUN"]
|
32
|
+
ENV["KINTAMA_EXPLICITLY_DONT_RUN"] = nil
|
33
|
+
output = `ruby #{path}`
|
34
|
+
ENV["KINTAMA_EXPLICITLY_DONT_RUN"] = prev
|
35
|
+
$?
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_passes(path)
|
39
|
+
assert_equal 0, run_test(path).exitstatus
|
40
|
+
end
|
41
|
+
|
42
|
+
def assert_fails(path)
|
43
|
+
assert_equal 1, run_test(path).exitstatus
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ExceptionsTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_should_capture_exceptions_in_tests_as_failing_tests
|
6
|
+
x = context "Given a test" do
|
7
|
+
should "that raises an exception" do
|
8
|
+
raise "aaargh"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
x.run
|
12
|
+
assert !x.passed?
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_capture_exceptions_in_setups_as_failing_tests
|
16
|
+
x = context "Given a test with setup that fails" do
|
17
|
+
setup do
|
18
|
+
raise "aargh"
|
19
|
+
end
|
20
|
+
should "that would otherwise pass" do
|
21
|
+
assert true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
x.run
|
25
|
+
assert !x.passed?
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_should_capture_exceptions_in_teardowns_as_failing_tests
|
29
|
+
x = context "Given a test with teardown that fails" do
|
30
|
+
teardown do
|
31
|
+
raise "aargh"
|
32
|
+
end
|
33
|
+
should "that would otherwise pass" do
|
34
|
+
assert true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
x.run
|
38
|
+
assert !x.passed?
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class KintamaTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_should_pass_when_all_tests_pass
|
6
|
+
x = context "Given something" do
|
7
|
+
should "work" do
|
8
|
+
assert true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
x.run
|
12
|
+
assert x.passed?
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_fail_when_all_tests_fail
|
16
|
+
x = context "Given something" do
|
17
|
+
should "work" do
|
18
|
+
flunk
|
19
|
+
end
|
20
|
+
end
|
21
|
+
x.run
|
22
|
+
assert !x.passed?
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_fail_when_any_tests_fail
|
26
|
+
x = context "Given something" do
|
27
|
+
should "work" do
|
28
|
+
flunk
|
29
|
+
end
|
30
|
+
should "also work" do
|
31
|
+
assert true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
x.run
|
35
|
+
assert !x.passed?
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_should_fail_when_any_assertion_within_a_test_fails
|
39
|
+
x = context "Given something" do
|
40
|
+
should "ultimately not work" do
|
41
|
+
flunk
|
42
|
+
assert true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
x.run
|
46
|
+
assert !x.passed?
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_should_not_run_any_code_beyond_a_failing_assertion
|
50
|
+
x = context "Given something" do
|
51
|
+
should "ultimately not work" do
|
52
|
+
flunk
|
53
|
+
raise "should not get here!"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
x.run
|
57
|
+
assert !x.passed?
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_allow_nesting_of_contexts
|
61
|
+
x = context "Given something" do
|
62
|
+
context "and another thing" do
|
63
|
+
should "work" do
|
64
|
+
flunk
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
x.run
|
69
|
+
assert !x.passed?
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_should_allow_multiple_subcontexts
|
73
|
+
x = context "Given something" do
|
74
|
+
context "and another thing" do
|
75
|
+
should "work" do
|
76
|
+
flunk
|
77
|
+
end
|
78
|
+
end
|
79
|
+
context "and another different thing" do
|
80
|
+
should "work" do
|
81
|
+
assert true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
x.run
|
86
|
+
assert !x.passed?
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_should_allow_deep_nesting_of_subcontexts
|
90
|
+
x = context "Given something" do
|
91
|
+
context "and another thing" do
|
92
|
+
context "and one more thing" do
|
93
|
+
should "work" do
|
94
|
+
flunk
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
x.run
|
100
|
+
assert !x.passed?
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_should_clear_previous_failure_when_running_test_again
|
104
|
+
$thing = 456
|
105
|
+
x = context "Given something" do
|
106
|
+
should "work" do
|
107
|
+
assert_equal 123, $thing
|
108
|
+
end
|
109
|
+
end
|
110
|
+
assert_equal false, x.run
|
111
|
+
$thing = 123
|
112
|
+
assert_equal true, x.run
|
113
|
+
end
|
114
|
+
end
|