Unit Test Transactions in Visual Studio Load Tests
Visual Studio Ultimate provides extremely robust performance and load testing capabilities if you have the license for it. One of my favorite capabilities is the ability to use existing unit tests as load tests. This is a very nice way to leverage existing code to provide a fairly robust load test suite.
Unfortunately, load test results from the converted unit tests are extremely course since they report on unit test execution time and can’t hook into underlying HTTP calls. However, the TestContext.BeginTimer
method allows the load test runner to record more granular transactions in converted unit tests.
There is a fairly large gotcha in that the BeginTimer
method will throw an exception if called outside a load test. However, the test execution context is readily available in the unit test’s TestContext
property. The detection code also presents a nice opportunity to wrap the transaction logging code in an IDisposable
interface which provides a nice, clean API for the functionality.
The following example wraps this up to show unit test code that produces granular transaction results when executed as a load test.
Unit Test
[TestMethod]
public void TestFooBar()
{
var fooBar = new FooBar();
using (this.LogTransaction("foo"))
{
fooBar.foo();
}
using (this.LogTransaction("bar"))
{
var barResults = fooBar.bar();
Assert.IsNotNull(barResults, "barResults should not be null");
}
}
Transaction Logging Helper
protected ITestTransactionTimer LogTransaction(string transactionName)
{
if ((null == this.TestContext) || !this.TestContext.Properties.Contains("$LoadTestUserContext"))
{
return new NoOpTestTransactionTimer();
}
return new TestTransactionTimer(this.TestContext, transactionName);
}
Transaction Timer Interface and Implementations
public interface ITestTransactionTimer : IDisposable { }
public class TestTransactionTimer : ITestTransactionTimer
{
public TestContext TestContext { get; private set; }
public string TransactionName { get; private set; }
public TestTransactionTimer(TestContext testContext, string transactionName)
{
this.TestContext = testContext;
this.TransactionName = transactionName;
this.TestContext.BeginTimer(this.TransactionName);
}
public void Dispose()
{
this.TestContext.EndTimer(this.TransactionName);
}
}
public class NoOpTestTransactionTimer : ITestTransactionTimer
{
public void Dispose() { }
}
comments powered by Disqus