Monday, 18 February 2008

XML automation - part I

" mission is to build a test driver for our API which can be executed stand-alone in parallell with QTP"


I've recently got several requests on how to use the COM-object WinHttp, so I thought I would try to explain how I use the object in my test framework in a series of posts.

Part I - Building a simple client in order to send XML-request using WinHttp:

See html-source code below. I have removed some specific features (XML-templates and log handling) which I use internally.

Why this tool when there are several free tools out there? Well, it is a light-weight client (one html-file) which is easy to customize and it is a good way to get familiar with the WinHttp-object which you can use heavily in VBScript-based automation.

Up next: Part II - Using XML templates

Purpose: To send XML http request.
Assumptions: Proper security settings in browser and DLL for WinHttp5.1 object
Author: Stefan Thelenius 2008-02-18.
<title>Web Service Test Tool</title>
<script language="JavaScript">
select {font-family: verdana; font-size: 8pt; font-weight: 500;}
input {font-family: verdana; font-size: 8pt; font-weight: 500;}
textarea {font-family: verdana; font-size: 8pt; font-weight: 500;}
<FONT FACE="verdana" SIZE=3>
<center>Web Service Test Tool</center>
<FONT FACE="verdana" SIZE=1>
<FORM NAME="frmForm1">
<SCRIPT LANGUAGE="vbscript">
document.write("<table width=""100%"" border=""0"" cellspacing=""0"" cellpadding=""0"">")
document.write("<FONT FACE=""verdana"" SIZE=1>URL&nbsp")
document.write("<INPUT TYPE=""text"" NAME=""url"" SIZE=70 TITLE=""URL"">")
document.write("<FONT FACE=""verdana"" SIZE=1>&nbsp&nbspUser&nbsp")
document.write("<INPUT TYPE=""text"" NAME=""username"" SIZE=20 TITLE=""UserName"">")
document.write("<FONT FACE=""verdana"" SIZE=1>&nbsp&nbspPassword&nbsp")
document.write("<INPUT TYPE=""password"" NAME=""password"" SIZE=12>")
document.write("<FONT FACE=""verdana"" SIZE=1>&nbsp&nbspResponse to Clipboard<input type=""checkbox"" name=""blnSave"">")
document.write("<table width=""100%"" border=""0"" cellspacing=""0"" cellpadding=""0"">")
'Autofit request and response textarea
intWidth = screen.width / 13
intHeight = screen.height / 23
document.write("<td><FONT FACE=""verdana"" SIZE=1>Request<BR>")
document.write("<textarea name=""IN"" rows=""" & intHeight & """ cols=""" & intWidth & """></textarea></td>")
document.write("<td><FONT FACE=""verdana"" SIZE=1>Response<BR>")
document.write("<textarea name=""OUT"" rows=""" & intHeight & """ cols=""" & intWidth & """></textarea></td>")
document.write("</tr><tr><td><INPUT TYPE=""button"" NAME=""cmdSend"" VALUE=""Send"" onclick=""SendRequest()"">")
document.write("&nbsp<INPUT TYPE=""button"" NAME=""cmdPretty"" VALUE=""Parse input"" onclick=""ParseInput()"">")
document.write("&nbsp<INPUT TYPE=""button"" NAME=""cmdClean"" VALUE=""Clean output"" onclick=""CleanResponse()"">")
document.write("</td><td id=""tid""><FONT FACE=""verdana"" SIZE=1>&nbsp</td>")
Get current user as default
Dim objNet
Set objNet = CreateObject("WScript.NetWork")
frmForm1.username.Value = objNet.UserDomain &
"\" & objNet.UserName
Set objNet = Nothing
Sub SendRequest
Dim WinHttpReq
Set WinHttpReq = CreateObject("
strStart = Timer
WinHttpReq.Open "
", frmForm1.url.Value, False
WinHttpReq.setRequestHeader "
Content-Type", "text/xml;charset=utf-8
WinHttpReq.setRequestHeader "
Accept", "text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
WinHttpReq.setRequestHeader "
Content-Transfer-Encoding", "binary
WinHttpReq.setRequestHeader "
Connection", "keep-alive
WinHttpReq.SetCredentials frmForm1.username.Value, frmForm1.password.Value, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER
strStop = Timer
Set xmlDoc = CreateObject("
'Parse output
If (xmlDoc.parseError.errorCode <> 0) Then
frmForm1.OUT.Value = WinHttpReq.ResponseText
frmForm1.OUT.Value = xmlDoc.xml
End If
Set xmlDoc = Nothing
strTime = strStop - strStart
strTime = FormatNumber(strTime,2)
tid.Innertext = "
Response time: " & strTime & " s
Set WinHttpReq = Nothing
'Set clipboard = output
If frmForm1.blnSave.Value = True Then window.clipboardData.setData "
End Sub
Sub ParseInput
Set xmlDoc = CreateObject("
If (xmlDoc.parseError.errorCode <> 0) Then
Set myErr = xmlDoc.parseError
Msgbox "
" & myErr.reason
Set myErr = Nothing
Set xmlDoc = Nothing
Exit Sub
End If
frmForm1.IN.Value = xmlDoc.xml
Set xmlDoc = Nothing
End Sub
Sub CleanResponse
frmForm1.OUT.Value = "
End Sub


Niterat said...

Hey, I just wanted to say thanks for this one. I had been looking for a solution to some changes made in out web services and this provided the needed web GUI to get the project back on it's feet. Thanks. Ryan Oglesby

Stefan said...

Glad it helped!


Anonymous said...

Thanks for the post Stepan !!!

I've got to produce a client certificate to use a web service.

I've downloaded / installed the cert and added it to the trusted store. All these cert & store files are now in my D:\ drive.

The following command doesn't seem to recognize the certificate.
WinhttpReq.SetClientCertificate "D:\MyCertNameHere"

Looks like i got to use the registry path as below.
WinhttpReq.SetClientCertificate "LOCAL_MACHINE\MY\MyCertNameHere"

But i'm wondering how to move my cert and trusted store file from D:\ drive to registry under "LOCAL_MACHINE\MY"

Thanks in Advance !!!


Stefan said...


I have not had to deal with certificate issues that much in my xml automation so far so I am not much of help here...however I remember there is a flag for ignore certificates errors which can be set prior a request (search the blog for it) but I guess it won't help in your case. Good luck!


Tomas said...

Hi Vinoth,

WinhttpReq.SetClientCertificate automaticaly looks to LOCAL_MACHINE\MY. So you just need to have imported your client certificate in your personal cert. store and know the name of the certificate. Lets say its called "my_certificate", then can set it like this: WinhttpReq.SetClientCertificate "my_certificate". Hope this helps.