calificador 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -16
  3. data/TODO.md +16 -0
  4. data/calificador.gemspec +54 -0
  5. data/lib/calificador.rb +8 -4
  6. data/lib/calificador/assert.rb +15 -0
  7. data/lib/calificador/assertor.rb +79 -35
  8. data/lib/calificador/build/attribute_evaluator.rb +34 -30
  9. data/lib/calificador/build/basic_factory.rb +195 -0
  10. data/lib/calificador/build/mock_factory.rb +151 -0
  11. data/lib/calificador/build/object_factory.rb +85 -0
  12. data/lib/calificador/build/trait.rb +0 -20
  13. data/lib/calificador/context/basic_context.rb +406 -0
  14. data/lib/calificador/context/class_method_context.rb +0 -0
  15. data/lib/calificador/{spec → context}/condition_context.rb +1 -3
  16. data/lib/calificador/{spec/type_context.rb → context/instance_context.rb} +5 -10
  17. data/lib/calificador/context/operation_context.rb +27 -0
  18. data/lib/calificador/context/override/argument_override.rb +73 -0
  19. data/lib/calificador/context/override/basic_override.rb +14 -0
  20. data/lib/calificador/context/override/factory_override.rb +31 -0
  21. data/lib/calificador/context/override/property_override.rb +61 -0
  22. data/lib/calificador/context/test_environment.rb +283 -0
  23. data/lib/calificador/{spec → context}/test_method.rb +2 -31
  24. data/lib/calificador/{spec → context}/test_root.rb +3 -15
  25. data/lib/calificador/{spec/examine_context.rb → context/type_context.rb} +7 -10
  26. data/lib/calificador/key.rb +27 -15
  27. data/lib/calificador/minitest/minitest_patches.rb +0 -2
  28. data/lib/calificador/test.rb +1 -3
  29. data/lib/calificador/test_mixin.rb +143 -139
  30. data/lib/calificador/util/call_formatter.rb +5 -5
  31. data/lib/calificador/util/core_extensions.rb +104 -79
  32. data/lib/calificador/util/proxy_object.rb +63 -0
  33. data/lib/calificador/version.rb +1 -1
  34. metadata +22 -42
  35. data/lib/calificador/build/attribute_container.rb +0 -103
  36. data/lib/calificador/build/factory.rb +0 -132
  37. data/lib/calificador/spec/basic_context.rb +0 -353
  38. data/lib/calificador/spec/class_method_context.rb +0 -42
  39. data/lib/calificador/spec/instance_method_context.rb +0 -38
  40. data/lib/calificador/spec/test_environment.rb +0 -141
  41. data/lib/calificador/spec/value_override.rb +0 -37
@@ -1,17 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- using Calificador::Util::CoreExtensions
4
-
5
3
  module Calificador
6
- module Spec
4
+ module Context
7
5
  # Factory class
8
6
  class TestMethod < BasicContext
9
- class Dsl < BasicContext::Dsl
10
- def body(&block)
11
- delegate.body = block
12
- end
13
- end
14
-
15
7
  attr_reader :body, :expected_to_fail
16
8
 
17
9
  def initialize(parent:, subject_key:, description:, overrides:, expected_to_fail: false, body:)
@@ -28,7 +20,7 @@ module Calificador
28
20
 
29
21
  test_class.class_eval(<<~METHOD, file, line_number)
30
22
  define_method(test_method_name) do
31
- __run_test(test_method: test_method)
23
+ __run_test(context: test_method)
32
24
  end
33
25
  METHOD
34
26
 
@@ -38,27 +30,6 @@ module Calificador
38
30
  def method_name
39
31
  @method_name ||= "test_: #{full_description}"
40
32
  end
41
-
42
- def run_test(test:)
43
- body = self.body
44
- environment = TestEnvironment.new(test: test, context: self)
45
-
46
- if expected_to_fail
47
- passed = begin
48
- environment.instance_exec(&body)
49
- true
50
- rescue ::Minitest::Assertion => e
51
- test.pass(e.message)
52
- false
53
- end
54
-
55
- test.flunk("Expected test to fail") if passed
56
- else
57
- environment.instance_exec(&body)
58
- end
59
-
60
- environment.__done
61
- end
62
33
  end
63
34
  end
64
35
  end
@@ -1,20 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- using Calificador::Util::CoreExtensions
4
-
5
3
  module Calificador
6
- module Spec
7
- class TestRoot < ExamineContext
8
- class Dsl < ExamineContext::Dsl
9
- def body(&block)
10
- delegate.body = block
11
- end
12
- end
13
-
4
+ module Context
5
+ class TestRoot < InstanceContext
14
6
  attr_accessor :test_class
15
7
 
16
8
  def initialize(test_class:, subject_key:, description:, &body)
17
- super(parent: nil, subject_key: subject_key, description: description, overrides: {})
9
+ super(parent: nil, subject_key: subject_key, description: description)
18
10
 
19
11
  @test_class = test_class
20
12
  @body = body
@@ -30,10 +22,6 @@ module Calificador
30
22
  super
31
23
  end
32
24
 
33
- def create_result(subject:, arguments:, options:, block:)
34
- subject
35
- end
36
-
37
25
  protected
38
26
 
39
27
  def setup_body
@@ -1,24 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- using Calificador::Util::CoreExtensions
4
-
5
3
  module Calificador
6
- module Spec
7
- class ExamineContext < BasicContext
8
- class Dsl < BasicContext::Dsl
9
- end
4
+ module Context
5
+ class TypeContext < BasicContext
6
+ def initialize(parent:, subject_key:, description:, overrides: [])
7
+ raise ArgumentError, "Subject must be a must be a #{BasicObject}" unless subject_key.type <= BasicObject
10
8
 
11
- def initialize(parent:, subject_key:, description:, overrides: {})
12
9
  super(
13
10
  parent: parent,
14
11
  description: description,
15
12
  subject_key: subject_key,
16
- overrides: overrides,
13
+ overrides: overrides
17
14
  )
18
15
  end
19
16
 
20
- def create_subject(environment:, subject_key:)
21
- environment.create_object(key: subject_key)
17
+ def create_subject(environment:)
18
+ subject_key.type
22
19
  end
23
20
 
24
21
  def subtree_root?
@@ -2,27 +2,36 @@
2
2
 
3
3
  require "minitest"
4
4
 
5
- using Calificador::Util::CoreExtensions
6
-
7
5
  module Calificador
8
6
  # Test subject key
9
7
  class Key
8
+ NO_TRAIT = :"<none>"
10
9
  DEFAULT_TRAIT = :"<default>"
11
- INHERITED_TRAIT = :"<inherited>"
12
10
 
13
11
  class << self
14
- def [](type, trait = DEFAULT_TRAIT)
12
+ def [](type, trait = NO_TRAIT)
15
13
  new(type: type, trait: trait)
16
14
  end
17
15
  end
18
16
 
19
17
  attr_reader :type, :trait
20
18
 
21
- def initialize(type:, trait: DEFAULT_TRAIT)
22
- raise ArgumentError, "Illegal trait value #{trait}" if trait == INHERITED_TRAIT
19
+ def initialize(type:, trait: NO_TRAIT)
20
+ trait ||= NO_TRAIT
21
+
22
+ raise ArgumentError, "Type must be a #{Module}, not '#{type}' (#{type.class})" unless type.is_a?(Module)
23
+ raise ArgumentError, "Trait must be a #{Symbol}" unless trait.is_a?(Symbol)
23
24
 
24
25
  @type = type
25
- @trait = trait || DEFAULT_TRAIT
26
+ @trait = trait
27
+ end
28
+
29
+ def trait?
30
+ @trait != NO_TRAIT && @trait != DEFAULT_TRAIT
31
+ end
32
+
33
+ def default_trait?
34
+ @trait == DEFAULT_TRAIT
26
35
  end
27
36
 
28
37
  def hash
@@ -30,30 +39,33 @@ module Calificador
30
39
  end
31
40
 
32
41
  def ==(other)
33
- (@type == other.type) && (@trait == other.trait)
42
+ other.is_a?(Key) && (@type == other.type) && (@trait == other.trait)
34
43
  end
35
44
 
36
45
  alias_method :eql?, :==
37
46
 
38
- def to_s
39
- trait == DEFAULT_TRAIT ? type.to_s : "#{type} (#{trait})"
47
+ def to_s(base_module: nil)
48
+ type_name = @type.name_without_common_parents(base: base_module)
49
+ @trait == NO_TRAIT ? type_name : "#{type_name} (#{@trait})"
40
50
  end
41
51
 
42
52
  alias_method :inspect, :to_s
43
53
 
44
54
  def with(trait)
45
55
  case trait
46
- when INHERITED_TRAIT
47
- self
48
56
  when nil, DEFAULT_TRAIT
49
- @trait == DEFAULT_TRAIT ? self : Key.new(type: @type, trait: DEFAULT_TRAIT)
57
+ self
50
58
  else
51
59
  trait == @trait ? self : Key.new(type: @type, trait: trait)
52
60
  end
53
61
  end
54
62
 
55
- def trait?
56
- @trait != DEFAULT_TRAIT
63
+ def with_default(key)
64
+ if @trait == DEFAULT_TRAIT && @trait != key.trait
65
+ Key[@type, key.trait]
66
+ else
67
+ self
68
+ end
57
69
  end
58
70
  end
59
71
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  require "minitest/test"
4
4
 
5
- using Calificador::Util::CoreExtensions
6
-
7
5
  module Calificador
8
6
  module Minitest
9
7
  # Patches to minitest classes
@@ -2,11 +2,9 @@
2
2
 
3
3
  require "minitest"
4
4
 
5
- using Calificador::Util::CoreExtensions
6
-
7
5
  module Calificador
8
6
  # Base class for unit tests
9
7
  class Test < ::Minitest::Test
10
- include TestMixin
8
+ prepend TestMixin
11
9
  end
12
10
  end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "minitest"
4
-
5
- using Calificador::Util::CoreExtensions
4
+ require "forwardable"
6
5
 
7
6
  module Calificador
8
7
  # Mixin for unit tests
9
8
  module TestMixin
9
+ extend Forwardable
10
+
10
11
  Key = Calificador::Key
11
12
 
12
13
  class << self
@@ -19,189 +20,155 @@ module Calificador
19
20
  end
20
21
  end
21
22
 
22
- def __run_test(test_method:)
23
+ def singleton_method_added(method)
24
+ raise "Adding singleton methods (#{method}) to tests is not supported here" if __current_test_environment?
25
+
26
+ super
27
+ end
28
+
29
+ def_delegator :__current_test_environment, :subject
30
+ def_delegator :__current_test_environment, :create
31
+
32
+ def __run_test(context:)
23
33
  stack_marker = "calificador_test_#{SecureRandom.uuid.gsub("-", "_")}"
24
34
 
25
- __register_current_run(stack_marker: stack_marker, test_method: test_method)
35
+ environment = Context::TestEnvironment.new(parent: context, test_instance: self)
36
+ __register_current_environment(stack_marker: stack_marker, environment: environment)
26
37
 
27
38
  begin
28
39
  instance_eval(<<~METHOD, stack_marker, 1)
29
- test_method.run_test(test: self)
40
+ environment.run_test
30
41
  METHOD
31
42
  ensure
32
- __unregister_current_run(stack_marker: stack_marker)
43
+ __unregister_current_environment(stack_marker: stack_marker)
33
44
  end
34
45
  end
35
46
 
36
47
  protected
37
48
 
38
- TestRun = Struct.new(:test_instance, :test_method, keyword_init: true)
39
-
40
- def __register_current_run(stack_marker:, test_method:)
41
- @__calificador_current_test_run = TestRun.new(test_instance: self, test_method: test_method)
42
- Calificador::Test.__register_current_run(stack_marker: stack_marker, test_run: @__calificador_current_test_run)
49
+ def __register_current_environment(stack_marker:, environment:)
50
+ @__calificador_current_test_environment = environment
51
+ Calificador::Test.__register_current_environment(stack_marker: stack_marker, environment: environment)
43
52
  end
44
53
 
45
- def __unregister_current_run(stack_marker:)
46
- if !instance_variable_defined?(:@__calificador_current_test_run) || @__calificador_current_test_run.nil?
54
+ def __unregister_current_environment(stack_marker:)
55
+ if !instance_variable_defined?(:@__calificador_current_test_environment) || @__calificador_current_test_environment.nil?
47
56
  raise StandardError, "No current test run registered"
48
57
  end
49
58
 
50
- Calificador::Test.__unregister_current_run(stack_marker: stack_marker)
51
- @__calificador_current_test_run = nil
59
+ Calificador::Test.__unregister_current_environment(stack_marker: stack_marker)
60
+ @__calificador_current_test_environment = nil
52
61
  end
53
62
 
54
- def __current_test_run
55
- if !instance_variable_defined?(:@__calificador_current_test_run) || @__calificador_current_test_run.nil?
63
+ def __current_test_environment
64
+ if !instance_variable_defined?(:@__calificador_current_test_environment) || @__calificador_current_test_environment.nil?
56
65
  raise StandardError, "No current test run registered"
57
66
  end
58
67
 
59
- @__calificador_current_test_run
68
+ @__calificador_current_test_environment
69
+ end
70
+
71
+ def __current_test_environment?
72
+ instance_variable_defined?(:@__calificador_current_test_environment) || !@__calificador_current_test_environment
60
73
  end
61
74
 
62
75
  # Class methods for unit tests
63
76
  module ClassMethods
77
+ extend Forwardable
78
+
64
79
  def run_all_tests(reporter: MiniTest::CompositeReporter.new)
65
80
  runnable_methods.each do |method|
66
81
  run_one_method(self, method, reporter)
67
82
  end
68
83
  end
69
84
 
70
- def examines(type = MISSING, trait: MISSING)
71
- self.__subject_type = type unless type.equal?(MISSING)
72
- self.__subject_trait = trait unless trait.equal?(MISSING)
73
-
74
- Key[__subject_type, __subject_trait]
75
- end
76
-
77
- def factory(type, description = nil, name: nil, &block)
78
- __root_context.dsl_config do
79
- factory(type, description, name: nil, &block)
80
- end
81
- end
82
-
83
- def examine(subject_type, description = nil, trait: Key::INHERITED_TRAIT, **values, &block)
84
- __root_context.dsl_config do
85
- examine(subject_type, description, trait: trait, **values, &block)
86
- end
87
- end
88
-
89
- def method(method, description = nil, **values, &block)
90
- __root_context.dsl_config do
91
- method(method, description, &block)
85
+ def examines(subject_class, *description_or_trait_or_init)
86
+ if instance_variable_defined?(:@__calificador_root_context) && @__calificador_root_context
87
+ raise <<~MESSAGE.gsub("\n", " ")
88
+ Cannot specify 'examines' after a test context has been defined. The 'examines' statement should be the first statement in your test class
89
+ MESSAGE
92
90
  end
93
- end
94
91
 
95
- def class_method(method, description = nil, **values, &block)
96
- __root_context.dsl_config do
97
- class_method(method, description, &block)
98
- end
99
- end
92
+ arguments = Context::BasicContext.extract_arguments(
93
+ subject_key: Key[subject_class],
94
+ values: description_or_trait_or_init,
95
+ names: %i[description trait init]
96
+ )
100
97
 
101
- def must(description, trait: Key::INHERITED_TRAIT, **values, &block)
102
- __root_context.dsl_config do
103
- must(description, trait: trait, **values, &block)
104
- end
105
- end
98
+ arguments.description ||= __default_instance_description(subject_key: arguments.subject_key)
106
99
 
107
- def must_fail(description, trait: Key::INHERITED_TRAIT, **values, &block)
108
- __root_context.dsl_config do
109
- must_fail(description, trait: trait, **values, &block)
110
- end
100
+ @__calificador_root_context = Context::TestRoot.new(
101
+ test_class: self,
102
+ subject_key: arguments.subject_key,
103
+ description: arguments.description
104
+ )
111
105
  end
112
106
 
113
- def with(description, trait: Key::INHERITED_TRAIT, **values, &block)
114
- __root_context.dsl_config do
115
- with(description, trait: trait, **values, &block)
116
- end
117
- end
118
-
119
- def without(description, trait: Key::INHERITED_TRAIT, **values, &block)
120
- __root_context.dsl_config do
121
- without(description, trait: trait, **values, &block)
122
- end
123
- end
124
-
125
- def where(description, trait: Key::INHERITED_TRAIT, **values, &block)
126
- __root_context.dsl_config do
127
- where(description, trait: trait, **values, &block)
128
- end
129
- end
107
+ def_delegators :__calificador_current_context, :factory, :mock
108
+ def_delegators :__calificador_current_context, :type, :examine, :operation, :with, :without, :where
109
+ def_delegators :__calificador_current_context, :must, :must_fail
110
+ def_delegators :__calificador_current_context, :args, :props
130
111
 
131
112
  def body(&block)
132
113
  class_eval(&block)
133
114
  end
134
115
 
135
- def __subject_type
136
- if !instance_variable_defined?(:@__calificador_subject_type) || @__calificador_subject_type.nil?
137
- type_name = name.gsub(%r{(?<=\w)Test\z}, "")
138
-
139
- if Kernel.const_defined?(type_name)
140
- @__calificador_subject_type = Kernel.const_get(type_name)
141
- else
142
- raise StandardError, "Cannot determine test subject type from test class name '#{name}'"
143
- end
144
- end
145
-
146
- @__calificador_subject_type
116
+ def __default_type_description(subject_key:)
117
+ subject_key.type.name_without_common_parents(base: self)
147
118
  end
148
119
 
149
- def __subject_type=(type)
150
- if instance_variable_defined?(:@__calificador_subject_type) && !@__calificador_subject_type.nil?
151
- raise StandardError, "Cannot redefine test subject type"
152
- end
120
+ def __default_instance_description(subject_key:)
121
+ description = StringIO.new
153
122
 
154
- @__calificador_subject_type = type
155
- end
123
+ description << subject_key.type.name_without_common_parents(base: self)
124
+ description << "(" << subject_key.trait.to_s.gsub("_", " ") << ")" if subject_key.trait?
156
125
 
157
- def __subject_trait
158
- if !instance_variable_defined?(:@__calificador_subject_trait) || @__calificador_subject_trait.nil?
159
- @__calificador_subject_trait = Key::DEFAULT_TRAIT
160
- end
161
-
162
- @__calificador_subject_trait
126
+ description.string
163
127
  end
164
128
 
165
- def __subject_trait=(trait)
166
- if instance_variable_defined?(:@__calificador_subject_trait) && !@__calificador_subject_trait.nil?
167
- raise StandardError, "Cannot redefine test subject trait"
168
- end
129
+ def __default_factory_name(subject_key:)
130
+ description = StringIO.new
131
+
132
+ description << subject_key.type.base_name.snake_case
133
+ description << "_" << subject_key.trait.to_s if subject_key.trait?
169
134
 
170
- @__calificador_subject_trait = trait
135
+ description.string
171
136
  end
172
137
 
173
138
  def __root_context
174
139
  if !instance_variable_defined?(:@__calificador_root_context) || @__calificador_root_context.nil?
175
- description = __subject_type.name.delete_prefix(parent_prefix)
176
- description = "#{description} {#{__subject_trait}}" unless __subject_trait.equal?(Key::DEFAULT_TRAIT)
140
+ subject_key = __calificador_guess_subject_key
177
141
 
178
- @__calificador_root_context = Spec::TestRoot.new(
142
+ @__calificador_root_context = Context::TestRoot.new(
179
143
  test_class: self,
180
- subject_key: Key[__subject_type, __subject_trait],
181
- description: description
144
+ subject_key: subject_key,
145
+ description: __default_instance_description(subject_key: subject_key)
182
146
  )
183
147
  end
184
148
 
185
149
  @__calificador_root_context
186
150
  end
187
151
 
188
- def __register_current_run(stack_marker:, test_run:)
152
+ def __register_current_environment(stack_marker:, environment:)
189
153
  __calificador_test_lock.synchronize do
190
- raise KeyError, "Test run #{stack_marker} already registered" if __calificador_test_runs.key?(stack_marker)
154
+ if __calificador_test_environments.key?(stack_marker)
155
+ raise KeyError,
156
+ "Test run #{stack_marker} already registered"
157
+ end
191
158
 
192
- __calificador_test_runs[stack_marker] = test_run
159
+ __calificador_test_environments[stack_marker] = environment
193
160
  end
194
161
  end
195
162
 
196
- def __unregister_current_run(stack_marker:)
163
+ def __unregister_current_environment(stack_marker:)
197
164
  __calificador_test_lock.synchronize do
198
- if __calificador_test_runs.delete(stack_marker).nil?
165
+ if __calificador_test_environments.delete(stack_marker).nil?
199
166
  raise KeyError, "Could not unregister test #{stack_marker}"
200
167
  end
201
168
  end
202
169
  end
203
170
 
204
- def __current_test_run
171
+ def __current_test_environment
205
172
  __calificador_test_lock.synchronize do
206
173
  location = ::Kernel.caller_locations.find do |l|
207
174
  %r{\Acalificador_test_[a-zA-Z0-9_]+\z} =~ l.path
@@ -209,49 +176,59 @@ module Calificador
209
176
 
210
177
  raise StandardError, "Could not find current test run in call stack" unless location
211
178
 
212
- __calificador_test_runs.fetch(location.path) do
179
+ __calificador_test_environments.fetch(location.path) do
213
180
  raise KeyError, "No test run registered for #{location.path}"
214
181
  end
215
182
  end
216
183
  end
217
184
 
218
- def __factory_methods
219
- @__calificador_factory_methods = Set.new unless instance_variable_defined?(:@__calificador_factory_methods)
185
+ def __calificador_configure(context:, block:)
186
+ __calificador_push_context(context)
220
187
 
221
- @__calificador_factory_methods.dup.freeze
188
+ begin
189
+ class_exec(&block)
190
+ ensure
191
+ __calificador_pop_context
192
+ end
222
193
  end
223
194
 
224
- def __define_factory_method(factory:)
225
- @__calificador_factory_methods = Set.new unless instance_variable_defined?(:@__calificador_factory_methods)
226
-
227
- if @__calificador_factory_methods.add?(factory.name)
228
- factory_method_name = if factory.name.to_s.start_with?("test_")
229
- "create_#{factory.name}"
230
- else
231
- factory.name
232
- end
195
+ def method_added(method)
196
+ if !method.start_with?("test_: ") && __calificador_contexts.size > 1
197
+ raise "Adding methods (#{method}) to tests is not supported here"
198
+ end
233
199
 
234
- if method_defined?(factory_method_name, true)
235
- raise "Cannot define factory method #{factory_method_name}, method already exists in #{self.class}"
236
- end
200
+ super
201
+ end
237
202
 
238
- type = factory.key.type # rubocop:disable Lint/UselessAssignment
239
- trait = factory.key.trait # rubocop:disable Lint/UselessAssignment
203
+ protected
240
204
 
241
- class_eval(<<~METHOD, factory.source_location.first, factory.source_location.last)
242
- define_method(factory_method_name) do
243
- __current_test_run.test_method.create(type: type, trait: trait)
244
- end
245
- METHOD
205
+ def __calificador_contexts
206
+ if !instance_variable_defined?(:@__calificador_contexts) || @__calificador_contexts.nil?
207
+ @__calificador_contexts = [__root_context]
246
208
  end
209
+
210
+ @__calificador_contexts
247
211
  end
248
212
 
249
- protected
213
+ def __calificador_push_context(context)
214
+ __calificador_contexts.push(context)
215
+ context
216
+ end
250
217
 
251
- def __calificador_test_runs
252
- @__calificador_test_runs = {} unless instance_variable_defined?(:@__calificador_test_runs)
218
+ def __calificador_pop_context
219
+ raise "Cannot remove root context" unless __calificador_contexts.size > 1
220
+
221
+ __calificador_contexts.pop
222
+ end
253
223
 
254
- @__calificador_test_runs
224
+ def __calificador_current_context
225
+ __calificador_contexts.last
226
+ end
227
+
228
+ def __calificador_test_environments
229
+ @__calificador_test_environments = {} unless instance_variable_defined?(:@__calificador_test_environments)
230
+
231
+ @__calificador_test_environments
255
232
  end
256
233
 
257
234
  def __calificador_test_lock
@@ -259,6 +236,33 @@ module Calificador
259
236
 
260
237
  @__calificador_test_lock
261
238
  end
239
+
240
+ def __calificador_guess_subject_key
241
+ type_name = name&.gsub(%r{(?<=\w)Test\z}, "")
242
+
243
+ unless type_name
244
+ raise StandardError, <<~MESSAGE.gsub("\n", " ")
245
+ Cannot guess test subject class from test class name '#{name}'. Please use 'examines' to specify the test subject.
246
+ MESSAGE
247
+ end
248
+
249
+ unless Kernel.const_defined?(type_name)
250
+ raise StandardError, <<~MESSAGE.gsub("\n", " ")
251
+ Guessed test subject type (#{type_name}) does not exist. Please use 'examines' to specify the test subject.
252
+ MESSAGE
253
+ end
254
+
255
+ subject_type = Kernel.const_get(type_name)
256
+
257
+ if subject_type <= Singleton || subject_type <= BasicObject || subject_type.is_a?(Module)
258
+ Key[subject_type]
259
+ else
260
+ raise StandardError, <<~MESSAGE.gsub("\n", " ")
261
+ Guessed test subject type (#{subject_type}) is not a Class, a Module or a Singleton. Please use 'examines'
262
+ to specify the test subject.
263
+ MESSAGE
264
+ end
265
+ end
262
266
  end
263
267
  end
264
268
  end