VSTS Tutorial
VSTS Tutorial
VSTS Rangers
This content was originally created by Geoff Gray for internal Microsoft use and then adopted
and expanded as a Visual Studio Team System (“VSTS”) Rangers project. “Our mission is to
accelerate the adoption of Team System by delivering out of band solutions for missing features
or guidance. We work closely with members of Microsoft Services to make sure that our
solutions address real world blockers.” -- Bijan Javidi, VSTS Rangers Lead
The document contains two Tables of Contents (high level overview, and list of every topic covered) as
well as an index. The current plan is to update the document on a regular basis as new information is
found.
The information contained in this document represents the current view of Microsoft Corporation
on the issues discussed as of the date of publication. Because Microsoft must respond to changing
market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and
Microsoft cannot guarantee the accuracy of any information presented after the date of
publication.
This document is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS,
IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.
Microsoft grants you a license to this document under the terms of the Creative Commons
Attribution 3.0 License. All other rights are reserved.
Microsoft, Active Directory, Excel, Internet Explorer, SQL Server, Visual Studio, and Windows are
trademarks of the Microsoft group of companies.
List of Chapters
SETUP CONSIDERATIONS 9
TEST CUSTOMIZATION 76
INDEX 82
Data _________________________________________________________________________________________ 9
How to set up a SQL Results Database ___________________________________________________________ 9
How to Change the Location Where Agents Store Run Files __________________________________________ 9
Troubleshooting ______________________________________________________________________________ 10
How to enable logging for test recording ________________________________________________________ 10
How to enable Verbose Logging on an agent for troubleshooting _____________________________________ 10
User Account requirements and how to troubleshoot authentication _________________________________ 11
Data ________________________________________________________________________________________ 19
CSV files created in VSTS or saved as Unicode will not work as data sources ____________________________ 19
Custom data binding in web tests ______________________________________________________________ 19
Incorrect SQL field type can cause errors in web tests ______________________________________________ 19
Adding random users to web tests _____________________________________________________________ 20
How to add a datasource value to a context parameter ____________________________________________ 20
Validation ___________________________________________________________________________________ 21
Troubleshooting ______________________________________________________________________________ 25
How to create Recorder Log Files (for troubleshooting Recording Issues) ______________________________ 25
How to configure Web Tests so Fiddler can capture playback info ____________________________________ 25
Miscellaneous ________________________________________________________________________________ 55
Coded web tests and web test plug-ins should not block threads _____________________________________ 55
Check Your Validation Level in the Load Test Run Settings __________________________________________ 55
Add an Analysis Comment ____________________________________________________________________ 55
Programatically Accessing the number of users in Load Tests ________________________________________ 55
INDEX _____________________________________________________________________________________________ 82
Open QTAgentService.exe.config
Add "<add key="WorkingDirectory" value="<location to use>"/>" under the <appSettings> node.
Create the <location to use> folder.
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\EnterpriseTools
\QualityTools\WebLoadTest]
"RecorderLogFolder"="C:\\recordlogs"
1. Go to c:\Program files\Microsoft Visual Studio 2008 Team Test Load Agent\LoadTest on the agent
machine.
2. Edit the QTAgentServiceUI.exe.config file
a. change the EqtTraceLevel to 4
<switches>
<add name="EqtTraceLevel" value="4" />
b. Change the CreateTraceListener value to yes
<appSettings>
<add key="CreateTraceListener" value="yes"/>
The above settings also apply to the QTAgent.exe.config, QTController.exe.config and the
QTColtrollerService.exe.config files.
Workgroup authentication
In a Microsoft® Windows® domain environment, there is a central authority to validate credentials. In a
workgroup environment, there is no such central authority. Still, we should be able to have computers in
a workgroup talk to each other and authenticate users. To enable this, local accounts have a special
characteristic that allows the local security authority on the computer to authenticate a "principal" in a
special way.
If you have two computers and a principal "UserXYZ" on both machines the security identifiers are
different for MACHINE1\UserXYZ and MACHINE2\UserXYZ and for all practical purposes they are two
completely different "Principals". However if the passwords are the same for them on each of these
computers, the local security authority treats them as the same principal.
So when MACHINE1\UserXYZ tries to authenticate to MACHINE2\UserXYZ, and if the passwords are the
same, then on MACHINE2, the UserXYZ is authenticated successfully and
is treated as MACHINE2\UserXYZ. Note the last sentence. The user MACHINE1\UserXYZ
is authenticated as MACHINE2\UserXYZ if the passwords are the same.
http://blogs.msdn.com/dgorti/archive/2007/10/02/vstt-controller-and-agent-setup.aspx
Controller-Agent Communications
Controller-Agent Communications
http://blogs.msdn.com/billbar/archive/2007/07/31/configuring-a-non-default-port-number-for-the-vs-
team-test-controller.aspx
Next, open VSTS and open up the Test Rig Management dialog (Test -> Administer Test Controllers) and
add each agent back to the list.
Summary
This white paper described the new web testing features implemented in Microsoft Visual Studio® 2008.
It describes how the recorder works, registry settings that will let you control what does and does not
get recorded, and problems you may encounter. Finally, it introduces new debugging techniques that
will enable you to find and fix your tests.
More information
http://blogs.msdn.com/edglas/archive/2007/12/02/web-test-authoring-and-debugging-techniques-for-
vs-2008.aspx
If you try to connect the two web tests before generating any code, your test will fail with the following
error:
There is no declarative Web test with the name 'DrillDown_Coded' included in this Web
test; the string argument to IncludeWebTest must match the name specified in an
IncludeDeclarativeWebTest attribute.
How to use methods other than GET and POST in a web test
Summary
FormPostHttpBody and StringHttpBody are the two built-in classes for generating HTTP request bodies.
If you need to generate requests containing something other than form parameters and strings then you
can implement an IHttpBody class.
More information
http://blogs.msdn.com/joshch/archive/2005/08/24/455726.aspx
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\EnterpriseTools\QualityTools\Web
LoadTest
Add a string value under this key with the name "RequestHeadersToRecord” and
value="SOAPAction;Pragma;x-microsoftajax;Content-Type; Referrer"
If you do this and re-record your Web test, the Referrer header should be included in the request like
this:
if (<condition>)
{
this.Stop();
yield break;
}
Summary
One of the new Web Test features in Visual Studio 2008 is the ability to filter dependent requests. If you
have a request in your web test that fetches a lot of content such as images, JavaScript files or CSS files,
it’s possible to programmatically determine which requests are allowed to execute during the course of
the web test, and which aren't.
More information
http://blogs.msdn.com/densto/pages/new-in-orcas-filtering-dependent-requests.aspx
If you wish to use the machine’s IE proxy settings then you can set the Proxy property to “default”
(without the quotes). In this case you should turn off Automatic Proxy Detection on each agent.
Automatic Proxy detection is very slow and can greatly impact the amount of load you can drive on an
agent.
The following link describes how to use X509 certificate collections to make a SOAP request in .NET;
code for using them in a web test will be similar.
More information
http://msdn.microsoft.com/en-us/library/ms819963.aspx
However, with VSTS 2008 if you want to completely disable caching of all dependent requests and
always fetch them, you can so with the following WebTestPlugin:
CSV files created in VSTS or saved as Unicode will not work as data sources
If you create a CSV file in VSTS, it saves the file with a 2 byte prefix indicating encoding type, which is
hidden. When you select the file as a data source, the first column will be prefixed with two unusual
characters. The problem is the two bytes on the front that cannot be seen unless the file is viewed in
hex format. The solution is to open the file in notepad and save as ANSI.
Also, if a data file is created in Windows® Notepad or Microsoft® Excel® and saved as Unicode, it looks
good in Notepad or VSTS, but cannot be read in web tests. The solution is to open the file in notepad
and save as ANSI.
Summary
It is possible to create a custom data binding to bind to something other than a table, such as a select
statement. This blog post describes one possible method – creating one class which will manage the
data and creating a web test plug-in to add the data into the web test context.
More information
http://blogs.msdn.com/slumley/pages/custom-data-binding-in-web-tests.aspx
this.Context.Add(“ContextNameToUse”,this.Datasource1[“ColumnToUse”]);
All of the rules in this release on CodePlex relate to the inner text of a tag. For example, for a select tag
(list box and combo box), the option text is stored in inner text rather than an attribute:
<select name="myselect1">
<option>Milk </option>
<option>Coffee</option>
<option selected="selected">Tea</option>
</select>
In order to extract the value of the list box, we need to parse out the inner text of the selected option.
TextArea is another tag that does this, but there are also a lot of other examples in HTML where you
might want to extract or validate inner text. The new project has these new rules as well as a parser for
inner text and select tag:
1. ExtractionRuleInnerText
2. ExtractionRuleSelectTag
3. ValidationRuleInnerText
4. ValidationRuleSelectTag
Download location
http://codeplex.com
validationRule.Validate(source, validationEventArgs);
Web tests recorded in Fiddler may throw errors when playing back in VSTT
When Fiddler converts a trace file into a web test for VSTT, it adds every HTTP header that comes across
the wire to your web test code. However, there are certain headers that should not be added by the
code, since they are automatically added by the System.Net.HttpWebRequest classes. Since these are
already in the core functionality, VSTT will throw a failure like:
To work around this error, simply remove the headers that should not be present in these requests. For
more information, you can also visit Sean Lumley’s blog post about Fiddler plugins at:
http://blogs.msdn.com/slumley/pages/writing-fiddler-web-test-plugins.aspx
WORKAROUND: Go through the test after recording is complete and adjust the think times manually.
Here’s what I’ve discovered. There is an option in VSTT that allows you to keep VSTestHost alive after a
test run completes: go to “Tools”, “Options”, “Test Tools”, “Test Execution” and see the check box “Keep
test execution engine running between test runs”. This is on by default, and I’m guessing it is on for
you. When you run just a unit test in a test run, this option works and VSTestHost does not get killed
when the test run completes, so neither does its child processes. However, when you run a Web test,
this option seems to be ignored and VSTestHost is killed by a call to Process.Kill() which I believe does kill
the child processes of VSTestHost as well (if you uncheck this option, you’ll see that running the unit test
has the same behavior). I’m not sure why VSTestHost goes away even when this option is set when a
Web test is run – this may have been intentional. Here’s a workaround that seems to work instead:
create a unit test that sleeps for 10 seconds (or whatever time is needed)
create an ordered test that includes your coded Web test first then the unit test that sleeps
run the ordered test rather than the coded Web test
NOTE: an example of this scenario is firing off a batch file that starts a NETCAP.EXE window to gather
trace data during the test run. This NETCAP process must run asynchronously so it will not block the web
test. It must also complete by itself or the resultant trace file will not get written.
“Request failed: 100-Continue may not be set using this property” Error
If you generate a web test using Fiddler and run the test, you may receive errors like “…may not be set
using this property”.
The Fiddler plug-in that generates the .webtest adds all of the headers that Fiddler records even though
some of these will generate errors when you run the Web test. The errors occur because the
System.Net.HttpWebRequest (which is used by the Web test to send the request) disallows the caller
from setting header that it will automatically add. The VSTS Web test recorder does filter these out, but
the Fiddler recorder does not. To fix this you could either manually delete the headers in the .webtest
or the generated code or you could write a Fiddler Web test plug-in to remove the header; see Sean’s
blog post on how to write these plug-ins at http://blogs.msdn.com/slumley/pages/writing-fiddler-web-
test-plugins.
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\EnterpriseTools
\QualityTools\WebLoadTest]
"CreateLog"=dword:00000001
"RecorderLogFolder"="c:\\RecorderLogs\"
This will result in a log file for each recording session.
this.Proxy = "http://localhost:8888";
WebProxy webProxy = (WebProxy)this.WebProxy;
webProxy.BypassProxyOnLocal = false;
m_loadTest.LoadTestStarting
m_loadTest.LoadTestFinished
m_loadTest.LoadTestAborted
m_loadTest.LoadTestWarmupComplete
m_loadTest.TestStarting
m_loadTest.TestFinished
m_loadTest.TestSelected
m_loadTest.ThresholdExceeded
m_loadTest.Heartbeat
this.PreWebTest
this.PostWebTest
this.PreTransaction (2008 SP1 and later)
this.PostTransaction (2008 SP1 and later)
this.PrePage (2008 SP1 and later)
this.PostPage (2008 SP1 and later)
this.PreRequest
this.PostRequest
Validation Rule:
this.ValidateResponse
Extraction Rule:
request1.ExtractValues
This behavior has been changed in SP1, HOWEVER, there are a couple of gotchas to be aware of:
The compressed size will only be reported in VSTS if the response in NOT using “chunked
encoding”
The test results window will not indicate whether the reported size is the compressed or the
uncompressed size.
VSTS has a receive buffer that defaults to 1,500,000 bytes and it throws away anything over
that. The number reported is what is saved in the buffer, not the number of bytes received.
You can increase the size of this buffer by altering the ResponseBodyCaptureLimit at the start of
your test. This needs to be done in code and cannot be modified in a declarative test.
Client Code does not execute because Web Tests Work at the HTTP Layer
The following blog outlines where and how web tests work. This is important to understand if you are
wondering why client side code is not tested.
http://blogs.msdn.com/slumley/pages/web-tests-work-at-the-http-layer.aspx
We added optimizations to control the amount data that is stored in the TRX for request/response
bodies by only storing one copy of a unique response bodies (in mutli-iteration runs you may end up
with multiple identical responses). Also, the request and response bodies are compressed to
dramatically reduce the amount of space they require in the TRX. However, if I recall correctly, the XML
serializer may be writing four bytes for each one byte of response (nnn, nnn, nnn where nnn is a decimal
value for each byte in the compressed result).
The request/response headers and the test context snapshots are not compressed and duplicates are
not eliminated, so they have the potential to become bloated.
The web test engine does not write responses to disk, so you don’t need to specify a location for the file.
It does read the entire response back to the client, but only stores the first 1.5M of the response in
memory
We call the number at the end as the bucket number, e.g. $HIDDEN0 is bucket 0.
The easiest example to explain is a frames page with two frames. Each frame will have an independent
bucket, and requests can be interleaved across the frames. Other examples that require multiple
buckets are popup windows and certain AJAX calls (since web tests support correlation of viewstate in
ASP.NET AJAX responses).
The algorithm to determine that a given request matches a particular bucket uses the heuristic that the
hidden fields parsed out of the response will match form post fields on a subsequent request.
Then on a subsequent post we see Field1 and Field2 posted, then this request and response match and a
hidden field bucket will be created for them. The first available bucket number is assigned to the hidden
field bucket.
Once a bucket is “consumed” by a subsequent request via binding, that bucket is made available again.
So if the test has a single frame, it will always reuse bucket 0:
Page 1
o Extract bucket 0
Page 2
o Bind bucket 0 params
Page 3
o Extract bucket 0
Page 4
o Bind bucket 0 params
If a test has 2 frames that interleave requests, it will use two buckets:
Frame 1, Page 1
o Extract bucket 0
Frame 2, Page 1
o Extract bucket 1
Frame 2, Page 2
Or if a test uses a popup window, or Viewstate, you would see a similar pattern as the frames page
where multiple buckets are used to keep the window state.
Some hidden fields values are modified in java script. I believe EVENT_ARGUMENT is example of this. In
that case, it won’t work to simply extract the value from the hidden field in the response and play it
back. If the recorder detects this is the case, it put the actual value that was posted back as the form
post parameter value rather than binding it to the hidden field.
I can’t think of any case where a single page would have >1 hidden field extraction rule applied, that
sounds like a bug to me. The case of multiple forms on a given page is interesting, but there should be
just one down-stream post of form fields, resulting in one application of the hidden field extraction rule.
We’re trying to drive as many of these out of the product as we can, if you or anyone else hits a case
where this happens, send us the recording log, .webtest, and playback trx. Of course it’s helpful if we
can hit the website, but given these files should be enough for us to determine the problem.
//************************************************************************************
*************
// WebTestDependentFilter.cs
// Owner: Ed Glas
//
// This web test plugin filters dependents from a particular site.
// For example, if the site you are testing has ads served by another company
// you probably don't want to hit that site as part of a load test.
// This plugin enables you to filter all dependents from a particular site.
//
// Copyright(c) Microsoft Corporation, 2008
//************************************************************************************
*************
using Microsoft.VisualStudio.TestTools.WebTesting;
namespace SampleWebTestRules
{
public class WebTestDependentFilter : WebTestPlugin
{
string m_startsWith;
public string FilterDependentRequestsThatStartWith
{
get { return m_startsWith; }
set { m_startsWith = value; }
}
// Note, you can't modify the collection inside a foreach, hence the
second collection
// requests to remove.
foreach (WebTestRequest r in e.Request.DependentRequests)
{
if (!string.IsNullOrEmpty(FilterDependentRequestsThatStartWith) &&
r.Url.StartsWith(FilterDependentRequestsThatStartWith))
{
depsToRemove.Add(r);
}
}
foreach (WebTestRequest r in depsToRemove)
{
e.Request.DependentRequests.Remove(r);
}
}
}
}
http://blogs.msdn.com/slumley/pages/load-testing-web-services-with-unit-tests.aspx
{{Datasource.Table.Column}}
Here is a sample:
How to Do Things
Define a static member variable of the unit test class, or if you have multiple unit test classes that need
to share the data, create a singleton object that is accessed by all of the unit tests. The only case in
which this would not work is if you have multiple unit test assemblies being used in the same load test
that all need to share the global data and you also need to set the “Run Unit Tests in Application
Domain” load test setting to true. In that case each unit test assembly has its own app domain and its
own copy of the static or singleton object.
CAVEAT: This will not work in a multi-agent test rig. If you have a multi-agent rig and you want truly
global data, you’d either need to create a common Web service or use a database that all of the agents
access.
The first thing to do is create a custom class that does the data initialization (as described in the first
part of this post: http://blogs.msdn.com/slumley/pages/custom-data-binding-in-web-tests.aspx). Next,
instantiate the class inside your unit test as follows:
[TestClass]
public class VSTSClass1
{
private TestContext testContextInstance;
[ClassInitialize]
public static void ClassSetup(TestContext a)
{
string m_ConnectionString = @"Provider=SQLOLEDB.1;Data
Source=dbserver;Integrated Security=SSPI;Initial Catalog=Northwind";
CustomDs.Instance.Initialize(m_ConnectionString);
}
[TestMethod]
public void Test1()
{
Dictionary<string, string> dictionary = customDs.Instance.GetNextRow();
//......Add the rest of your code here.
}
using System.Threading;
using System.Diagnostics;
using System.IO;
.......
[TestMethod]
public void TestMethod1()
{
int x=0;
int iDuration = 10000;
try
{
Process myProcess = new Process();
myProcess = Process.Start("c:\\temp\\conapp2.exe", “arg1”, “arg2”);
Possible DESKTOP HEAP errors when driving command line unit tests
When you run a large number of unit tests that call command line apps, and they are run on a test rig
(this does not happen when running tests locally), you could have several of the tests fail due to running
out of desktop heap. You need to increase the amount of heap that is allocated to a service and
decrease the amount allocated to the interactive user. See the following post for in depth information,
and consider changing the registry as listed below:
http://blogs.msdn.com/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems
OLD SETTING: “Windows SharedSection=1024,3072,512”
NEW SETTING: “Windows SharedSection=1024,1024,2460”
Unit Tests that require the use of App.Config files (App Domain Issue)
When a unit test is run by itself, a separate application domain is created in the test process for each
unit test assembly. There is some overhead associated with marshalling tests and test results across
the application domain boundary, so when running unit tests in a load test, the application domain is
not created by default. This provides some performance boost in terms of the number of tests per
second that the test process can execute before running out of CPU. The only drawback is that if the
unit test depends on an app.config file, this doesn’t work without creating the app domain. In this case,
you can enable the creation of app domain for the unit tests: in the Load Test editor’s Run Setting’s
properties set the property “Run unit tests in application domain” to True.
Adding Console Output to the results store when running Unit tests under load
The following link points to a write-up on how to allow unit tests to write custom output messages to
the Load Test Results Store database from Unit tests while they are running in a load test:
http://blogs.msdn.com/billbar/pages/adding-console-output-to-load-tests-running-unit-tests.aspx
1. ClassInitialize and ClassCleanup: Since ClassInitialize and ClassCleanUp are static, they are only
executed once even though several instances of a test class can be created by MSTest.
ClassInitialize executes in the instance of the test class corresponding to the first test method in
the test class. Similarly, MSTest executes ClassCleanUp in the instance of the test class
corresponding to the last test method in the test class.
2. Execution Interleaving: Since each instance of the test class is instantiated separately on a
different thread, there are no guarantees regarding the order of execution of unit tests in a
single class, or across classes. The execution of tests may be interleaved across classes, and
potentially even assemblies, depending on how you chose to execute your tests. The key thing
here is – all tests could be executed in any order, it is totally undefined.
3. TextContext Instances: TestContexts are different for each test method, with no sharing
between test methods.
[TestClass]
public class VSTSClass1
{
private TestContext testContextInstance;
[ClassInitialize]
public static void ClassSetup(TestContext a)
{
Console.WriteLine("Class Setup");
}
[TestInitialize]
public void TestInit()
{
Console.WriteLine("Test Init");
}
[TestMethod]
public void Test3()
{
Console.WriteLine("Test3");
}
[TestCleanup]
public void TestCleanUp()
{
Console.WriteLine("TestCleanUp");
}
[ClassCleanup]
public static void ClassCleanUp ()
{
Console.WriteLine("ClassCleanUp");
}
}
(This consists of 3 Test Methods, ClassInitialize, ClassCleanup, TestInitialize, TestCleanUp and an explicit
declaration of TestContext)
Test1 [Thread 1]: new TestContext -> ClassInitialize -> TestInitialize -> TestMethod1 ->
TestCleanUp
Test2 [Thread 2]: new TestContext -> TestInitialize -> TestMethod2 -> TestCleanUp
Test3 [Thread 3]: new TestContext -> TestInitialize -> TestMethod2 -> TestCleanUp ->
ClassCleanUp
The output after running all the tests in the class would be:
Class Setup
Test Init
Test1
TestCleanUp
Test Init
Test2
TestCleanUp
Test Init
Test3
TestCleanUp
ClassCleanUp
Any ThinkTime that has a value of zero will remain zero regardless of the distribution settings.
Bill Barnett Blog on various considerations for web tests running under load
The following blog entry describes a number of different features and settings to consider when running
web tests under a load test in VSTT (a link to the blog entry is at the bottom of this topic). The following
topics are covered:
http://blogs.msdn.com/billbar/articles/517081.aspx
When remotely reading performance counters the Performance Logs and Alerts service on the remote
system communicates with the Remote Registry service on the target x64 system. By default the
Remote Registry service that is loaded is the 64-bit version and it looks to the 64-bit registry structure,
causing the x64 system to send back the 64-bit counter information to the remote system, even if the
remote system is a 32-bit OS. Thus we are unable to remote monitor any 32-bit counters on the x64
system. To change this behavior, set the following keys in the registry:
This will load the 32-bit version of the Remote Registry service, which looks to the 32-bit registry
structure, causing the x64 system to send back the 32-bit counter information to the remote system.
Further testing showed that remote administration tools, like Regedit, Computer Management, System
Information, etc., all still work even with the 32-bit version of Remote Registry loaded on the x64
system.
In addition to the registry changes please make sure to follow-up with a reboot of the machine where
you changed the registry and also your load test controller (although it might be good enough just
restarting the controller service).
Finally, the ASP.NET counter category will have the version appended to it. So you need to open
<installdir>\common7\IDE\Templates\LoadTest\CounterSets\ASP.NET.counterset, and
change<CounterCategory Name="ASP.NET"> To <CounterCategory Name="ASP.NET v2.0.50727">
The below is how you can set memory to 512mb. The size of the memory you use will vary based on the
machine, testing and how much memory you have.
Change the values as needed and note that the time is in milliseconds.
By default the load test results will save only 1000 errors of a particular type, but you can change this
setting in the appropriate configuration file (depending on whether this is for local runs or for test rig
runs):
If running with a controller, on the controller machine edit <Program Files>\Microsoft Visual
Studio 9.0 Team Test Load Agent\LoadTest\QTController.exe.config file.
then add a key to the "appSettings" section of the file (add the "appSettings" section if needed) with the
name "LoadTestMaxErrorsPerType" and the desired value.
For example, the following config file sets the maximum errors per type to 5000.
<appSettings>
<add key="LoadTestMaxErrorsPerType" value="5000"/>
</appSettings>
These setting affect the total numbers of errors per each different "error subtype" and not the total
number of errors. For example with the default setting of 1000, you can get 1,000 404 Not Found
errors and 1,000 "Test Errors" which are unit test failures.
Test timeout setting for load test configuration does not affect web tests
The “Test Timeout” setting in the Test Run Configuration file (in the “Test -> Edit Test Run Configuration”
menu) does not have an effect in all cases.
This particular test timeout is enforced by the agent test execution code, but load test and Web test
execution are tightly coupled for performance reasons and when a load test executes a Web test, the
agent test execution code that enforces the test timeout setting is bypassed.
If you create a load test that has a test mix model “Based on user pace”, then the pacing calculated by
the test engine will override any settings you declare for “Think Time Between Tests”.
Warmup:
VSTS 2008 Load Test warmup periods are very quick to ramp up users (the agents are currently set
to spin up 10 new users every second on each agent). If you choose to use a constant load pattern
to avoid having the ramp-up requests in your final data set, you will need to implement a plugin to
control the speed at which users come online during warmup. See the following post for more
information and a sample code snippet:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1311729&SiteId=1
NOTE: This behavior is changed in VSTT 2008 SP1. It will now increase the number of users every 1
second by the initial user load (of the load pattern to be used after warm-up) divided by the number
of seconds in the warm-up period (rounded to the nearest integer value) so that user load reaches
the initial user load for the load pattern specified exactly at the end of the warm-up period
Cool down:
The Load test Terminate method does not fire unless you use a cool down period.
Sequential – This is the default and tells the web test to start with the first row then fetch rows in order
from the data source. When it reaches the end of the data source, loop back to the beginning and start
again. Continue until the load test completes.
Random – This indicates to choose rows at random. Continue until the load test completes.
Unique – This indicates to start with the first row and fetch rows in order. Once every row is used, stop
the web test. If this is the only web test in the load test, then the load test will stop.
Sequential – This works that same as if you are on one machine. Each agent receives a full copy of the
data and each starts with row 1 in the data source. Then each agent will run through each row in the
data source and continue looping until the load test completes.
Random – This also works the same as if you run the test on one machine. Each agent will receive a full
copy of the data source and randomly select rows.
Unique – This one works a little differently. Each row in the data source will be used once. So if you
have 3 agents, the data will be spread across the 3 agents and no row will be used more than once. As
with one machine, once every row is used, the web test will stop executing.
There is an extra thread for each unit test execution thread that is used to monitor the execution of the
unit test, implement timing out of the test, etc. However, the stack size for this thread is smaller than
the default size so it should take up less memory.
There is a property named on each request in a Web test named “Cache Control” in the Web
test editor (and named “Cache” on the WebTestRequest object in the API used by coded Web
tests).
When the Cache Control property on a request in the Web test is false, the request is always
issued.
When the Cache Control property is true, the VSTS load test runtime code attempts to emulate
the Internet Explorer caching behavior (with the “Automatically” setting).
(This includes reading and following the HTTP cache control directives.)
The Cache Control property is automatically set to true for all dependent requests (typically for
images, style sheets, etc embedded on the page).
In a load test, the browser caching behavior is simulated separately for each user running in the
load test.
When a virtual user in a load test completes a Web test and a new Web test session is started to
keep the user load at the same level, sometimes the load test starts simulates a “new user” with
a clean cache, and sometimes the load test simulates a return user that has items cached from a
previous session. This is determined by the “Percentage of New Users” property on the
Scenario in the load test. The default for “Percentage of New Users” is 100 in which case all
user sessions are started with a clean cache. This is probably not correct for most applications
where there are return users, so users should consider the most appropriate value to use for
this setting depending on the actual usage of the application being load tested.
Important Note: When running a Web test by itself (outside of the load test), the Cache Control
property is automatically set to false for all dependent requests so they are always fetched; this is so
that they can be displayed in the browser pane of the Web test results viewer without broken images.
Update for VSTS 2008: The Web test API enhancement in VSTS 2008 now allow you to write a
WebTestPlugin that disables caching of all dependent requests. See this blog post:
http://blogs.msdn.com/billbar/archive/2008/06/06/disabling-caching-of-all-dependent-
requests.aspx.
This temp file is known to get very large when the timing details setting is on. If you start running out of
disk space during a test run, consider cleaning up the disk or turning off timing details.
Resolution: We've analyzed this memory leak and determined that this is a bug in the
System.Net.HttpWebRequest class (used to issue Web test requests) that occurs when the Web test
target https Web sites. A workaround is to set the Load Test to use the "Connection Pool" connection
model.
This can occur if you have signed code in your test harness and you make changes to some of the code
without resigning it. You can try either one of the below options to attempt to resolve it:
OPTION 1:
1. In the .NET Framework 2.0 Configuration, Go to Runtime Security Policy | Machine | All_Code
2. Right click All_Code, select "New...", and select any name for your new group. Click Next
3. Select URL as your condition
4. Type \\machine_name\shared_folder\assembly.dll or \\machine_name\shared_folder\* and
click Next
5. Make sure permission is set to FullTrust
6. Click Next, and Finish
7. Close all your Visual Studio IDEs, restart, and try again
OPTION 2:
caspol -machine -addgroup 1 -url file:<location XXX>/* FullTrust -name
FileW
Verifying saved results when a test hangs in the “In Progress” state after the test has
finished
If you run a test and either the test duration or the number of iterations needed for completion of the
test have been reached, but the test stays in the “In Progress” state for a long time, you can check if all
of the results have been written to the load test results repository by running this SQL query against the
LoadTest database:
If the EndTime has a non-NULL value then the controller is done writing results to the load test results
database and it should be safe to restart the rig (killing anything if needed).
This doesn’t necessarily mean that all results from all agents (if the agents got hung) were successfully
written to the load test database, but it does mean that there’s no point in waiting before killing the
agents/tests.
These are often due to exhaustion of available connection ports either on the VSTS machine(s) or on the
machines under test. To see if this could be happening, open a CMD window on your VSTS machine(s)
and on the machine(s) under test, and run the following command:
If you see this, then you are suffering from port exhaustion. The following explains what is happening
and talks about some ways to deal with it.
The TIME_WAIT state is a throwback from the old days (well more accurately the default of 4 minutes is
the throwback). The idea is that if the client closes a connection, the server puts the socket into a
TIME_WAIT state. That way, if the client decides to reconnect, the TCP negotiation does not need to
occur again and can save a little bit of time and overhead. The concept was created because creating a
TCP connection was a costly operation years ago when networks were very slow).
To get around this issue, you need to make more connections available and/or decrease the amount of
time that a connection is kept in TIME_WAIT. In the machine’s registry, open the following key and
either add or modify the values for the two keys shown:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
]
"TcpTimedWaitDelay"=dword:0000001e (30 seconds)
"MaxUserPort"=dword:0000fffe (65,535 ports)
If you are experiencing the issue on one of the VSTT load machines, you may also need to change the
load test connection model to “Connection Pooling” and increase the pool size considerably.
Coded web tests and web test plug-ins should not block threads
http://blogs.msdn.com/billbar/archive/2007/06/13/coded-web-tests-and-web-test-plug-ins-should-not-
block-the-thread.aspx
Any comments and descriptions added will show up in the “Manage Load Test Results” dialog and will
make it much easier to determine which result set maps to the test run you wish to look at.
((LoadTestScenario)m_loadTest.Scenarios[0]).CurrentLoad = newLoad;
Unfortunately in VSTS 2008 there is still no way to directly access the max load defined for the Scenario
from a LoadTestPlugin or anywhere else. You could make this a LoadTest Context parameter (but you’d
have to make sure that the value of the Load Test context parameter stays in sync with the max user
load specified in the Scenario.
In VSTS 2008 SP1, we are adding the ability for a load test plugin to access or update the properties of a
Load Test Scenario’s load pattern. A description of that enhancement with examples is contained in
the above link.
Known Issues
Multi-proc boxes used as agents should have .NET garbage collection set to server
mode
To enable your application to use Server GC, you need to modify either the VSTestHost.exe.config or
the QTAgent.exe.config. If you are not using a Controller and Agent setup, then you need to modify the
VSTesthost.exe.config. If you are using a controller and agent, then modify the QTAgent.exe.config for
each agent machine. Open the correct file. The locations are
Local Machine Resolution: I think the problem may be that you effectively have two IP addresses on this
machine. The following entries in the controller log confirm my suspicion that this is the problem:
In regedit:
Read the following support article for the steps to resolve this issue on a test rig:
http://support.microsoft.com/kb/944496
If your load test uses “Connection per User” (which is the default) in VSTS 2008 and you set the size of
the IP address range equal to the number of virtual users per agent, then you will get a unique IP
address for each user, however it will not stick across iterations for each user. You must use “Connection
Pool Model” in order for your unique IP Address to persist across iterations.
The biggest problem with assigning unique IP Addresses to every user is that currently the IP switching
configuration limits you to a range of 256 IP addresses per agent, which would mean you would also be
limited to 256 virtual users per agent. One solution is to use VMs to get multiple load test agents on a
single physical machine.
Windows IP Configuration
Where to enable IP Switching for the Load Test Itself (after configuring the agents to use it)
2) Make sure that none of the IP addresses in the range specified for a particular agent are already
configured on the chosen NIC.
* Edit the file QTAgentService.exe.config: (located at: <Program Files>\Microsoft Visual Studio
9.0 Team Test Load Agent\LoadTest\QTAgentService.exe.config)
* Change:
<add key="CreateTraceListener" value="no"/> to "yes"
* Change:
<add name="EqtTraceLevel" value="3" /> to “4”
* Restart the Load Test Agent service
* Re-run the load test with verbose logging configured, and look for lines in the log file that contain the
text: "Attempting to configure IP address:" and "Configured IP address:" This will tell you whether or not
you the agent service is attempting to configure the IP address you've specified. If you see the
"Configured IP address:" line, it has succeeded in configuring this IP address. If not, there should be
some error logged.
If you have verified the items in step 1 & 2 above, and the log indicates that the configuration of the IP
address is failing but you cannot determine the cause of the failure from the error message in the log (or
if there is no error message in the log), post a new thread to the Web and Load testing forum, or open a
Microsoft Support incident for further assistance, and provide details on the setup including the relevant
portions of the log file.
4) Make sure that the load test you are running is set to use IP Switching: Click on each of the "Scenario"
nodes in the load test editor, go to the property sheet, and verify that the "IP Switching" property is set
to True (normally it should be since this is the default, but it's worth checking).
If the log file created in step 3 shows that the IP addresses are being successfully configured, the next
step is to check the agent process log file to verify that the load test is actually sending requests using
those IP addresses.
6) If the number of unique IP addresses being used as shown by the log entries in step 5 is less than the
number in the range that was configured, it could be because your load test is configured to use a
connection pool with a smaller number of connections than the number of IP addresses specified. If
this is the case, you can increase the size of the connection pool, or switch to "Connection per User"
mode in the load test's run settings properties.
(BUG) Changes made to Web Test Plugins may not show up properly
If you have a plugin that is part of the same project as a declarative web test, and you make changes in
the plugin, you may not always see those changes reflected in the test run. For instance, if you have a
plugin that writes a certain string out to an event log, and you change the string in the plugin, you still
see the old string value in the event log. This is a known issue and may be fixed in VSTT 2008 SP1 (it is
not in the beta release of SP1). In order for the bug to appear, the following conditions must be met:
If you are experiencing the bug, you can work around it by:
Having a slow WAN between the controller and agents may definitely cause some timeouts or delays in
performance counter collection. Each performance counter category is read in a separate operation:
that’s one method call at the level of the .NET classes that we call, and I don’t know if each call results in
just one or more than one network read.
There are some timeout settings for performance counter collection that you can change by editing the
QTController.exe.config file and adding these lines:
<appSettings>
<add key="LoadTestCounterCategoryReadTimeout" value="9000"/>
<add key="LoadTestCounterCategoryExistsTimeout" value="30000"/>
</appSettings>
The values are in ms, so 9000 is 9 seconds. If you make this change, also change the load test sample
rate to be larger than this: at least 10 or preferably 15 seconds, and yes with many agents located far
from the controller, it is recommended to delete most of the categories in the Agent counter set
(perhaps just leave Processor and Memory).
<DefaultCountersForAutomaticGraphs>
<DefaultCounter CategoryName="Memory" CounterName="Available MBytes"/>
</DefaultCountersForAutomaticGraphs>
Consider enabling SQL Tracing Throught the Load Test Instead of Separately
There is a set of properties on the Run Settings in the Load Test Editor that allow the SQL tracing feature
of Microsoft SQL Server to be enabled for the duration of the load test. If enabled, this allows SQL trace
data to be displayed in the load test analyzer on the "SQL Trace" table available in the Tables dropdown.
This is a fairly easy-to-use alternative to starting a separate SQL Profiler session while the load test is
running to diagnose SQL performance problems. To enable this feature, the user running the load test
(or the controller user in the case of a load test run on a rig) must have the SQL privileges needed to
perform SQL tracing, and a directory (usually a share) where the trace file will be written must be
specified. At the completion of the load test, the trace file data is imported into the load test repository
and associated with the load test that was run so that it can be viewed at any later time using the load
test analyzer.
Error “Failed to load results from the load test results store”
“Unable to cast object of type ‘System.DBNull’ to type ‘System.Byte*+’” error when trying to retrieve
load test results from the DB inside VSTS.
This error will occur if you get a NULL value in the LoadTest column of the LoadTestRun table. To fix it,
go to the table and delete the row that has the NULL value. The occurrence of this issue should be
extremely rare.
In the Load Test editor, all of the performance counter categories that start with “LoadTest:” (see the
LoadTest counter set in the load test editor) is data that is collected on the agents by the load test
runtime engine. These are not real Perfmon counters in the sense that if you try to look at them with
Perfmon you won’t see them, though we make them look like Perfmon counters for consistency in the
load test results database and display. The agents send this some of this data (see below) in messages to
the controller every 5 seconds which rolls up the agent (e.g. Requests / sec across the entire rig rather
than per agent). The controller returns the rolled up results to Visual Studio for display during the run
and also stores them in the load test results database.
[Requests Per Second Counters] The VSTT RPS does not count cached requests, even though VSTS is
sending an http GET with if-modified-since headers.
What data is sent every 5 seconds? we do everything possible to limit how much data is sent back in
that message. What we do send back is the average, min, max values for all of the pseudo
performance counters in the categories that start with “LoadTest:” that you see under the “Overall”,
“Scenarios” and “Errors” nodes in the load test analyzer tree (nothing under the “Machines” node).
Note that the biggest factor in the size of these result messages is the number of performance counter
instances, which for Web tests is mostly determined by the number of unique URLs reported on during
the load test. We also send back errors in these 5 seconds messages, but details about the failed
requests are not sent until the end of the test, so tests with lots of errors will have bigger messages.
Lastly, we only send back metadata such as the category names and counter names once and use
numeric identifiers in subsequent messages, so the messages at the start of the load test may be slightly
larger than later messages.
One thing you could do to reduce the size of the messages is to reduce the level of reporting on
dependent requests. You could do this by setting the “RecordResult” property of the
WebTestRequest object to false. This eliminate the page and request level reporting for that request,
but you could add a transaction around that request single request and that would really match the
page time for that request
90% of the total transactions were completed in less than <time> seconds
95% of the total transactions were completed in less than <time> seconds
The calculation of the percentile data for transactions is based not on the sampled data that is shown in
the graph, but on the individual timing details data that is stored in the table
LoadTestTransactionDetail. The calculation is done using a SQL stored procedure that orders the data
by the slowest transaction times, uses the SQL “top 10 percent” clause, to find the 10% of the slowest
transactions then uses the min() function on that set of rows to get the for the value for the 90th
percentile value for example. The stored procedure in the LoadTest database that does this is
“Prc_UpdateTransactionPercentiles”.
http://blogs.msdn.com/profiler/archive/2007/10/19/articles-on-new-visual-studio-team-system-2008-
profiler-features.aspx
How to clean up results data from runs that did not complete
If you have a Load Test Run that abnormally aborts and does not show data in a consistent manner (or
does not show up in the list of runs as either completed or aborted), you can use the following query on
the SQL repository server to clean up the database:
Answer: To make a long story short it is a unique identifier that is used mostly internally to distinguish
between cases where you have the same test name in two different scenarios in the load test or the
same page name (simple file name) in different folders in two different requests.
Once in the manager, you choose a controller name from the drop down list (or <local> if you want the
results from the local database) and the manager will populate with the tests it finds. You can select
whatever test results you wish to move, and then choose “export” to move them into a file (compressed
with an extension of .ltrar). That file can be moved to another machine and then imported into a new
results store.
this.MoveDataTableCursor(<”DataSource1”>, <”Products”>);
The problem is that in the Microsoft-Ajax partial rendering (update panel) responses, hidden fields can
appear in two places: a field that is marked by the type “|hiddenField|” (where we were looking), but
also in a regular hidden field input tag in the HTML within an “|updatePanel|” field in the Ajax response
(which we were not looking at).
A fix is being worked on and may appear in SP1. In the meantime, to work around the issue, simply
remove the hard-coded value and replace it with a parameterized value: {{$HIDDEN0.__VIEWSTATE}}
(where the bucket (0,1,2, etc matches the bucket of the other HIDDEN parameters in the request)
http://blogs.msdn.com/irenak/archive/2008/02/22/sysk-365-how-to-get-your-unit-tests-test-project-in-
visual-studio-2008-a-k-a-mstest
KB 956397 (http://support.microsoft.com/kb/956397/en-us)
http://blogs.msdn.com/billbar/archive/2008/08/04/bug-in-vsts-2008-sp1-causes-think-time-for-
redirected-requests-to-be-ignored-in-a-load-test.aspx
Four New Methods added to the WebTestPlugin Class for 2008 SP1
http://blogs.msdn.com/billbar/pages/web-test-api-enhancements-available-in-vsts-2008-sp1-beta.aspx
Average Max and Min time taken for each page type
-i:IISW3C -recurse:-1 -Q:on "SELECT EXTRACT_EXTENSION(cs-uri-stem) as Type, AVG(time-
taken) AS Average, MAX(time-taken) AS Maximum, MIN(time-taken) AS Minimum INTO
PageTimes.txt FROM ex*.log WHERE time-taken &amp;gt; 0 GROUP BY Type ORDER BY
Average DESC"
Pulling data from inside the body string of event viewer logs
logparser -i:evt "SELECT extract_prefix(extract_suffix(Strings,0,'left text'),0,'right
text') as String INTO optimizer.txt FROM *.EVT WHERE Strings LIKE '%Optimizer
Results%'" -q:ON
(variation) Pulling data from inside the body string of event viewer logs constrained by timeframe
logparser -i:evt -q:ON "SELECT Count(*) AS Qty, SUBSTR(extract_suffix(Message, 0,
'Message :'), 0, 75) as String FROM Error! Hyperlink reference not
valid.name>\Application WHERE SourceName LIKE '%Enterprise%' AND Message LIKE
'%Timestamp: %' AND TimeGenerated > TIMESTAMP ('2008-06-06 07:23:15', 'yyyy-MM-dd
hh:mm:ss' ) GROUP BY String ORDER BY Qty DESC"
List of exceptions from saved event logs searching for keywords in the text output
-I:evt "SELECT QUANTIZE(TimeGenerated, 3600) AS Hour, COUNT(*) As Total, ComputerName
FROM *.evt WHERE EventID = 100 AND strings like '%overflow%' GROUP BY ComputerName,
hour"
Logparser command for querying netstat
netstat.exe -anp TCP | LogParser “SELECT [Local Address] AS Server,[Foreign
Address] AS Client,State FROM STDIN WHERE Server LIKE '%:443' OR Server LIKE
'%:80'” -i:TSV -iSeparator:space -nSep:2 -fixedSep:OFF -nSkipLines:3 -o:TSV -
headers:ON
Command to query Netmon file and list out data on each TCP conversation
LogParser -fMode:TCPConn -rtp:-1 "SELECT DateTime, TO_INT(TimeTaken) AS Time,
DstPayloadBytes, SUBSTR(DstPayload, 0, 128) AS Start_Of_Payload INTO IE-Take2.txt FROM
IE-Take2.cap WHERE DstPort=80 ORDER BY DateTime ASC" -headers:ON
Command to query Netmon and find frame numbers based on specific text in payload
LogParser -fMode:TCPIP -rtp:-1 "SELECT Frame, Payload INTO 3dvia.txt FROM 3dvia.cap
WHERE DstPort=80 AND Payload LIKE '%ppContent%' " -headers:ON
I U
L V
lusrmgr.msc .............................................................13 validate .......................... 11, 21, 22, 26, 27, 28, 55, 76
verbose logging ............................................ 10, 62, 63
M VIEWSTATE .................................................. 31, 32, 77
MSTest ......................................................... 40, 47, 77 VSTT Classes
FormPostHttpBody ..............................................14