Complex Comparisons
Comparing values with GUT’s asserts works the way you would expect it to in most cases. Arrays and dictionaries are a little more complicated. The following methods can help with this:
compare_shallowcompare_deep
The asserts listed are convenience wrappers around compare_shallow and compare_deep. In most cases this will be all you need. If you would like to further inspect the differences with code then or adjust the number of differences displayed then use the “compare” methods. These methods return a CompareResult object which is described below.
Shallow
A shallow compare will look at each element in a dictionary or array and use the default Godot equivalence logic. Floats and Integers are never equal. See assert_eq_shallow for examples.
Deep
A deep compare will recursively compare all values in the dictionary/array and all sub-dictionaries and sub-arrays. Floats and Integers are never equal. See assert_eq_deep for examples.
Comparing Arrays
Godot compares arrays by value with some caveats.
Unlike when using
==, floats never == integers in an array.Dictionaries are compared by reference. Two different dictionaries with the same values are not equal.
Sub arrays are compared the same way.
Cannot compare arrays by reference.
Asserts and Arrays
The
assert_eqandassert_nefunctions simulate Godot’s behavior but have improved output.Up to 30 differences in index values are listed including any missing indexes.
Dictionaries anywhere in the array are compared-by-ref.
Sub-arrays are summarized, the number of indexes that do not match are listed, but each different value is not.
assert_calledandassert_not_calledperform deep compares on any parameters specified.assert_signal_emitted_with_parametersperforms a deep compare on the parameters specified.assert_hasandassert_does_not_haveuse Godot’s default behavior.
Shallow
A shallow compare of arrays acts the same as assert_eq/assert_ne. Any dictionaries in the array or sub-arrays will be compared by reference. Floats and Integers are never equal.
Deep
A deep compare of arrays will compare all indexes and the values in all sub-arrays/sub-dictionaries found. Floats and Integers are never equal.
Comparing Dictionaries
Godot compares dictionaries by reference.
Dictionary keys are ordered (which is unusual).
The dictionary
hashfuction requires dictionary keys be in the same order to generate the same hash so comparing dictionaries by value cannot be done reliably without additional coding.In order to compare values in dictionary you must use one of the shallow or deep methods listed above.
Asserts and Dictionaries
The
assert_eqandassert_neuses Godot’s default behavior and compares them by reference.assert_calledandassert_not_calledperform deep compares on any parameters specified.assert_signal_emitted_with_parametersperforms a deep compare on the parameters specified.assert_hasandassert_does_not_haveuse Godot’s default behavior.
Shallow
A shallow compare of dictionaries will compare all values found in the dictionary. Sub-dictionaries are compared by value. Sub-arrays are compared with ==. Floats and Integers are never equal.
Deep
A deep compare of dictionaries will compare all keys and the values in all sub-arrays/sub-dictionaries found. Floats and Integers are never equal.
CompareResult
A CompareResult object is returned from compare_shallow and compare_deep. You can use this object to further inspect the differences or adjust the output.
Properties
are_equal: returnstrue/falseif the two objects are equal based on the kind of comparison performed.summary: returrns a string of all the differences found. This will displaymax_differencesdifferences. When performing a deep compare, it will also displaymax_differencesper each sub-array/sub-dictionary. This is returned if you usestron aCompareResult.max_differences: The number of differences to display. This only affects output, all differences are accessible from thedifferencesproperty. Set this to -1 to show the maximum number of differences (10,000)differences: This is a dictionary of all the keys/indexes that are different between the compared items. The key is the key/index that is different. Keys/indexes that are missing from one of the compared objects are included. The value of each index is aCompareResult.
CompareResults for sub-arrays/sub-dictionariesdifferenceswill contain all their differences. You can use thedifferencesproperty for that key to dig deeper into the differences.differenceswill be an empty dictionary for any element that is not an array or dictionary.
Examples
Deep array compare:
var a1 = [
[1, 2, 3, 4],
[[4, 5, 6], ['same'], [7, 8, 9]]
]
var a2 = [
["1", 2.0, 13],
[[14, 15, 16], ['same'], [17, 18, 19]]
]
var result = compare_deep(a1, a2)
print(result.summary)
print('Traversing differences:')
print(result.differences[1].differences[2].differences[0])
Output
[[1, 2, 3, 4], [[4, 5, 6], [same], [7, 8...7, 8, 9]]] != [[1, 2, 13], [[14, 15, 16], [same], [17,... 18, 19]]] 2 of 2 indexes do not match.
[
0: [
0: 1 != "1". Cannot compare Int with String.
1: 2 != 2.0. Cannot compare Int with Float/Real.
2: 3 != 13
3: 4 != <missing index>
]
1: [
0: [
0: 4 != 14
1: 5 != 15
2: 6 != 16
]
2: [
0: 7 != 17
1: 8 != 18
2: 9 != 19
]
]
]
Traversing differences:
7 != 17
Deep Dictionary Compare
var v1 = {'a':{'b':{'c':{'d':1}}}}
var v2 = {'a':{'b':{'c':{'d':2}}}}
var result = compare_deep(v1, v2)
print(result.summary)
print('Traversing differences:')
print(result.differences['a'].differences['b'].differences['c'])
Output
{a:{b:{c:{d:1}}}} != {a:{b:{c:{d:2}}}} 1 of 1 keys do not match.
{
a: {
b: {
c: {
d: 1 != 2
}
}
}
}
Traversing differences:
{d:1} != {d:2} 1 of 1 keys do not match.
{
d: 1 != 2
}
Mix Bag of Differences
var a1 = [
'a', 'b', 'c',
[1, 2, 3, 4],
{'a':1, 'b':2, 'c':3},
[{'a':1}, {'b':2}]
]
var a2 = [
'a', 2, 'c',
['a', 2, 3, 'd'],
{'a':11, 'b':12, 'c':13},
[{'a':'diff'}, {'b':2}]
]
var result = compare_deep(a1, a2)
print(result.summary)
print('Traversing differences:')
print(result.differences[5].differences[0].differences['a'])
Output
[a, b, c, [1, 2, 3, 4], {a:1, b:2, c:3},...}, {b:2}]] != [a, 2, c, [a, 2, 3, d], {a:11, b:12, c:1...}, {b:2}]] 4 of 6 indexes do not match.
[
1: "b" != 2. Cannot compare String with Int.
3: [
0: 1 != "a". Cannot compare Int with String.
3: 4 != "d". Cannot compare Int with String.
]
4: {
a: 1 != 11
b: 2 != 12
c: 3 != 13
}
5: [
0: {
a: 1 != "diff". Cannot compare Int with String.
}
]
]
Traversing differences:
1 != "diff". Cannot compare Int with String.