/
environment.rb
115 lines (95 loc) · 2.82 KB
/
environment.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
module Exemplor
class ExampleEnv
class << self
alias_method :helpers, :class_eval
attr_accessor :setup_block
def setup(&blk) self.setup_block = blk end
# runs the block in the example environment, returns triple:
# [status, result, stderr]
def run(&code)
env = self.new
stderr = fake_stderr!
status, result = begin
env.instance_eval(&self.setup_block) if self.setup_block
value = env.instance_eval(&code)
if env._checks.empty?
[:info, render_value(value)]
else # :infos or :success
[env._status, render_checks(env._checks)]
end
rescue Check::Failure => failure
[:failure, render_checks(env._checks)]
rescue Object => error
[:error, render_error(error)]
ensure
restore_stderr!
end
[status, result, stderr.rewind && stderr.read]
end
# tests are run with a fake stderr so warnings output can be assoicated
# with the specific test. this is still a little hokey and hard to test
# properly
def fake_stderr!
fake = StringIO.new
@real_stderr = $stderr
$stderr = fake
end
def restore_stderr!
$stderr = @real_stderr
end
# -- these "render" methods could probably be factored away
# yaml doesn't want to print a class
def render_value(value)
value.kind_of?(Class) ? value.inspect : value
end
def render_checks(checks)
failure = nil
out = []
checks.each do |check|
failure = check if check.failure?
break if failure
out << OrderedHash do |o|
o['name'] = check.name
o['status'] = check.status.to_s
o['result'] = render_value check.value
end
end
if failure
out << OrderedHash do |o|
o['name'] = failure.name
o['status'] = failure.status.to_s
o['expected'] = failure.expectation
o['actual'] = render_value failure.value
end
end
out
end
def render_error(error)
OrderedHash do |o|
o['class'] = error.class.name
o['message'] = error.message
o['backtrace'] = error.backtrace
end
end
end
attr_accessor :_checks
def initialize
@_checks = []
end
def Check(value)
file, line_number = caller.first.match(/^(.+):(\d+)/).captures
line = File.readlines(file)[line_number.to_i - 1].strip
name = line[/Check\((.+?)\)\s*($|#|\[|\.is.+)/,1]
check = Check.new(name, value)
_checks << check
check
end
def _status
(:success if _checks.all? { |c| c.success? }) ||
:infos
end
end
def environment
ExampleEnv
end
end