smartest 0.3.3.alpha3 → 0.3.3.alpha4
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/DEVELOPMENT.md +1 -0
- data/README.md +8 -8
- data/lib/smartest/constant_stub_helpers.rb +45 -0
- data/lib/smartest/execution_context.rb +1 -0
- data/lib/smartest/fixture.rb +1 -37
- data/lib/smartest/hook_contexts.rb +4 -0
- data/lib/smartest/version.rb +1 -1
- data/lib/smartest.rb +1 -0
- data/smartest/simple_stub_test.rb +69 -32
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 75e3f0538afd3f490c37121ae4eee497a4691f35926ff50201e035acb64d2314
|
|
4
|
+
data.tar.gz: 53fea3bdbbb788167d13c6a7b6c18a9258de42b971c4f2a1f36906176f75813a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba646897bc5994e7caf30fc9b1127a1ad72f2545a4ed8734820c5eeeca3e5e1e7e0302394b38916fbc9d9c153dccfdae96496093dce1f23af172fa74a01cbd75
|
|
7
|
+
data.tar.gz: 5c12f0c3532da8eb44c3e832d28e479b1f8a54f5797a4c67c61c865bbbedf31e2225fe441c1f433d8de6ce3b2246c374de998d2aae9b2cfa8a7ea63f043ed949
|
data/DEVELOPMENT.md
CHANGED
data/README.md
CHANGED
|
@@ -637,16 +637,16 @@ end
|
|
|
637
637
|
```
|
|
638
638
|
|
|
639
639
|
Use `simple_stub(Time, :now) { fixed_time }` for singleton methods such as class
|
|
640
|
-
methods.
|
|
641
|
-
|
|
642
|
-
|
|
640
|
+
methods.
|
|
641
|
+
|
|
642
|
+
Use `simple_stub_const("AppConfig::PAYMENT_PROVIDER", "fake") { ... }` for
|
|
643
|
+
constants in test bodies, `around_test`, or `around_suite`. Constant stubs are
|
|
644
|
+
process-global; avoid concurrent tests that stub the same constant.
|
|
643
645
|
|
|
644
646
|
The method stub helpers call `Smartest::SimpleStub` internally, apply the stub,
|
|
645
647
|
register `cleanup { stub.reset }`, and return the stub object.
|
|
646
|
-
`simple_stub_const` records the previous constant value, replaces it,
|
|
647
|
-
restores or removes
|
|
648
|
-
`Smartest::Fixture` fixture blocks because they need cleanup to tie the stub
|
|
649
|
-
lifetime to the fixture scope.
|
|
648
|
+
`simple_stub_const` records the previous constant value, replaces it, yields to
|
|
649
|
+
the block, and restores or removes the constant with `ensure`.
|
|
650
650
|
|
|
651
651
|
`Smartest::SimpleStub#apply` and `#reset` are idempotent in the current Fiber.
|
|
652
652
|
`apply!` raises
|
|
@@ -880,7 +880,7 @@ Smartest currently focuses on a small runner API:
|
|
|
880
880
|
- fixture dependencies through keyword arguments
|
|
881
881
|
- fixture cleanup
|
|
882
882
|
- suite-scoped fixtures through `suite_fixture`
|
|
883
|
-
- fixture-scoped method and constant stubs
|
|
883
|
+
- fixture-scoped method stubs and block-scoped constant stubs
|
|
884
884
|
- suite hooks with `around_suite`
|
|
885
885
|
- test hooks with `around_test`
|
|
886
886
|
- skipped and pending tests through `skip` and `pending`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Smartest
|
|
4
|
+
module ConstantStubHelpers
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def simple_stub_const(constant_path, value)
|
|
8
|
+
raise ArgumentError, "simple_stub_const block is required" unless block_given?
|
|
9
|
+
|
|
10
|
+
owner, constant_name = resolve_simple_stub_constant(constant_path)
|
|
11
|
+
original_defined = owner.const_defined?(constant_name, false)
|
|
12
|
+
original_value = owner.const_get(constant_name, false) if original_defined
|
|
13
|
+
|
|
14
|
+
owner.__send__(:remove_const, constant_name) if original_defined
|
|
15
|
+
owner.const_set(constant_name, value)
|
|
16
|
+
|
|
17
|
+
yield
|
|
18
|
+
ensure
|
|
19
|
+
if owner && constant_name
|
|
20
|
+
owner.__send__(:remove_const, constant_name) if owner.const_defined?(constant_name, false)
|
|
21
|
+
owner.const_set(constant_name, original_value) if original_defined
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def resolve_simple_stub_constant(constant_path)
|
|
26
|
+
unless constant_path.is_a?(String) || constant_path.is_a?(Symbol)
|
|
27
|
+
raise ArgumentError, "constant path must be a String or Symbol"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
names = constant_path.to_s.split("::")
|
|
31
|
+
names.shift if names.first == ""
|
|
32
|
+
raise ArgumentError, "constant path must not be empty" if names.empty?
|
|
33
|
+
|
|
34
|
+
names.each do |name|
|
|
35
|
+
raise ArgumentError, "invalid constant path: #{constant_path}" unless name.match?(/\A[A-Z]\w*\z/)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
constant_name = names.pop.to_sym
|
|
39
|
+
owner = names.reduce(Object) { |namespace, name| namespace.const_get(name, false) }
|
|
40
|
+
raise ArgumentError, "constant owner must be a Module or Class" unless owner.is_a?(Module)
|
|
41
|
+
|
|
42
|
+
[owner, constant_name]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/smartest/fixture.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Smartest
|
|
4
4
|
class Fixture
|
|
5
|
-
RESERVED_CONTEXT_METHODS = %i[skip pending].freeze
|
|
5
|
+
RESERVED_CONTEXT_METHODS = %i[skip pending simple_stub_const].freeze
|
|
6
6
|
|
|
7
7
|
class << self
|
|
8
8
|
def fixture(name, scope: :test, &block)
|
|
@@ -73,48 +73,12 @@ module Smartest
|
|
|
73
73
|
apply_simple_stub(SimpleStub.new(object.singleton_class, method_name, &block))
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
def simple_stub_const(constant_path, value)
|
|
77
|
-
owner, constant_name = resolve_simple_stub_constant(constant_path)
|
|
78
|
-
original_defined = owner.const_defined?(constant_name, false)
|
|
79
|
-
original_value = owner.const_get(constant_name, false) if original_defined
|
|
80
|
-
|
|
81
|
-
owner.__send__(:remove_const, constant_name) if original_defined
|
|
82
|
-
owner.const_set(constant_name, value)
|
|
83
|
-
|
|
84
|
-
cleanup do
|
|
85
|
-
owner.__send__(:remove_const, constant_name) if owner.const_defined?(constant_name, false)
|
|
86
|
-
owner.const_set(constant_name, original_value) if original_defined
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
value
|
|
90
|
-
end
|
|
91
|
-
|
|
92
76
|
def apply_simple_stub(stub)
|
|
93
77
|
stub.apply!
|
|
94
78
|
cleanup { stub.reset }
|
|
95
79
|
stub
|
|
96
80
|
end
|
|
97
81
|
|
|
98
|
-
def resolve_simple_stub_constant(constant_path)
|
|
99
|
-
unless constant_path.is_a?(String) || constant_path.is_a?(Symbol)
|
|
100
|
-
raise ArgumentError, "constant path must be a String or Symbol"
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
names = constant_path.to_s.split("::")
|
|
104
|
-
names.shift if names.first == ""
|
|
105
|
-
raise ArgumentError, "constant path must not be empty" if names.empty?
|
|
106
|
-
|
|
107
|
-
names.each do |name|
|
|
108
|
-
raise ArgumentError, "invalid constant path: #{constant_path}" unless name.match?(/\A[A-Z]\w*\z/)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
constant_name = names.pop.to_sym
|
|
112
|
-
owner = names.reduce(Object) { |namespace, name| namespace.const_get(name, false) }
|
|
113
|
-
raise ArgumentError, "constant owner must be a Module or Class" unless owner.is_a?(Module)
|
|
114
|
-
|
|
115
|
-
[owner, constant_name]
|
|
116
|
-
end
|
|
117
|
-
|
|
118
82
|
def method_missing(method_name, *args, &block)
|
|
119
83
|
return super if RESERVED_CONTEXT_METHODS.include?(method_name)
|
|
120
84
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Smartest
|
|
4
4
|
class AroundSuiteContext
|
|
5
|
+
include ConstantStubHelpers
|
|
6
|
+
|
|
5
7
|
def initialize(suite)
|
|
6
8
|
@suite = suite
|
|
7
9
|
end
|
|
@@ -30,6 +32,8 @@ module Smartest
|
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
class AroundTestContext
|
|
35
|
+
include ConstantStubHelpers
|
|
36
|
+
|
|
33
37
|
def initialize(test_run, run_state:)
|
|
34
38
|
@test_run = test_run
|
|
35
39
|
@run_state = run_state
|
data/lib/smartest/version.rb
CHANGED
data/lib/smartest.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "smartest/version"
|
|
4
4
|
require_relative "smartest/errors"
|
|
5
5
|
require_relative "smartest/simple_stub"
|
|
6
|
+
require_relative "smartest/constant_stub_helpers"
|
|
6
7
|
require_relative "smartest/parameter_extractor"
|
|
7
8
|
require_relative "smartest/test_case"
|
|
8
9
|
require_relative "smartest/test_registry"
|
|
@@ -158,64 +158,101 @@ test("simple_stub applies and resets singleton methods from fixture cleanup") do
|
|
|
158
158
|
expect(status).to eq(0)
|
|
159
159
|
end
|
|
160
160
|
|
|
161
|
-
test("simple_stub_const applies and resets existing constants
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
test("simple_stub_const applies and resets existing constants in test body blocks") do
|
|
162
|
+
result = simple_stub_const("SimpleStubSelfTestConfig::PROVIDER", :stubbed_provider) do
|
|
163
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:stubbed_provider)
|
|
164
|
+
:block_result
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
expect(result).to eq(:block_result)
|
|
168
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:original_provider)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
test("simple_stub_const removes newly defined constants after test body blocks") do
|
|
172
|
+
simple_stub_const("SimpleStubSelfTestConfig::MISSING_PROVIDER", :stubbed_missing_provider) do
|
|
173
|
+
expect(SimpleStubSelfTestConfig::MISSING_PROVIDER).to eq(:stubbed_missing_provider)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
expect(SimpleStubSelfTestConfig.const_defined?(:MISSING_PROVIDER, false)).to eq(false)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
test("simple_stub_const restores constants when the block raises") do
|
|
180
|
+
error = SimpleStubSelfTest.capture_error(RuntimeError) do
|
|
181
|
+
simple_stub_const("SimpleStubSelfTestConfig::PROVIDER", :stubbed_provider) do
|
|
182
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:stubbed_provider)
|
|
183
|
+
raise "stubbed block failed"
|
|
165
184
|
end
|
|
166
185
|
end
|
|
167
186
|
|
|
187
|
+
expect(error.message).to eq("stubbed block failed")
|
|
188
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:original_provider)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
test("simple_stub_const requires a block") do
|
|
192
|
+
error = SimpleStubSelfTest.capture_error(ArgumentError) do
|
|
193
|
+
simple_stub_const("SimpleStubSelfTestConfig::PROVIDER", :stubbed_provider)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
expect(error.message).to eq("simple_stub_const block is required")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
test("simple_stub_const wraps around_test hooks") do
|
|
168
200
|
suite = Smartest::Suite.new
|
|
169
|
-
suite.
|
|
201
|
+
suite.around_test_hooks << proc do |test_run|
|
|
202
|
+
simple_stub_const("SimpleStubSelfTestConfig::PROVIDER", :around_test_provider) do
|
|
203
|
+
test_run.run
|
|
204
|
+
end
|
|
205
|
+
end
|
|
170
206
|
suite.tests.add(
|
|
171
207
|
SimpleStubSelfTest.test_case(
|
|
172
|
-
"uses constant stub
|
|
173
|
-
proc
|
|
174
|
-
expect(stubbed_provider).to eq(:stubbed_provider)
|
|
175
|
-
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:stubbed_provider)
|
|
176
|
-
end
|
|
208
|
+
"uses around_test constant stub",
|
|
209
|
+
proc { expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:around_test_provider) }
|
|
177
210
|
)
|
|
178
211
|
)
|
|
212
|
+
|
|
213
|
+
status, = SimpleStubSelfTest.run_suite(suite)
|
|
214
|
+
|
|
215
|
+
expect(status).to eq(0)
|
|
216
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:original_provider)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
test("simple_stub_const wraps around_suite hooks") do
|
|
220
|
+
suite = Smartest::Suite.new
|
|
221
|
+
suite.around_suite_hooks << proc do |suite_run|
|
|
222
|
+
simple_stub_const("SimpleStubSelfTestConfig::PROVIDER", :around_suite_provider) do
|
|
223
|
+
suite_run.run
|
|
224
|
+
end
|
|
225
|
+
end
|
|
179
226
|
suite.tests.add(
|
|
180
227
|
SimpleStubSelfTest.test_case(
|
|
181
|
-
"
|
|
182
|
-
proc { expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:
|
|
228
|
+
"uses around_suite constant stub",
|
|
229
|
+
proc { expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:around_suite_provider) }
|
|
183
230
|
)
|
|
184
231
|
)
|
|
185
232
|
|
|
186
233
|
status, = SimpleStubSelfTest.run_suite(suite)
|
|
187
234
|
|
|
188
235
|
expect(status).to eq(0)
|
|
236
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:original_provider)
|
|
189
237
|
end
|
|
190
238
|
|
|
191
|
-
test("simple_stub_const
|
|
239
|
+
test("simple_stub_const is not available inside fixture blocks") do
|
|
192
240
|
fixture_class = Class.new(Smartest::Fixture) do
|
|
193
|
-
fixture :
|
|
194
|
-
simple_stub_const("SimpleStubSelfTestConfig::
|
|
241
|
+
fixture :bad_constant_stub do
|
|
242
|
+
simple_stub_const("SimpleStubSelfTestConfig::PROVIDER", :fixture_provider) { :fixture_provider }
|
|
195
243
|
end
|
|
196
244
|
end
|
|
197
245
|
|
|
198
246
|
suite = Smartest::Suite.new
|
|
199
247
|
suite.fixture_classes.add(fixture_class)
|
|
200
|
-
suite.tests.add(
|
|
201
|
-
SimpleStubSelfTest.test_case(
|
|
202
|
-
"uses new constant stub fixture",
|
|
203
|
-
proc do |stubbed_missing_provider:|
|
|
204
|
-
expect(stubbed_missing_provider).to eq(:stubbed_missing_provider)
|
|
205
|
-
expect(SimpleStubSelfTestConfig::MISSING_PROVIDER).to eq(:stubbed_missing_provider)
|
|
206
|
-
end
|
|
207
|
-
)
|
|
208
|
-
)
|
|
209
|
-
suite.tests.add(
|
|
210
|
-
SimpleStubSelfTest.test_case(
|
|
211
|
-
"sees removed constant",
|
|
212
|
-
proc { expect(SimpleStubSelfTestConfig.const_defined?(:MISSING_PROVIDER, false)).to eq(false) }
|
|
213
|
-
)
|
|
214
|
-
)
|
|
248
|
+
suite.tests.add(SimpleStubSelfTest.test_case("uses bad fixture", proc { |bad_constant_stub:| bad_constant_stub }))
|
|
215
249
|
|
|
216
|
-
status, = SimpleStubSelfTest.run_suite(suite)
|
|
250
|
+
status, output = SimpleStubSelfTest.run_suite(suite)
|
|
217
251
|
|
|
218
|
-
expect(status).to eq(
|
|
252
|
+
expect(status).to eq(1)
|
|
253
|
+
expect(output).to include("NoMethodError")
|
|
254
|
+
expect(output).to include("simple_stub_const")
|
|
255
|
+
expect(SimpleStubSelfTestConfig::PROVIDER).to eq(:original_provider)
|
|
219
256
|
end
|
|
220
257
|
|
|
221
258
|
test("simple stub preserves receiver self and method blocks") do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: smartest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.3.
|
|
4
|
+
version: 0.3.3.alpha4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yusuke Iwaki
|
|
@@ -44,6 +44,7 @@ files:
|
|
|
44
44
|
- lib/smartest.rb
|
|
45
45
|
- lib/smartest/autorun.rb
|
|
46
46
|
- lib/smartest/cli_arguments.rb
|
|
47
|
+
- lib/smartest/constant_stub_helpers.rb
|
|
47
48
|
- lib/smartest/dsl.rb
|
|
48
49
|
- lib/smartest/errors.rb
|
|
49
50
|
- lib/smartest/execution_context.rb
|