r_spec 1.0.0.beta6 → 1.0.0.beta7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6facf7764beddac81425ab44d80ed3b306f6c63c3532401bb658240654b06845
4
- data.tar.gz: 944d53b22a1ffeeca3afe990aa99a613493f9ff1b3aad3ceaa43ae0b9a8ec019
3
+ metadata.gz: 46557ee64f6cc554942399aa9219e9102879b2b7b113e53dc4ba63d2c0c5c0af
4
+ data.tar.gz: a83b773e20cf2db46b28586be6836d7913a4c3b8f9bf2ce747110f2556737374
5
5
  SHA512:
6
- metadata.gz: c28b4fbd53cf2a368022418c2ccbbf31cf4a35abce141f0999285bff90b4c84d7f36209894dafcf5362464d01fad3dcb724d942ae5db5c1095387997b087964f
7
- data.tar.gz: 4c7a23212c2ce90a67b04e9fe25dda7812c37902eba8f6febdb9e4e2dcd33633fa43642d6905f9bfffa6215b467eb88cbb921d596f0276fb788cc876bc63e291
6
+ metadata.gz: b7c89ce9b933e7adcfc26e03c2f4417ed44c423ca56932f173b2161572877967df37d99c9a560e8cf64c58458777842cb0db7eb1396c89a7f052d981b45f9864
7
+ data.tar.gz: 51c4b747116d8f1bb3bb2e593b00aa940ec463d1b9a03506984f2b445f3607febd455884051279f73cef2fc2edac7cfe6d9b4de210c1f1cef6402bd501729f6c
data/README.md CHANGED
@@ -11,11 +11,12 @@ A minimalist __[RSpec](https://github.com/rspec/rspec) clone__ with all the esse
11
11
  [![Inline Docs](https://inch-ci.org/github/cyril/r_spec.rb.svg)](https://inch-ci.org/github/cyril/r_spec.rb)
12
12
  [![Documentation](https://img.shields.io/:yard-docs-38c800.svg)](https://rubydoc.info/gems/r_spec/frames)
13
13
 
14
- ## Goal
14
+ ## Project Goals
15
15
 
16
- This clone attempts to provide most of RSpec's DSL to express expected outcomes of a code example without magic power.
16
+ * Enforce the guidelines and best practices outlined in the community [RSpec style guide](https://rspec.rubystyle.guide/).
17
+ * Provide most of RSpec's DSL to express expected outcomes of a code example without magic power.
17
18
 
18
- ## Some differences
19
+ ## Some Differences
19
20
 
20
21
  * Less features and an implementation with much less code complexity.
21
22
  * Spec files can also be executed directly with the `ruby` executable.
@@ -28,6 +29,10 @@ This clone attempts to provide most of RSpec's DSL to express expected outcomes
28
29
  * [Arbitrary helper methods](https://relishapp.com/rspec/rspec-core/v/3-10/docs/helper-methods/arbitrary-helper-methods) are not exposed to examples.
29
30
  * The `let` method defines a helper method rather than a memoized helper method.
30
31
  * The one-liner `is_expected` syntax also works with block expectations.
32
+ * All `subject` definitions must come _before_ examples.
33
+ * All `before` definitions must come _before_ examples.
34
+ * All `after` definitions must come _before_ examples.
35
+ * All `let` definitions must come _before_ examples.
31
36
 
32
37
  ## Important ⚠️
33
38
 
@@ -46,7 +51,7 @@ Following [RubyGems naming conventions](https://guides.rubygems.org/name-your-ge
46
51
  Add this line to your application's Gemfile:
47
52
 
48
53
  ```ruby
49
- gem "r_spec", ">= 1.0.0.beta6"
54
+ gem "r_spec", ">= 1.0.0.beta7"
50
55
  ```
51
56
 
52
57
  And then execute:
@@ -215,15 +220,18 @@ task default: :test
215
220
 
216
221
  ## Performance
217
222
 
218
- Benchmark against an single expectation executed 100 times from the console.
223
+ ### Runtime
224
+
225
+ Benchmark against [100 executions of a file containing one expectation](https://github.com/cyril/r_spec.rb/blob/main/benchmark/) (lower is better).
219
226
 
220
227
  | Framework | Seconds to complete |
221
228
  |-------------|---------------------|
222
- | RSpec clone | [13.2](https://github.com/cyril/r_spec.rb/blob/main/benchmark/r_spec.rb) |
223
- | RSpec | [32.7](https://github.com/cyril/r_spec.rb/blob/main/benchmark/rspec.rb) |
224
- | minitest | [17.6](https://github.com/cyril/r_spec.rb/blob/main/benchmark/minitest.rb) |
229
+ | `r_spec` | 13.0 |
230
+ | `rspec` | 32.2 |
231
+ | `minitest` | 17.5 |
232
+ | `test-unit` | 20.5 |
225
233
 
226
- ## Test suite
234
+ ## Test Suite
227
235
 
228
236
  __RSpec clone__'s specifications are self-described here: [spec/](https://github.com/cyril/r_spec.rb/blob/main/spec/)
229
237
 
@@ -233,14 +241,14 @@ __RSpec clone__'s specifications are self-described here: [spec/](https://github
233
241
  * Source code: https://github.com/cyril/r_spec.rb
234
242
  * Twitter: [https://twitter.com/cyri\_](https://twitter.com/cyri\_)
235
243
 
236
- ## Special thanks ❤️
244
+ ## Special Thanks ❤️
237
245
 
238
246
  I would like to thank the whole [RSpec team](https://rspec.info/about/) for all their work.
239
247
  It's a great framework and it's a pleasure to work with every day.
240
248
 
241
249
  Without RSpec, this clone would not have been possible.
242
250
 
243
- ## Buy me a coffee
251
+ ## Buy me a Coffee
244
252
 
245
253
  If you like this project please consider making a small donation.
246
254
 
data/lib/r_spec.rb CHANGED
@@ -7,7 +7,7 @@ require_relative File.join("r_spec", "dsl")
7
7
  # @example The true from the false
8
8
  # require "r_spec"
9
9
  #
10
- # RSpec.describe do
10
+ # RSpec.describe "The true from the false" do
11
11
  # it { expect(false).not_to be true }
12
12
  # end
13
13
  #
@@ -71,7 +71,7 @@ module RSpec
71
71
  # @param block [Proc] The block to define the specs.
72
72
  #
73
73
  # @api public
74
- def self.describe(const = nil, &block)
74
+ def self.describe(const, &block)
75
75
  Dsl.describe(const, &block)
76
76
  end
77
77
  end
data/lib/r_spec/dsl.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom"
4
-
5
3
  require_relative "console"
6
4
  require_relative "error"
7
5
  require_relative "expectation_helper"
8
- require_relative "sandbox"
9
6
 
10
7
  module RSpec
11
8
  # Abstract class for handling the domain-specific language.
12
9
  class Dsl
10
+ BEFORE_METHOD = :initialize
11
+ AFTER_METHOD = :terminate
12
+
13
+ private_constant :BEFORE_METHOD, :AFTER_METHOD
14
+
13
15
  # Executes the given block before each spec in the current context runs.
14
16
  #
15
17
  # @example
@@ -40,12 +42,12 @@ module RSpec
40
42
  #
41
43
  # @param block [Proc] The content to execute at the class initialization.
42
44
  def self.before(&block)
43
- define_method(:initialize) do
45
+ define_method(BEFORE_METHOD) do
44
46
  super()
45
47
  instance_eval(&block)
46
48
  end
47
49
 
48
- private :initialize
50
+ private BEFORE_METHOD
49
51
  end
50
52
 
51
53
  # Executes the given block after each spec in the current context runs.
@@ -67,12 +69,12 @@ module RSpec
67
69
  #
68
70
  # @param block [Proc] The content to execute at the class initialization.
69
71
  def self.after(&block)
70
- define_method(:terminate) do
72
+ define_method(AFTER_METHOD) do
71
73
  instance_exec(&block)
72
74
  super()
73
75
  end
74
76
 
75
- private :terminate
77
+ private AFTER_METHOD
76
78
  end
77
79
 
78
80
  # Sets a user-defined property.
@@ -80,7 +82,7 @@ module RSpec
80
82
  # @example
81
83
  # require "r_spec"
82
84
  #
83
- # RSpec.describe do
85
+ # RSpec.describe "Name stories" do
84
86
  # let(:name) { "Bob" }
85
87
  #
86
88
  # it { expect(name).to eq "Bob" }
@@ -99,9 +101,11 @@ module RSpec
99
101
  # @param name [String, Symbol] The name of the property.
100
102
  # @param block [Proc] The content of the method to define.
101
103
  #
102
- # @return [Symbol] A protected method that define the block content.
104
+ # @return [Symbol] A private method that define the block content.
103
105
  def self.let(name, *args, **kwargs, &block)
104
- protected define_method(name.to_sym, *args, **kwargs, &block)
106
+ raise Error::ReservedMethod if [BEFORE_METHOD, AFTER_METHOD].include?(name.to_sym)
107
+
108
+ private define_method(name, *args, **kwargs, &block)
105
109
  end
106
110
 
107
111
  # Sets a user-defined property named {#subject}.
@@ -140,16 +144,11 @@ module RSpec
140
144
  # # Output to the console
141
145
  # # Success: expected to eq "foobar".
142
146
  #
143
- # @param const [Module, #object_id] A module to include in block context.
147
+ # @param const [Module, String] A module to include in block context.
144
148
  # @param block [Proc] The block to define the specs.
145
- def self.describe(const = nil, &block)
146
- desc = Sandbox.const_set(random_context_const_name, ::Class.new(self))
147
-
148
- if const.is_a?(::Module)
149
- desc.define_method(:described_class) { const }
150
- desc.send(:protected, :described_class)
151
- end
152
-
149
+ def self.describe(const, &block)
150
+ desc = ::Class.new(self)
151
+ desc.let(:described_class) { const } if const.is_a?(::Module)
153
152
  desc.instance_eval(&block)
154
153
  end
155
154
 
@@ -161,7 +160,7 @@ module RSpec
161
160
  # @example
162
161
  # require "r_spec"
163
162
  #
164
- # RSpec.describe do
163
+ # RSpec.describe "web resource" do
165
164
  # context "when resource is not found" do
166
165
  # pending "responds with 404"
167
166
  # end
@@ -179,7 +178,7 @@ module RSpec
179
178
  # "when", "with" or "without".
180
179
  # @param block [Proc] The block to define the specs.
181
180
  def self.context(_description = nil, &block)
182
- desc = Sandbox.const_set(random_context_const_name, ::Class.new(self))
181
+ desc = ::Class.new(self)
183
182
  desc.instance_eval(&block)
184
183
  end
185
184
 
@@ -224,14 +223,14 @@ module RSpec
224
223
  def self.it(_name = nil, &block)
225
224
  raise ::ArgumentError, "Missing example block" unless block
226
225
 
227
- i = it_example.new
228
- i.instance_eval(&block)
226
+ example = ::Class.new(self) { include ExpectationHelper::It }.new
227
+ example.instance_eval(&block)
229
228
  rescue ::SystemExit
230
229
  Console.source(*block.source_location)
231
230
 
232
231
  exit false
233
232
  ensure
234
- i.send(:terminate)
233
+ example.send(AFTER_METHOD)
235
234
  end
236
235
 
237
236
  # Use the {.its} method to define a single spec that specifies the actual
@@ -282,19 +281,21 @@ module RSpec
282
281
  def self.its(attribute, *args, **kwargs, &block)
283
282
  raise ::ArgumentError, "Missing example block" unless block
284
283
 
285
- i = its_example.new
284
+ example = ::Class.new(self) do
285
+ include ExpectationHelper::Its
286
286
 
287
- i.define_singleton_method(:actual) do
288
- subject.public_send(attribute, *args, **kwargs)
289
- end
287
+ define_method(:actual) do
288
+ subject.public_send(attribute, *args, **kwargs)
289
+ end
290
+ end.new
290
291
 
291
- i.instance_eval(&block)
292
+ example.instance_eval(&block)
292
293
  rescue ::SystemExit
293
294
  Console.source(*block.source_location)
294
295
 
295
296
  exit false
296
297
  ensure
297
- i.send(:terminate)
298
+ example.send(AFTER_METHOD)
298
299
  end
299
300
 
300
301
  # Defines a pending test case.
@@ -305,23 +306,16 @@ module RSpec
305
306
  # @example
306
307
  # require "r_spec"
307
308
  #
308
- # RSpec.describe do
309
+ # RSpec.describe "an example" do
309
310
  # pending "is implemented but waiting" do
310
- # expect("something").to eq("getting finished")
311
+ # expect something to be finished
311
312
  # end
312
- # end
313
313
  #
314
- # # Output to the console
315
- # # Warning: is implemented but waiting.
316
- #
317
- # @example
318
- # require "r_spec"
319
- #
320
- # RSpec.describe do
321
314
  # pending "is not yet implemented and waiting"
322
315
  # end
323
316
  #
324
317
  # # Output to the console
318
+ # # Warning: is implemented but waiting.
325
319
  # # Warning: is not yet implemented and waiting.
326
320
  #
327
321
  # @param message [String] The reason why the example is pending.
@@ -333,30 +327,7 @@ module RSpec
333
327
  Console.passed_spec Error::PendingExpectation.result(message)
334
328
  end
335
329
 
336
- # @private
337
- #
338
- # @return [Class<Dsl>] The class of the example to be tested.
339
- def self.it_example
340
- ::Class.new(self) { include ExpectationHelper::It }
341
- end
342
-
343
- # @private
344
- #
345
- # @return [Class<Dsl>] The class of the example to be tested.
346
- def self.its_example
347
- ::Class.new(self) { include ExpectationHelper::Its }
348
- end
349
-
350
- # @private
351
- #
352
- # @return [String] A random constant name for a test class.
353
- def self.random_context_const_name
354
- "Context#{::SecureRandom.hex(4).to_i(16)}"
355
- end
356
-
357
- private_class_method :it_example, :its_example, :random_context_const_name
358
-
359
- protected
330
+ private
360
331
 
361
332
  def described_class
362
333
  raise Error::UndefinedDescribedClass,
@@ -367,6 +338,8 @@ module RSpec
367
338
  raise Error::UndefinedSubject, "subject not explicitly defined"
368
339
  end
369
340
 
370
- def terminate; end
341
+ define_method(AFTER_METHOD) do
342
+ # do nothing by default
343
+ end
371
344
  end
372
345
  end
data/lib/r_spec/error.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative File.join("error", "pending_expectation")
4
+ require_relative File.join("error", "reserved_method")
4
5
  require_relative File.join("error", "undefined_described_class")
5
6
  require_relative File.join("error", "undefined_subject")
6
7
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Error
5
+ # Exception for reserved methods.
6
+ #
7
+ # @api private
8
+ class ReservedMethod < ::RuntimeError
9
+ end
10
+ end
11
+ end
@@ -4,7 +4,7 @@ require_relative File.join("expectation_helper", "it")
4
4
  require_relative File.join("expectation_helper", "its")
5
5
 
6
6
  module RSpec
7
- # Namespace for `it` and `its` helper modules.
7
+ # Namespace for {Dsl.it} and {Dsl.its}'s helper modules.
8
8
  module ExpectationHelper
9
9
  end
10
10
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
3
+ require_relative "shared"
4
4
  require_relative File.join("..", "expectation_target")
5
5
 
6
6
  module RSpec
7
7
  module ExpectationHelper
8
- # {RSpec::DSL#it}'s expectation helper module.
8
+ # {RSpec::Dsl.it}'s expectation helper module.
9
9
  module It
10
- include Base
10
+ include Shared
11
11
 
12
12
  # Create an expectation for a spec.
13
13
  #
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
3
+ require_relative "shared"
4
4
  require_relative File.join("..", "expectation_target", "block")
5
5
 
6
6
  module RSpec
7
7
  module ExpectationHelper
8
- # {RSpec::DSL#its}'s expectation helper module.
8
+ # {RSpec::Dsl.its}'s expectation helper module.
9
9
  module Its
10
- include Base
10
+ include Shared
11
11
 
12
12
  # Wraps the target of an expectation with the actual value.
13
13
  #
@@ -75,7 +75,7 @@ module RSpec
75
75
  #
76
76
  # @see https://github.com/fixrb/matchi
77
77
  # @see https://github.com/fixrb/matchi-rspec
78
- module Base
78
+ module Shared
79
79
  include ::Matchi::Helper
80
80
  end
81
81
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: r_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta6
4
+ version: 1.0.0.beta7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-13 00:00:00.000000000 Z
11
+ date: 2021-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: expresenter
@@ -30,28 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.1.1
33
+ version: 1.1.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.1.1
40
+ version: 1.1.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: spectus
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.3.3
47
+ version: 3.3.4
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 3.3.3
54
+ version: 3.3.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -191,17 +191,17 @@ files:
191
191
  - lib/r_spec/dsl.rb
192
192
  - lib/r_spec/error.rb
193
193
  - lib/r_spec/error/pending_expectation.rb
194
+ - lib/r_spec/error/reserved_method.rb
194
195
  - lib/r_spec/error/undefined_described_class.rb
195
196
  - lib/r_spec/error/undefined_subject.rb
196
197
  - lib/r_spec/expectation_helper.rb
197
- - lib/r_spec/expectation_helper/base.rb
198
198
  - lib/r_spec/expectation_helper/it.rb
199
199
  - lib/r_spec/expectation_helper/its.rb
200
+ - lib/r_spec/expectation_helper/shared.rb
200
201
  - lib/r_spec/expectation_target.rb
201
202
  - lib/r_spec/expectation_target/base.rb
202
203
  - lib/r_spec/expectation_target/block.rb
203
204
  - lib/r_spec/expectation_target/value.rb
204
- - lib/r_spec/sandbox.rb
205
205
  homepage: https://r-spec.dev/
206
206
  licenses:
207
207
  - MIT
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- # Namespace to collect test classes.
5
- #
6
- # @api private
7
- module Sandbox
8
- end
9
- end