calificador 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -16
- data/TODO.md +16 -0
- data/calificador.gemspec +54 -0
- data/lib/calificador.rb +8 -4
- data/lib/calificador/assert.rb +15 -0
- data/lib/calificador/assertor.rb +79 -35
- data/lib/calificador/build/attribute_evaluator.rb +34 -30
- data/lib/calificador/build/basic_factory.rb +195 -0
- data/lib/calificador/build/mock_factory.rb +151 -0
- data/lib/calificador/build/object_factory.rb +85 -0
- data/lib/calificador/build/trait.rb +0 -20
- data/lib/calificador/context/basic_context.rb +406 -0
- data/lib/calificador/context/class_method_context.rb +0 -0
- data/lib/calificador/{spec → context}/condition_context.rb +1 -3
- data/lib/calificador/{spec/type_context.rb → context/instance_context.rb} +5 -10
- data/lib/calificador/context/operation_context.rb +27 -0
- data/lib/calificador/context/override/argument_override.rb +73 -0
- data/lib/calificador/context/override/basic_override.rb +14 -0
- data/lib/calificador/context/override/factory_override.rb +31 -0
- data/lib/calificador/context/override/property_override.rb +61 -0
- data/lib/calificador/context/test_environment.rb +283 -0
- data/lib/calificador/{spec → context}/test_method.rb +2 -31
- data/lib/calificador/{spec → context}/test_root.rb +3 -15
- data/lib/calificador/{spec/examine_context.rb → context/type_context.rb} +7 -10
- data/lib/calificador/key.rb +27 -15
- data/lib/calificador/minitest/minitest_patches.rb +0 -2
- data/lib/calificador/test.rb +1 -3
- data/lib/calificador/test_mixin.rb +143 -139
- data/lib/calificador/util/call_formatter.rb +5 -5
- data/lib/calificador/util/core_extensions.rb +104 -79
- data/lib/calificador/util/proxy_object.rb +63 -0
- data/lib/calificador/version.rb +1 -1
- metadata +22 -42
- data/lib/calificador/build/attribute_container.rb +0 -103
- data/lib/calificador/build/factory.rb +0 -132
- data/lib/calificador/spec/basic_context.rb +0 -353
- data/lib/calificador/spec/class_method_context.rb +0 -42
- data/lib/calificador/spec/instance_method_context.rb +0 -38
- data/lib/calificador/spec/test_environment.rb +0 -141
- data/lib/calificador/spec/value_override.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 391cd5fa12b8710d063b8523dbb6d3350c13162ff241279c5d979ce9b7a3b555
|
4
|
+
data.tar.gz: 0d0527fda2ab45e903f057d6cd22a23588cde7b1a7c4ad352c718dc577785d59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 588366fbb53142a962e3a18b4b6fdfc9232729f22967d2ceb2105bd032293fea21d7c41ba3650d48a85827a12e926de27be63fe9523a6b9913aebb2f23fa4b39
|
7
|
+
data.tar.gz: 24c4a70eebd0528f2fb6a041a7283f65b23636048f480632e5975b6e78c862b479f0202142d45f2b9e77c3ee089b4852e4f0172989071e3f0390e10f833449c1
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# What is it?
|
2
2
|
|
3
3
|
A small Gem that lets you write concise and readable unit tests. It is heavily inspired by [Minitest], [Factory Bot], and [Assertive Expressive] but tries to boil everything down to be as concise as possible:
|
4
4
|
|
@@ -6,12 +6,18 @@ A small Gem that lets you write concise and readable unit tests. It is heavily i
|
|
6
6
|
module ReadMe
|
7
7
|
require "calificador"
|
8
8
|
|
9
|
-
# Define
|
9
|
+
# Define class to test
|
10
10
|
class HighTea
|
11
11
|
attr_accessor :scones, :posh
|
12
12
|
|
13
|
+
def initialize(scones:)
|
14
|
+
raise ArgumentError, "Cannot have a negative amount of scones" if scones.negative?
|
15
|
+
|
16
|
+
@scones = scones
|
17
|
+
end
|
18
|
+
|
13
19
|
def eat_scone
|
14
|
-
raise "Out of scones" if scones
|
20
|
+
raise "Out of scones" if scones.zero?
|
15
21
|
|
16
22
|
@scones -= 1
|
17
23
|
end
|
@@ -27,37 +33,50 @@ A small Gem that lets you write concise and readable unit tests. It is heavily i
|
|
27
33
|
|
28
34
|
# Define a factory for the test subject
|
29
35
|
factory HighTea do
|
30
|
-
|
36
|
+
# Set properties on the created object
|
31
37
|
posh { false }
|
32
38
|
|
33
|
-
#
|
39
|
+
# Define transient properties that will not be set automatically
|
40
|
+
transient do
|
41
|
+
# Constructor arguments are automatically set from properties
|
42
|
+
scones { 2 }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Use traits to define variants of your test subject
|
34
46
|
trait :style do
|
35
47
|
posh { true }
|
36
48
|
end
|
37
49
|
end
|
38
50
|
|
39
|
-
#
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
51
|
+
# Test class methods
|
52
|
+
type do
|
53
|
+
operation :new do
|
54
|
+
must "set a default amount of scones" do
|
55
|
+
# Write assertions using plain Ruby methods instead of spec DSL methods
|
56
|
+
assert { subject.scones } > 0
|
57
|
+
end
|
58
|
+
|
59
|
+
must "provide an instance that has tea" do
|
60
|
+
refute { subject.tea }.nil?
|
61
|
+
end
|
62
|
+
end
|
44
63
|
end
|
45
64
|
|
46
|
-
# Get nice test names. This one will be called "HighTea must
|
65
|
+
# Get nice test names. This one will be called "HighTea must let me have a scone"
|
47
66
|
must "let me have a scone" do
|
48
67
|
count = subject.scones
|
49
68
|
subject.eat_scone
|
50
69
|
assert { subject.scones } == count - 1
|
51
70
|
end
|
52
71
|
|
53
|
-
#
|
54
|
-
must "complain if out of scones", scones
|
72
|
+
# Modify test subject using traits or properties for minor variations
|
73
|
+
must "complain if out of scones", props { scones { 0 } } do
|
55
74
|
assert { subject.eat_scone }.raises?(StandardError)
|
56
75
|
end
|
57
76
|
|
58
77
|
# Create subcontexts for variations of the test subject using traits and properties
|
59
78
|
with :style do
|
60
|
-
# Still nice test names. This one is "HighTea with style
|
79
|
+
# Still nice test names. This one is "HighTea with style must have expensive tea"
|
61
80
|
must "have expensive tea" do
|
62
81
|
assert { subject.tea }.include?("First Flush")
|
63
82
|
end
|
@@ -79,8 +98,8 @@ Calificador is an experiment in getting rid of as much mental load, boilerplate
|
|
79
98
|
|
80
99
|
Only a handful of DSL methods are required:
|
81
100
|
|
82
|
-
* Test structure: examine,
|
83
|
-
* Factory methods: factory, traits
|
101
|
+
* Test structure: examine, type, operation, where/with/without, must
|
102
|
+
* Factory methods: factory, mock, traits
|
84
103
|
* Assertions: assert, refute and raises?
|
85
104
|
|
86
105
|
It also tries to keep things simple by avoiding all the special assertion and expectation methods you need to learn for other test frameworks. Instead of having to learn that `include` is the RSpec matcher for `include?`, or Minitest's `assert_match` is used to assert regular expression matches, you can write `refute { something }.include? "value"` or `assert { something }.match %r{pattern}` using Ruby's normal `String#match` method.
|
data/TODO.md
ADDED
data/calificador.gemspec
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
LIB_DIR = File.join(__dir__, "lib")
|
4
|
+
$LOAD_PATH.unshift(LIB_DIR) unless $LOAD_PATH.include?(LIB_DIR)
|
5
|
+
|
6
|
+
require "calificador/version"
|
7
|
+
require "json"
|
8
|
+
require "pathname"
|
9
|
+
|
10
|
+
Gem::Specification.new do |spec|
|
11
|
+
raise "RubyGems 2.0 or newer is required." unless spec.respond_to?(:metadata)
|
12
|
+
|
13
|
+
spec.name = "calificador"
|
14
|
+
spec.version = Calificador::VERSION
|
15
|
+
spec.summary = "Concise and readable unit tests"
|
16
|
+
|
17
|
+
spec.required_ruby_version = ">= 2.7"
|
18
|
+
|
19
|
+
spec.authors = ["Jochen Seeber"]
|
20
|
+
spec.email = ["jochen@seeber.me"]
|
21
|
+
spec.homepage = "https://github.com/jochenseeber/calificador"
|
22
|
+
|
23
|
+
spec.metadata["issue_tracker"] = "https://github.com/jochenseeber/calificador/issues"
|
24
|
+
spec.metadata["documentation"] = "http://jochenseeber.github.com/calificador"
|
25
|
+
spec.metadata["source_code"] = "https://github.com/jochenseeber/calificador"
|
26
|
+
spec.metadata["wiki"] = "https://github.com/jochenseeber/calificador/wiki"
|
27
|
+
|
28
|
+
spec.files = Dir[
|
29
|
+
"*.gemspec",
|
30
|
+
"*.md",
|
31
|
+
"*.txt",
|
32
|
+
"lib/**/*.rb",
|
33
|
+
]
|
34
|
+
|
35
|
+
spec.require_paths = [
|
36
|
+
"lib",
|
37
|
+
]
|
38
|
+
|
39
|
+
spec.bindir = "cmd"
|
40
|
+
spec.executables = spec.files.filter { |f| File.dirname(f) == "cmd" && File.file?(f) }.map { |f| File.basename(f) }
|
41
|
+
|
42
|
+
spec.add_dependency "minitest", "~> 5.14"
|
43
|
+
spec.add_dependency "zeitwerk", "~> 2.3"
|
44
|
+
|
45
|
+
spec.add_development_dependency "bundler", "~> 2.1"
|
46
|
+
spec.add_development_dependency "debase", "~> 0.2"
|
47
|
+
spec.add_development_dependency "qed", "~> 2.9"
|
48
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
49
|
+
spec.add_development_dependency "rubocop", ">= 0.85"
|
50
|
+
spec.add_development_dependency "rubocop-rake", ">= 0.5.1"
|
51
|
+
spec.add_development_dependency "ruby-debug-ide", "~> 0.7"
|
52
|
+
spec.add_development_dependency "simplecov", "~> 0.18"
|
53
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
54
|
+
end
|
data/lib/calificador.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "calificador/util/core_extensions"
|
4
4
|
require "minitest"
|
5
|
+
require "pathname"
|
6
|
+
require "zeitwerk"
|
5
7
|
|
6
8
|
loader = Zeitwerk::Loader.for_gem
|
7
9
|
loader.setup
|
8
10
|
|
9
11
|
# Main module
|
10
12
|
module Calificador
|
11
|
-
using Calificador::Util::CoreExtensions
|
12
|
-
|
13
13
|
MISSING = Util::Missing.instance
|
14
14
|
|
15
|
+
BASE_DIR = Pathname(__FILE__).expand_path.dirname
|
16
|
+
|
17
|
+
METHOD_PATTERN = %r{[[:alpha:]](?:[[:alnum:]]|_)*}.freeze
|
18
|
+
|
15
19
|
class << self
|
16
20
|
attr_writer :call_formatter
|
17
21
|
|
@@ -40,5 +44,5 @@ module Calificador
|
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
43
|
-
Minitest::Assertion.prepend(Calificador::Minitest::MinitestPatches::AssertionMethods)
|
44
47
|
Class.include(Calificador::Util::ClassMixin)
|
48
|
+
Minitest::Assertion.prepend(Calificador::Minitest::MinitestPatches::AssertionMethods)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "calificador"
|
4
|
+
|
5
|
+
module Calificador
|
6
|
+
module Assert
|
7
|
+
def assert(&block)
|
8
|
+
Calificador::Assertor.new(block: block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def refute(&block)
|
12
|
+
Calificador::Assertor.new(negated: true, block: block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/calificador/assertor.rb
CHANGED
@@ -1,64 +1,67 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "minitest"
|
4
|
+
require "singleton"
|
4
5
|
|
5
6
|
module Calificador
|
6
|
-
class Assertor <
|
7
|
-
|
8
|
-
|
7
|
+
class Assertor < Util::ProxyObject
|
8
|
+
class DefaultHandler
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
def assert(condition, message)
|
12
|
+
raise ::Minitest::Assertion, message unless condition
|
13
|
+
end
|
14
|
+
|
15
|
+
def refute(condition, message)
|
16
|
+
raise ::Minitest::Assertion, message if condition
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(handler: DefaultHandler.instance, negated: false, block: nil)
|
21
|
+
super()
|
22
|
+
|
23
|
+
@handler = handler
|
9
24
|
@negated = negated ? true : false
|
10
25
|
@block = block
|
11
26
|
@value = MISSING
|
12
27
|
@triggered = false
|
13
28
|
end
|
14
29
|
|
15
|
-
def respond_to?(method, include_all = false)
|
16
|
-
__value.respond_to?(method, include_all) || super
|
17
|
-
end
|
18
|
-
|
19
|
-
def method_missing(method, *arguments, **options, &block) # rubocop:disable Style/MissingRespondToMissing
|
20
|
-
if __value.respond_to?(method)
|
21
|
-
__check(method: method, arguments: arguments, options: options, &block)
|
22
|
-
else
|
23
|
-
super
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
30
|
def ==(other)
|
28
31
|
message = ::Kernel.proc do
|
29
|
-
actual = ::Calificador.call_formatter.
|
30
|
-
expected = ::Calificador.call_formatter.
|
32
|
+
actual = ::Calificador.call_formatter.format_value(value: __value)
|
33
|
+
expected = ::Calificador.call_formatter.format_value(value: other)
|
31
34
|
|
32
35
|
"Expected #{actual} (#{__value.class}) to#{@negated ? " not" : ""} be equal to #{expected} (#{other.class})"
|
33
36
|
end
|
34
37
|
|
35
|
-
__check(
|
38
|
+
__check(name: :"==", message: message, arguments: [other])
|
36
39
|
end
|
37
40
|
|
38
41
|
def !=(other)
|
39
42
|
message = ::Kernel.proc do
|
40
|
-
actual = ::Calificador.call_formatter.
|
41
|
-
expected = ::Calificador.call_formatter.
|
43
|
+
actual = ::Calificador.call_formatter.format_value(value: __value)
|
44
|
+
expected = ::Calificador.call_formatter.format_value(value: other)
|
42
45
|
|
43
46
|
"Expected #{actual} (#{__value.class}) to#{@negated ? "" : " not"} be equal to #{expected} (#{other.class})"
|
44
47
|
end
|
45
48
|
|
46
|
-
__check(
|
49
|
+
__check(name: :"!=", message: message, arguments: [other])
|
47
50
|
end
|
48
51
|
|
49
52
|
def identical?(other)
|
50
53
|
message = ::Kernel.proc do
|
51
|
-
actual = ::Calificador.call_formatter.
|
52
|
-
expected = ::Calificador.call_formatter.
|
54
|
+
actual = ::Calificador.call_formatter.format_value(value: __value)
|
55
|
+
expected = ::Calificador.call_formatter.format_value(value: other)
|
53
56
|
|
54
57
|
"Expected #{actual} (#{__value.class}) to#{@negated ? " not" : ""} be identical to #{expected} (#{other.class})"
|
55
58
|
end
|
56
59
|
|
57
|
-
__check(
|
60
|
+
__check(name: :"equal?", message: message, arguments: [other])
|
58
61
|
end
|
59
62
|
|
60
63
|
def not
|
61
|
-
Assertor.new(
|
64
|
+
Assertor.new(handler: @handler, negated: !@negated, block: @block)
|
62
65
|
end
|
63
66
|
|
64
67
|
def raises?(*exception_classes, &block)
|
@@ -70,23 +73,23 @@ module Calificador
|
|
70
73
|
::Kernel.raise ::ArgumentError, "Exception assert must have a block" if block.nil?
|
71
74
|
|
72
75
|
message = ::Kernel.proc do
|
73
|
-
actual = ::Calificador.call_formatter.
|
76
|
+
actual = ::Calificador.call_formatter.format_value(value: @block)
|
74
77
|
"Expected #{actual} (#{@block}) to#{@negated ? " not" : ""} raise #{exception_classes.join(", ")}"
|
75
78
|
end
|
76
79
|
|
77
80
|
begin
|
78
81
|
result = block.call
|
79
82
|
|
80
|
-
|
83
|
+
__assert(@negated, message: message)
|
81
84
|
|
82
85
|
result
|
83
86
|
rescue *exception_classes => e
|
84
|
-
|
87
|
+
__refute(@negated, message: __exception_details(e, message: message))
|
85
88
|
e
|
86
89
|
rescue ::Minitest::Assertion, ::SignalException, ::SystemExit
|
87
90
|
::Kernel.raise
|
88
91
|
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
89
|
-
|
92
|
+
__assert(@negated, message: __exception_details(e, message: message))
|
90
93
|
end
|
91
94
|
end
|
92
95
|
|
@@ -101,6 +104,18 @@ module Calificador
|
|
101
104
|
|
102
105
|
protected
|
103
106
|
|
107
|
+
def __respond_to_missing?(name:, include_all:)
|
108
|
+
__value.respond_to?(name, false)
|
109
|
+
end
|
110
|
+
|
111
|
+
def __method_missing(name:, arguments:, keywords:, block:)
|
112
|
+
if __value.respond_to?(name)
|
113
|
+
__check(name: name, arguments: arguments, keywords: keywords, &block)
|
114
|
+
else
|
115
|
+
super
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
104
119
|
def __value
|
105
120
|
if @value.equal?(MISSING)
|
106
121
|
::Kernel.raise ::StandardError, "No block set for assertion" if @block.nil?
|
@@ -111,24 +126,53 @@ module Calificador
|
|
111
126
|
@value
|
112
127
|
end
|
113
128
|
|
114
|
-
def __check(
|
129
|
+
def __check(name:, message: nil, arguments: [], keywords: {}, &block)
|
115
130
|
@triggered = true
|
116
131
|
|
117
|
-
result =
|
132
|
+
result = begin
|
133
|
+
__value.send(name, *arguments, **keywords, &block)
|
134
|
+
rescue ::StandardError => e
|
135
|
+
raise ::Minitest::UnexpectedError, e
|
136
|
+
end
|
118
137
|
|
119
138
|
message ||= ::Kernel.proc do
|
120
|
-
actual = ::Calificador.call_formatter.
|
121
|
-
call = ::Calificador.call_formatter.
|
139
|
+
actual = ::Calificador.call_formatter.format_value(value: __value)
|
140
|
+
call = ::Calificador.call_formatter.format_method(name: name, arguments: arguments, keywords: keywords)
|
122
141
|
"Expected #{actual} (#{__value.class}) to#{@negated ? " not" : ""} #{call}"
|
123
142
|
end
|
124
143
|
|
125
144
|
if @negated
|
126
|
-
|
145
|
+
__refute(result, message: message)
|
127
146
|
else
|
128
|
-
|
147
|
+
__assert(result, message: message)
|
129
148
|
end
|
130
149
|
|
131
150
|
result
|
132
151
|
end
|
152
|
+
|
153
|
+
def __assert(condition, message:)
|
154
|
+
message = message.call if !condition && message.is_a?(::Proc)
|
155
|
+
|
156
|
+
@handler.assert(condition, message)
|
157
|
+
end
|
158
|
+
|
159
|
+
def __refute(condition, message:)
|
160
|
+
message = message.call if condition && message.is_a?(::Proc)
|
161
|
+
|
162
|
+
@handler.refute(condition, message)
|
163
|
+
end
|
164
|
+
|
165
|
+
def __exception_details(exception, message:)
|
166
|
+
message = message.call if message.is_a?(::Proc)
|
167
|
+
|
168
|
+
[
|
169
|
+
message,
|
170
|
+
"Class: <#{exception.class}>",
|
171
|
+
"Message: #{exception.message}",
|
172
|
+
"---Backtrace---",
|
173
|
+
exception.backtrace.map(&:to_s),
|
174
|
+
"---------------",
|
175
|
+
].flatten.join("\n")
|
176
|
+
end
|
133
177
|
end
|
134
178
|
end
|
@@ -1,67 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
using Calificador::Util::CoreExtensions
|
4
|
-
|
5
3
|
module Calificador
|
6
4
|
module Build
|
7
5
|
class AttributeEvaluator
|
8
6
|
EVALUATING = Object.new.freeze
|
9
7
|
|
10
|
-
class Proxy
|
11
|
-
def initialize(
|
12
|
-
|
13
|
-
end
|
8
|
+
class Proxy < Util::ProxyObject
|
9
|
+
def initialize(evaluator:)
|
10
|
+
super()
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
@delegate.create_object(key: key)
|
12
|
+
@evaluator = evaluator
|
13
|
+
@environment_proxy = evaluator.environment.proxy
|
18
14
|
end
|
19
15
|
|
20
|
-
|
21
|
-
|
16
|
+
protected
|
17
|
+
|
18
|
+
def __respond_to_missing?(name:, include_all:)
|
19
|
+
@evaluator.attribute?(name: name) || @environment_proxy.respond_to?(name)
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
25
|
-
if @
|
22
|
+
def __method_missing(name:, arguments:, keywords:, block:)
|
23
|
+
if @evaluator.attribute?(name: name)
|
26
24
|
raise ArgumentError, "Getter must not be called with arguments" unless arguments.empty?
|
27
25
|
|
28
|
-
@
|
26
|
+
@evaluator.value(name: name)
|
29
27
|
else
|
30
|
-
|
28
|
+
@environment_proxy.__send__(name, *arguments, **keywords, &block)
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
35
|
-
attr_reader :attributes, :values
|
33
|
+
attr_reader :attributes, :values, :environment
|
36
34
|
|
37
|
-
def initialize(
|
38
|
-
@
|
35
|
+
def initialize(key:, environment:)
|
36
|
+
@key = key
|
37
|
+
@environment = environment
|
39
38
|
@attributes = {}
|
40
39
|
@values = {}
|
41
|
-
@proxy = Proxy.new(
|
40
|
+
@proxy = Proxy.new(evaluator: self)
|
42
41
|
end
|
43
42
|
|
44
|
-
def
|
45
|
-
@
|
46
|
-
end
|
47
|
-
|
48
|
-
def add_values(values)
|
49
|
-
@values.merge!(values)
|
43
|
+
def add_attribute(attribute)
|
44
|
+
@attributes[attribute.name] = attribute
|
50
45
|
end
|
51
46
|
|
52
47
|
def add_attributes(attributes)
|
53
48
|
attributes.each do |attribute|
|
54
|
-
|
49
|
+
add_attribute(attribute)
|
55
50
|
end
|
56
51
|
end
|
57
52
|
|
53
|
+
def add_values(values)
|
54
|
+
@values.merge!(values)
|
55
|
+
end
|
56
|
+
|
58
57
|
def value(name:)
|
59
58
|
result = @values.fetch(name) do
|
60
59
|
@values[name] = EVALUATING
|
61
60
|
|
62
61
|
begin
|
63
|
-
|
64
|
-
|
62
|
+
attribute = @attributes.fetch(name) do
|
63
|
+
raise KeyError, "Could not find attribute '#{name}' for factory #{@key}"
|
64
|
+
end
|
65
|
+
|
66
|
+
@values[name] = evaluate(&attribute.config)
|
65
67
|
rescue StandardError
|
66
68
|
@values.delete(name)
|
67
69
|
raise
|
@@ -73,10 +75,12 @@ module Calificador
|
|
73
75
|
result
|
74
76
|
end
|
75
77
|
|
76
|
-
def evaluate(*arguments,
|
77
|
-
|
78
|
+
def evaluate(*arguments, &block)
|
79
|
+
@proxy.instance_exec(*arguments, &block)
|
78
80
|
end
|
79
81
|
|
82
|
+
ruby2_keywords :evaluate
|
83
|
+
|
80
84
|
def attribute?(name:)
|
81
85
|
@attributes.key?(name)
|
82
86
|
end
|