calificador 0.1.0 → 0.2.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 +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
|