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 classSet className = $CLASSNAME(object)
If (className '= $CLASSNAME(objectToCompare)) {
Set returnValue = 0Set difference = "not same class"
}
If (returnValue) {
// Get the definition to browse propertiesSet classDef = ##class(%Library.ClassDefinition).%OpenId(className)
Set propertiesDef = classDef.Properties
// Check the value for each propertySet 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 + valueIf ((propertyValue '= "") && (propertyValue '= $PROPERTY(objectToCompare,propertyName)))
{
Set difference = difference _ "; " _ propertyName _ " = " _ propertyValue
}
}
}
if difference = ""
{Set msg = "equal"}
else {
Set msg = difference
}
Return$$$OK
}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 !
Comments
Here's an example.
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= $$$OKSet returnValue = 1Try{
// check if same class Set className = $CLASSNAME(expectedObject)
If (className '= $CLASSNAME(actualObject)) {
Set returnValue = 0Set ^||differences(expectedObject,actualObject) = "not same class"
}
If (returnValue) {
// Get the definition to browse propertiesSet classDef = ##class(%Library.ClassDefinition).%OpenId(className)
Set propertiesDef = classDef.Properties
// Check the value for each propertyFor 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 + valueIf$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=$$$OKSet 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.