5.11 判断“请求-响应”的测试结果
问题
如何判断一个“请求-响应”的测试用例是否通过。
设计
通过StreamReader.ReadLine()方法逐行读入HTTP响应。然后通过String.IndexOf()方法逐行解析HTTP响应,看是否能够找到目标字符串,如果找到则测试结果为pass,否则为fail。
方案
//初始化url
// 把待发送数据缓存到字节数组
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = buffer.Length;
// 把缓存数组中的数据写入请求数据流
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
//取回响应数据流并关联到StreamReader sr
string expected = "someTargetString";
bool expectedFound = false;
string line = null;
while ((line = sr.ReadLine()) != null && !expectedFound)
{
if (line.IndexOf(expected) >= 0)
{
Console.WriteLine("expected value found");
expectedFound = true;
}
}
if (expectedFound)
Console.WriteLine("Pass");
else
Console.WriteLine("Fail");
注解
针对ASP.NET Web程序实施“请求-响应”测试的关键步骤包括:发送HTTP请求到待测程序,取回HTTP响应,根据期望值对响应进行检查。准备好请求,然后发送请求,接下来把取回的响应与一个Stream对象相关联:
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
Stream resst = res.GetResponseStream(); //取回HTTP响应
然后从这个Stream对象创建一个StreamReader对象,这样就可以访问响应数据流:
StreamReader sr = new StreamReader(resst);
我们需要指定一个用于在HTTP响应中进行搜索的目标字符串:
string expected = "someTargetString";
期望字符串是这样定义的:如果在HTTP响应中找到这个字符串,则可以判定这个响应正确。这个字符串并不总是很容易指定的。例如,设想有一个Web程序包含一个DropDownList控件,这个控件有“red”,“blue”和“green”选项。如果用户选择“red”,会有一条类似于“apples are red”这样的消息显示在TextBox控件里。如果你想当然地使用字符串“red”作为期望值,那么得到的结果将永远是pass,因为“red”是<option>这个HTML tag的一部分:
<select name="DropDownList1" id="DropDownList1">
<option value="red">red</option>
<option value="blue">blue</option>
<option value="green">green</option>
</select>
而且<input>这个HTML tag也包含“red”:
<input name="TextBox1" type="text" value="apples are red"
id="TextBox1" />
我们可以通过指定更为详细的期望值来避免这种错误:
string expected = "value=\"apples are red\"";
我们对HTTP响应进行逐行查找,定义一个布尔变量expectedFound并把它的初值设为false,然后声明一个字符串变量line来保存HTTP响应的当前行。接下来,我们检查HTTP响应的每一行:
while ((line = sr.ReadLine()) != null && !expectedFound)
{
if (line.IndexOf(expected) >= 0)
{
Console.WriteLine("Found expected target");
expectedFound = true;
}
}
如果HTTP响应数据流到达末尾或者期望的目标字符串被找到,则退出循环。循环结束以后,如果expectedFound仍然为false,则说明是在没有找到目标字符串的情况下,因为数据流到达末尾而退出循环的,这也就意味着测试用例没有通过。如果expectedValue的值为true,则意味着循环退出是因为找到了目标字符串,即测试用例通过。
另外,你也可以通过StreamReader.ReadToEnd()把HTTP响应作为一个长字符串取回,然后通过String.IndexOf()对其进行查找:
string entireResponse = sr.ReadToEnd();
if (entireResponse.IndexOf(expected) >= 0)
Console.WriteLine("Pass");
else
Console.WriteLine("*FAIL*");
这种方法更为简单,但是如果HTTP响应非常大,则不适合使用该方法。
对于轻量级的自动化测试程序来说,当需要使用唯一的目标字符串或其他特征值的时候,通常都可以创建测试平台场景(test bed scenarios)。但在某些情况下,则可能需要在HTTP响应里查找非唯一的目标字符串。针对这个问题的一个解决方案是,指定两个字符串表示响应里查找开始和结束的地方:
private static bool IsThere(string strToSearch,
string strTarget,
string strBegin, string strEnd)
{
int start = strToSearch.IndexOf(strBegin);
int end = strToSearch.IndexOf(strEnd);
int numCharsToSearch = end - (start + strBegin.Length);
if (strToSearch.IndexOf(strTarget, start, numCharsToSearch) >= 0)
return true;
else
return false;
}
(这段代码假定strTarget和strBegin并不相同。)换句话说,即使某些目标字符串可能在你的HTTP响应里多次出现,但是如果限制对某个目标字符串进行查找的范围,那么还是可以对非唯一的目标字符串进行查找的。采用这种方法,可以对HTTP响应进行全面地查找:
string entireResponse = sr.ReadToEnd();
string target = "red";
if (IsThere(entireResponse, target, "<form", "</form>"))
Console.WriteLine("Pass");
else
Console.WriteLine("*FAIL*");
如果“red”在HTTP响应的“<form”和“</form>”之间被找到,这段代码将返回true。请注意,我们用“<form”表示“<form>”,少了一个“>”,这是因为响应字符串应该是:
<form name="Form1" method="post" action="WebForm.aspx" id="Form1">
...
</form>
而不是
<form>
...
</form>
还有一种方法可以用来查找HTTP响应数据流中非唯一的目标字符串,那就是使用正则表达式。正则表达式比简单的字符串查找要更为强大,但是通常情况下,用正则表达式编写代码有一定难度,并且难以修改和维护。







