test_bench-fixture 1.0.0.0
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/lib/test_bench/fixture.rb +18 -0
- data/lib/test_bench/fixture/assertion_failure.rb +19 -0
- data/lib/test_bench/fixture/controls.rb +10 -0
- data/lib/test_bench/fixture/controls/caller_location.rb +72 -0
- data/lib/test_bench/fixture/controls/error.rb +47 -0
- data/lib/test_bench/fixture/controls/error/backtrace.rb +31 -0
- data/lib/test_bench/fixture/controls/fixture.rb +85 -0
- data/lib/test_bench/fixture/controls/output.rb +64 -0
- data/lib/test_bench/fixture/controls/result.rb +23 -0
- data/lib/test_bench/fixture/controls/test_file.rb +72 -0
- data/lib/test_bench/fixture/error_policy.rb +75 -0
- data/lib/test_bench/fixture/fixture.rb +149 -0
- data/lib/test_bench/fixture/output.rb +56 -0
- data/lib/test_bench/fixture/output/log.rb +109 -0
- data/lib/test_bench/fixture/output/multiple.rb +42 -0
- data/lib/test_bench/fixture/output/null.rb +9 -0
- data/lib/test_bench/fixture/output/substitute.rb +141 -0
- data/lib/test_bench/fixture/session.rb +246 -0
- data/lib/test_bench/fixture/session/substitute.rb +126 -0
- data/lib/test_bench/fixture/session/substitute/match_tests.rb +131 -0
- metadata +76 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
module TestBench
|
2
|
+
module Fixture
|
3
|
+
module ErrorPolicy
|
4
|
+
def self.configure(receiver, policy: nil, attr_name: nil)
|
5
|
+
attr_name ||= :error_policy
|
6
|
+
|
7
|
+
instance = Build.(policy)
|
8
|
+
receiver.public_send(:"#{attr_name}=", instance)
|
9
|
+
instance
|
10
|
+
end
|
11
|
+
|
12
|
+
module Build
|
13
|
+
PolicyError = Class.new(RuntimeError)
|
14
|
+
|
15
|
+
def self.call(policy=nil)
|
16
|
+
cls = policy_class(policy)
|
17
|
+
|
18
|
+
cls.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.policy_class(policy=nil)
|
22
|
+
policy ||= Defaults.policy
|
23
|
+
|
24
|
+
policies.fetch(policy) do
|
25
|
+
*policies, final_policy = self.policies.keys
|
26
|
+
|
27
|
+
policy_list = "#{policies.map(&:inspect) * ', '} or #{final_policy.inspect}"
|
28
|
+
|
29
|
+
raise PolicyError, "Policy #{policy.inspect} is unknown. It must be one of: #{policy_list}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.policies
|
34
|
+
{
|
35
|
+
:abort => Abort,
|
36
|
+
:raise => Raise,
|
37
|
+
:rescue => Rescue,
|
38
|
+
:rescue_assert => RescueAssert
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
module Defaults
|
43
|
+
def self.policy
|
44
|
+
:rescue_assert
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Abort
|
50
|
+
def call(error)
|
51
|
+
abort "TestBench is aborting (#{self.class})"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Raise
|
56
|
+
def call(error)
|
57
|
+
raise error
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Rescue
|
62
|
+
def call(error)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class RescueAssert
|
67
|
+
def call(error)
|
68
|
+
unless error.instance_of?(AssertionFailure)
|
69
|
+
raise error
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module TestBench
|
2
|
+
module Fixture
|
3
|
+
Error = Class.new(RuntimeError)
|
4
|
+
|
5
|
+
def self.build(cls, *args, session: nil, output: nil, error_policy: nil, factory_method: nil, **kwargs, &block)
|
6
|
+
factory_method = factory_method(cls)
|
7
|
+
|
8
|
+
if kwargs.empty?
|
9
|
+
instance = factory_method.(*args, &block)
|
10
|
+
else
|
11
|
+
instance = factory_method.(*args, **kwargs, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
Session.configure(instance, session: session, output: output, error_policy: error_policy)
|
15
|
+
|
16
|
+
instance
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.factory_method(cls)
|
20
|
+
if cls.respond_to?(:build)
|
21
|
+
cls.method(:build)
|
22
|
+
elsif cls.respond_to?(:new)
|
23
|
+
cls.method(:new)
|
24
|
+
else
|
25
|
+
raise Error, "Must be given a class (Argument: #{cls.inspect})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.call(cls, *args, **kwargs, &block)
|
30
|
+
factory_method = factory_method(cls)
|
31
|
+
|
32
|
+
last_parameter_type, _ = factory_method.parameters.last
|
33
|
+
|
34
|
+
if last_parameter_type == :block
|
35
|
+
instance = build(cls, *args, **kwargs, &block)
|
36
|
+
block = nil
|
37
|
+
else
|
38
|
+
instance = build(cls, *args, **kwargs)
|
39
|
+
end
|
40
|
+
|
41
|
+
instance.test_session.fixture(instance, &block)
|
42
|
+
|
43
|
+
instance
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_session
|
47
|
+
@test_session ||= Session::Substitute.build
|
48
|
+
end
|
49
|
+
attr_writer :test_session
|
50
|
+
alias_method :session, :test_session
|
51
|
+
alias_method :session=, :test_session=
|
52
|
+
|
53
|
+
def comment(text)
|
54
|
+
test_session.comment(text)
|
55
|
+
end
|
56
|
+
|
57
|
+
ArgumentOmitted = Object.new
|
58
|
+
def assert(value=ArgumentOmitted, caller_location: nil, &block)
|
59
|
+
caller_location ||= caller_locations.first
|
60
|
+
|
61
|
+
unless value == ArgumentOmitted
|
62
|
+
unless block.nil?
|
63
|
+
raise ArgumentError, "Must supply a boolean value or a block (but not both)"
|
64
|
+
end
|
65
|
+
|
66
|
+
test_session.assert(value, caller_location: caller_location)
|
67
|
+
else
|
68
|
+
test_session.assert_block(caller_location: caller_location, &block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def refute(value, caller_location: nil)
|
73
|
+
caller_location ||= caller_locations.first
|
74
|
+
|
75
|
+
test_session.assert(!value, caller_location: caller_location)
|
76
|
+
end
|
77
|
+
|
78
|
+
def assert_raises(error_class=nil, message=nil, strict: nil, caller_location: nil, &block)
|
79
|
+
if error_class.nil?
|
80
|
+
strict ||= false
|
81
|
+
error_class = StandardError
|
82
|
+
else
|
83
|
+
strict = true if strict.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
caller_location ||= caller_locations.first
|
87
|
+
|
88
|
+
assert(caller_location: caller_location) do
|
89
|
+
comment "Expected Error: #{error_class}#{' (strict)' if strict}"
|
90
|
+
comment "Expected Message: #{message.inspect}" unless message.nil?
|
91
|
+
|
92
|
+
block.()
|
93
|
+
|
94
|
+
comment "(No error was raised)"
|
95
|
+
|
96
|
+
rescue error_class => error
|
97
|
+
|
98
|
+
comment "Raised error: #{error.inspect}#{" (subclass of #{error_class})" if error.class < error_class}"
|
99
|
+
|
100
|
+
if strict && !error.instance_of?(error_class)
|
101
|
+
raise error
|
102
|
+
end
|
103
|
+
|
104
|
+
assert(message.nil? || error.message == message)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def refute_raises(error_class=nil, strict: nil, caller_location: nil, &block)
|
109
|
+
if error_class.nil?
|
110
|
+
strict ||= false
|
111
|
+
error_class = StandardError
|
112
|
+
else
|
113
|
+
strict = true if strict.nil?
|
114
|
+
end
|
115
|
+
|
116
|
+
caller_location ||= caller_locations.first
|
117
|
+
|
118
|
+
assert(caller_location: caller_location) do
|
119
|
+
comment "Prohibited Error: #{error_class}#{' (strict)' if strict}"
|
120
|
+
|
121
|
+
block.()
|
122
|
+
|
123
|
+
comment "(No error was raised)"
|
124
|
+
|
125
|
+
assert(true)
|
126
|
+
|
127
|
+
rescue error_class => error
|
128
|
+
|
129
|
+
comment "Raised Error: #{error.inspect}"
|
130
|
+
|
131
|
+
if strict && !error.instance_of?(error_class)
|
132
|
+
raise error
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def context(text=nil, &block)
|
138
|
+
test_session.context(text, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test(text=nil, &block)
|
142
|
+
test_session.test(text, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
def fixture(cls, *args, **kwargs, &block)
|
146
|
+
Fixture.(cls, *args, session: test_session, **kwargs, &block)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module TestBench
|
2
|
+
module Fixture
|
3
|
+
module Output
|
4
|
+
def start
|
5
|
+
end
|
6
|
+
|
7
|
+
def finish(result)
|
8
|
+
end
|
9
|
+
|
10
|
+
def enter_file(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def exit_file(path, result)
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_fixture(fixture)
|
17
|
+
end
|
18
|
+
|
19
|
+
def finish_fixture(fixture, result)
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert(result, caller_location)
|
23
|
+
end
|
24
|
+
|
25
|
+
def enter_assert_block(caller_location)
|
26
|
+
end
|
27
|
+
|
28
|
+
def exit_assert_block(result, caller_location)
|
29
|
+
end
|
30
|
+
|
31
|
+
def comment(text)
|
32
|
+
end
|
33
|
+
|
34
|
+
def error(error)
|
35
|
+
end
|
36
|
+
|
37
|
+
def start_test(title)
|
38
|
+
end
|
39
|
+
|
40
|
+
def finish_test(title, result)
|
41
|
+
end
|
42
|
+
|
43
|
+
def skip_test(title)
|
44
|
+
end
|
45
|
+
|
46
|
+
def enter_context(title)
|
47
|
+
end
|
48
|
+
|
49
|
+
def exit_context(title, result)
|
50
|
+
end
|
51
|
+
|
52
|
+
def skip_context(title)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module TestBench
|
2
|
+
module Fixture
|
3
|
+
module Output
|
4
|
+
class Log
|
5
|
+
include Output
|
6
|
+
|
7
|
+
attr_reader :logger
|
8
|
+
|
9
|
+
def initialize(logger)
|
10
|
+
@logger = logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(device=nil)
|
14
|
+
device ||= $stderr
|
15
|
+
|
16
|
+
logger = Logger.new(device)
|
17
|
+
|
18
|
+
new(logger)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.configure(receiver, device=nil, attr_name: nil)
|
22
|
+
attr_name ||= :output
|
23
|
+
|
24
|
+
instance = build(device)
|
25
|
+
receiver.public_send(:"#{attr_name}=", instance)
|
26
|
+
instance
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
logger.debug { "Start" }
|
31
|
+
end
|
32
|
+
|
33
|
+
def finish(result)
|
34
|
+
logger.info { "Finish (Result: #{result})" }
|
35
|
+
end
|
36
|
+
|
37
|
+
def enter_file(path)
|
38
|
+
logger.debug { "Enter file (Path: #{path})" }
|
39
|
+
end
|
40
|
+
|
41
|
+
def exit_file(path, result)
|
42
|
+
logger.info { "Exit file (Path: #{path}, Result: #{result})" }
|
43
|
+
end
|
44
|
+
|
45
|
+
def start_fixture(fixture)
|
46
|
+
logger.debug { "Start fixture (Fixture: #{fixture.inspect})" }
|
47
|
+
end
|
48
|
+
|
49
|
+
def finish_fixture(fixture, result)
|
50
|
+
logger.info { "Finish fixture (Fixture: #{fixture.inspect}, Result: #{result})" }
|
51
|
+
end
|
52
|
+
|
53
|
+
def assert(result, caller_location)
|
54
|
+
logger.info { "Assertion (Result: #{result}, Caller Location: #{caller_location})" }
|
55
|
+
end
|
56
|
+
|
57
|
+
def enter_assert_block(caller_location)
|
58
|
+
logger.debug { "Entering assert block (Caller Location: #{caller_location})" }
|
59
|
+
end
|
60
|
+
|
61
|
+
def exit_assert_block(caller_location, result)
|
62
|
+
logger.info { "Exited assert block (Caller Location: #{caller_location}, Result: #{result})" }
|
63
|
+
end
|
64
|
+
|
65
|
+
def comment(text)
|
66
|
+
logger.info { "Comment (Text: #{text})" }
|
67
|
+
end
|
68
|
+
|
69
|
+
def error(error)
|
70
|
+
logger.error { "Error (Error: #{error})" }
|
71
|
+
end
|
72
|
+
|
73
|
+
def start_test(title)
|
74
|
+
logger.debug { "Starting test (Title: #{title || '(none)'})" }
|
75
|
+
end
|
76
|
+
|
77
|
+
def finish_test(title, result)
|
78
|
+
logger.info { "Finished test (Title: #{title || '(none)'}, Result: #{result})" }
|
79
|
+
end
|
80
|
+
|
81
|
+
def skip_test(title)
|
82
|
+
logger.info { "Skipped test (Title: #{title || '(none)'})" }
|
83
|
+
end
|
84
|
+
|
85
|
+
def enter_context(title)
|
86
|
+
logger.debug { "Entering context (Title: #{title || '(none)'})" }
|
87
|
+
end
|
88
|
+
|
89
|
+
def exit_context(title, result)
|
90
|
+
logger.info { "Exited context (Title: #{title || '(none)'}, Result: #{result})" }
|
91
|
+
end
|
92
|
+
|
93
|
+
def skip_context(title)
|
94
|
+
logger.info { "Skipped context (Title: #{title || '(none)'})" }
|
95
|
+
end
|
96
|
+
|
97
|
+
def device?(device)
|
98
|
+
self.device == device
|
99
|
+
end
|
100
|
+
|
101
|
+
def device
|
102
|
+
logger.instance_exec do
|
103
|
+
@logdev.dev
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module TestBench
|
2
|
+
module Fixture
|
3
|
+
module Output
|
4
|
+
class Multiple
|
5
|
+
include Output
|
6
|
+
|
7
|
+
def outputs
|
8
|
+
@outputs ||= []
|
9
|
+
end
|
10
|
+
attr_writer :outputs
|
11
|
+
|
12
|
+
def self.build(*outputs)
|
13
|
+
outputs = Array(outputs)
|
14
|
+
|
15
|
+
instance = new
|
16
|
+
|
17
|
+
outputs.each do |output|
|
18
|
+
instance.register(output)
|
19
|
+
end
|
20
|
+
|
21
|
+
instance
|
22
|
+
end
|
23
|
+
|
24
|
+
Output.instance_methods.each do |method_name|
|
25
|
+
define_method(method_name) do |*args|
|
26
|
+
outputs.map do |output|
|
27
|
+
output.public_send(method_name, *args)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def register(output)
|
33
|
+
outputs << output
|
34
|
+
end
|
35
|
+
|
36
|
+
def registered?(output)
|
37
|
+
outputs.include?(output)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module TestBench
|
2
|
+
module Fixture
|
3
|
+
module Output
|
4
|
+
module Substitute
|
5
|
+
def self.build
|
6
|
+
Output.new
|
7
|
+
end
|
8
|
+
|
9
|
+
MatchError = Class.new(RuntimeError)
|
10
|
+
|
11
|
+
class Output
|
12
|
+
include Fixture::Output
|
13
|
+
|
14
|
+
def records
|
15
|
+
@records ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
record(:start)
|
20
|
+
end
|
21
|
+
|
22
|
+
def finish(result)
|
23
|
+
record(:finish, result)
|
24
|
+
end
|
25
|
+
|
26
|
+
def enter_file(path)
|
27
|
+
record(:enter_file, path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def exit_file(path, result)
|
31
|
+
record(:exit_file, path, result)
|
32
|
+
end
|
33
|
+
|
34
|
+
def start_fixture(fixture)
|
35
|
+
record(:start_fixture, fixture)
|
36
|
+
end
|
37
|
+
|
38
|
+
def finish_fixture(fixture, result)
|
39
|
+
record(:finish_fixture, fixture, result)
|
40
|
+
end
|
41
|
+
|
42
|
+
def assert(result, caller_location)
|
43
|
+
record(:assert, result, caller_location)
|
44
|
+
end
|
45
|
+
|
46
|
+
def enter_assert_block(caller_location)
|
47
|
+
record(:enter_assert_block, caller_location)
|
48
|
+
end
|
49
|
+
|
50
|
+
def exit_assert_block(caller_location, result)
|
51
|
+
record(:exit_assert_block, caller_location, result)
|
52
|
+
end
|
53
|
+
|
54
|
+
def comment(text)
|
55
|
+
record(:comment, text)
|
56
|
+
end
|
57
|
+
|
58
|
+
def error(error)
|
59
|
+
record(:error, error)
|
60
|
+
end
|
61
|
+
|
62
|
+
def start_test(title)
|
63
|
+
record(:start_test, title)
|
64
|
+
end
|
65
|
+
|
66
|
+
def finish_test(title, result)
|
67
|
+
record(:finish_test, title, result)
|
68
|
+
end
|
69
|
+
|
70
|
+
def skip_test(title)
|
71
|
+
record(:skip_test, title)
|
72
|
+
end
|
73
|
+
|
74
|
+
def enter_context(title)
|
75
|
+
record(:enter_context, title)
|
76
|
+
end
|
77
|
+
|
78
|
+
def exit_context(title, result)
|
79
|
+
record(:exit_context, title, result)
|
80
|
+
end
|
81
|
+
|
82
|
+
def skip_context(title)
|
83
|
+
record(:skip_context, title)
|
84
|
+
end
|
85
|
+
|
86
|
+
def record(signal, *data)
|
87
|
+
record = Record.new(signal, data)
|
88
|
+
records << record
|
89
|
+
record
|
90
|
+
end
|
91
|
+
|
92
|
+
def replay_records(output)
|
93
|
+
records.each do |record|
|
94
|
+
output.public_send(record.signal, *record.data)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def recorded?(signal=nil, &block)
|
99
|
+
matching_records(signal, &block).any?
|
100
|
+
end
|
101
|
+
|
102
|
+
def recorded_once?(signal=nil, &block)
|
103
|
+
one_record(signal, &block) ? true : false
|
104
|
+
end
|
105
|
+
|
106
|
+
def one_record(signal=nil, &block)
|
107
|
+
matching_records = matching_records(signal, &block)
|
108
|
+
|
109
|
+
return if matching_records.empty?
|
110
|
+
|
111
|
+
unless matching_records.one?
|
112
|
+
raise MatchError, "More than one records match"
|
113
|
+
end
|
114
|
+
|
115
|
+
matching_records.shift
|
116
|
+
end
|
117
|
+
|
118
|
+
def matching_records(signal=nil, &block)
|
119
|
+
unless signal.nil?
|
120
|
+
inner_block = block || proc { true }
|
121
|
+
|
122
|
+
block = proc { |sig, *data|
|
123
|
+
if sig == signal
|
124
|
+
inner_block.(*data)
|
125
|
+
else
|
126
|
+
false
|
127
|
+
end
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
records.select do |record|
|
132
|
+
block.(record.signal, *record.data)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
Record = Struct.new(:signal, :data)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|