Encapsulated unit testing logic I have some C# unit tests which each basically perform the same steps but supply different arguments to the unit under test.

I wanted to encapsulate the logic inside some "helper methods" but found that the method names, while descriptive, were cumbersome. For example, the code inside a test method would look like this contrived example:

var expected = 1;
var set = new [] { 1, 2, 3, 4, 5 };
AssertThatCallToGetSmallestReturnsExpectedValueFromGivenSet(expected, set);


I simplified the method names and took up a convention of using C#'s named arguments feature:

AssertThatCallToGetSmallest(
    returnsValue: 1, 
    fromSet: new [] { 1, 2, 3, 4, 5 }
);


The latter approach seems cleaner and more readable to me. I've been working with objective-c for a few months now so invoking methods in this manner has become less of an issue for me aesthetically. The other advantage is that this convention scales better with an increase in the number of parameters (if that should ever really be of value).

One thing I'm particularly concerned with is the lack of enforced readability because named arguments are optional. There is the potential for programmers to later come along and "misuse" the helper methods I've created by failing to specify the parameter names:

AssertThatCallToGetSmallest(1, new [] { 1, 2, 3, 4, 5 }); // what does this even mean?


So, which way is "better"?

I'm using the Visual Studio Unit Testing Framework with MSTest.
The most canonical way of accomplishing what you want is to use the testing framework's functionality for writing data-driven tests, rather than writing a common helper method and then a number of separate tests which pass arguments into it.

Different frameworks do this differently, so I will focus on MSTest first, as that is the framework you use.

In MSTest, there is a DataSource attribute you can supply, which defines how the framework can locate your test data.  Additionally, you supply a TestContext property of type TestContext.

When the tests execute, TestContext will be populated with the data for a single test case, and you can access it by using named indexing into the TestContext.DataRow property.

(Note: I haven't done MSTest in some time, so feel free chime in if there's a better way nowadays)

Example:
(Embedded resource: foo.xml)

&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Tests&gt;
   &lt;Test&gt;
      &lt;a&gt;1&lt;/a&gt;
      &lt;b&gt;2&lt;/b&gt;
      &lt;result&gt;3&lt;result&gt;
   &lt;/Test&gt;
   &lt;Test&gt;
      &lt;a&gt;2&lt;/a&gt;
      &lt;b&gt;2&lt;/b&gt;
      &lt;result&gt;4&lt;result&gt;
   &lt;/Test&gt;
&lt;/Tests&gt;


(test file)

  public TestContext TestContext { get; set; }

  [TestMethod]
  [DeploymentItem ("foo.xml")]
  [DataSource ("Microsoft.VisualStudio.TestTools.DataSource.XML",
               "|DataDirectory|\\foo.xml",
               "Test",
               DataAccessMethod.Sequential)]
  public void TestAdd ()
  {
     var first = (int) TestContext.DataRow ["a"];
     var second = (int) TestContext.DataRow ["b"];
     var expected = (int) TestContext.DataRow ["result"];
     var result = testObject.Add(first,second);
     Assert.AreEqual(expected, result);
  }


Adding more test cases is just a matter of adding  elements with new data and re-building/re-running.

The How-To MSDN page can be found here, and some examples of DataSource configuration strings can be found here.

Just to give you a taste of this in other frameworks:

NUnit TestCase

  [TestCase(1,2,3)]
  [TestCase(2,2,4)]
  public void TestAdd(int first, int second, int expected)
  {
     var result = testObject.Add(first, second);
     Assert.That(result, Is.EqualTo(expected));
  }


NUnit TestCaseSource

  public static IEnumerable&lt;TestCaseData&gt; TestData
  {
     yield return new TestCaseData(1, 2, 3);
     yield return new TestCaseData(2, 2, 4);
  }

  [TestCaseSource("TestData")]
  public void TestAdd(int first, int second, int expected)
  {
     var result = testObject.Add(first, second);
     Assert.That(result, Is.EqualTo(expected));
  }


MbUnit Row

  [RowTest]
  [Row(1,2,3)]
  [Row(2,2,4)]
  public void TestAdd(int first, int second, int expected)
  {
     var result = testObject.Add(first, second);
     Assert.AreEqual(result, expected);
  }