共用方式為


Useful C# method for unit testing

I’m unit testing a UI that needs to show some lists in various sorted orders, and I wanted to ensure that my tests would cover that. I found this method to come in handy:

 

    1:  public static bool IsOrderedBy<T>(this IEnumerable<T> coll,
    2:                     Func<T, IComparable> val)
    3:  {
    4:      if (coll == null || coll.Count() == 0)
    5:          return true;
    6:   
    7:      var curVal = val(coll.ElementAt(0));
    8:      for (int i = 0; i < coll.Count(); i++)
    9:      {
   10:          if (val(coll.ElementAt(i)).CompareTo(curVal) < 0)
   11:              return false;
   12:   
   13:          curVal = val(coll.ElementAt(i));
   14:      }
   15:   
   16:      return true;
   17:  }

 

Here’s how to determine if a simple array is in order:

 var arr = new int[] { 1, 2, 3, 5 };
bool ordered = arr.IsOrderedBy(i => i);

 

Here’s how you’d call it on a more complex object:

 var arr = Enumerable.Range(1, 10)
    .Select(e => new
    {
        Name = "bob",
        Salary = 10 * e
    });
bool ordered = arr.IsOrderedBy(i => i.Salary);

 

 

Avi

Comments

  • Anonymous
    July 16, 2009
    The Count() extension method will iterate over the collection to find the count so you can cache it. The same is true for ElementAt. I think IsOrderedBy is not very good as extension method on IEnumerable<T> (in terms of performance). It's used for your unit test it's not production code but still you should be aware of this. Also no need to compare the first element against itself, and a sequence with only one element is sorted :)When you consider this here's what I'm suggesting
        public static bool IsOrderedBy&lt;T&gt;(this IEnumerable&lt;T&gt; sequence, Func&lt;T, IComparable&gt; extractor)    {        if (sequence == null)        {            return true;        }        var count = sequence.Count();        if (count &lt;= 1)        {            return true;        }        var i = 0;        var currentValue = extractor(sequence.ElementAt(i++));        while (i &lt; count)        {            var nextValue = extractor(sequence.ElementAt(i++));            if (currentValue.CompareTo(nextValue) &gt; 0)            {                return false;            }        }        return true;    }
  • Anonymous
    July 16, 2009
    This is not the most efficient implementation because of the coll.Count() which causes all the IEnumrable elements to be resolved, for better efficiency call MoveNext() explicitly.
  • Anonymous
    July 16, 2009
    Good call on the perf issues, guys. I was only using this in unit tests for collections of 5-10 elements, so wasn't paying attention to them.