@@ -75,6 +75,48 @@ func ObjectsAreEqual(expected, actual interface{}) bool {
7575	return  bytes .Equal (exp , act )
7676}
7777
78+ // ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two structs are considered equal. 
79+ // If the two objects are not of the same type, or if either of them are not a struct, they are not considered equal. 
80+ // 
81+ // This function does no assertion of any kind. 
82+ func  ObjectsExportedFieldsAreEqual (expected , actual  interface {}) bool  {
83+ 	if  expected  ==  nil  ||  actual  ==  nil  {
84+ 		return  expected  ==  actual 
85+ 	}
86+ 
87+ 	expectedType  :=  reflect .TypeOf (expected )
88+ 	actualType  :=  reflect .TypeOf (actual )
89+ 
90+ 	if  expectedType  !=  actualType  {
91+ 		return  false 
92+ 	}
93+ 
94+ 	if  expectedType .Kind () !=  reflect .Struct  ||  actualType .Kind () !=  reflect .Struct  {
95+ 		return  false 
96+ 	}
97+ 
98+ 	expectedValue  :=  reflect .ValueOf (expected )
99+ 	actualValue  :=  reflect .ValueOf (actual )
100+ 
101+ 	for  i  :=  0 ; i  <  expectedType .NumField (); i ++  {
102+ 		field  :=  expectedType .Field (i )
103+ 		isExported  :=  field .PkgPath  ==  ""  // should use field.IsExported() but it's not available in Go 1.16.5 
104+ 		if  isExported  {
105+ 			var  equal  bool 
106+ 			if  field .Type .Kind () ==  reflect .Struct  {
107+ 				equal  =  ObjectsExportedFieldsAreEqual (expectedValue .Field (i ).Interface (), actualValue .Field (i ).Interface ())
108+ 			} else  {
109+ 				equal  =  ObjectsAreEqualValues (expectedValue .Field (i ).Interface (), actualValue .Field (i ).Interface ())
110+ 			}
111+ 
112+ 			if  ! equal  {
113+ 				return  false 
114+ 			}
115+ 		}
116+ 	}
117+ 	return  true 
118+ }
119+ 
78120// ObjectsAreEqualValues gets whether two objects are equal, or if their 
79121// values are equal. 
80122func  ObjectsAreEqualValues (expected , actual  interface {}) bool  {
@@ -473,6 +515,47 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
473515
474516}
475517
518+ // EqualExportedValues asserts that the types of two objects are equal and their public 
519+ // fields are also equal. This is useful for comparing structs that have private fields 
520+ // that could potentially differ. 
521+ // 
522+ //	 type S struct { 
523+ //		Exported     	int 
524+ //		notExported   	int 
525+ //	 } 
526+ //	 assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true 
527+ //	 assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false 
528+ func  EqualExportedValues (t  TestingT , expected , actual  interface {}, msgAndArgs  ... interface {}) bool  {
529+ 	if  h , ok  :=  t .(tHelper ); ok  {
530+ 		h .Helper ()
531+ 	}
532+ 
533+ 	aType  :=  reflect .TypeOf (expected )
534+ 	bType  :=  reflect .TypeOf (actual )
535+ 
536+ 	if  aType  !=  bType  {
537+ 		return  Fail (t , fmt .Sprintf ("Types expected to match exactly\n \t %v != %v" , aType , bType ), msgAndArgs ... )
538+ 	}
539+ 
540+ 	if  aType .Kind () !=  reflect .Struct  {
541+ 		return  Fail (t , fmt .Sprintf ("Types expected to both be struct \n \t %v != %v" , aType .Kind (), reflect .Struct ), msgAndArgs ... )
542+ 	}
543+ 
544+ 	if  bType .Kind () !=  reflect .Struct  {
545+ 		return  Fail (t , fmt .Sprintf ("Types expected to both be struct \n \t %v != %v" , bType .Kind (), reflect .Struct ), msgAndArgs ... )
546+ 	}
547+ 
548+ 	if  ! ObjectsExportedFieldsAreEqual (expected , actual ) {
549+ 		diff  :=  diff (expected , actual )
550+ 		expected , actual  =  formatUnequalValues (expected , actual )
551+ 		return  Fail (t , fmt .Sprintf ("Not equal (comparing only exported fields): \n " + 
552+ 			"expected: %s\n " + 
553+ 			"actual  : %s%s" , expected , actual , diff ), msgAndArgs ... )
554+ 	}
555+ 
556+ 	return  true 
557+ }
558+ 
476559// Exactly asserts that two objects are equal in value and type. 
477560// 
478561//    assert.Exactly(t, int32(123), int64(123)) 
0 commit comments