问题
如何把测试用例的结果存入独立于测试程序的简单文本文件。
设计
在处理测试用例的主循环中,使用一个System.IO.StreamWriter对象,把测试用例ID和测试结果写到一个文本文件。
方案
//此处打开StreamReader sr
FileStream ofs = new FileStream("..//..//TestResults.txt",FileMode.CreateNew);
StreamWriter sw = new StreamWrite(ofs);
String line,caseID,method,expected;
double actual= 0.0;
while((line = sr.ReadLine()) != null )
{
//此处对“line”进行解析
if(method == "ArithmeticMean")
{
actual = MathLib.Methods.ArithmeticMean(input);
if (actual.ToString("F4") == expected)
sw.WriteLine(caseID + " Pass");
else
sw.WriteLine(caseID + " *FAIL*");
}
else
{
sw.WriteLine(caseID + " Unknown method");
}
}//while
sw.Close();
ofs.Close();
注解
许多情况下,我们都希望把测试用例结果写到外部的存储文件,而不(仅仅)是在命令行程序里显示出这些结果,最简单的外部存储文件就是文本文件。其他的方法还包括写到SQL表或者XML文件中。首先,需要创建一个FileStream对象和一个StreamWriter对象用于把测试用例结果写入外部存储文件。本方案中,采用FileMode.CreateNew参数,在测试套件可执行程序所在目录的上两级目录里创建一个名为TestResult.txt的文本文件。使用相对路径可以在必要的时候整体移动测试套件的目录结构。然后可以使用StreamWriter对象把测试结果写入外部存储文件,就像把它们写到控制台程序一样。
当传入FileMode.CreateNew和"TestResult.txt"作为参数时,如果名为TestResult.txt的文本已经存在,就会抛出一个异常。我们可以通过使用FileMode.Create参数来避免这种情况,但是已有TestResult.txt文件的所有内容都会被覆盖,这样有可能会丢失测试结果。可以采取的一种策略是,把测试结果的文件名作为参数传进来:
Static void Main(string[] args)
{
string testResultFile = args[0];
FileStream ofs = new FileStream(testResultFile,FileMode.CreateNew);
StreamWriter sw = new StreamWriter(ofs);
//etc.
}
并且每次运行测试程序时,都传入一个手工产生的新的测试结果文件名:
C:/Harness/bin/Debug>Run.exe Results-10-12-10.txt
还有一种做法是通过编程把时间戳另在测试结果的文件名称里,然后把测试结果写入这个文件。
到目前为止,我们的例子程序要么把测试结果写入命令行窗口,要么写入一个.txt文件,但是也可以在写入命令行窗口的同时写入.txt文件:
if(method == "ArithmeticMean")
{
actual = MathLib.Methods.ArithmeticMean(input);
if (actual.ToString("F4") == expected)
{
Console.WriteLine(caseID + " Pass");
sw.WriteLine(caseID + " Pass");
}
else
{
Console.WriteLine(caseID + " *FAIL*");
sw.WriteLine(caseID + " *FAIL*");
}
}
当StreamWriter.WriteLine()语句被执行时,它实际并没有把结果写到输出文件里。它会缓存这些结果,然后当StreamWriter.Close()语句被执行时,才把结果写入文件。也可以显示地调用StreamWrite.Flush()语句来强制把结果写入文件。这个方法在有很多测试用例或者捕获异常时候通常是很重要的。如果捕获到异常,一定不能忘了在catch块或finally块晨关掉所有已打开的输入输出流,这样缓存的结果就可以写入文件,而不会丢失:
catch(Exception ex)
{
Console.WriteLine("Unexcpected fatal error: " + ex.Message);
sw.Close();
//关闭其他已打开的stream
}