SSL-Based ASP. NET web application testing automation

Source: Internet
Author: User
Tags md5 hash urlencode ssl certificate ssl connection

If you are using Secure Sockets Layer (SSL) Over HTTP to encrypt user data and want to program your web application, you will find that this technology is not widely known. In this topic this month, I will demonstrate how to create an SSL test server, write test automation code, and verify it through a simple and representative web application.
The Microsoft. NET environment provides powerful testing tools to test ASP. NET web applications that adopt the SSL security mechanism. To illustrate their usage, I will build an SSL server and demonstrate how to automatically test the https-based Web example application through a short and sophisticated program. Although some of the technologies are very classic and well described in this article, during communication with many of my colleagues, I found that the overall process of testing SSL Web applications is relatively inadequate. Use two screens to illustrate the problem. Figure 1 shows a simple but representative ASP. NET web application.


Figure 1 an ASP. NET web application

Note that I am using an SSL connection because I want to transmit sensitive credit card information over the Internet (note the "https: //" protocol and a small lock icon in the status bar ).
Now, let's imagine how to manually test this application. We must enter hundreds or even thousands of user names, numbers, and credit card numbers on the web page, check each confirmation code, and check each line of code for the expected results to determine whether the results are correct, the results are then recorded in some tables, such as Excel workbooks or text files. The entire process is time-consuming, inefficient, cumbersome, and error-prone.
A better method is to use. net Framework powerful ability to write automated test routines, send test data with SSL in the program, and then check the response stream for the expected confirmation code, Figure 2 is a console application, it demonstrates the above ideas.


Figure 2 Test Application

As you can see, the basic practice of automated test cases is the same as that of manual test in Figure 1. The user name is "Smith", the number of items is "3", and the credit card number is "1234 5678 9012". After SSL-based HTTP encryption, it is submitted to the Web application, the tester gets the HTTP Response stream and searches for the "C3-57-ED-DA-8B" in the response stream, where the desired confirmation code is found, so the test automation record the "pass" result. In the three chapters after this topic, I will explain how to generate the test program output as shown in figure 2. Demonstrate how to create a test server that accepts SSL requests, and discuss how to extend the technology presented in this article to meet your own needs.
Before I explain how to write a test automation program, let's first review the Example Web application in this article. As you can see in Figure 1, there are three textbox controls. I use the default ID of Visual Studio. NET: textbox1, textbox2, and textbox3 to name them. They correspond to the user name, item quantity, and credit card account respectively. The label5 control is used to display application information. When I write a test automation program, I need to know this information and how the order confirmation code is generated so that I can determine the expected results of my test cases. The following is the core code used to test this web application:

if (TextBox3.Text.Length == 0)
  Label5.Text = "Please enter credit card number";
else
{
  byte[] input = Encoding.Unicode.GetBytes(TextBox3.Text);
  byte[] hashed;          
  using(MD5 m = new MD5CryptoServiceProvider())
  {
      hashed = m.ComputeHash(input);
  }
  Label5.Text = "Thank you. Your confirmation code is " +
    BitConverter.ToString(hashed).Substring(0,14);
}

To simulate the generation of the validation code, I only use the credit card number entered by the user to generate an MD5 hash, and then take 14 characters at the leftmost of the hash value. In the actual production system, you may produce confirmation codes in a more complex way. In this case, it may be more skillful to determine the expected results. However, you must note that you cannot call the tested program to determine the expected results, because this will undermine the test validity, because you want to check whether the results returned by the test automation program are consistent with those returned by the tested program.

Test automation program

This test automation program is surprisingly short. All the code is shown in figure 3. Although the technology of submitting data to an ASP. NET web application by programming has been described in the msdn library, there are several techniques that require special attention.
I decided to write a C # console program as my test program. Developing test automation programs in the same language as the tested programs is usually a good idea. In any case, well-planned design and integration with the. NET environment means that you can safely use Visual Basic. Net or any other language compatible with. net. Generally, the console program type is most suitable for testing automation programs. Although the testing program has a beautiful user interface that can impress users, the Automated Testing Program is a tool rather than a personal show. In addition, console programs are easier to integrate into the build system than gui programs.
The entire structure of the test automation program is quite simple. I save the test case data in a simple text file. each row of data represents a single test case. The following is the content of the test case file:

001:Smith:3:1234 5678 9012:C3-57-ED-DA-8B
002:Baker:2:1111 2222 3333:CE-81-8C-2F-94
003:Gates:9:9999 9999 9999:95-D6-05-31-8A

Information is separated by a colon. I can also use any character as the separator, but it is important to avoid fuzzy characters in actual test cases. The first field is the test case number, the second field is the user name, the third field is the number, the fourth field is the credit card number, and the fifth field is the expected confirmation code. If you do not want to use text files, XML files or SQL tables are good options.
The basic structure of my test automation program is related to my test case data file. The pseudocode is as follows:

loop
  read a test case line
  parse out test case data
  build up data to post to application
  convert post data to a byte array
  post the data
  retrieve the response stream
  if response stream contains expected confirmation code
    log "pass" result
  else
    log "fail" result
end loop

First, I declare the namespace to be used, so that I do not have to write the full name limit name for every. Net class or object. At the same time, it is clear which class library functions will be involved in the testing automation program.

using System;
using System.Web; 
using System.Text; 
using System.Net;  
using System.IO;   

System. the Web namespace contains the httputility class, which can convert some special characters into escape character sequences because the default console program does not reference its Assembly, that is, system. web. DLL, We must manually Add a reference to it. The system. Text namespace contains an encoding class, which is used to process byte arrays ). The system. Net namespace contains the httpwebrequest class, which is the basic class for submitting data to ASP. NET web applications. Using the system. Io namespace is because I want to use data streams to process SSL-based HTTP responses. In addition, I also need to use it to read test case data from text files. Note: The using directive allows you to use a namespace without specifying a long name.
Next, after a simple startup information is displayed in the command shell, declare the key variables used for testing the automation program:

string url = "https://localhost/LitwareOrder/Order.aspx";
string viewstate = HttpUtility.UrlEncode(
    "dDw0MDIxOTUwNDQ7Oz6E/7ailqx8X9zCUfpbWTPybfS4MA==");
string line;
string[] tokens;
StringBuilder data = new StringBuidler();
byte[] buffer;
string proxy = null;

The purpose of most of the above variables is clear from its naming. Only viewstate is a new variable, so I will briefly explain it. Now I open the test case file and read it one row at a time:

using(FileStream fs = new FileStream(args[0], FileMode.Open))
{
    StreamReader tc = new StreamReader(fs);
    while ((line = tc.ReadLine()) != null)
    {
      // parse line, post data, get response
      // determine pass or fail, log result
    }
}

Although there are many optional methods to design this automated process, the above simple structure has been proven robust in several large projects. The next step is to parse each field of the data in the test case and construct a string containing the "name-value" pair.

tokens = line.Split('':'');
data.Length = 0;
data.Append("TextBox1=" + tokens[1]);   // Last name
data.Append("&TextBox2=" + tokens[2]); // Quantity
data.Append("&TextBox3=" + tokens[3]); // Credit card number
data.Append("&Button1=clicked");
data.Append("&__VIEWSTATE=" + viewstate); 

I use string. the split method separates test case data rows and saves each field to the tokens array. the test case ID is saved to tokens [0, the user name is saved to tokens [1], the number of items is saved to tokens [2], and the credit card number is saved to tokens [3. For clarity, you can also copy these values to additional descriptive string variables, such as "caseid" and "lastname", as shown below:

caseID = tokens[0];
lastName = tokens[1];
// etc.

However, I want to minimize the number of variables used. Traditional Web servers generally use "name-value" pairs to submit (post) data, separate multiple data with the "&" symbol as follows:

lastName=Smith&quantity=3&creditCardNo=123456789012

However, Asp. net extension. In this example, there are five "name-value" pairs, the first pair, you may want to: textbox1 = tokens [1], it assigns the User Name of the current test case (saved in tokens [1]) to the control whose ID attribute is "textbox1. The second is textbox2 = tokens [2], and the third is textbox3 = tokens [3], which respectively assign the item quantity and credit card number to the corresponding control. The next pair is "button1 = clicked". If you have used a traditional ASP page to submit data, it may be different from what you think. In ASP. NET, button1 is a server-side control. I must keep the viewstate value synchronously and will explain it later. Assigning any value to it does not work, So I simply use code like "button1 =. I prefer the form of "clicked" because it is more readable. The fifth line is _ viewstate (note the first two underlines), which is the most critical point for programming to submit data to the ASP. NET Server.
What is the value of siewstate? Although HTTP is a stateless protocol-each request-the response is a mutually isolated transaction-Asp. Net processes it behind the scenes to create a supporting State environment. It uses HTML to hide an input control named _ viewstate. This is an encoded base64 string used to indicate the page status when the server performs the last processing. This method maintains the page status by retaining the values before and after each call, to correct ASP.. NET web applications submit data. The value of viewstate must be sent to the server. Review how I set this value:

string viewstate = HttpUtility.UrlEncode(    "dDw0MDIxOTUwNDQ7Oz6E/7ailqx8X9zCUfpbWTPybfS4MA==");

Where does this value come from? The simplest way to get the initial value of viewstate for a Web application is to start the IE browser to get the page, and then use "View | source file" on the menu bar to open the source file. It is very important to obtain the initial value of viewstate, because if you reload the page, the value of viewstate will change, and the program you write to submit data will generate a server error. The original viewstate value must be processed using the urlencode method. The urlencode method converts invalid characters in the URL to escape character sequences, for example, "=" can be converted to % 3d.
Once the viewstate value is available, you can construct all the data strings to be submitted to the Web application. The next step is to convert the string into a byte array, because the data to be submitted later needs to be stored in bytes:

buffer = Encoding.UTF8.GetBytes(data);

The getbytes method is a member function of the encoding class in the system. Text namespace. In addition to the UTF attribute, there are ASCII, Unicode, utf7 and other attributes. Now we instantiate an httpwebrequest object and assign a value to its attributes:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = buffer.Length;
req.Proxy = new WebProxy(proxy, true);
req.CookieContainer = new CookieContainer();

Note: In the factory mode of webrequest, here I explicitly call the create method, instead of using the new keyword to call the constructor. I use the POST method because I am sending form data. I set the contenttype attribute to "application/X-WWW-form-urlencoded ". This is a MIME type. You can think of it as a magic string that tells the ASP. NET Server to receive form data. Set the contentlength attribute to the number of bytes of the submitted data. The data is previously saved in the byte array buffer.
In this example, if you do not send data through the proxy server, you can ignore the proxy attribute. The Boolean parameter in the WebProxy constructor is true, meaning that the proxy is ignored when the local address is used. To obtain the cookies returned by the cookies attribute, you must assign a value to the cookiecontainer attribute. Here, httpwebrequest is returned by getresponse. Note that I assigned a null value to the cookiecontainer object. When I understood this technology, it was one of the many details that caused the trouble.
Before submitting data to an ASP. NET application, you must add the data to be submitted to the request object. As shown below:

using (Stream reqst = req.GetRequestStream())
{
    reqst.Write(buffer, 0, buffer.Length);
}

Next, after outputting some information I submitted, I receive the response data stream from the server.

using(HttpWebResponse res = (HttpWebResponse)req.GetResponse())
{
  string result;
  using(Stream resst = res.GetResponseStream())
  {
      result = new StreamReader(resst).ReadToEnd();
  } 
  //Console.WriteLine(result);
}

You may want to use something similar to req. send (data) statements to send data, but use httpwebrequest. getrequeststream is used to open a connection with the server and use httpwebrequest. getresponse obtains the httpwebresponse object, which indicates the server response. (If getrequeststream is not used, actually getresponse will establish a connection to the server ). I use readtoend to retrieve the entire response stream and save it to a string variable called "result. You can also read the response row by row using the Readline method. Note that I have commented out a statement that shows the entire response stream in the command shell. If you are a beginner in programming, remove this comment to see the entire response stream, this is helpful to you.
Finally, I checked the response data stream to check whether the expected verification code was included (it was saved in tokens [4 ).

if (result.IndexOf(tokens[4]) >= 0)
  Console.WriteLine("PASS");
else
  Console.WriteLine("FAIL");

If I find the expected results, I will record a pass result to the shell. Of course, if you want to, you can also write the test case results to a text file, XML file or SQL table.

Set SSL test Server

Setting up an SSL-enabled web server is a cumbersome task. You can buy a "real" SSL certificate from one of several vendors, but it takes a certain amount of time and money. The makecert.exe utility is used to generate a self-signed certificate. It is part of the. NET Framework tool and then installed on your Web server. But now I have a simpler method.
Iis6.0's resource package (you can download multiple available tools from Windows deployment and resource package with selfssl.exe, which makes it easy to create and install self-Signed SSL certificates for testing purposes. Figure 4 details how to use this tool.


Figure 4

The key is to use the/T switch so that the local browser can trust this certificate, and also use the/n switch to specify localhost as the public name. Surprisingly, you only need to do this to test HTTPS directly on the Web server. If you want to test SSL-based HTTP from a remote client, a security warning dialog box will pop up when you manually browse the test server for the first time, asking if you want to continue. If you click "view Certificate" and then click "Install Certificate", you will enter a wizard. If you accept all the default options in the Wizard. After the certificate is installed, the client can access the test server without a warning dialog box and the test automation program will run from the client.
The selfssl.exe tool is part of the iis6.0 resource kit and does not explicitly support earlier versions of IIS, my colleagues and I have successfully performed experiments on IIS 5.0. I also use the makecert.exe tool to generate X.509 certificates that can be used for testing. The certificate creation tool in the msdn Library provides an introduction to the makecert.exetool. It is easier to use the selfssl.exe tool.
After you use a self-Signed SSL certificate to complete the test, you will want to delete the certificate from the test server to avoid the interaction impact on the test server. The easiest way to delete a certificate is to use the Microsoft Management Console (MMC ). Execute MMC and add a certificate management unit for the computer account that manages the local computer. Now, you should expand "certificate", then "personal", select the "certificate" folder, your self-signed certificate will be displayed, then delete it.

Further work

You can extend the technology provided in this column in many ways. Some of the information I use is hard-coded (for example, test URL), which may not be suitable for you. You may find that parameterization of them can make your test system more flexible. Another interesting extension is programming to determine the initial value of viewstate. In my example, I started the browser manually, checked the source code to get the initial value of viewstate, and wrote it to the test program through hard encoding. Although this method works, you have to retrieve the viewstate every time the core code of the Web application is modified. A better solution is to use system. the WebClient class of the net namespace requests the initial web application page through programming, parses the response stream to extract the value of _ viewstate, and then assigns it to the viewstate variable. Although this method adds an additional request/response round-trip overhead when calling each test case, it greatly increases the flexibility of your test automation program.
The technology presented in this column is a good supplement to testing with the Microsoft Application Center Test (ACT) tool. Act is designed to perform stress testing on Web servers, analyze the performance of web applications to solve the scaling problem. However, Act is not used for functional verification, and the technology described here is mainly used for functional verification.
In this column, I used the httpwebrequest class to submit data to the ASP. NET web application to be tested through programming. Several alternative methods can be used. At a lower level, you can use the sockets class in the system. net. Sockets namespace. at a higher level, you can use the WebClient class of the system. Net namespace. These three technologies can work well, but most of my colleagues and I like to use the httpwebrequest class, you will find that this is your personal hobby and you can select different implementation methods based on your actual situation.

If you have any questions, contact James: testrun@microsoft.com

Author profile:
James McCaffrey
Working at volt Information Sciences Inc. Where he is responsible for technical training for Microsoft software engineers. He has participated in several Microsoft products, including IE and MSN Search. James can be contacted via jmccaffrey@volt.com or v-jammc@microsoft.com.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.