given 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.
- data/README.textile +206 -0
- data/Rakefile +35 -0
- data/examples/stack.rb +29 -0
- data/examples/stack_test.rb +46 -0
- data/lib/given.rb +6 -0
- data/lib/given/anonymous_code.rb +22 -0
- data/lib/given/code.rb +20 -0
- data/lib/given/dsl.rb +114 -0
- data/lib/given/errors.rb +4 -0
- data/lib/given/expectation.rb +90 -0
- data/lib/given/framework.rb +2 -0
- data/lib/given/test_unit.rb +22 -0
- data/lib/given/test_unit/adapter.rb +27 -0
- data/lib/given/version.rb +7 -0
- data/test/functional/fails_with_test.rb +93 -0
- data/test/functional/invalid_use_test.rb +60 -0
- data/test/functional/invariant_test.rb +87 -0
- data/test/functional/setup_test.rb +79 -0
- data/test/functional/then_test.rb +62 -0
- data/test/functional/when_test.rb +43 -0
- data/test/given/anonymous_code_contract.rb +15 -0
- data/test/given/expectation_test.rb +83 -0
- data/test/given/test_unit/adapter_contract.rb +37 -0
- data/test/test_helper.rb +190 -0
- metadata +87 -0
data/lib/given/errors.rb
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module Given
|
|
2
|
+
class Expectation
|
|
3
|
+
include Comparable
|
|
4
|
+
|
|
5
|
+
def initialize(value, test_case)
|
|
6
|
+
@value = value
|
|
7
|
+
@test_case = test_case
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def not()
|
|
11
|
+
NegativeExpectation.new(@value, @test_case)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def evaluate_condition
|
|
15
|
+
yield(@value)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def check(condition, msg, *args)
|
|
19
|
+
bool = evaluate_condition(&condition)
|
|
20
|
+
@test_case.given_check(bool, msg, [@value, twist] + args)
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def twist
|
|
25
|
+
""
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ==(other)
|
|
29
|
+
check(
|
|
30
|
+
lambda { |value| value == other },
|
|
31
|
+
"<%s> expected to %sbe equal to\n<%s>.\n",
|
|
32
|
+
other)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def >(other)
|
|
36
|
+
check(lambda { |value| value > other },
|
|
37
|
+
"<%s> expected to %sbe greater than\n<%s>.\n",
|
|
38
|
+
other)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def <(other)
|
|
42
|
+
check(lambda { |value| value < other },
|
|
43
|
+
"<%s> expected to %sbe less than\n<%s>.\n",
|
|
44
|
+
other)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def <=(other)
|
|
48
|
+
check(lambda { |value| value <= other },
|
|
49
|
+
"<%s> expected to %sbe less than or equal to\n<%s>.\n",
|
|
50
|
+
other)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def >=(other)
|
|
54
|
+
check(lambda { |value| value >= other },
|
|
55
|
+
"<%s> expected to %sbe greater than or equal to\n<%s>.\n",
|
|
56
|
+
other)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def =~(pattern)
|
|
60
|
+
check(lambda { |value| value =~ pattern },
|
|
61
|
+
"<%s> expected to %sbe matched by\n<%s>.\n",
|
|
62
|
+
pattern)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def nil?
|
|
66
|
+
check(lambda { |value| value.nil? },
|
|
67
|
+
"<%s> expected to %sbe nil")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def method_missing(sym, *args, &block)
|
|
71
|
+
method_name = sym.to_s
|
|
72
|
+
if method_name =~ /\?$/
|
|
73
|
+
check(lambda { |value| value.send(sym, *args, &block) },
|
|
74
|
+
"<%s> expected to %sbe %s",
|
|
75
|
+
[method_name[0..-2]])
|
|
76
|
+
else
|
|
77
|
+
fail Given::UsageError.new("cannot expect anything about #{sym}")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class NegativeExpectation < Expectation
|
|
83
|
+
def evaluate_condition
|
|
84
|
+
! yield(@value)
|
|
85
|
+
end
|
|
86
|
+
def twist
|
|
87
|
+
"not "
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'given'
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'given/test_unit/adapter'
|
|
4
|
+
|
|
5
|
+
module Given
|
|
6
|
+
module TestCaseMethods
|
|
7
|
+
def self.included(mod)
|
|
8
|
+
mod.module_eval do
|
|
9
|
+
extend Given::DSL
|
|
10
|
+
include Given::DSL::TestHelper
|
|
11
|
+
include Given::TestUnit::Adapter
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestCase < Test::Unit::TestCase
|
|
17
|
+
include Given::TestCaseMethods
|
|
18
|
+
|
|
19
|
+
def test_DUMMY
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
|
|
3
|
+
module Given
|
|
4
|
+
def self.assertion_failed_exception
|
|
5
|
+
Test::Unit::AssertionFailedError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module TestUnit
|
|
9
|
+
module Adapter
|
|
10
|
+
def given_failure(message, code=nil)
|
|
11
|
+
if code
|
|
12
|
+
message = "\n#{code.file_line} #{message}\n"
|
|
13
|
+
end
|
|
14
|
+
raise Test::Unit::AssertionFailedError.new(message)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def given_assert(clause, code)
|
|
18
|
+
_wrap_assertion do
|
|
19
|
+
ok = code.run(self)
|
|
20
|
+
if ! ok
|
|
21
|
+
given_failure("#{clause} Condition Failed", code)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'test/test_helper'
|
|
2
|
+
require 'given'
|
|
3
|
+
|
|
4
|
+
class FailsTest < GivenTestCase
|
|
5
|
+
def test_fails_with_expected_failure_is_ok
|
|
6
|
+
assert_all_pass do
|
|
7
|
+
Given do
|
|
8
|
+
When { fail "OUCH" }
|
|
9
|
+
FailsWith(RuntimeError)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_actual_exception_is_available
|
|
15
|
+
assert_all_pass do
|
|
16
|
+
Given do
|
|
17
|
+
When { fail "OUCH" }
|
|
18
|
+
FailsWith(RuntimeError)
|
|
19
|
+
Then { exception.class == RuntimeError }
|
|
20
|
+
And { exception.message == "OUCH" }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_failure_block_must_be_true
|
|
26
|
+
line = 0
|
|
27
|
+
tally = run_tests do
|
|
28
|
+
Given do
|
|
29
|
+
When { fail "OUCH" }
|
|
30
|
+
FailsWith(RuntimeError)
|
|
31
|
+
Then { exception.class == RuntimeError }
|
|
32
|
+
line = __LINE__ + 1
|
|
33
|
+
And { exception.message == "XXXX" }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
assert ! tally.passed?
|
|
37
|
+
assert_match(/Then Condition Failed/, failure_message(tally))
|
|
38
|
+
assert_match(/:#{line}/, failure_message(tally))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_fails_without_expected_failure_is_not_ok
|
|
42
|
+
line = 0
|
|
43
|
+
tally = run_tests do
|
|
44
|
+
Given do
|
|
45
|
+
line = __LINE__ + 1
|
|
46
|
+
When { }
|
|
47
|
+
FailsWith(RuntimeError)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
assert ! tally.passed?
|
|
51
|
+
assert_match(/Expected RuntimeError Exception/i, failure_message(tally))
|
|
52
|
+
assert_match(/:#{line}/, failure_message(tally))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class ExpectedError < RuntimeError
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class ActualError < RuntimeError
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_fails_with_unexpected_failure_is_not_ok
|
|
62
|
+
line = 0
|
|
63
|
+
tally = run_tests do
|
|
64
|
+
Given do
|
|
65
|
+
line = __LINE__ + 1
|
|
66
|
+
When { fail ActualError }
|
|
67
|
+
FailsWith(ExpectedError)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
assert ! tally.passed?
|
|
71
|
+
assert_match(/Expected FailsTest::ExpectedError Exception/i,
|
|
72
|
+
failure_message(tally))
|
|
73
|
+
assert_match(/but got FailsTest::ActualError/i,
|
|
74
|
+
failure_message(tally))
|
|
75
|
+
assert_match(/:#{line}/, failure_message(tally))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_invariants_run_after_failure
|
|
79
|
+
tally = run_tests do
|
|
80
|
+
Given do
|
|
81
|
+
Invariant { false }
|
|
82
|
+
|
|
83
|
+
When { fail "OUCH" }
|
|
84
|
+
FailsWith(RuntimeError)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
assert ! tally.passed?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# No Operation
|
|
91
|
+
def noop
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'test/test_helper'
|
|
2
|
+
|
|
3
|
+
class InvalidUseTest < GivenTestCase
|
|
4
|
+
def test_then_must_be_inside_given
|
|
5
|
+
ex = assert_raise(Given::UsageError) do
|
|
6
|
+
run_tests do
|
|
7
|
+
Then { }
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
assert_equal "A Then clause must be inside a given block", ex.message
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_then_must_be_inside_given_part_2
|
|
14
|
+
ex = assert_raise(Given::UsageError) do
|
|
15
|
+
run_tests do
|
|
16
|
+
Given do end
|
|
17
|
+
Then { }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
assert_equal "A Then clause must be inside a given block", ex.message
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_when_must_be_inside_given
|
|
24
|
+
ex = assert_raise(Given::UsageError) do
|
|
25
|
+
run_tests do
|
|
26
|
+
When { }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
assert_equal "A When clause must be inside a given block", ex.message
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_when_must_be_inside_given_part_2
|
|
33
|
+
ex = assert_raise(Given::UsageError) do
|
|
34
|
+
run_tests do
|
|
35
|
+
Given do end
|
|
36
|
+
When { }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
assert_equal "A When clause must be inside a given block", ex.message
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_fails_with_must_be_inside_given
|
|
43
|
+
ex = assert_raise(Given::UsageError) do
|
|
44
|
+
run_tests do
|
|
45
|
+
FailsWith(RuntimeError)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
assert_equal "A FailsWith clause must be inside a given block", ex.message
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_fails_with_must_be_inside_given_part_2
|
|
52
|
+
ex = assert_raise(Given::UsageError) do
|
|
53
|
+
run_tests do
|
|
54
|
+
Given do end
|
|
55
|
+
FailsWith(RuntimeError)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
assert_equal "A FailsWith clause must be inside a given block", ex.message
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'test/test_helper'
|
|
2
|
+
|
|
3
|
+
require 'given'
|
|
4
|
+
|
|
5
|
+
class InvariantTest < GivenTestCase
|
|
6
|
+
def test_failing_invariants_fail_all_thens
|
|
7
|
+
tally = run_tests do
|
|
8
|
+
Given do
|
|
9
|
+
Invariant { false }
|
|
10
|
+
Then { true }
|
|
11
|
+
Then { true }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
assert ! tally.passed?
|
|
15
|
+
assert_equal 2, tally.failure_count
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_multiple_invariants_are_all_checked_part_1
|
|
19
|
+
tally = run_tests do
|
|
20
|
+
Given do
|
|
21
|
+
Invariant { false }
|
|
22
|
+
Invariant { true }
|
|
23
|
+
Then { true }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
assert ! tally.passed?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_multiple_invariants_are_all_checked_part_2
|
|
30
|
+
tally = run_tests do
|
|
31
|
+
Given do
|
|
32
|
+
Invariant { true }
|
|
33
|
+
Invariant { false }
|
|
34
|
+
Then { true }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
assert ! tally.passed?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_failing_global_invariants_fail_all_thens
|
|
41
|
+
line = 0
|
|
42
|
+
tally = run_tests do
|
|
43
|
+
line = __LINE__ + 1
|
|
44
|
+
Invariant { false }
|
|
45
|
+
Given do
|
|
46
|
+
Then { true }
|
|
47
|
+
Then { true }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
assert ! tally.passed?
|
|
51
|
+
assert_equal 2, tally.failure_count
|
|
52
|
+
assert_match(/Invariant Condition/, failure_message(tally))
|
|
53
|
+
assert_match(/:#{line}/, failure_message(tally))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_invariants_run_after_given_setup
|
|
57
|
+
assert_all_pass do
|
|
58
|
+
Invariant { ! @track.nil? }
|
|
59
|
+
Given(:a_track) do
|
|
60
|
+
Invariant { ! @track.nil? }
|
|
61
|
+
|
|
62
|
+
Then { @track == [] }
|
|
63
|
+
|
|
64
|
+
When { @track << :w }
|
|
65
|
+
Then { @track == [:w] }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_invariants_nest_with_givens
|
|
71
|
+
assert_all_pass do
|
|
72
|
+
Given(:a_track) do
|
|
73
|
+
Invariant { ! @track.nil? }
|
|
74
|
+
|
|
75
|
+
Given(:a_track_with_b) do
|
|
76
|
+
Invariant { @track == [:b] }
|
|
77
|
+
Then { @track == [:b] }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
Then { @track == [] }
|
|
81
|
+
end
|
|
82
|
+
def a_track_with_b
|
|
83
|
+
@track << :b
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'test/test_helper'
|
|
2
|
+
|
|
3
|
+
require 'given'
|
|
4
|
+
|
|
5
|
+
class SetupTest < GivenTestCase
|
|
6
|
+
def test_given_setup_is_run
|
|
7
|
+
assert_all_pass do
|
|
8
|
+
Given(:a_number) do
|
|
9
|
+
Then { @number == 10 }
|
|
10
|
+
end
|
|
11
|
+
def a_number
|
|
12
|
+
@number = 10
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_multiple_setups_are_run
|
|
18
|
+
assert_all_pass do
|
|
19
|
+
Given(:a_number, :another_number) do
|
|
20
|
+
Then { @number == 10 && @another_number == 20 }
|
|
21
|
+
end
|
|
22
|
+
def a_number
|
|
23
|
+
@number = 10
|
|
24
|
+
end
|
|
25
|
+
def another_number
|
|
26
|
+
@another_number = 20
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_setups_can_nest
|
|
32
|
+
assert_all_pass do
|
|
33
|
+
Given(:a_number) do
|
|
34
|
+
Given(:another_number) do
|
|
35
|
+
Then { @number == 10 && @another_number == 20 }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
def a_number
|
|
39
|
+
@number = 10
|
|
40
|
+
end
|
|
41
|
+
def another_number
|
|
42
|
+
@another_number = 20
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_nested_setups_clean_up
|
|
48
|
+
assert_all_pass do
|
|
49
|
+
Given(:set_nil) do
|
|
50
|
+
Given(:set_non_nil) do
|
|
51
|
+
end
|
|
52
|
+
Then { @stuff.nil? }
|
|
53
|
+
end
|
|
54
|
+
def set_nil
|
|
55
|
+
@stuff = nil
|
|
56
|
+
end
|
|
57
|
+
def set_non_nil
|
|
58
|
+
@stuff = :non_nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_nested_setups_clean_up_even_with_errors
|
|
64
|
+
assert_all_pass do
|
|
65
|
+
Given(:set_nil) do
|
|
66
|
+
Given(:set_non_nil) do
|
|
67
|
+
fail "OOPS"
|
|
68
|
+
end rescue nil
|
|
69
|
+
Then { @stuff.nil? }
|
|
70
|
+
end
|
|
71
|
+
def set_nil
|
|
72
|
+
@stuff = nil
|
|
73
|
+
end
|
|
74
|
+
def set_non_nil
|
|
75
|
+
@stuff = :non_nil
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|