ergomentum_rspec 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +5 -0
- data/README.md +62 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/ergomentum_rspec.gemspec +32 -0
- data/lib/ergomentum_rspec.rb +16 -0
- data/lib/ergomentum_rspec/helpers/environment.rb +15 -0
- data/lib/ergomentum_rspec/helpers/fixture.rb +27 -0
- data/lib/ergomentum_rspec/matchers/active_model.rb +15 -0
- data/lib/ergomentum_rspec/matchers/active_model/be_invalid_for.rb +57 -0
- data/lib/ergomentum_rspec/matchers/active_model/be_valid_for.rb +43 -0
- data/lib/ergomentum_rspec/matchers/array.rb +18 -0
- data/lib/ergomentum_rspec/matchers/array/be_monotonically_decreasing.rb +31 -0
- data/lib/ergomentum_rspec/matchers/array/be_monotonically_increasing.rb +31 -0
- data/lib/ergomentum_rspec/matchers/array/be_strictly_decreasing.rb +31 -0
- data/lib/ergomentum_rspec/matchers/array/be_strictly_increasing.rb +31 -0
- data/lib/ergomentum_rspec/matchers/array/be_unique.rb +30 -0
- data/lib/ergomentum_rspec/matchers/performance.rb +14 -0
- data/lib/ergomentum_rspec/matchers/performance/allocate_objects.rb +94 -0
- data/lib/ergomentum_rspec/matchers/yield.rb +14 -0
- data/lib/ergomentum_rspec/matchers/yield/yield_all.rb +64 -0
- data/lib/ergomentum_rspec/version.rb +5 -0
- metadata +233 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1be2f4dbd6207d59937bb9e9428f969f50060d452d72ee13930be52c77114f73
|
4
|
+
data.tar.gz: c6ad0baad96d8334730fad66c79b9f35935d6a59c8dda165d5898392a5c1712d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6298b845ca13d986ba8ba4288d4a3131559065bf3fbe54ca839b0c185a7ec66b314ea0f7c15841cb034a04d94335d0adc9d82012d37b5ecca5f8fb23e30c7c50
|
7
|
+
data.tar.gz: d10d3053bf0e4b11d6606ba7eca2b2bb81de29d0283d3d845c16076f9693850387eeeb51ef3e4182dc09e6f8f6c7b633888ab1515eff0e35f270ef4dca5d939c
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Ergomentum Rspec Matcher
|
2
|
+
|
3
|
+
[![Depfu](https://badges.depfu.com/badges/24f5ce37c343c844f70d9186bbe16850/count.svg)](
|
4
|
+
https://depfu.com/repos/github/ergomentum/ergomentum_rspec?project_id=17277)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/47249b4acfb1b02fdd8d/maintainability)](
|
6
|
+
https://codeclimate.com/repos/5f9734dfabc428018c0022a0/maintainability)
|
7
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/47249b4acfb1b02fdd8d/test_coverage)](
|
8
|
+
https://codeclimate.com/repos/5f9734dfabc428018c0022a0/test_coverage)
|
9
|
+
[![CircleCI](https://circleci.com/gh/ergomentum/ergomentum_rspec.svg?style=shield&circle-token=e20239599f07aab2a009ccfd9f12a51b6e163ca7)](
|
10
|
+
https://circleci.com/gh/ergomentum/ergomentum_rspec)
|
11
|
+
|
12
|
+
The missing [rspec matchers](https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/custom-matchers) and helpers not
|
13
|
+
found somewhere else.
|
14
|
+
|
15
|
+
## Array matchers
|
16
|
+
|
17
|
+
See specs for examples.
|
18
|
+
|
19
|
+
[Credits](https://rcode5.wordpress.com/2013/06/07/custom-rspec-matchers-for-arrays/)
|
20
|
+
|
21
|
+
## yield matchers
|
22
|
+
|
23
|
+
See specs for examples.
|
24
|
+
|
25
|
+
## Performance matchers
|
26
|
+
|
27
|
+
Utilize the [allocation_stats](https://github.com/srawlins/allocation_stats) Gem. This allows to assure memory
|
28
|
+
consumption. It might be useful after fixing memory holes.
|
29
|
+
|
30
|
+
See specs for examples.
|
31
|
+
|
32
|
+
[Credits](https://www.honeybadger.io/blog/testing-object-allocations/)
|
33
|
+
|
34
|
+
## Development
|
35
|
+
|
36
|
+
Create a PR to make changes. If your change is intended to release a new gem version increment the gem version in
|
37
|
+
`lib/ergomentum_rspec/version.rb` ([semantic versioning](https://semver.org/)).
|
38
|
+
|
39
|
+
After your PR is merged into `main` the gem is build by GitHub actions and deployed to
|
40
|
+
[https://github.com/ergomentum/ergomentum_rspec/packages](https://github.com/ergomentum/ergomentum_rspec/packages).
|
41
|
+
|
42
|
+
Build locally:
|
43
|
+
|
44
|
+
```bash
|
45
|
+
gem build ergomentum_rspec
|
46
|
+
```
|
47
|
+
|
48
|
+
## Resources
|
49
|
+
|
50
|
+
RSpec documentation for [Custom Matchers](
|
51
|
+
https://relishapp.com/rspec/rspec-expectations/v/3-9/docs/custom-matchers/define-a-custom-matcher).
|
52
|
+
|
53
|
+
To inspect Rspec details look into the [built in matcher implementations](
|
54
|
+
https://github.com/rspec/rspec-expectations/tree/master/lib/rspec/matchers/built_in). As well as into the
|
55
|
+
[`RSpec::Matchers::Composable`](
|
56
|
+
https://github.com/rspec/rspec-expectations/blob/master/lib/rspec/matchers/composable.rb) class.
|
57
|
+
|
58
|
+
Or have a look into the the [`shoulda-matchers`](https://github.com/thoughtbot/shoulda-matchers) implementation [work](
|
59
|
+
https://thoughtbot.com/blog/shoulda-matchers).
|
60
|
+
|
61
|
+
Blog article about the [different ways to write custom matchers](
|
62
|
+
https://makandracards.com/makandra/662-write-custom-rspec-matchers).
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "ergomentum_rspec"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "lib/ergomentum_rspec/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
5
|
+
spec.name = "ergomentum_rspec"
|
6
|
+
spec.version = ErgomentumRspec::VERSION
|
7
|
+
spec.authors = ["Ergomentum"]
|
8
|
+
spec.email = ["info@ergomentum.de"]
|
9
|
+
spec.summary = "Provides regular used rspec custom matchers"
|
10
|
+
spec.description = "Regular used rspec matchers not found somewhere else."
|
11
|
+
spec.homepage = "https://www.ergomentum.de/"
|
12
|
+
spec.licenses = "Nonstandard"
|
13
|
+
|
14
|
+
spec.files = Dir.glob("{bin,lib}/**/*") + %w[README.md Gemfile ergomentum_rspec.gemspec]
|
15
|
+
spec.bindir = "exe"
|
16
|
+
spec.executables = spec.files.grep(%r{^exe/}, &:basename)
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
spec.required_ruby_version = ">= 3.0.1"
|
19
|
+
|
20
|
+
spec.add_development_dependency "byebug", "~> 11.1.3"
|
21
|
+
spec.add_development_dependency "rake", "~> 13.0.1"
|
22
|
+
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.1"
|
23
|
+
spec.add_development_dependency "rubocop", "~> 1.8"
|
24
|
+
spec.add_development_dependency "rubocop-performance", "~> 1.9"
|
25
|
+
spec.add_development_dependency "rubocop-rake"
|
26
|
+
spec.add_development_dependency "simplecov", "~> 0.21.2"
|
27
|
+
spec.add_development_dependency "test-prof", "~> 1.0.2"
|
28
|
+
spec.add_dependency "activemodel", "~> 6.0"
|
29
|
+
spec.add_dependency "activesupport", "~> 6.0"
|
30
|
+
spec.add_dependency "allocation_stats", "~> 0.1.5"
|
31
|
+
spec.add_dependency "rspec", "~> 3.9"
|
32
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "allocation_stats"
|
4
|
+
require "active_support/inflector"
|
5
|
+
# It's important to load Rspec before calling RSpec.configure:
|
6
|
+
require "rspec"
|
7
|
+
require "active_model"
|
8
|
+
require_relative "ergomentum_rspec/version"
|
9
|
+
require_relative "ergomentum_rspec/helpers/environment"
|
10
|
+
require_relative "ergomentum_rspec/helpers/fixture"
|
11
|
+
require_relative "ergomentum_rspec/matchers/active_model"
|
12
|
+
require_relative "ergomentum_rspec/matchers/array"
|
13
|
+
require_relative "ergomentum_rspec/matchers/performance"
|
14
|
+
require_relative "ergomentum_rspec/matchers/yield"
|
15
|
+
|
16
|
+
module ErgomentumRspec; end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Helpers
|
5
|
+
module Environment
|
6
|
+
def mock_environment_variables(options)
|
7
|
+
stub_const("ENV", ENV.to_h.merge(options))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.include Environment
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Helpers
|
5
|
+
module Fixture
|
6
|
+
def load_fixture(relative_path)
|
7
|
+
File.read(fixture(relative_path))
|
8
|
+
end
|
9
|
+
|
10
|
+
def fixture(relative_path)
|
11
|
+
fixtures_directory / relative_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def fixtures_directory
|
15
|
+
spec_directory / "fixtures"
|
16
|
+
end
|
17
|
+
|
18
|
+
def spec_directory
|
19
|
+
Pathname.getwd / "spec"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.include Fixture
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "active_model/be_invalid_for"
|
4
|
+
require_relative "active_model/be_valid_for"
|
5
|
+
|
6
|
+
module ErgomentumRspec
|
7
|
+
module Matchers
|
8
|
+
module ActiveModel
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include ErgomentumRspec::Matchers::ActiveModel
|
15
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module ActiveModel
|
6
|
+
def be_invalid_for(value)
|
7
|
+
BeInvalidFor.new(value)
|
8
|
+
end
|
9
|
+
|
10
|
+
class BeInvalidFor
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(validator)
|
16
|
+
model = Class.new do
|
17
|
+
include ::ActiveModel::Model
|
18
|
+
include ::ActiveModel::Attributes
|
19
|
+
|
20
|
+
# ActiveModel sometimes needs a non nil class name.
|
21
|
+
# Because we are using an anonymous class, which have no name by default, we have to override the name
|
22
|
+
# method.
|
23
|
+
def self.name
|
24
|
+
"SomeClass"
|
25
|
+
end
|
26
|
+
|
27
|
+
attribute :some_attribute
|
28
|
+
validates :some_attribute, validator
|
29
|
+
end.new(some_attribute: @value)
|
30
|
+
if model.valid?
|
31
|
+
@message = "expecting '#{@value}' to be invalid"
|
32
|
+
false
|
33
|
+
elsif model.errors.messages[:some_attribute].include?(@expected_error_message)
|
34
|
+
true
|
35
|
+
else
|
36
|
+
@message = "expecting error message '#{@expected_error_message}' for invalid value '#{@value}' but got "\
|
37
|
+
"'#{model.errors.messages[:some_attribute].join(', ')}'"
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def and_add_error(expected_error_message)
|
43
|
+
@expected_error_message = expected_error_message
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def failure_message
|
48
|
+
@message
|
49
|
+
end
|
50
|
+
|
51
|
+
def description
|
52
|
+
"'#{@value}' be a invalid value"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module ActiveModel
|
6
|
+
def be_valid_for(value)
|
7
|
+
BeValidFor.new(value)
|
8
|
+
end
|
9
|
+
|
10
|
+
class BeValidFor
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(validator)
|
16
|
+
model = Class.new do
|
17
|
+
include ::ActiveModel::Model
|
18
|
+
include ::ActiveModel::Attributes
|
19
|
+
|
20
|
+
# ActiveModel sometimes needs a non nil class name.
|
21
|
+
# Because we are using an anonymous class, which have no name by default, we have to override the name
|
22
|
+
# method.
|
23
|
+
def self.name
|
24
|
+
"SomeClass"
|
25
|
+
end
|
26
|
+
|
27
|
+
attribute :some_attribute
|
28
|
+
validates :some_attribute, validator
|
29
|
+
end.new(some_attribute: @value)
|
30
|
+
model.valid? && model.errors.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_message
|
34
|
+
"expect '#{@value}' to be valid"
|
35
|
+
end
|
36
|
+
|
37
|
+
def description
|
38
|
+
"'#{@value}' be an valid value"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "array/be_unique"
|
4
|
+
require_relative "array/be_monotonically_decreasing"
|
5
|
+
require_relative "array/be_monotonically_increasing"
|
6
|
+
require_relative "array/be_strictly_decreasing"
|
7
|
+
require_relative "array/be_strictly_increasing"
|
8
|
+
|
9
|
+
module ErgomentumRspec
|
10
|
+
module Matchers
|
11
|
+
module Array
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.include ErgomentumRspec::Matchers::Array
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Array
|
6
|
+
def be_monotonically_decreasing
|
7
|
+
MonotonicallyDecreasing.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class MonotonicallyDecreasing
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual
|
13
|
+
derivative = actual.each_cons(2).map { |x, y| y <=> x }
|
14
|
+
derivative.all? { |v| v <= 0 }
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
"expected array #{@actual.inspect} to be monotonically decreasing"
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message_when_negated
|
22
|
+
"expected array #{@actual.inspect} to not be monotonically decreasing"
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
"be monotonically decreasing"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Array
|
6
|
+
def be_monotonically_increasing
|
7
|
+
MonotonicallyIncreasing.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class MonotonicallyIncreasing
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual
|
13
|
+
derivative = actual.each_cons(2).map { |x, y| y <=> x }
|
14
|
+
derivative.all? { |v| v >= 0 }
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
"expected array #{@actual.inspect} to be monotonically increasing"
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message_when_negated
|
22
|
+
"expected array #{@actual.inspect} to not be monotonically increasing"
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
"be monotonically increasing"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Array
|
6
|
+
def be_strictly_decreasing
|
7
|
+
StrictlyDecreasing.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class StrictlyDecreasing
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual
|
13
|
+
derivative = actual.each_cons(2).map { |x, y| y <=> x }
|
14
|
+
derivative.all?(&:negative?)
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
"expected array #{@actual.inspect} to be strictly decreasing"
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message_when_negated
|
22
|
+
"expected array #{@actual.inspect} to not be strictly decreasing"
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
"be strictly decreasing"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Array
|
6
|
+
def be_strictly_increasing
|
7
|
+
StrictlyIncreasing.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class StrictlyIncreasing
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual
|
13
|
+
derivative = actual.each_cons(2).map { |x, y| y <=> x }
|
14
|
+
derivative.all?(&:positive?)
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
"expected array #{@actual.inspect} to be strictly increasing"
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message_when_negated
|
22
|
+
"expected array #{@actual.inspect} to not be strictly increasing"
|
23
|
+
end
|
24
|
+
|
25
|
+
def description
|
26
|
+
"be strictly increasing"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Array
|
6
|
+
def be_unique
|
7
|
+
BeUnique.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class BeUnique
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual
|
13
|
+
actual.detect { |e| actual.count(e) == 1 }
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure_message
|
17
|
+
"expected array #{@actual.inspect} to be unique"
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message_when_negated
|
21
|
+
"expected array #{@actual.inspect} to be not unique"
|
22
|
+
end
|
23
|
+
|
24
|
+
def description
|
25
|
+
"be unique"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "performance/allocate_objects"
|
4
|
+
|
5
|
+
module ErgomentumRspec
|
6
|
+
module Matchers
|
7
|
+
module Performance
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include ErgomentumRspec::Matchers::Performance
|
14
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Performance
|
6
|
+
def allocates
|
7
|
+
AllocateObjects.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class IncompleteExpectationError < StandardError
|
11
|
+
def initialize
|
12
|
+
super("Comparision operator required. E. g. allocates.exactly(1)")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class AllocateObjects
|
17
|
+
def supports_block_expectations?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def matches?(*actual, &block)
|
22
|
+
@trace = if block
|
23
|
+
AllocationStats.trace(&block)
|
24
|
+
elsif actual.first.is_a?(Proc)
|
25
|
+
AllocationStats.trace(&actual.first)
|
26
|
+
else
|
27
|
+
actual.first
|
28
|
+
end
|
29
|
+
@compare || raise(IncompleteExpectationError)
|
30
|
+
@compare.call
|
31
|
+
end
|
32
|
+
|
33
|
+
def exactly(expected)
|
34
|
+
@expected = expected
|
35
|
+
@compare = Proc.new { @trace.new_allocations.size == @expected }
|
36
|
+
@message = ""
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def less_than(expected)
|
41
|
+
@expected = expected
|
42
|
+
@compare = Proc.new { @trace.new_allocations.size < @expected }
|
43
|
+
@message = "less than "
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def more_than(expected)
|
48
|
+
@expected = expected
|
49
|
+
@compare = Proc.new { @trace.new_allocations.size > @expected }
|
50
|
+
@message = "more than "
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def max(expected)
|
55
|
+
@expected = expected
|
56
|
+
@compare = Proc.new { @trace.new_allocations.size <= @expected }
|
57
|
+
@message = "max "
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def min(expected)
|
62
|
+
@expected = expected
|
63
|
+
@compare = Proc.new { @trace.new_allocations.size >= @expected }
|
64
|
+
@message = "min "
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def object
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def objects
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def failure_message
|
77
|
+
"expected #{@message}#{@expected} objects to be allocated; "\
|
78
|
+
"got #{@trace.new_allocations.size}:\n\n"\
|
79
|
+
"#{@trace.allocations(alias_paths: true).group_by(:sourcefile, :sourceline, :class).to_text}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def failure_message_when_negated
|
83
|
+
"expected not #{@message}#{@expected} objects to be allocated; "\
|
84
|
+
"got #{@trace.new_allocations.size}:\n\n"\
|
85
|
+
"#{@trace.allocations(alias_paths: true).group_by(:sourcefile, :sourceline, :class).to_text}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def description
|
89
|
+
"allocates number of objects"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ErgomentumRspec
|
4
|
+
module Matchers
|
5
|
+
module Yield
|
6
|
+
def yield_all(expected)
|
7
|
+
YieldAll.new(expected)
|
8
|
+
end
|
9
|
+
|
10
|
+
class NoBlockGivenError < StandardError
|
11
|
+
def initialize
|
12
|
+
super("Block required. E.g. expect { |b| [0].each(&b) }.to yield_all(0)")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class YieldAll
|
17
|
+
include RSpec::Matchers::Composable
|
18
|
+
|
19
|
+
def initialize(expected)
|
20
|
+
@expected = expected
|
21
|
+
end
|
22
|
+
|
23
|
+
def supports_block_expectations?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def matches?(*block)
|
28
|
+
@count = 0
|
29
|
+
@result = true
|
30
|
+
if block_given?
|
31
|
+
yield(method(:match))
|
32
|
+
elsif block.first.is_a?(Proc)
|
33
|
+
block.first.call(method(:match))
|
34
|
+
else
|
35
|
+
raise NoBlockGivenError
|
36
|
+
end
|
37
|
+
@result
|
38
|
+
end
|
39
|
+
|
40
|
+
def match(actual)
|
41
|
+
@count += 1
|
42
|
+
@last = actual
|
43
|
+
@result &&= if @expected.respond_to?(:matches?)
|
44
|
+
@expected.matches?(actual)
|
45
|
+
else
|
46
|
+
values_match?(@expected, actual)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def failure_message
|
51
|
+
if @expected.respond_to?(:failure_message)
|
52
|
+
"Failed for #{ActiveSupport::Inflector.ordinalize(@count)} yield with:\n#{@expected.failure_message}"
|
53
|
+
else
|
54
|
+
"Expecting #{@expected} got #{@last} for #{ActiveSupport::Inflector.ordinalize(@count)} yield"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def description
|
59
|
+
"yields all"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ergomentum_rspec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ergomentum
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-06-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: byebug
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 11.1.3
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 11.1.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 13.0.1
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 13.0.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec_junit_formatter
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.4.1
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-performance
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.9'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.9'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.21.2
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.21.2
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: test-prof
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.0.2
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.0.2
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: activemodel
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '6.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '6.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: activesupport
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '6.0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '6.0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: allocation_stats
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.1.5
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.1.5
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rspec
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '3.9'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '3.9'
|
181
|
+
description: Regular used rspec matchers not found somewhere else.
|
182
|
+
email:
|
183
|
+
- info@ergomentum.de
|
184
|
+
executables: []
|
185
|
+
extensions: []
|
186
|
+
extra_rdoc_files: []
|
187
|
+
files:
|
188
|
+
- Gemfile
|
189
|
+
- README.md
|
190
|
+
- bin/console
|
191
|
+
- bin/setup
|
192
|
+
- ergomentum_rspec.gemspec
|
193
|
+
- lib/ergomentum_rspec.rb
|
194
|
+
- lib/ergomentum_rspec/helpers/environment.rb
|
195
|
+
- lib/ergomentum_rspec/helpers/fixture.rb
|
196
|
+
- lib/ergomentum_rspec/matchers/active_model.rb
|
197
|
+
- lib/ergomentum_rspec/matchers/active_model/be_invalid_for.rb
|
198
|
+
- lib/ergomentum_rspec/matchers/active_model/be_valid_for.rb
|
199
|
+
- lib/ergomentum_rspec/matchers/array.rb
|
200
|
+
- lib/ergomentum_rspec/matchers/array/be_monotonically_decreasing.rb
|
201
|
+
- lib/ergomentum_rspec/matchers/array/be_monotonically_increasing.rb
|
202
|
+
- lib/ergomentum_rspec/matchers/array/be_strictly_decreasing.rb
|
203
|
+
- lib/ergomentum_rspec/matchers/array/be_strictly_increasing.rb
|
204
|
+
- lib/ergomentum_rspec/matchers/array/be_unique.rb
|
205
|
+
- lib/ergomentum_rspec/matchers/performance.rb
|
206
|
+
- lib/ergomentum_rspec/matchers/performance/allocate_objects.rb
|
207
|
+
- lib/ergomentum_rspec/matchers/yield.rb
|
208
|
+
- lib/ergomentum_rspec/matchers/yield/yield_all.rb
|
209
|
+
- lib/ergomentum_rspec/version.rb
|
210
|
+
homepage: https://www.ergomentum.de/
|
211
|
+
licenses:
|
212
|
+
- Nonstandard
|
213
|
+
metadata: {}
|
214
|
+
post_install_message:
|
215
|
+
rdoc_options: []
|
216
|
+
require_paths:
|
217
|
+
- lib
|
218
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: 3.0.1
|
223
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
224
|
+
requirements:
|
225
|
+
- - ">="
|
226
|
+
- !ruby/object:Gem::Version
|
227
|
+
version: '0'
|
228
|
+
requirements: []
|
229
|
+
rubygems_version: 3.2.15
|
230
|
+
signing_key:
|
231
|
+
specification_version: 4
|
232
|
+
summary: Provides regular used rspec custom matchers
|
233
|
+
test_files: []
|