← Back to team overview

nunit-core team mailing list archive

[Bug 787106] [NEW] EqualConstraint provides inadequate failure information for IEnumerables

 

Public bug reported:

When an EqualConstraint compares two IEnumerables and one of them is
_not_ a collection, the failure reported inadequately. This was called
to our attention by the following post on nunit-discuss by Gishu Pillai
but applies more generally than the post indicates.

Given any CustomType containing a Data (int) property and Name
(string) property. Equals and ToString overridden

           var someArray = new[] { "A001", "B002", "C003" };
           CollectionAssert.AreEqual( new[] { "x", "Y", "Z" },
someArray);

 Expected and actual are both <System.String[3]>
 Values differ at index [0]
 Expected string length 1 but was 4. Strings differ at index 0.
 Expected: "x"
 But was:  "A001"

-------------------------------------------------------------------------------------
Which is perfect. But now if any of the arguments to AreEqual are a
result of a Linq query, the failure message drops in readability
           var someArray = new[] { "A001", "B002", "C003" };
           CollectionAssert.AreEqual( new[] { "x", "Y", "Z" },

someArray.Select(item => item));

 Expected: < "x", "Y", "Z" >
 But was:  <System.Linq.Enumerable
+WhereSelectArrayIterator`2[System.String,System.String]>

----------------------------------------------------------------------------------------
Even worse
              CollectionAssert.AreEqual( new []{'A', 'B',
'C'}.Select(item=>item.ToString()),
                                       new [] {"Apple", "Ball",
"Dog"}.Select(item=> item.Substring(0,1)));

 Expected: <System.Linq.Enumerable
+WhereSelectArrayIterator`2[System.Char,System.String]>
 But was:  <System.Linq.Enumerable
+WhereSelectArrayIterator`2[System.String,System.String]>

if you change the 'C' to 'D' - the test passes as expected.

I've been trying to write something similar for my custom-adaptation
of Hamcrest and I think I see what is happening (an are-types-
compatible check failing for IEnumerable<T> and IEnumerable<K>) .
However if CollectionAssert.AreEqual internally uses a ToList() or
ToArray() before processing its arguments, I think the error messages
would be much more helpful.

** Affects: nunitv2
     Importance: High
     Assignee: Charlie Poole (charlie.poole)
         Status: Fix Committed

** Changed in: nunitv2
       Status: New => Triaged

** Changed in: nunitv2
   Importance: Undecided => High

** Changed in: nunitv2
     Assignee: (unassigned) => Charlie Poole (charlie.poole)

** Changed in: nunitv2
    Milestone: None => 2.6.0b1

-- 
You received this bug notification because you are a member of NUnit
Developers, which is subscribed to NUnit V2.
https://bugs.launchpad.net/bugs/787106

Title:
  EqualConstraint provides inadequate failure information for
  IEnumerables

Status in NUnit V2 Test Framework:
  Fix Committed

Bug description:
  When an EqualConstraint compares two IEnumerables and one of them is
  _not_ a collection, the failure reported inadequately. This was called
  to our attention by the following post on nunit-discuss by Gishu
  Pillai but applies more generally than the post indicates.

  Given any CustomType containing a Data (int) property and Name
  (string) property. Equals and ToString overridden

             var someArray = new[] { "A001", "B002", "C003" };
             CollectionAssert.AreEqual( new[] { "x", "Y", "Z" },
  someArray);

   Expected and actual are both <System.String[3]>
   Values differ at index [0]
   Expected string length 1 but was 4. Strings differ at index 0.
   Expected: "x"
   But was:  "A001"

  -------------------------------------------------------------------------------------
  Which is perfect. But now if any of the arguments to AreEqual are a
  result of a Linq query, the failure message drops in readability
             var someArray = new[] { "A001", "B002", "C003" };
             CollectionAssert.AreEqual( new[] { "x", "Y", "Z" },

  someArray.Select(item => item));

   Expected: < "x", "Y", "Z" >
   But was:  <System.Linq.Enumerable
  +WhereSelectArrayIterator`2[System.String,System.String]>

  ----------------------------------------------------------------------------------------
  Even worse
                CollectionAssert.AreEqual( new []{'A', 'B',
  'C'}.Select(item=>item.ToString()),
                                         new [] {"Apple", "Ball",
  "Dog"}.Select(item=> item.Substring(0,1)));

   Expected: <System.Linq.Enumerable
  +WhereSelectArrayIterator`2[System.Char,System.String]>
   But was:  <System.Linq.Enumerable
  +WhereSelectArrayIterator`2[System.String,System.String]>

  if you change the 'C' to 'D' - the test passes as expected.

  I've been trying to write something similar for my custom-adaptation
  of Hamcrest and I think I see what is happening (an are-types-
  compatible check failing for IEnumerable<T> and IEnumerable<K>) .
  However if CollectionAssert.AreEqual internally uses a ToList() or
  ToArray() before processing its arguments, I think the error messages
  would be much more helpful.


Follow ups

References