Skip to content

codegourmet/structure_compare

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

structure_compare

Compares the structure of two deep nested Ruby structures

General

Use case: you're writing an API response or a JSON export and want to unit test it. Optionally you can ignore the leaf values or any hash key types/order (see below).

Gives error results with the path to where exactly the structures differ.

This README file is mirrored on my blog

Installation

gem install structure_compare

or add it to your Gemfile:

gem structure_compare

quick-n-dirty example:

require 'structure_compare'
comparison = StructureCompare::StructureComparison.new

expected = { a: 1, b: 2, c: [1, 2, 3] }
actual   = { a: 1, b: 2, c: [1, 2, "A"] }

comparison.structures_are_equal?(expected, actual)
puts comparison.error
# => root[:c][2] : expected String to be kind of Fixnum

MiniTest

require 'structure_compare'
require 'structure_compare/minitest'

assert_structures_equal({ a: 1, b: 2 }, { a: 1, b: 2 })
refute_structures_equal({ a: 1, b: 2 }, { c: 1, d: 2 })

Options

Strict key ordering

name: strict_key_order (default: false)

expected = { a: 1, b: 2 }
actual   = { b: 2, a: 1 }

comparison = StructureCompare::StructureComparison.new(strict_key_order: false)
comparison.structures_are_equal?(expected, actual)
# => true

Value checking

name: check_values (default: true)

expected = { a: 1, b: { c: 1 } }
actual   = { a: 8, b: { c: 8 } }

comparison = StructureCompare::StructureComparison.new
comparison.structures_are_equal?(expected, actual)
# => false

comparison = StructureCompare::StructureComparison.new(check_values: false)
comparison.structures_are_equal?(expected, actual)
# => true

Indifferent Access

Hash symbol keys are treated as equal to string keys

NOTE: an exception will be raised if there's a key present as symbol and string

name: indifferent_access (default: false)

expected = { a: 1 }
actual   = { "a" => 1 }

comparison = StructureCompare::StructureComparison.new
comparison.structures_are_equal?(expected, actual)
# => false

comparison = StructureCompare::StructureComparison.new(indifferent_access: true)
comparison.structures_are_equal?(expected, actual)
# => true

hash = { a: 1, "a" => 2 }
comparison = StructureCompare::StructureComparison.new(indifferent_access: true)
comparison.structures_are_equal?(hash, hash)
# => StructureCompare::IndifferentAccessError

Float tolerance

When dealing with floats, you will want to introduce a tolerance.

NOTE: Float::EPSILON is always used for comparing Float type values.

NOTE: The check_values option must be set.

name: float_tolerance_factor (default: 0)

tolerance = +- (expected * (1.0 + tolerance_factor) + Float::EPSILON)

This means a float_tolerance_factor setting of 0.01 means that actual can be 1% different from expected to still be treated equal.

expected = { a: 10.0 }
actual_1 = { a: 10.1 }
actual_2 = { a: 10.11 }

# 1% tolerance factor
comparison = StructureCompare::StructureComparison.new(
  float_tolerance_factor: 0.01, check_values: true
)
comparison.structures_are_equal?(expected, actual_1)
# => true

comparison.structures_are_equal?(expected, actual_2)
# => false

TODOS

RSpec helpers. Refactoring.

Contributing

Fork me and send me a pull request with your feature and working tests, or just request a feature.

License

MIT License, see LICENSE file in the root directory

About

Compares the structure of two deeply nested Ruby structures

Resources

License

Stars

0 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages