any_value 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +115 -0
- data/Rakefile +9 -0
- data/any_value.gemspec +25 -0
- data/lib/any_value/version.rb +3 -0
- data/lib/any_value.rb +285 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 34e46954b67b61b298a1fb9032192aa102cf7c47
|
4
|
+
data.tar.gz: 922af0fc2c8b978580bab08fd6b94809af4e9748
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4015a9e6956be16714891d3923be52db9a238d0da720abe18a623a7b722f381f9a65547580053b7ca90ba22d5c565127351b6aedf365811fcd872247144b692b
|
7
|
+
data.tar.gz: 0d0e6c196643d1992b8ca8f417594f4e450243e750f27f1fd8c030946bf87c3fd03d8ecffba4d5fdebb12cdb3c1269c5f3654b0ff267e5b482fc08ebfbf15517
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Wojtek Mach
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# Anything
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/wojtekmach/anything.svg)](https://travis-ci.org/wojtekmach/anything)
|
4
|
+
|
5
|
+
Anything is a collection of helper methods like: `anything`, `any_number`, `any_string` that is useful for testing nested data structures (like arrays or hashes) when you care more about some particular elements and the "shape" of the data, than about the entire data structure.
|
6
|
+
|
7
|
+
So, instead of either:
|
8
|
+
|
9
|
+
* Asserting all elements, even the attributes you don't really care about (ids, created_at fields etc)
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
def test_create
|
13
|
+
item1 = Item.create!(name: "Item 1")
|
14
|
+
item2 = Item.create!(name: "Item 2")
|
15
|
+
|
16
|
+
get "/items"
|
17
|
+
|
18
|
+
assert_equal [
|
19
|
+
{"id" => item1.id, "name" => "Item 1"},
|
20
|
+
{"id" => item2.id, "name" => "Item 2"},
|
21
|
+
], JSON(response.body)
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
or
|
26
|
+
|
27
|
+
* Extracting out subset of attributes you care about:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
def test_create
|
31
|
+
item1 = Item.create!(name: "Item 1")
|
32
|
+
item2 = Item.create!(name: "Item 2")
|
33
|
+
|
34
|
+
get "/items"
|
35
|
+
|
36
|
+
assert_equal [
|
37
|
+
"Item 1", "Item 2",
|
38
|
+
], JSON(response.body).map { |h| h['name'] }
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
You can do this:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
def test_create
|
46
|
+
item1 = Item.create!(name: "Item 1")
|
47
|
+
item2 = Item.create!(name: "Item 2")
|
48
|
+
|
49
|
+
get "/items"
|
50
|
+
|
51
|
+
assert_equal [
|
52
|
+
{"id" => any_integer, "name" => "Item 1"},
|
53
|
+
{"id" => any_integer, "name" => "Item 2"},
|
54
|
+
], JSON(response.body)
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
## Usage
|
59
|
+
|
60
|
+
All you have to do is to include `Anything` module to your program/test/whatever.
|
61
|
+
|
62
|
+
Example:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
require 'anything'
|
66
|
+
|
67
|
+
class Minitest::Test
|
68
|
+
include Anything
|
69
|
+
end
|
70
|
+
|
71
|
+
require 'minitest/autorun'
|
72
|
+
|
73
|
+
class Test < Minitest::Test
|
74
|
+
def test_anything
|
75
|
+
assert_equal any_number, 42
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
### Composition
|
81
|
+
|
82
|
+
You can compose helpers like this:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
acronym = upcase_string ^ string_of_length(3)
|
86
|
+
|
87
|
+
acronym == "NBA" # => true
|
88
|
+
acronym == "nba" # => false
|
89
|
+
acronym == "NASA" # => false
|
90
|
+
```
|
91
|
+
|
92
|
+
And like that for arrays:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
array_of_integers = array_of(any_integer)
|
96
|
+
|
97
|
+
array_of_integers == [1, 2, 3] # => true
|
98
|
+
array_of_integers == [1, nil, 3] # => false
|
99
|
+
```
|
100
|
+
|
101
|
+
See: https://github.com/wojtekmach/anything/blob/master/test/anything_test.rb for more examples.
|
102
|
+
|
103
|
+
## Installation
|
104
|
+
|
105
|
+
The gem is not released to rubygems.org yet, since this name is taken.
|
106
|
+
|
107
|
+
You can install it via bundler by adding `gem 'anything', github: 'wojtekmach/anything'` to your Gemfile or by cloning it and running `rake install`.
|
108
|
+
|
109
|
+
## Contributing
|
110
|
+
|
111
|
+
1. Fork it ( https://github.com/wojtekmach/anything/fork )
|
112
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
113
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
114
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
115
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/any_value.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "any_value/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "any_value"
|
8
|
+
spec.version = AnyValue::VERSION
|
9
|
+
spec.authors = ["Wojtek Mach"]
|
10
|
+
spec.email = ["wojtek@wojtekmach.pl"]
|
11
|
+
|
12
|
+
spec.summary = %q{Helper objects for testing nested data structures}
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = "https://github.com/wojtekmach/any_value"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "minitest"
|
25
|
+
end
|
data/lib/any_value.rb
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
# Sometimes, especially when working with JSON APIs,
|
2
|
+
# when testing I found myself wanting to test the "shape" of data and only some particular elements, rather than either:
|
3
|
+
#
|
4
|
+
# - test everything - which is tricky with things like auto_increment primary keys, created_at fields etc
|
5
|
+
# - test only subset of data - do stuff like: `JSON(response.body).map { |h| h['name'] }.should == ['Item 1', 'Item 2']
|
6
|
+
#
|
7
|
+
# Here, I want to try something different. See:
|
8
|
+
# `test_why_someone_would_ever_use_it`
|
9
|
+
|
10
|
+
require "any_value/version"
|
11
|
+
require "delegate"
|
12
|
+
require "set"
|
13
|
+
require "date"
|
14
|
+
require "uri"
|
15
|
+
|
16
|
+
module AnyValue
|
17
|
+
class Anything
|
18
|
+
def initialize(*args)
|
19
|
+
@args = args
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(*)
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"#<%s>" % self.class.name.sub("Anything::", "")
|
28
|
+
end
|
29
|
+
|
30
|
+
def ^(other)
|
31
|
+
Composite.new(self, other)
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_ary
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_str
|
39
|
+
self
|
40
|
+
end
|
41
|
+
end
|
42
|
+
def anything
|
43
|
+
Anything.new
|
44
|
+
end
|
45
|
+
|
46
|
+
class Composite < SimpleDelegator
|
47
|
+
def initialize(left, right)
|
48
|
+
super(left)
|
49
|
+
@right = right
|
50
|
+
end
|
51
|
+
|
52
|
+
def ==(o)
|
53
|
+
__getobj__.==(o) && @right.==(o)
|
54
|
+
end
|
55
|
+
|
56
|
+
def ^(other)
|
57
|
+
Composite.new(self, other)
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
"#<Composite #{__getobj__.inspect} #{@right.inspect}>"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class AnyInteger < Anything
|
66
|
+
def ==(o)
|
67
|
+
o.is_a?(Integer)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
def any_integer
|
71
|
+
AnyInteger.new
|
72
|
+
end
|
73
|
+
|
74
|
+
class AnyNumber < Anything
|
75
|
+
def ==(o)
|
76
|
+
o.is_a?(Numeric)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
def any_number
|
80
|
+
AnyNumber.new
|
81
|
+
end
|
82
|
+
|
83
|
+
class EvenNumber < AnyNumber
|
84
|
+
def ==(o)
|
85
|
+
super && o.even?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
def even_number
|
89
|
+
EvenNumber.new
|
90
|
+
end
|
91
|
+
|
92
|
+
class OddNumber < AnyNumber
|
93
|
+
def ==(o)
|
94
|
+
super && o.odd?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
def odd_number
|
98
|
+
OddNumber.new
|
99
|
+
end
|
100
|
+
|
101
|
+
class AnyString < Anything
|
102
|
+
def ==(o)
|
103
|
+
o.is_a?(String)
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_str
|
107
|
+
self
|
108
|
+
end
|
109
|
+
end
|
110
|
+
def any_string
|
111
|
+
AnyString.new
|
112
|
+
end
|
113
|
+
|
114
|
+
class OneOf < Anything
|
115
|
+
def initialize(*values)
|
116
|
+
super
|
117
|
+
@values = values
|
118
|
+
end
|
119
|
+
|
120
|
+
def ==(o)
|
121
|
+
@values.include?(o)
|
122
|
+
end
|
123
|
+
|
124
|
+
def inspect
|
125
|
+
"#<OneOf #{@values.map(&:inspect).join(" ")}>"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
def one_of(*values)
|
129
|
+
OneOf.new(*values)
|
130
|
+
end
|
131
|
+
|
132
|
+
class StringOfLength < AnyString
|
133
|
+
def initialize(expected_length)
|
134
|
+
super
|
135
|
+
@expected_length = expected_length
|
136
|
+
end
|
137
|
+
|
138
|
+
def ==(o)
|
139
|
+
super && o.length == @expected_length
|
140
|
+
end
|
141
|
+
|
142
|
+
def inspect
|
143
|
+
"#<StringOfLength #@expected_length>"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
def string_of_length(expected_length)
|
147
|
+
StringOfLength.new(expected_length)
|
148
|
+
end
|
149
|
+
|
150
|
+
class StringMatching < AnyString
|
151
|
+
def initialize(pattern)
|
152
|
+
super
|
153
|
+
@pattern = pattern
|
154
|
+
end
|
155
|
+
|
156
|
+
def ==(o)
|
157
|
+
super && o =~ @pattern
|
158
|
+
end
|
159
|
+
|
160
|
+
def inspect
|
161
|
+
"#<StringMatching #@pattern>"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
def string_matching(pattern)
|
165
|
+
StringMatching.new(pattern)
|
166
|
+
end
|
167
|
+
|
168
|
+
# It's the same as:
|
169
|
+
#
|
170
|
+
# sorted_array = array_of(increasing)
|
171
|
+
class SortedArray < Anything
|
172
|
+
def ==(o)
|
173
|
+
o == o.sort
|
174
|
+
end
|
175
|
+
|
176
|
+
def to_ary
|
177
|
+
self
|
178
|
+
end
|
179
|
+
end
|
180
|
+
def sorted_array
|
181
|
+
SortedArray.new
|
182
|
+
end
|
183
|
+
|
184
|
+
class ArrayOf < Anything
|
185
|
+
def initialize(element)
|
186
|
+
unless element.is_a?(Anything)
|
187
|
+
raise ArgumentError, "invalid argument: #{element.inspect}"
|
188
|
+
end
|
189
|
+
|
190
|
+
super
|
191
|
+
@element = element
|
192
|
+
end
|
193
|
+
|
194
|
+
def ==(o)
|
195
|
+
o.all? { |x| x == @element }
|
196
|
+
end
|
197
|
+
|
198
|
+
def inspect
|
199
|
+
"#<ArrayOf #{@element.inspect}>"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
def array_of(element)
|
203
|
+
ArrayOf.new(element)
|
204
|
+
end
|
205
|
+
|
206
|
+
class AnyUnique < Anything
|
207
|
+
def initialize
|
208
|
+
@seen = Set.new
|
209
|
+
end
|
210
|
+
def ==(o)
|
211
|
+
if @seen.include?(o)
|
212
|
+
false
|
213
|
+
else
|
214
|
+
@seen << o
|
215
|
+
true
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
def any_unique
|
220
|
+
@_any_unique ||= AnyUnique.new
|
221
|
+
end
|
222
|
+
|
223
|
+
class Increasing < Anything
|
224
|
+
def initialize
|
225
|
+
@last = nil
|
226
|
+
@for_inspect = nil
|
227
|
+
end
|
228
|
+
|
229
|
+
def ==(o)
|
230
|
+
@for_inspect = @last
|
231
|
+
if @last
|
232
|
+
result = o > @last
|
233
|
+
@last = o
|
234
|
+
result
|
235
|
+
else
|
236
|
+
@last = o
|
237
|
+
super
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def inspect
|
242
|
+
"#<Increasing last=#{@for_inspect.inspect}>"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
def increasing
|
246
|
+
@_increasing ||= Increasing.new
|
247
|
+
end
|
248
|
+
|
249
|
+
class UpcaseString < AnyString
|
250
|
+
def ==(o)
|
251
|
+
super && o.upcase == o
|
252
|
+
end
|
253
|
+
end
|
254
|
+
def upcase_string
|
255
|
+
UpcaseString.new
|
256
|
+
end
|
257
|
+
|
258
|
+
class AnyTime < Anything
|
259
|
+
def ==(o)
|
260
|
+
o.is_a?(Time)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
def any_time
|
264
|
+
AnyTime.new
|
265
|
+
end
|
266
|
+
|
267
|
+
class AnyDate < Anything
|
268
|
+
def ==(o)
|
269
|
+
o.is_a?(Date)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
def any_date
|
273
|
+
AnyDate.new
|
274
|
+
end
|
275
|
+
|
276
|
+
class AnyHTTPURI < Anything
|
277
|
+
def ==(o)
|
278
|
+
uri = URI(o)
|
279
|
+
uri.is_a?(URI::HTTP)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
def any_http_uri
|
283
|
+
AnyHTTPURI.new
|
284
|
+
end
|
285
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: any_value
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wojtek Mach
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Helper objects for testing nested data structures
|
56
|
+
email:
|
57
|
+
- wojtek@wojtekmach.pl
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".travis.yml"
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- any_value.gemspec
|
69
|
+
- lib/any_value.rb
|
70
|
+
- lib/any_value/version.rb
|
71
|
+
homepage: https://github.com/wojtekmach/any_value
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.5.1
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Helper objects for testing nested data structures
|
95
|
+
test_files: []
|