Friday, April 2, 2010

The Zero-Argument Overload of Any

I'm a pretty big fan of Linq. I use it all the time in my C# code. But it's a relatively big library, and I've never studied it exhaustively, so from time to time I come across some neat corner of it I've never seen before. In fact, that happened just the other day. 


I find that I'll frequently write test code that looks like this: 


Assert.AreEqual(0, collection.Count()); 


or the inverse: 


Assert.AreNotEqual(0, collection.Count()); 


I've done it often enough that I have thought I ought to write a pair of extension methods on Assert called IsEmpty and IsNotEmpty. That's probably still a good idea, but it also turns out that the Linq extension method Any (normally used to test if at least one element of an enumeration meets some criteria) also has a zero-overload method that simply returns true if the enumeration has any elements at all. So I could rewrite the above tests as: 


Assert.IsFalse(collection.Any());


and


Assert.IsTrue(collection.Any());


respectively. While having Assert.IsEmpty and Assert.IsNotEmpty extension methods would be better (perhaps your test framework already provides them), this is still a handy little thing to know about. 

7 comments:

  1. "While having Assert.IsEmpty and Assert.IsNotEmpty extension methods would be better"?!?

    "Would be"? Just write them!

    ReplyDelete
  2. Not going to argue with you: I should. But you know how it is: you're coding along, and you have the choice of stopping to do every little thing in the best possible way or continuing with what you've already typed. Even when refactoring is the best choice, I don't always stop to do it. Something I need to get better about, I'm sure.

    ReplyDelete
  3. For anyone using NUnit, I'd suggest look a little further than the Assert class. For example, the CollectionAssert already has IsEmpty and IsNotEmpty and a few other goodies. There's also StringAssert.

    ReplyDelete
  4. http://xunit.codeplex.com/wikipage?title=Comparisons says they all have an Empty/IsEmpty? What test FW are you using. Tried xUnit and/or SubSpec yet?

    ReplyDelete
  5. Just one more point I dont want to go unremarked - while it's extremely unlikely that Craig and the commenters have it in mind... While it doesnt matter in the context of a little test, there's a significant difference between using Any and Count - one doesnt need to walk all the items, i.e., in SQL terms its Exists vs Count. (Which is reflected in the impl of Empty in xunit:- http://xunit.codeplex.com/sourcecontrol/network/Show?projectName=xunit&changeSetId=d947e347c5c3#Main%2fxunit%2fAssert.cs). And (again not saying anyone here desparately needs to but...) order yourself the 2e of the skeet book, it doesnt take long to go from 90 to 100% coverage of C# and the payback is great!

    ReplyDelete
  6. I'm using mstest, which is the only one listed on that page without an IsEmpty. I haven't tried xUnit yet, but I definitely want to. It just made sense to use mstest on this project, since it was for Microsoft. :)

    Thanks for the tip on the book, too!

    ReplyDelete
  7. Of course, as I later realized, the real problem with creating an extension method is that it's impossible: extension methods must be instance methods. I want a static extension method.

    Which is just one more piece of evidence implying - to me - that the idea that every piece of code has to belong to a class is just wrong.

    ReplyDelete