As we get closer to the release of Visual Studio Team System, I'd like to begin sharing some of its less-publicized features. Of course, these aren't really "hidden", but they can be easy to miss if you're new to using the product.
In this post, I'll introduce two of the specialized classes available for unit testing in Visual Studio Team System, CollectionAssert and StringAssert.
A major feature that Team System brings to the developer is the ability to create unit tests from within the development environment, without having to rely on external third-party tools. Unit testing involves creating code which verifies typically low-level behavior in other code. If you're not already familiar with VSTS unit testing, there is a good introductory article on MSDN.
At the center of unit testing in VSTS is the Microsoft.VisualStudio.TestTools.UnitTesting namespace. This can be found in the "Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll" assembly. You'll quickly become familiar with the Assert class and the many features it offers for developing unit tests. Those familiar with NUnit will feel right at home. However, VSTS offers some additional features to help abstract several other common unit testing scenarios.
Using CollectionAssert
The CollectionAssert class, also found in the Microsoft.VisualStudio.TestTools.UnitTesting namespace, features methods which will help you write unit tests that verify behavior of collection types. For example, you might be using collections and wish to verify their contents or perhaps you've written a custom collection class and need to verify it works as expected.
The following methods are exposed by CollectionAssert:
- AllItemsAreInstancesOfType - Verifies all elements are a specific type (e.g. System.String)
- AllItemsAreNotNull - Verifies each element is not null
- AllItemsAreUnique - Ensures no elements are repeated
- AreEqual / AreNotEqual - Verifies two collections are (or are not) exactly equal, having the same number of elements and each element is reference-identical
- AreEquivalent / AreNotEquivalent - Similar to AreEqual, but each element needs only to be value-equivalent, not necessarily referencing the same instance
- Contains / DoesNotContain - Searches a collection for a specific object
- IsSubsetOf / IsNotSubsetOf - Ensures all members of a collection are (or are not) also in another collection
Here's a very simplistic example of using some of these methods, using a fictitious collection class as a target. This evening as I write this I'm in a "beer" mood, so you'll have to pardon the example...
[TestMethod]
public void CollectBeer()
{
BeerCollection beers = new BeerCollection();
beers.Add("Porter");
beers.Add("Barleywine");
beers.Add("Wee Heavy");
beers.Add("Stout");
// beers.Add(12345); // Breaks AllItemsAreInstancesOfType below
// Was everything not null and a string type?
CollectionAssert.AllItemsAreNotNull(beers);
CollectionAssert.AllItemsAreInstancesOfType(
beers, typeof(string));
// Labmics need not apply
CollectionAssert.DoesNotContain(beers, "Lambic");
BeerCollection strings2 = new BeerCollection();
beers2.Add("Porter");
beers2.Add("Stout");
// Verify the collections do have the same members
CollectionAssert.AreNotEquivalent(beers, beers2);
// All members of the second collection
// can be found in the first
CollectionAssert.IsSubsetOf(beers2, beers);
}
Using StringAssert
Another class within the TestTools.UnitTesting namespace, StringAssert, contains methods to make common text-based assertions.
StringAssert exposes the following methods:
- Contains - Searches a string for a substring and fails if not found
- StartsWith / EndsWith - Fails if the string does not begin (or end) with another string
- Matches / DoesNotMatch - Matches a string with a regular expression, failing if no matches (or any matches) are found
These are generally straightforward to use, but Matches and DoesNotMatch do require use of a System.Text.RegularExpressions.Regex instance. Continuing the beer theme in another example...
[TestMethod]
public void StringMeAlong()
{
// Various searching options...
StringAssert.Contains(
"Have a favorite beer? What is it?", "beer");
StringAssert.EndsWith(
"Roomba? No, 'Beerba', a robot to fetch beer", "beer");
StringAssert.StartsWith(
"Beer is not a substitute for milk in cereal", "Beer");
// Ensure this sentence has whitespace
StringAssert.Matches("Dogfish Head make some fantastic brews",
new System.Text.RegularExpressions.Regex(@"\s+"));
// ... and that this one does not
StringAssert.DoesNotMatch("NoWhitespaceFoundHere",
new System.Text.RegularExpressions.Regex(@"\s+"));
}
Conclusion
Integrated unit testing is a major feature offered to developers with Team System and it is important to understand what tools are available for creating effective unit tests. The Assert class contains much of what you'll need, but you'll soon find common cases where you're applying the same logic in your tests. Before VSTS, developers had to create libraries of functions to accomplish these common unit testing tasks. Now, with Team System, Microsoft has integrated some of these common scenarios, allowing you to simply use CollectionAssert and StringAssert, relying on the Framework itself instead of custom code.
Now you can spend your newly-found time... sampling beer? Enjoy!
-Chris