Adding Console Output to Load Tests running Unit Tests
VSTS allows you to use the Console.WriteLine within unit tests, but the output is only valid when doing a single pass of the unit test. When running the unit test in a load test, there is no built in mechanism for outputting comments or data. The following routines will allow you to track custom messages. It requires you to make some modifications to the LoadTest database and then add the appropriate code to your unit tests.
Modifying the LoadTest Database
Use the following SQL code to generate the table used to store your information:
USE [LoadTest]
GO
/****** Object: Table [dbo].[LoadTestConsoleOutput] Script Date: 01/09/2008 08:24:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[LoadTestConsoleOutput](
[LoadTestRunId] [int] NULL,
[AgentId] [int] NULL,
[UserId] [int] NULL,
[IterationId] [int] NULL,
[ScenarioName] [nchar](64) NULL,
[MessageText] [text] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Next, locate the stored procedures that are already built into the LoadTest database. In the Stored Procedure dbo.Prc_DeleteLoadTestRun, add the following line just above the END keyword:
DELETE FROM LoadTestConsoleOutput WHERE LoadTestRunId = @LoadTestRunId
This line will allow VSTS to automatically delete any messages you added for a given test pass whenever you delete the test pass in the GUI.
Building the Code to Do the work
The following two methods and associated properties do the brunt of the work. Add these to your test class:
public int userId;
public int LoadTestRunId;
public int iteration;
public int agentId;
public string scenarioName;
public bool bWriteConsoleOutput;
public SqlConnection _Outputconnection;
public void SetupConsoleOutput()
{
if (this.TestContext.Properties.Contains("$LoadTestUserContext"))
{
// This case occurs when the unit test is run inside a load test
// Get the LoadTestUserContext
SqlDataReader reader;
SqlCommand cmd;
LoadTestUserContext loadTestUserContext = this.TestContext.Properties["$LoadTestUserContext"] as LoadTestUserContext;
cmd = new SqlCommand();
cmd.Connection = _Outputconnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT MAX(LoadTestRunId) AS RunId FROM LoadTestRun";
reader = cmd.ExecuteReader();
reader.Read();
LoadTestRunId = Convert.ToInt32(reader["RunId"]);
reader.Dispose();
// Get MyUserData object from the LoadTestUserContext object, or create and add it if not already there
userId = loadTestUserContext.UserId;
iteration = loadTestUserContext.CompletedTestCount;
agentId = Convert.ToInt32(this.TestContext.Properties["AgentId"]);
scenarioName = loadTestUserContext.ScenarioName;
bWriteConsoleOutput = false;
}
else
{
userId = 0;
iteration = 0;
agentId = 0;
scenarioName = "UnitTest";
bWriteConsoleOutput = true;
}
}
public void WriteConsoleOutput(string sMessage)
{
if (bWriteConsoleOutput)
Console.WriteLine(sMessage);
else
{
//setup the database connection to store the output
SqlCommand cmd;
cmd = new SqlCommand();
cmd.Connection = _Outputconnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO LoadTestConsoleOutput VALUES ('" +
Convert.ToString(LoadTestRunId) + "', '" +
Convert.ToString(agentId) + "', '" +
Convert.ToString(userId) + "', '" +
Convert.ToString(iteration) + "', '" +
scenarioName + "', '" +
sMessage + "')";
cmd.ExecuteNonQuery();
cmd.Dispose();
}
}
Next, add the following using declaration at the top of your code:
using Microsoft.VisualStudio.TestTools.LoadTesting;
Now you can initialize and use the code. Do this within the actual test method:
[TestMethod()]
public void DepositApprovals()
{
...
_Outputconnection = new SqlConnection(@"Data Source=collection;
Integrated Security=SSPI;Initial Catalog=LoadTest;
Application Name=DepositApprovals");
_Outputconnection.Open();
SetupConsoleOutput();
...
...
//Do some work. Call the below statement each time
//You want to add a comment
WriteConsoleOutput("This is a message for Blah");
...
...
_Outputconnection.Dispose();
}
You need to open and close the connection for each test iteration. The code will automatically detect if you are running a unit test by itself or as a load test. If this is a single unit test, the routine uses Console.WriteLine, but if you are running a load test, the routine will use the LoadTest database.
Thanks to Geoff Gray of Microsoft Testing Services Labs (https://www.microsoft.com/services/microsoftservices/default.mspx) for providing input to this article.
Comments
- Anonymous
April 03, 2008
I've posted an article on "Adding Console Output to Load Tests running Unit Tests": http://blogs.msdn.com/billbar/pages/adding-console-output-to-load-tests-running-unit-tests.aspx - Anonymous
February 21, 2010
I really liked your post . It is an added knowledge. Good work, Keep it up - Anonymous
April 21, 2010
There are some very great sources here and thank you for being so kind to post them here. .