structure_compare 0.1.0
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 +7 -0
- data/.gitignore +40 -0
- data/.simplecov +13 -0
- data/Gemfile +3 -0
- data/Guardfile +13 -0
- data/LICENSE +21 -0
- data/README.md +6 -0
- data/Rakefile +29 -0
- data/lib/structure_compare.rb +156 -0
- data/lib/version.rb +3 -0
- data/structure_compare.gemspec +28 -0
- data/test/structure_compare_test.rb +176 -0
- data/test/test_helper.rb +12 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 535404ee3a6c198af0c7788bee7f0a31d15fee6c
|
4
|
+
data.tar.gz: c133617419e3d5b8e3338e63ae08b123b74a3ad3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4decfee7c6aafed708585478a69be43475a2a52db8b1484bc179df16c53610f7c47dbf98b77a8d0249615f9a9d5832b882ad1c4d0235b3cffb9b1bdbb506693c
|
7
|
+
data.tar.gz: 78f2b98c8c8af06034ffada10178cd343ee479e4004732caff6a8bb70f47ae122fe299755d5247435e8389ca7c62158cc91a0d45a0a3d36716fae96f6d6c5c14
|
data/.gitignore
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# SimpleCov
|
2
|
+
test/coverage
|
3
|
+
|
4
|
+
# Bundler
|
5
|
+
Gemfile.lock
|
6
|
+
|
7
|
+
*.gem
|
8
|
+
*.rbc
|
9
|
+
/.config
|
10
|
+
/coverage/
|
11
|
+
/InstalledFiles
|
12
|
+
/pkg/
|
13
|
+
/spec/reports/
|
14
|
+
/test/tmp/
|
15
|
+
/test/version_tmp/
|
16
|
+
/tmp/
|
17
|
+
|
18
|
+
## Specific to RubyMotion:
|
19
|
+
.dat*
|
20
|
+
.repl_history
|
21
|
+
build/
|
22
|
+
|
23
|
+
## Documentation cache and generated files:
|
24
|
+
/.yardoc/
|
25
|
+
/_yardoc/
|
26
|
+
/doc/
|
27
|
+
/rdoc/
|
28
|
+
|
29
|
+
## Environment normalisation:
|
30
|
+
/.bundle/
|
31
|
+
/lib/bundler/man/
|
32
|
+
|
33
|
+
# for a library or gem, you might want to ignore these files since the code is
|
34
|
+
# intended to run in multiple environments; otherwise, check them in:
|
35
|
+
Gemfile.lock
|
36
|
+
.ruby-version
|
37
|
+
.ruby-gemset
|
38
|
+
|
39
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
40
|
+
.rvmrc
|
data/.simplecov
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
guard :minitest do
|
2
|
+
|
3
|
+
# run all tests when lib main module file changes
|
4
|
+
watch(%r{^lib/structure_compare.rb$}) { "test" }
|
5
|
+
|
6
|
+
# run accompanying test for single source file if it changes
|
7
|
+
watch(%r{^lib/(.*)\.rb$}) {|m| "test/#{m[1]}_test.rb" }
|
8
|
+
|
9
|
+
# run test whenever it changes
|
10
|
+
watch(%r{^test/(.*)\/?(.*)?_test\.rb$})
|
11
|
+
|
12
|
+
end
|
13
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Markus Seeger
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rubocop/rake_task'
|
7
|
+
|
8
|
+
task :default => [:test]
|
9
|
+
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.libs << 'lib'
|
12
|
+
t.libs << 'test'
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
14
|
+
t.verbose = false
|
15
|
+
end
|
16
|
+
|
17
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
18
|
+
# NOTE: do not define task.patterns here, since this
|
19
|
+
# would override the .rubocop.yml include/exclude
|
20
|
+
# definition
|
21
|
+
|
22
|
+
task.formatters = ['offenses', 'simple']
|
23
|
+
task.options = ['-D'] # Display cop name
|
24
|
+
|
25
|
+
# don't abort rake on failure
|
26
|
+
task.fail_on_error = false
|
27
|
+
end
|
28
|
+
|
29
|
+
task default: [:test, :rubocop]
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# TODO rename to structure_compare
|
2
|
+
# TODO Enumerable to support non-array enumerables
|
3
|
+
# TODO doc
|
4
|
+
module StructureCompare
|
5
|
+
|
6
|
+
class StructuresNotEqualError < RuntimeError; end
|
7
|
+
class ArgumentError < ArgumentError; end
|
8
|
+
|
9
|
+
class StructureComparison
|
10
|
+
def initialize(options = {})
|
11
|
+
@options = {
|
12
|
+
strict_key_order: false,
|
13
|
+
check_values: false,
|
14
|
+
treat_hash_symbols_as_strings: false,
|
15
|
+
float_tolerance_factor: 0
|
16
|
+
}.merge(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO doc
|
20
|
+
def structures_are_equal?(expected, actual)
|
21
|
+
@path = []
|
22
|
+
@error = nil
|
23
|
+
|
24
|
+
begin
|
25
|
+
check_structures_equal!(expected, actual)
|
26
|
+
rescue StructuresNotEqualError => _error
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
|
33
|
+
# TODO doc
|
34
|
+
def error
|
35
|
+
"#{@path.join} : #{@error}"
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def check_structures_equal!(expected, actual)
|
41
|
+
check_kind_of!(expected, actual)
|
42
|
+
|
43
|
+
case expected
|
44
|
+
when Array
|
45
|
+
check_arrays_equal!(expected, actual)
|
46
|
+
when Hash
|
47
|
+
check_hashes_equal!(expected, actual)
|
48
|
+
else
|
49
|
+
check_leafs_equal!(expected, actual)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_arrays_equal!(expected, actual)
|
54
|
+
check_equal!(
|
55
|
+
expected.count, actual.count, "array length: #{expected.count} != #{actual.count}"
|
56
|
+
)
|
57
|
+
|
58
|
+
expected.each_with_index do |expected_value, index|
|
59
|
+
path_segment = "[#{index}]"
|
60
|
+
@path.push(path_segment)
|
61
|
+
|
62
|
+
check_structures_equal!(expected_value, actual[index])
|
63
|
+
@path.pop
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def check_hashes_equal!(expected, actual)
|
68
|
+
check_hash_keys_equal!(expected, actual)
|
69
|
+
|
70
|
+
expected_values = expected.values
|
71
|
+
actual_values = actual.values
|
72
|
+
|
73
|
+
expected_values.each_with_index do |expected_value, index|
|
74
|
+
key = expected.keys[index]
|
75
|
+
path_segment = key.is_a?(Symbol) ? "[:#{key}]" : "[\"#{key}\"]"
|
76
|
+
@path.push(path_segment)
|
77
|
+
|
78
|
+
check_structures_equal!(expected_value, actual_values[index])
|
79
|
+
@path.pop
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def check_hash_keys_equal!(expected, actual)
|
84
|
+
expected_keys = expected.keys
|
85
|
+
actual_keys = actual.keys
|
86
|
+
|
87
|
+
if @options[:treat_hash_symbols_as_strings]
|
88
|
+
# NOTE: not all hash keys are symbols/strings, only convert symbols
|
89
|
+
expected_keys.map! { |key| key.is_a?(Symbol) ? key.to_s : key }
|
90
|
+
actual_keys.map! { |key| key.is_a?(Symbol) ? key.to_s : key }
|
91
|
+
end
|
92
|
+
|
93
|
+
if @options[:strict_key_order]
|
94
|
+
check_equal!(expected_keys, actual_keys)
|
95
|
+
else
|
96
|
+
begin
|
97
|
+
expected_keys.sort!
|
98
|
+
actual_keys.sort!
|
99
|
+
rescue ::ArgumentError => error
|
100
|
+
raise StructureCompare::ArgumentError.new(
|
101
|
+
"Unable to sort hash keys: \"#{error}\"." +
|
102
|
+
'Try enabling :strict_key_order option to prevent sorting of mixed-type hash keys.'
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
check_equal!(expected_keys, actual_keys)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def check_leafs_equal!(expected, actual)
|
111
|
+
check_equal!(expected, actual) if @options[:check_values]
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_kind_of!(expected, actual)
|
115
|
+
unless actual.kind_of?(expected.class)
|
116
|
+
failure_message = "expected #{actual.class.to_s} to be kind of #{expected.class.to_s}"
|
117
|
+
not_equal_error!(expected, actual, failure_message)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def check_equal!(expected, actual, failure_message = nil)
|
122
|
+
if expected.is_a?(Float) && actual.is_a?(Float)
|
123
|
+
is_equal = float_equal_with_tolerance_factor?(
|
124
|
+
expected, actual, @options[:float_tolerance_factor]
|
125
|
+
)
|
126
|
+
else
|
127
|
+
is_equal = (expected == actual)
|
128
|
+
end
|
129
|
+
|
130
|
+
if !is_equal
|
131
|
+
failure_message ||= "expected: #{expected.inspect}, got: #{actual.inspect}"
|
132
|
+
not_equal_error!(expected, actual, failure_message)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def float_equal_with_tolerance_factor?(expected, actual, tolerance_factor)
|
137
|
+
raise StructureCompare::ArgumentError.new("tolerance_factor must be > 0") if tolerance_factor < 0
|
138
|
+
|
139
|
+
lower_bound = (expected * (1.0 - tolerance_factor) - Float::EPSILON)
|
140
|
+
upper_bound = (expected * (1.0 + tolerance_factor) + Float::EPSILON)
|
141
|
+
|
142
|
+
return (lower_bound <= actual) && (actual <= upper_bound)
|
143
|
+
end
|
144
|
+
|
145
|
+
# TODO make this part of an overridden exception?
|
146
|
+
def not_equal_error!(expected, actual, failure_message)
|
147
|
+
@error = failure_message
|
148
|
+
raise StructuresNotEqualError.new() # TODO error message, path
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
# TODO test if monkeypatching MiniTest::Assertions works
|
155
|
+
|
156
|
+
require 'version'
|
data/lib/version.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "structure_compare"
|
8
|
+
gem.version = StructureCompare::VERSION
|
9
|
+
gem.authors = ["Markus Seeger"]
|
10
|
+
gem.email = ["mail@codegourmet.de"]
|
11
|
+
gem.description = "Compares the structure of two deep nested Ruby structures"
|
12
|
+
gem.summary = ""
|
13
|
+
gem.homepage = "https://github.com/codegourmet/structure_compare"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_development_dependency "rake", "~> 10.1"
|
22
|
+
gem.add_development_dependency "guard"
|
23
|
+
gem.add_development_dependency "guard-minitest"
|
24
|
+
gem.add_development_dependency "minitest"
|
25
|
+
gem.add_development_dependency "minitest-reporters"
|
26
|
+
gem.add_development_dependency "simplecov"
|
27
|
+
gem.add_development_dependency "rubocop"
|
28
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require_relative "test_helper"
|
2
|
+
require_relative "../lib/structure_compare"
|
3
|
+
|
4
|
+
class StructureCompareTest < MiniTest::Test
|
5
|
+
|
6
|
+
def setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_compares_keys_of_hashes
|
10
|
+
refute_structures_equal({a: 1, b: 2}, {a: 1, other_key: 2})
|
11
|
+
refute_structures_equal({a: 1, b: 2}, {a: 1, b: 2, c: 3})
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_hash_key_order_is_compared_if_option_set
|
15
|
+
assert_structures_equal({a: 1, b: 2}, {b: 2, a: 1})
|
16
|
+
assert_structures_equal({a: 1, b: 2}, {b: 2, a: 1}, strict_key_order: false)
|
17
|
+
refute_structures_equal({a: 1, b: 2}, {b: 2, a: 1}, strict_key_order: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_compares_leaf_value_types
|
21
|
+
assert_structures_equal({a: 1, b: 2}, {b: 2, a: 1})
|
22
|
+
refute_structures_equal({a: 1, b: 2}, {a: 1, b: 2.0})
|
23
|
+
|
24
|
+
assert_structures_equal(%w(a b c d), %w(a b c d))
|
25
|
+
refute_structures_equal(%w(a b c d), ['a', 'b', 'c', 111])
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_leaf_values_are_compared_if_option_set
|
29
|
+
assert_structures_equal({a: 1, b: 2}, {a: 111, b: 222})
|
30
|
+
refute_structures_equal({a: 1, b: 2}, {a: 111, b: 222}, check_values: true)
|
31
|
+
|
32
|
+
assert_structures_equal(%w(a b c d), %w(a b c d))
|
33
|
+
refute_structures_equal(%w(a b c d), %w(A b c d), check_values: true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_compares_arrays
|
37
|
+
assert_structures_equal([1, 2, 3], [1, 2, 3])
|
38
|
+
refute_structures_equal([1, 2], [1, 2, 3])
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_stores_error_with_path_in_getter
|
42
|
+
structure_a = { x: 1, a: [{ b: [1, 1, 1] }] }
|
43
|
+
structure_b = { x: 1, a: [{ b: [1, 9, 1] }] }
|
44
|
+
|
45
|
+
comparison = StructureCompare::StructureComparison.new(check_values: true)
|
46
|
+
comparison.structures_are_equal?(structure_a, structure_b)
|
47
|
+
assert_match "[:a][0][:b][1]", comparison.error
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_shows_values_for_expected_and_actual_if_error
|
51
|
+
structure_a = { x: 1, a: [{ b: [1, "FOO", 1] }] }
|
52
|
+
structure_b = { x: 1, a: [{ b: [1, "BAR", 1] }] }
|
53
|
+
|
54
|
+
assert_structures_equal(structure_a, structure_b)
|
55
|
+
comparison = StructureCompare::StructureComparison.new(check_values: true)
|
56
|
+
comparison.structures_are_equal?(structure_a, structure_b)
|
57
|
+
assert_match "FOO", comparison.error
|
58
|
+
assert_match "BAR", comparison.error
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_compares_deep_structures
|
62
|
+
structure_a = { x: 1, a: [{ b: [1, 1, 1] }] }
|
63
|
+
structure_b = { x: 1, a: [{ b: [1, 9, 1] }] }
|
64
|
+
|
65
|
+
assert_structures_equal(structure_a, structure_a, check_values: true)
|
66
|
+
refute_structures_equal(structure_a, structure_b, check_values: true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_mixed_type_hash_keys_trigger_error_unless_strict_order_set
|
70
|
+
hash = { a: 1, 5 => 6 }
|
71
|
+
|
72
|
+
assert_raises StructureCompare::ArgumentError do
|
73
|
+
assert_structures_equal(hash, hash)
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_structures_equal(hash, hash, strict_key_order: true)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_symbol_keys_are_strings_if_option_set
|
80
|
+
string_hash = {"a" => 1, "b" => 2, 5 => 6}
|
81
|
+
symbol_hash = {a: 1, b: 2, 5 => 6}
|
82
|
+
|
83
|
+
refute_structures_equal(string_hash, symbol_hash, strict_key_order: true)
|
84
|
+
assert_structures_equal(
|
85
|
+
string_hash, symbol_hash,
|
86
|
+
treat_hash_symbols_as_strings: true, strict_key_order: true
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_compares_floats_correctly
|
91
|
+
assert_structures_equal([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], check_values: true)
|
92
|
+
assert_structures_equal(
|
93
|
+
[1.0 - Float::EPSILON * 0.5, 2.0 + Float::EPSILON * 0.5, 3.0],
|
94
|
+
[1.0, 2.0, 3.0],
|
95
|
+
check_values: true
|
96
|
+
)
|
97
|
+
|
98
|
+
refute_structures_equal(
|
99
|
+
[1.0 - Float::EPSILON * 2, 2.0, 3.0],
|
100
|
+
[1.0, 2.0, 3.0],
|
101
|
+
check_values: true
|
102
|
+
)
|
103
|
+
|
104
|
+
refute_structures_equal(
|
105
|
+
[1.0 + Float::EPSILON * 2, 2.0, 3.0],
|
106
|
+
[1.0, 2.0, 3.0],
|
107
|
+
check_values: true
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_compares_with_tolerance_if_options_set
|
112
|
+
assert_structures_equal(%w(a b c d), %w(a b c d), {
|
113
|
+
# just to catch bugs with this option concerning non-floats
|
114
|
+
check_values: true, float_tolerance_factor: 0.1
|
115
|
+
})
|
116
|
+
|
117
|
+
refute_structures_equal([1.0, 2.0, 3.0], [1.0001, 2.0001, 3.0001], {
|
118
|
+
check_values: true
|
119
|
+
})
|
120
|
+
|
121
|
+
assert_structures_equal([1.0, 2.0, 3.0], [1.0001, 2.0001, 3.0001], {
|
122
|
+
check_values: true, float_tolerance_factor: 0.1
|
123
|
+
})
|
124
|
+
assert_structures_equal([1.0, 2.0, 3.0], [1.1, 2.1, 3.1], {
|
125
|
+
check_values: true, float_tolerance_factor: 0.1
|
126
|
+
})
|
127
|
+
assert_structures_equal([1.0, 2.0, 3.0], [0.9, 1.9, 2.9], {
|
128
|
+
check_values: true, float_tolerance_factor: 0.1
|
129
|
+
})
|
130
|
+
|
131
|
+
assert_structures_equal(
|
132
|
+
[1.0, 2.0, 3.0],
|
133
|
+
[0.9 - Float::EPSILON * 0.5, 2.1, 3.1],
|
134
|
+
{ check_values: true, float_tolerance_factor: 0.1 }
|
135
|
+
)
|
136
|
+
refute_structures_equal(
|
137
|
+
[1.0, 2.0, 3.0],
|
138
|
+
[0.9 - Float::EPSILON * 2, 2.1, 3.1],
|
139
|
+
{ check_values: true, float_tolerance_factor: 0.1 }
|
140
|
+
)
|
141
|
+
|
142
|
+
assert_structures_equal(
|
143
|
+
[1.0, 2.0, 3.0],
|
144
|
+
[1.1 + Float::EPSILON * 0.5, 2.1, 3.1],
|
145
|
+
{ check_values: true, float_tolerance_factor: 0.1 }
|
146
|
+
)
|
147
|
+
refute_structures_equal(
|
148
|
+
[1.0, 2.0, 3.0],
|
149
|
+
[1.1 + Float::EPSILON * 2, 2.1, 3.1],
|
150
|
+
{ check_values: true, float_tolerance_factor: 0.1 }
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_ensures_tolerance_factor_is_gt_0
|
155
|
+
assert_raises StructureCompare::ArgumentError do
|
156
|
+
assert_structures_equal(
|
157
|
+
[1.0], [1.0], check_values: true, float_tolerance_factor: -0.1
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
protected
|
163
|
+
|
164
|
+
def assert_structures_equal(expected, actual, options = {})
|
165
|
+
comparison = StructureCompare::StructureComparison.new(options)
|
166
|
+
is_equal = comparison.structures_are_equal?(expected, actual)
|
167
|
+
assert is_equal, comparison.error
|
168
|
+
end
|
169
|
+
|
170
|
+
def refute_structures_equal(expected, actual, options = {})
|
171
|
+
comparison = StructureCompare::StructureComparison.new(options)
|
172
|
+
is_equal = comparison.structures_are_equal?(expected, actual)
|
173
|
+
refute is_equal, "structures are not expected to be equal"
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'simplecov' # has to be at top, will execute ../.simplecov
|
2
|
+
|
3
|
+
require 'structure_compare'
|
4
|
+
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require 'minitest/reporters'
|
7
|
+
|
8
|
+
if ENV["RM_INFO"] || ENV["TEAMCITY_VERSION"]
|
9
|
+
MiniTest::Reporters.use! MiniTest::Reporters::RubyMineReporter.new
|
10
|
+
else
|
11
|
+
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: structure_compare
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Markus Seeger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10.1'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '10.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: guard
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: guard-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
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-reporters
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
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: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Compares the structure of two deep nested Ruby structures
|
112
|
+
email:
|
113
|
+
- mail@codegourmet.de
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".simplecov"
|
120
|
+
- Gemfile
|
121
|
+
- Guardfile
|
122
|
+
- LICENSE
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- lib/structure_compare.rb
|
126
|
+
- lib/version.rb
|
127
|
+
- structure_compare.gemspec
|
128
|
+
- test/structure_compare_test.rb
|
129
|
+
- test/test_helper.rb
|
130
|
+
homepage: https://github.com/codegourmet/structure_compare
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.4.5
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: ''
|
154
|
+
test_files:
|
155
|
+
- test/structure_compare_test.rb
|
156
|
+
- test/test_helper.rb
|