Web Performance Test Using Visual Studio- Part I

Ambily.raj
Posted by in Visual Studio category on for Beginner level | Views : 139637 red flag
Rating: 4.5 out of 5  
 4 vote(s)

Visual Studio is one of the tools used for Performance Test. Visual Studio Test edition or Visual Studio 2010 Ultimate provides the support for test automation. This article describes the web test feature available in visual studio.

Introduction

Performance of an application is very important for a multi-user application. Performance is not only the speed of execution; it includes the load and concurrency aspects. Performance Test is an answer for the following questions

  • How can we ensure that our new application will support the expected user load?
  • How to avoid the issues which will arise only in real load conditions?
  • How to find the response time?
  • How to plan the capacity of the servers?

Visual Studio is one of the tools used for Performance Test. Visual Studio Test edition or Visual Studio 2010 Ultimate provides the support for test automation.

This will be the first part of a series of articles.

  • Part I:  Web Test and Customization
  • Part II: Load Test, RIG and Load test terminologies.
  • Part III: Performance Counters, Load Test Result Analysis.

VS 2010 Test Types

Visual studio support various test types to perform the test automation. Figure 1 shows the main Test types available in VSTS 2010.

 

Basic Unit Test, Unit Test and Unit Test Wizard helps in creating new Unit test for a class file. This will be helpful for both developers and testers to perform unit level testing.

Coded UI test is used for recording the UI activities of a manual test. 

Database Unit Test used for testing stored procedures and functions.

Generic Test is for wrapping an executable as a test method. You can wrap the executable using generic Test and can include the same in test automation.

Ordered test is for executing multiple test scripts in a particular order. 

Web Performance Test used for recording the URLs and generating the code for performance testing.

Web Test

Web Performance Test or Web test allows performing the web application test. We will create a test project by selecting the Test project template.

Once you created the test project right click on the project and add new Item. Select the web performance test, which will open the recorder in an internet explorer and start recording the navigation URLs and associated parameters. 

Recording

Following figure shows the Web test recorder, records the Google search operation.

 

In this example, we are recording the search feature of Google. Once the recording is over, stop recording using the Stop button in Web test recorder. This will generate the recorded URLs as a web test and add dynamic correlations to.

Correlation

Correlation is nothing but linking the response of one web request to the next web request.

For example, when you login to the site it generates a SID for tracking the session. This SID is passed to the client after the login request. Along with the next request, the stored SID will be send to server. When you record this operation using Web test, it records the values and saves as hardcoded value. SID will be different for the next run.

For avoiding such situation, correlate the SID value from the response of the login request to the next request parameters.  First we will extract the SID values and save in a context parameter, which will be passed to the next request as a parameter. 

Context Parameter

Context Parameters is just like to global variables. If you want to refer one parameter across all URLs, declare the same as Context Parameter.

For example, we need to run the script in multiple environments. Instead of recording the script for each environment separately, define the context parameter as ‘Webserver’ and use the same for URL formation. Context Parameters should be referred inside double curly brackets like {{Webserver}}. All the URLs should be modified using the same context parameter. When you want to run the script in another environment, modify the value of the context parameter, which will automatically take care of the URLs.

The query string we used for searching is recorded as part of the URL recording.

In test environment the input value will differ depends on the positive testing, negative testing, boundary testing, etc. For passing multiple values to the parameters, we will do the parameterization.

Parameterization

For parameterizing the arguments, add the data source from where we can pick the values. Right click on the Web test -> Select Add Data Source option.

Select the type of data source. Data Source can be a Database like SQl Server, Oracle and Excel, or data can be fetched from CSV or XML files too.

Select the Data file or the database and table contains the input data. Preview of the data will be displayed on the wizard.

 

Click on the query string and move to the properties of the querystring. Change the value using the Data Source mapping as below.

Data source binding will be displayed as the query string value

 

 

Extraction Rule

Extraction rules are used for extracting the data from the response of a request. We have the following options for extracting the values; extract the form fields, extract HTTP header, etc. Extracted values can be used as part of the next web request or can be used for making any business decisions.

In following example, I used Extract Text option to extract an id passed from the server. By analyzing the html output of the request, you can form the Starts With and Ends With frames. The HTML response is displayed as part of the result window(will discuss soon).

Validation Rule

 

Validation rules are to enforce you are in the correct page only. After SignIn or Login In, you may be expecting a page with SignOut text. Following validation rule validates, whether the current response contains the text “SignOut’ or not.

We can form the validation rules using any of the following options. Visual Studio 2010 and 2008 automatically add the Response URL validations to the recorded test.

Transaction

 

Transactions are a set of operations or round-trips required to perform a particular operation. For example, the process of buying a Book consist of steps for select a Book, Add to cart, Check out and Payment.

Defining transactions will be helpful for analyzing the results. Normally the response time, Response Byte, etc. will be displayed for each URL separately. Once you define the transactions, the response time and all other measures will be displayed for the transaction level.

 

Run Test

When you run the test, you will get the following screen, where you can see the status of each URL, how the result appear in Web Browser, what are the parameters passed as part of the request, HTML response, context parameters and the details.

 

This is related to single run. If you want to check the parameterization to want to run the test multiple times, click on the Edit run Settings option displayed on top the screen.

 

Here, you can specify the number of times the test needs to be run. Each run will pick one record from the Parameter data source and run the test. Along with run count, we can specify the browser types too; which simulates how the site appears in different browser.

After setting the run settings, select the Click here to run again option specified on top of the screen.

Generate Code

 

Generate code option allows you to create the code corresponding to the script.

 

This will generate the C# code corresponding to the web test and also create a separate Test itself. We can modify the code project without affecting the web test and vice versa.

We can use the C# capabilities to automate or customize the coded web test. Can use loop for iterating one operation or ADO.Net to connect to database and pull some data for request, enforce think times (will discuss in Part II) and process WCF services.

//------------------------------------------------------------------------------

// <auto-generated>

// This code was generated by a tool.

// Runtime Version:4.0.30128.1

//

// Changes to this file may cause incorrect behavior and will be lost if

// the code is regenerated.

// </auto-generated>

//------------------------------------------------------------------------------

namespace GoogleTestProject

{

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.VisualStudio.TestTools.WebTesting;

using Microsoft.VisualStudio.TestTools.WebTesting.Rules;

public class WebTest1Coded : WebTest

{

public WebTest1Coded()

{

this.Context.Add("WebServer", "www.google.co.in");

this.PreAuthenticate = true;

}

public override IEnumerator<WebTestRequest> GetRequestEnumerator()

{

// Initialize validation rules that apply to all requests in the WebTest

if ((this.Context.ValidationLevel >= Microsoft.VisualStudio.TestTools.WebTesting.ValidationLevel.Low))

{

ValidateResponseUrl validationRule1 = new ValidateResponseUrl();

this.ValidateResponse += new EventHandler<ValidationEventArgs>(validationRule1.Validate);

}

if ((this.Context.ValidationLevel >= Microsoft.VisualStudio.TestTools.WebTesting.ValidationLevel.Low))

{

ValidationRuleResponseTimeGoal validationRule2 = new ValidationRuleResponseTimeGoal();

validationRule2.Tolerance = 0D;

this.ValidateResponseOnPageComplete += new EventHandler<ValidationEventArgs>(validationRule2.Validate);

}

WebTestRequest request1 = new WebTestRequest("http://www.google.com/");

request1.ThinkTime = 1;

request1.ExpectedResponseUrl = "http://www.google.co.in/";

ExtractHiddenFields extractionRule1 = new ExtractHiddenFields();

extractionRule1.Required = true;

extractionRule1.HtmlDecode = true;

extractionRule1.ContextParameterName = "1";

request1.ExtractValues += new EventHandler<ExtractionEventArgs>(extractionRule1.Extract);

yield return request1;

request1 = null;

WebTestRequest request2 = new WebTestRequest("http://clients1.google.co.in/generate_204");

yield return request2;

request2 = null;

WebTestRequest request3 = new WebTestRequest("http://www.google.co.in/csi");

request3.QueryStringParameters.Add("v", "3", false, false);

request3.QueryStringParameters.Add("s", "webhp", false, false);

request3.QueryStringParameters.Add("action", "", false, false);

request3.QueryStringParameters.Add("e", "17259,18168,23730,24808", false, false);

request3.QueryStringParameters.Add("ei", "gV_yS7vIKYqC7QPFmZznCw", false, false);

request3.QueryStringParameters.Add("expi", "17259,18168,23730,24808", false, false);

request3.QueryStringParameters.Add("imc", "1", false, false);

request3.QueryStringParameters.Add("imn", "1", false, false);

request3.QueryStringParameters.Add("imp", "1", false, false);

request3.QueryStringParameters.Add("rt", "prt.77,xjsls.102,ol.1085,iml.353,xjses.1817,xjs.1849", false, false);

yield return request3;

request3 = null;

WebTestRequest request4 = new WebTestRequest("http://clients1.google.co.in/complete/search");

request4.QueryStringParameters.Add("hl", this.Context["$HIDDEN1.hl"].ToString(), false, false);

request4.QueryStringParameters.Add("client", "hp", false, false);

request4.QueryStringParameters.Add("expIds", "17259,18168,23730,24808", false, false);

request4.QueryStringParameters.Add("q", "as", false, false);

request4.QueryStringParameters.Add("cp", "2", false, false);

yield return request4;

request4 = null;

WebTestRequest request5 = new WebTestRequest("http://clients1.google.co.in/complete/search");

request5.QueryStringParameters.Add("hl", this.Context["$HIDDEN1.hl"].ToString(), false, false);

request5.QueryStringParameters.Add("client", "hp", false, false);

request5.QueryStringParameters.Add("expIds", "17259,18168,23730,24808", false, false);

request5.QueryStringParameters.Add("q", "asp", false, false);

request5.QueryStringParameters.Add("cp", "3", false, false);

yield return request5;

request5 = null;

WebTestRequest request6 = new WebTestRequest("http://clients1.google.co.in/complete/search");

request6.QueryStringParameters.Add("hl", this.Context["$HIDDEN1.hl"].ToString(), false, false);

request6.QueryStringParameters.Add("client", "hp", false, false);

request6.QueryStringParameters.Add("expIds", "17259,18168,23730,24808", false, false);

request6.QueryStringParameters.Add("q", "asp.", false, false);

request6.QueryStringParameters.Add("cp", "4", false, false);

yield return request6;

request6 = null;

WebTestRequest request7 = new WebTestRequest("http://clients1.google.co.in/complete/search");

request7.QueryStringParameters.Add("hl", this.Context["$HIDDEN1.hl"].ToString(), false, false);

request7.QueryStringParameters.Add("client", "hp", false, false);

request7.QueryStringParameters.Add("expIds", "17259,18168,23730,24808", false, false);

request7.QueryStringParameters.Add("q", "asp.n", false, false);

request7.QueryStringParameters.Add("cp", "5", false, false);

yield return request7;

request7 = null;

WebTestRequest request8 = new WebTestRequest(("http://"

+ (this.Context["WebServer"].ToString() + "/")));

request8.ExpectedResponseUrl = "http://www.google.co.in/#hl=en&source=hp&q=asp.net&rlz=1R2ADFA_enIN375&aq=f&aqi=&" +

"aql=&oq=&gs_rfai=&fp=4a7b17d2fd7e8e7";

yield return request8;

request8 = null;

WebTestRequest request9 = new WebTestRequest("http://clients1.google.co.in/complete/search");

request9.QueryStringParameters.Add("hl", this.Context["$HIDDEN1.hl"].ToString(), false, false);

request9.QueryStringParameters.Add("client", "hp", false, false);

request9.QueryStringParameters.Add("expIds", "17259,18168,23730,24808", false, false);

request9.QueryStringParameters.Add("q", "asp.net", false, false);

request9.QueryStringParameters.Add("cp", "7", false, false);

yield return request9;

request9 = null;

WebTestRequest request10 = new WebTestRequest("http://www.google.co.in/search");

request10.ThinkTime = 1;

request10.QueryStringParameters.Add("hl", this.Context["$HIDDEN1.hl"].ToString(), false, false);

request10.QueryStringParameters.Add("source", this.Context["$HIDDEN1.source"].ToString(), false, false);

request10.QueryStringParameters.Add("q", "asp.net", false, false);

request10.QueryStringParameters.Add("rlz", "1R2ADFA_enIN375", false, false);

request10.QueryStringParameters.Add("aq", "f", false, false);

request10.QueryStringParameters.Add("aqi", "", false, false);

request10.QueryStringParameters.Add("aql", "", false, false);

request10.QueryStringParameters.Add("oq", "", false, false);

request10.QueryStringParameters.Add("gs_rfai", "", false, false);

request10.QueryStringParameters.Add("fp", "4a7b17d2fd7e8e7", false, false);

yield return request10;

request10 = null;

WebTestRequest request11 = new WebTestRequest("http://www.google.co.in/csi");

request11.QueryStringParameters.Add("v", "3", false, false);

request11.QueryStringParameters.Add("s", "web", false, false);

request11.QueryStringParameters.Add("action", "", false, false);

request11.QueryStringParameters.Add("ei", "hl_yS7TeHYTHrAfgy7jKDQ", false, false);

request11.QueryStringParameters.Add("e", "17259,18168,23730,24808", false, false);

request11.QueryStringParameters.Add("cp", "false", false, false);

request11.QueryStringParameters.Add("imp", "0", false, false);

request11.QueryStringParameters.Add("imn", "1", false, false);

request11.QueryStringParameters.Add("rt", "prt.586,pprt.599,ol.599,jsrt.565,iml.599", false, false);

yield return request11;

request11 = null;

WebTestRequest request12 = new WebTestRequest("http://clients1.google.co.in/generate_204");

yield return request12;

request12 = null;

}

}

}

 

Conclusion

Web Performance Test can be used for recording the website navigations and generating the Code. We can use this test or the generated coded test as an input to the performance test. Customization of the test can be done using

                Parameterization – makes the user inputs dynamic

                Correlation – Extract the Server generated data for subsequent requests.

In second part, we will look into the Load test aspects and on third part of this article series is for analyzing the performance test results and understanding the major performance counters.

Page copy protected against web site content infringement by Copyscape

About the Author

Ambily.raj
Full Name: Ambily KK
Member Level: Silver
Member Status: Member,Microsoft_MVP,MVP
Member Since: 5/18/2010 1:05:25 AM
Country: India
Thanks Ambily K K http://ambilykk.com/
http://ambilykk.com/
I have over 9 years of experience working on Microsoft Technologies. I am carrying the passion on Microsoft technologies specifically on web technologies such as ASP .Net and Ajax. My interests also include Office Open XML, Azure, Visual Studio 2010. Technology adoption and learning is my key strength and technology sharing is my passion.

Login to vote for this post.

Comments or Responses

Posted by: Majith on: 7/20/2010
Excellent Article.


Posted by: Anup1252000 on: 7/22/2010
Very useful article
Posted by: Ambily.raj on: 7/22/2010
Thanks
Posted by: mohanyo-7165 on: 10/25/2010 | Points: 10
can u please elobrate on method names used in correlation and parametarization.
if any sample code avilable please share it for better understanding.
Thanks
Mohan
mohan.yo@gmail.com
Posted by: Msghoneimy on: 5/16/2011 | Points: 25
Thanks Ambily. Great article
Posted by: MadhaviS on: 9/22/2011 | Points: 25
Thanks AMbily.
Posted by: Arefin on: 11/25/2011 | Points: 25
Good article. If it possible, you can share sample project.
Thanks.
Posted by: Leelamanohar11 on: 12/22/2011 | Points: 25
Thanks for the detailed explanation along with the screenshots Ambiliy.
Nice article :-)
Posted by: Silviosqa on: 7/5/2012 | Points: 25
Hi Ambily
Performance Tester (Visual Studio 2010).

I have a doubt about Run Duration, what difference this, what impact this make in may test?.
If i put 100 virtual users and choose 00:00:30?. I did understantd about this. Can you explain about this time e what difference?

I understand what the framework should show me the time, and i do not should input this..

Thanks a lot
Posted by: Ambily.Raj on: 7/6/2012 | Points: 25
Hi

Run Duration means how much time the test needs to run. If you selected 100 virtual users and 00:00:30 means the test will run for 30 seconds and try to launch 100 virtual users.

For getting proper data, we need to run the test for at least 30 min and collect the performance counters.

Regards
Ambily
Posted by: Andewadikar.Raghavendra on: 9/25/2012 | Points: 25
superb article
Posted by: Nero on: 1/10/2013 | Points: 25
Hi Ambily

Thanks for sharing the knowledge!
I was wondering why can't I see the custom counters that I added. I added some counters and ran the test. but in the results screen I do not see those added counters - it still shows the same old original counters. Any idea?
Posted by: Nero on: 1/25/2013 | Points: 25
If my test scenario contains one SharePoint Web Front End (FE) server and one Back End (BE) Content DB and I want performance data from both based on the hits to the FE only, do I need to configure Agent on both FE and BE or Agent configuration on FE is enough and get BE performance data through Controller - no need to install Agent there?
Posted by: Nero on: 2/13/2013 | Points: 25
I am running load test with 20 users in the Users.CSV file but in the test result summary why does it show 'Max User Load' = 25?So the test really ran for 20 virtual users or 25 virtual users?
And do these virtual users hit the pages simultaneously during testing?

And feedback would be greatly appreciated. Many thanks.

Login to post response

Comment using Facebook(Author doesn't get notification)