How to compare two Registered Object
I would like to compare two Registered Object and list the properties that differ.
For now, I achieve this :
ClassMethod AssertObjectEquals(object As %RegisteredObject, objectToCompare As %RegisteredObject, Output msg As %String) As %Status
{
Set returnValue = 1
// check if same class
Set className = $CLASSNAME(object)
If (className '= $CLASSNAME(objectToCompare)) {
Set returnValue = 0
Set difference = "not same class"
}
If (returnValue) {
// Get the definition to browse properties
Set classDef = ##class(%Library.ClassDefinition).%OpenId(className)
Set propertiesDef = classDef.Properties
// Check the value for each property
Set difference = ""
For i = 1:1:propertiesDef.Count() {
Set propertyName = propertiesDef.GetAt(i).Name
Set propertyValue = $PROPERTY(object,propertyName)
// if different, supply the variable difference with the name of property + value
If ((propertyValue '= "") && (propertyValue '= $PROPERTY(objectToCompare,propertyName)))
{
Set difference = difference _ "; " _ propertyName _ " = " _ propertyValue
}
}
}
if difference = ""
{Set msg = "equal"}
else {
Set msg = difference
}
Return $$$OK
}
ObjectScriptObjectScript
But it does not take into account complex properties as list, array or object.
Has somebody an idea to complete the ClassMethod or an other totally different solution?
Thanks in advance !
Product version: Ensemble 2018.1
$ZV: Cache for Windows (x86-64) 2018.1.4 (Build 505_1U) Thu May 28 2020 10:01:40 EDT
Here's an example.
And you can install it with IPM as:
USER>zpm "install utils-code-snippets"
See more on OEX
Another option is to use embedded python (not for your version sadly). You would use jsondiff Python library to compare the JSON projection of the objects.
Hello Corentin,
I took your code as base and improved it a bit to compare complex object:
ClassMethod CompareObjects(expectedObject As %RegisteredObject, actualObject As %RegisteredObject) As %Status { Set status= $$$OK Set returnValue = 1 Try{ // check if same class Set className = $CLASSNAME(expectedObject) If (className '= $CLASSNAME(actualObject)) { Set returnValue = 0 Set ^||differences(expectedObject,actualObject) = "not same class" } If (returnValue) { // Get the definition to browse properties Set classDef = ##class(%Library.ClassDefinition).%OpenId(className) Set propertiesDef = classDef.Properties // Check the value for each property For i = 1:1:propertiesDef.Count() { Set propertyName = propertiesDef.GetAt(i).Name Set propertyValueExpected = $PROPERTY(expectedObject,propertyName) Set propertyValueActual=$PROPERTY(actualObject,propertyName) // if different, supply the variable difference with the name of property + value If $ISOBJECT(propertyValueExpected){ If propertyValueExpected.%Extends("%Collection.Super"){ For ii=1:1:propertyValueExpected.Count(){ Set tSC= ..CompareObjects(propertyValueExpected.GetAt(ii),propertyValueActual.GetAt(ii)) } } Else{ Set tSC= ..CompareObjects(propertyValueExpected,propertyValueActual) } } Else{ If ((propertyValueExpected '= "") && (propertyValueExpected '= propertyValueActual)) { Set ^||differences(expectedObject,propertyName)=propertyValueExpected _ " != " _ propertyValueActual } } } } }Catch e{ Set status=e.AsStatus() } Quit status } ClassMethod AssertObjectEquals(expectedObject As %RegisteredObject, actualObject As %RegisteredObject, Output msg) As %Status { Set status=$$$OK Set status=..CompareObjects(expectedObject,actualObject) If $DATA(^||differences){ Set key=$ORDER(^||differences("")) Set key2=$ORDER(^||differences(key,"")) Set msg="" While key'=""{ While key2'=""{ Set msg = msg_"; "_key2_": "_^||differences(key,key2) Set key2=$ORDER(^||differences(key,key2)) } Set key=$ORDER(^||differences(key)) Set:(key'="") key2=$ORDER(^||differences(key,"")) } If $LENGTH(msg){ Quit $$$ERROR(1,"Objects not equal") } } Quit status }
Please give me your opinion if there's anything to improve
Thanks @Corentin Blondeau and @Amaury Hashemi for sharing code/ideas and tools.
💡 This question is considered a Key Question. More details here.