《软件测试自动化之道》读书笔记 之 XML测试

《软件测试自动化之道》读书笔记 之 XML测试

2014-10-07

待测程序
测试程序
  通过XmlTextReader解析XML
  通过XmlDocument解析XML
  通过XmlPathDocument解析XML
  通过XmlSerializer解析XML
  通过DataSet解析XML
  通过XSD Schema对XML文件进行验证
  通过XSLT对XML文件进行修改
  通过XmlTextWrite对XML文件进行写操作
  比较两个XML文件是否严格相等
  不考虑编码方式,比较两个XML文件是否严格相等
  比较两个XML文件的规范等价性
  示例代码 

待测程序


 返回

‘testCases.xml’示例代码:

 1 <?xml version="1.0" encoding="utf-8" ?>

 2 <suite>

 3   <testcase id="001" bvt="yes">

 4     <inputs>

 5       <arg1>red</arg1>

 6       <arg2>blue</arg2>

 7     </inputs>

 8     <expected>purple</expected>

 9   </testcase>

10   

11   <testcase id="002" bvt="no">

12     <inputs>

13       <arg1>blue</arg1>

14       <arg2>yellow</arg2>

15     </inputs>

16     <expected>green</expected>

17   </testcase>

18 

19   <testcase id="003" bvt="yes">

20     <inputs>

21       <arg1>white</arg1>

22       <arg2>black</arg2>

23     </inputs>

24     <expected>gray</expected>

25   </testcase>

26 </suite>
View Code

测试程序


 返回

本章给出5种解析技术,都是把‘testCases.xml’解析成测试用例Suite对象,Suite的定义如下:

 1 namespace Utility

 2 {

 3     public class TestCase

 4     {

 5         public string id;

 6         public string bvt;

 7         public string arg1;

 8         public string arg2;

 9         public string expected;

10     }

11 

12     public class Suite

13     {

14         public System.Collections.ArrayList cases = new System.Collections.ArrayList();

15         public void Display()

16         {

17             foreach (TestCase tc in cases)

18             {

19                 Console.WriteLine(tc.id + " " + tc.bvt + " " + tc.arg1 + " " + tc.arg2 + " " + tc.expected);

20             }

21         }

22     }

23 }
View Code

通过XmlTextReader解析XML 

示例代码:

 1         private static void ParseByXMLTextReader(Utility.Suite suite, string tcPath)

 2         {

 3             XmlTextReader xtr = new XmlTextReader(tcPath);

 4             xtr.WhitespaceHandling = WhitespaceHandling.None;

 5             xtr.Read(); //read xml declaration, move to tag<suite>

 6 

 7             while (!xtr.EOF)

 8             {

 9                 if (xtr.Name == "suite" && !xtr.IsStartElement()) break;

10                 while (xtr.Name != "testcase" || !xtr.IsStartElement())

11                     xtr.Read(); //move to tag<testcase>

12 

13                 Utility.TestCase tc = new Utility.TestCase();

14                 tc.id = xtr.GetAttribute("id");

15                 tc.bvt = xtr.GetAttribute("bvt");

16                 xtr.Read(); //move to tag <inputs>

17                 xtr.Read(); //move to tag <arg1>

18                 tc.arg1 = xtr.ReadElementString("arg1");

19                 tc.arg2 = xtr.ReadElementString("arg2");

20                 xtr.Read(); //move to tag <expected>

21                 tc.expected = xtr.ReadElementString("expected");

22                 //current tag is </testcase>

23                 suite.cases.Add(tc);

24 

25                 xtr.Read(); //current tag is <testcase> or </suite>

26             }

27             xtr.Close();            

28         }

29     }
View Code

分析:

XmlTextReader把XML 解析成单个的数据片,如下xml:

<?xml version="1.0" encoding="utf-8" ?>

<alpha id="001">

  <beta>123</beta>

</alpha>

不计空格,这里共有6个结点:XML声明、<alpha id="001">、<beta>、123、</beta>、</alpha>。

  • Read()方法:每次向前读取一个结点。与其它类的Read()不同,该方法并不返回有意义的数据;
  • ReadElementString()方法:才会返回单个标签和结尾之间的数据,并向前糯稻标签结束后面的下一个结点。
  • EOF属性:判断是否碰到文件结尾

当被解析的XML文件结构相对比较简单并且前后一致,且需要向前进行处理的时候,使用XmlTextReader是 一种直接有效的方法。与本章其他解析技术相比,也是最快的方法。与本章其他解析技术相比,XmlTextReader所进行的操作在比较地的抽象层次上,也就以为这作为程序员,要负责正确跟踪XML文件中的位置和正确调用Read()。

通过XmlDocument解析XML

示例代码:

 1         private static void ParseByXMLDocument(Utility.Suite suite, string tcPath)

 2         {

 3             XmlDocument xd = new XmlDocument();

 4             xd.Load(tcPath);

 5 

 6             //get all <testcase> nodes

 7             XmlNodeList nodeList = xd.SelectNodes("/suite/testcase");

 8             foreach (XmlNode node in nodeList)

 9             {

10                 Utility.TestCase tc = new Utility.TestCase();

11                 tc.id = node.Attributes.GetNamedItem("id").Value;

12                 tc.bvt = node.Attributes.GetNamedItem("bvt").Value;

13 

14                 XmlNode n = node.SelectSingleNode("inputs");

15                 tc.arg1 = n.ChildNodes.Item(0).InnerText;

16                 tc.arg2 = n.ChildNodes.Item(1).InnerText;

17                 tc.expected = node.ChildNodes.Item(1).InnerText;

18 

19                 suite.cases.Add(tc);

20             }

21         }
View Code

分析:

XmlDocument.Load()方法:把整个XML文件读如内存中。XmlDocument对象基于XML结点和子结点的概念。我们不采用顺序的方式遍历XML文件,而是通过SelectNodes()方法选择一组结点,或这通过SelectSingleNode()选择单个的结点。请注意:因为XML文件的attributes和elements之间有着显著的差别,所以我们必须通过Attributes.GetNamedItem()方法得到某个元素结点的id和bvt值。

因为XmlDocument会一次把整个XML文挡读入到内存中,所以对于被解析的XML文件非常大的情况,这种方法并不合适。

通过XmlPathDocument解析XML

示例代码:

 1         private static void ParseByXPathDocument(Utility.Suite suite, string tcPath)

 2         {

 3             System.Xml.XPath.XPathDocument xpd = new XPathDocument(tcPath);

 4             XPathNavigator xpn = xpd.CreateNavigator();

 5             XPathNodeIterator xpi = xpn.Select("/suite/testcase");

 6 

 7             while (xpi.MoveNext())

 8             {

 9                 Utility.TestCase tc = new Utility.TestCase();

10                 tc.id = xpi.Current.GetAttribute("id", xpn.NamespaceURI);

11                 tc.bvt = xpi.Current.GetAttribute("bvt", xpn.NamespaceURI);

12 

13                 XPathNodeIterator tcChild = xpi.Current.SelectChildren(XPathNodeType.Element);

14                 while (tcChild.MoveNext())

15                 {

16                     

17                         if (tcChild.Current.Name == "inputs")

18                         {

19                             XPathNodeIterator tcSubChild = tcChild.Current.SelectChildren(XPathNodeType.Element);

20                             while (tcSubChild.MoveNext())

21                             {

22                                 if (tcSubChild.Current.Name == "arg1")

23                                     tc.arg1 = tcSubChild.Current.Value;

24                                 else if (tcSubChild.Current.Name == "arg2")

25                                     tc.arg2 = tcSubChild.Current.Value;

26                             }

27                         }

28                         else if (tcChild.Current.Name == "expected")

29                             tc.expected = tcChild.Current.Value;

30 

31                 }

32                 suite.cases.Add(tc);

33             }

34         }
View Code

分析:

  • XpathDocument()构造函数:把整个XML文件存入内存。
  • XpathNavigator对象的Select()方法:选择XML文挡的一部分
  • XpathNodeIterator对象的MoveNext()方法:遍历XpathDocument对象。
  • GetAttribut()方法:取得attribute的值
  • SelectChildren()方法和Current.Value属性:取得XML元素的值

通过XmlPathDocument对象对XML文件进行解析,给人的感觉是它一部分是过程式的、底层的(类似于XmlTextReader)处理方法,一部分是面向对象的、高层次的(类似于XMLDocument)的处理方法。

XmlPathDocument类是针对XPath数据模型特别优化过的。所以当要解析的XML文件嵌套层次很深、结构很复杂或者需要大范围的查找炒作,这种方法尤为合适。但XmlPathDocument只能对XML文件进行读取,所以如果想对文件在内存中进行直接的操作,这种方法不行。

通过XmlSerializer解析XML

示例代码:

内存结构对应类:

 1 namespace SerializerLib

 2 {

 3     using System.Xml.Serialization;

 4 

 5     [XmlRootAttribute("suite")]

 6     public class Suite

 7     {

 8         [XmlElementAttribute("testcase")]

 9         public TestCase[] items;

10         public void Display()

11         {

12             foreach(TestCase tc in items)

13             {

14                 Console.WriteLine(tc.id + " " + tc.bvt + " " + tc.inputs.arg1 + " " + tc.inputs.arg2 + " " + tc.expected);

15             }

16         }

17         

18     }

19 

20     public class TestCase

21     {

22         [XmlAttributeAttribute()]

23         public string id;

24         [XmlAttributeAttribute()]

25         public string bvt;

26         [XmlElementAttribute("inputs")]

27         public Inputs inputs;

28         public string expected;

29 

30     }

31 

32     public class Inputs

33     {

34         public string arg1;

35         public string arg2;

36     }

37 }
View Code

ParseByXmlSerializer()方法:

1         private static void ParseByXmlSerializer(string tcPath)

2         {

3             XmlSerializer xs = new XmlSerializer(typeof(SerializerLib.Suite));

4             StreamReader sr = new StreamReader(tcPath);

5             SerializerLib.Suite suite = (SerializerLib.Suite)xs.Deserialize(sr);

6             sr.Close();

7             suite.Display();

8         }
View Code

分析:

通过XmlSerializer类对XML文件进行解析于其他5中XML解析类有着很大的不同,因为采用这种方法必须很仔细的把存储结构预先准备好。我们注意到把XML加载到内存中的操作只通过下面一个语句就完成了:

SerializerLib.Suite suite = (SerializerLib.Suite)xs.Deserialize(sr);

存储结构可以手工编写一个目标类,也可以通过Visual Studio .NET自带的xsd.exe命令行工具:

首先,执行以下命令(假设testCase.xml位于C盘根目录):

C:\>xsd.exe testCases.xml /o:.

这个命令的意思上创建testCases.xml文件的XSD schema定义并且把结果按照默认名保存到当前目录

然后,执行以下命令:

C:\xsd.exe testCases.xsd /c /o:.

这个命令的意思是使用testCase.xsd定义文件,通过默认的C#语言产生一组于Deserialize()方法兼容的类,并且以默认文件名testCases.cs保存到当前目录。

现在你可以把testCases.cs的代码直接拷贝到测试套间中,稍加修改(比如:去处一些不需要的代码,加一些额外的方法,改名等)

XmlSerialzier类为XML文件的解析提供了一种非常优雅的解决方案。所进行的操作也在最高的抽象层次,也就是说算法的细节大多屏蔽掉了。但也失去了一些对XML处理过程的处理。

通过DataSet解析XML 

示例代码:

 1         private static void ParseByDataSet(Utility.Suite suite, string tcPath)

 2         {

 3             DataSet ds = new DataSet();

 4             ds.ReadXml(tcPath);

 5 

 6             foreach (DataRow row in ds.Tables["testcase"].Rows)

 7             {

 8                 Utility.TestCase tc=new Utility.TestCase();

 9                 tc.id = row["id"].ToString();

10                 tc.bvt = row["bvt"].ToString();

11                 tc.expected = row["expected"].ToString();

12 

13                 DataRow[] children = row.GetChildRows("testcase_inputs"); //relation name

14                 tc.arg1=(children[0]["arg1"]).ToString();

15                 tc.arg2=(children[0]["arg2"]).ToString();

16 

17                 suite.cases.Add(tc);

18             }

19         }
View Code

分析:

ReadXml()方法:把XML文件直接读如一个System.Data.DataSet对象。你可以把DataSet对象想像成一个内存中的关系型数据库。通过DataSet对象对XML进行解析,关键是要理解XML(本质上是层次型的)是如何映射到一组DataTable对象(本质上是平面型的)的。XML源文件的每个层次都会在DataSet中产生一个表。

顶层的<testcase>产生一个名为testcase的DataTable。下一层次<inputs>产生一个名为inputs的DataTable。这时候还会产生一个叫做testcase_inputs的关系对象用来连接DataTable对象。请注意:XML的根结点所在的层次和最低层(本例中即<arg>所表示的数据)并不会产生表。

下面这个‘DisplayInfo’方法的代码提供一些你需要的信息:

 1         public static void DisplayInfo(DataSet ds)

 2         {

 3             foreach (DataTable dt in ds.Tables)

 4             {

 5                 Console.WriteLine("\n==========================================");

 6                 Console.WriteLine("Table= " + dt.TableName + "\n");

 7                 foreach (DataColumn dc in dt.Columns)

 8                     Console.Write("{0,-14}", dc.ColumnName);

 9                 Console.WriteLine("\n------------------------------------------");

10                 foreach (DataRow dr in dt.Rows)

11                 {

12                     foreach(object data in dr.ItemArray)

13                         Console.Write("{0,-14}", data.ToString());

14                     Console.WriteLine();

15                 }

16                 Console.WriteLine("\n==========================================");

17             }

18             foreach (DataRelation dr in ds.Relations)

19             {

20                 Console.WriteLine("\n\nRelations:");

21                 Console.WriteLine(dr.RelationName+"\n\n");

22             }

23         }
View Code

《软件测试自动化之道》读书笔记 之 XML测试

图1 DataSet信息

通过XSD Schema对XML文件进行验证

示例代码:

 1         private static void VerifyByXsdSchema(string tcPath)

 2         {

 3             XmlSchemaCollection xsc = new XmlSchemaCollection();

 4             xsc.Add(null, @"..\..\testCases.xsd");

 5             XmlTextReader xtr = new XmlTextReader(tcPath);

 6             XmlValidatingReader xvr = new XmlValidatingReader(xtr);

 7             xvr.ValidationType = ValidationType.Schema;

 8             xvr.Schemas.Add(xsc);

 9             xvr.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

10             while (xvr.Read()) ;

11 

12             Console.WriteLine("If no error message then XML is valid");

13         }

14 

15         private static void ValidationCallBack(object sender, ValidationEventArgs ea)

16         {

17             Console.WriteLine("Validation error: " + ea.Message);

18             Console.ReadLine();

19         }
View Code

 

分析:

通过XmlValidatingReader对象对想要验证的XML文件进行遍历。如果这个文件不是有效的XML文件,程序控制流程转向一个代理方法(delegate method),这个代理方法会打印出错误信息。

通过XmlSchemaCollection对象加载用于验证的schema定义,通过这种方法可以针对XML文件应用多个schema定义。

通过XSLT对XML文件进行修改

‘testCase.xml’原始形式如下:

 1 <?xml version="1.0" encoding="utf-8" ?>

 2 <suite>

 3   <testcase id="001" bvt="yes">

 4     <inputs>

 5       <arg1>red</arg1>

 6       <arg2>blue</arg2>

 7     </inputs>

 8     <expected>purple</expected>

 9   </testcase>

10 

11 <suite>
View Code

修改后的版本:

 1 <?xml version="1.0" encoding="utf-8"?>

 2 <allOfTheTestCases>

 3   <aCase caseID="001">

 4     <bvt>yes</bvt>

 5     <expRes>purple</expRes>

 6     <inputs>

 7       <input1>red</input1>

 8       <input2>blue</input2>

 9     </inputs>

10   </aCase>

11 

12 </allOfTheTestCases>
View Code

示例代码:

‘testCasesModifier.xslt’代码:

 1 <?xml version="1.0" encoding="utf-8"?>

 2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

 3     xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"

 4 >

 5     <xsl:output method="xml" indent="yes"/>

 6 

 7     <xsl:template match="/">

 8       <allOfTheTestCases>

 9         <xsl:for-each select ="//testcase">

10           <aCase>

11             <xsl:attribute name="caseID">

12               <xsl:value-of select ="@id"/>

13             </xsl:attribute>

14             <bvt>

15               <xsl:value-of select="@bvt"/>

16             </bvt>

17             <expRes>

18               <xsl:value-of select="expected"/>

19             </expRes>

20             <inputs>

21               <xsl:for-each select="inputs">

22                 <input1>

23                   <xsl:value-of select="arg1"/>

24                 </input1>

25                 <input2>

26                   <xsl:value-of select="arg2"/>

27                 </input2>

28               </xsl:for-each>

29             </inputs>

30           </aCase>

31         </xsl:for-each>

32       </allOfTheTestCases>

33     </xsl:template>

34 </xsl:stylesheet>
View Code

UpdateXMLByXSLT()方法代码:

1         private static void UpdateXMLByXSLT(string tcPath)

2         {

3             XslTransform xst = new XslTransform();

4             xst.Load(@"..\..\testCasesModifier.xslt");

5             xst.Transform(tcPath, @"..\..\testCasesModifier.xml");

6             Console.WriteLine("Done. New XML file is 'testCasesModifier.xml'");

7         }
View Code

通过XmlTextWrite对XML文件进行写操作

示例代码:

 1         private static void WriteXMLbyXmlTextWrite()

 2         {

 3             string caseID = "0001";

 4             string result = "Pass";

 5             string whenRun = "10/09/2014";

 6             XmlTextWriter xtw = new XmlTextWriter(@"..\..\Results1.xml", System.Text.Encoding.UTF8);

 7             xtw.Formatting = Formatting.Indented;

 8             xtw.WriteStartDocument();

 9             xtw.WriteStartElement("Results");

10             xtw.WriteStartElement("result");

11             xtw.WriteAttributeString("id", caseID);

12             xtw.WriteStartElement("passfaill");

13             xtw.WriteString(result);

14             xtw.WriteEndElement();

15             xtw.WriteStartElement("whenRun");

16             xtw.WriteString(whenRun);

17             xtw.WriteEndElement();

18             xtw.WriteEndElement();

19             xtw.WriteEndElement();

20             xtw.Close();

21         }
View Code

结果‘TestResult1.xml’:

1 <?xml version="1.0" encoding="utf-8"?>

2 <Results>

3   <result id="0001">

4     <passfaill>Pass</passfaill>

5     <whenRun>10/09/2014</whenRun>

6   </result>

7 </Results>
View Code

比较两个XML文件是否严格相等

示例代码:

 1         private static bool XMLExactlySame(string file1,string file2)

 2         {

 3             FileStream fs1 = new FileStream(file1, FileMode.Open);

 4             FileStream fs2 = new FileStream(file2, FileMode.Open);

 5 

 6             if (fs1.Length != fs2.Length)

 7                 return false;

 8             else

 9             {

10                 int b1 = 0;

11                 int b2 = 0;

12 

13                 while ((b1 = fs1.ReadByte()) != -1)

14                 {

15                     b2 = fs2.ReadByte();

16                     if (b1 != b2)

17                     {

18                         fs1.Close();

19                         fs2.Close();

20                         return false;

21                     }

22                 }

23                 fs1.Close();

24                 fs2.Close();

25                 return true;

26             }

27         }
View Code

分析:

通过FileStream对象遍历两个XML文件。一个字节一个字节的读入文件内容,如果某个字节不匹配,则返回false。

不考虑编码方式,比较两个XML文件是否严格相等

示例代码:

 1         private static bool XMLExactlyExceptEncoding(string file1, string file2)

 2         {

 3             FileStream fs1 = new FileStream(file1, FileMode.Open);

 4             FileStream fs2 = new FileStream(file2, FileMode.Open);

 5             StreamReader sr1 = new StreamReader(fs1);

 6             StreamReader sr2 = new StreamReader(fs2);

 7 

 8             string s1 = sr1.ReadToEnd();

 9             string s2 = sr2.ReadToEnd();

10             sr1.Close();

11             sr2.Close();

12             fs1.Close();

13             fs2.Close();

14             return (s1==s2);

15         }
View Code

分析:

编写软件测试时,可能需要对实际的XML文件和期望的XML文件进行比较,而不关心它们的编码机制是否一样。换句话说,如果实际的XML文件和期望的XML文件包含相同的字符数据,只不过编码方式不同(比如:UTF-8,ANSI )。若要考虑编码,可用重载过的==运算符。

比较两个XML文件的规范等价性

第一个XML文件Books1.xml代码如下:

 1 <?xml version="1.0" encoding="utf-8"?>

 2 <books>

 3   

 4   <book>

 5     <title isbn='1111' storeid="A1A1">

 6       All About Apples

 7     </title>

 8     <author>

 9       <last>Anderson</last>

10       <first>Adam</first>

11     </author>

12   </book>

13 </books>
View Code

第二个XML文件Books2.xml代码如下:

 1 <books>

 2   <book>

 3     <title storeid="A1A1" isbn="1111">

 4       All About Apples

 5     </title>

 6     <author>

 7       <last>Anderson</last>

 8       <first>Adam</first>

 9     </author>

10   </book>

11 </books>
View Code

示例代码:

 1         private static void XMLCanonicalEquivalence()

 2         {

 3             string file1 = @"..\..\Books1.xml";

 4             string file2 = @"..\..\Books2.xml";

 5             

 6             XmlDocument xd1 = new XmlDocument();

 7             xd1.Load(file1);

 8 

 9             XmlDsigC14NTransform t1 = new XmlDsigC14NTransform(true); //true mean inclue comment

10 

11             t1.LoadInput(xd1);

12             Stream s1 = t1.GetOutput() as Stream;

13             XmlTextReader xtr1 = new XmlTextReader(s1);

14             MemoryStream ms1 = new MemoryStream();

15             XmlTextWriter xtw1 = new XmlTextWriter(ms1, System.Text.Encoding.UTF8);

16             xtw1.WriteNode(xtr1, false); //false mean not copy default properties

17 

18             xtw1.Flush();

19             ms1.Position = 0;

20             StreamReader sr1 = new StreamReader(ms1);

21             string str1 = sr1.ReadToEnd();

22             Console.WriteLine(str1);

23 

24             Console.WriteLine("\n==============\n");

25 

26             XmlDocument xd2 = new XmlDocument();

27             xd2.Load(file2);

28 

29             XmlDsigC14NTransform t2 = new XmlDsigC14NTransform(true); //true mean inclue comment

30 

31             t2.LoadInput(xd2);

32             Stream s2 = t2.GetOutput() as Stream;

33             XmlTextReader xtr2 = new XmlTextReader(s2);

34             MemoryStream ms2 = new MemoryStream();

35             XmlTextWriter xtw2 = new XmlTextWriter(ms2, System.Text.Encoding.UTF8);

36             xtw2.WriteNode(xtr2, false); //false mean not copy default properties

37 

38             xtw2.Flush();

39             ms2.Position = 0;

40             StreamReader sr2 = new StreamReader(ms2);

41             string str2 = sr2.ReadToEnd();

42             Console.WriteLine(str2);

43 

44             if (str1 == str2)

45                 Console.WriteLine("Files cannonically equivalent");

46             else

47                 Console.WriteLine("Files Not canonically equivalent");

48         }
View Code

分析:

通过XmlDsigC14NTransform类对两个要比较的XML文件实施C14N规范花转换,然后通过两个MemoryStream对象对内存中两个转换后文件进行比较。你可以把规范等价性想像成“从大多数实际应用的角度来看都是相等的”。

上面两个XML文件‘Books1.xml’,‘Bools2.xml’具有规范等价性。两个文件中的空格不影响比较的结果;引号双引号不影响比较的结果;XML声明不影响比较的结果;attributes的顺序不影响比较的结果。

C14N规范等价性是相当复杂的。它是有W3C定义的,主要用于安全领域,XmlDsigC14NTransform类位于System.Security.dll中。为了判断一个XML文件在网络传输的过程中是否被无意中修改或被恶意修改,我们可以比较发送文件和接受文件加密哈希值。但是,由于网络可能会修改这个文件,我们需要以某种方式来判断它们的规范等价性。

示例代码

  1 using System;

  2 using System.Text;

  3 

  4 using System.Xml;

  5 using System.Xml.XPath;

  6 

  7 using System.Xml.Serialization;

  8 using System.IO;

  9 using System.Data;

 10 using System.Xml.Schema;

 11 using System.Xml.Xsl;

 12 

 13 using System.Security.Cryptography.Xml;

 14 

 15 namespace XMLTest

 16 {

 17     class Program

 18     {

 19         static void Main(string[] args)

 20         {

 21             Console.WriteLine("Start\n");

 22             string tcPath = @"..\..\testCases.xml";

 23             //Utility.Suite suite = new Utility.Suite();

 24 

 25             //ParseByXMLTextReader(suite, tcPath);

 26             //ParseByXMLDocument(suite, tcPath);

 27             //ParseByXPathDocument(suite, tcPath);

 28             //ParseByXmlSerializer(suite, tcPath);

 29             //ParseByDataSet(suite, tcPath);

 30             

 31             //suite.Display();

 32 

 33             //VerifyByXsdSchema(tcPath);

 34             //UpdateXMLByXSLT(tcPath);

 35             //WriteXMLbyXmlTextWrite();

 36 

 37             //XMLExactlySame

 38             //XMLExactlyExceptEncoding

 39             XMLCanonicalEquivalence();

 40 

 41             Console.WriteLine("\nDone");

 42             Console.Read();

 43         }

 44 

 45         private static void XMLCanonicalEquivalence()

 46         {

 47             string file1 = @"..\..\Books1.xml";

 48             string file2 = @"..\..\Books2.xml";

 49             

 50             XmlDocument xd1 = new XmlDocument();

 51             xd1.Load(file1);

 52 

 53             XmlDsigC14NTransform t1 = new XmlDsigC14NTransform(true); //true mean inclue comment

 54 

 55             t1.LoadInput(xd1);

 56             Stream s1 = t1.GetOutput() as Stream;

 57             XmlTextReader xtr1 = new XmlTextReader(s1);

 58             MemoryStream ms1 = new MemoryStream();

 59             XmlTextWriter xtw1 = new XmlTextWriter(ms1, System.Text.Encoding.UTF8);

 60             xtw1.WriteNode(xtr1, false); //false mean not copy default properties

 61 

 62             xtw1.Flush();

 63             ms1.Position = 0;

 64             StreamReader sr1 = new StreamReader(ms1);

 65             string str1 = sr1.ReadToEnd();

 66             Console.WriteLine(str1);

 67 

 68             Console.WriteLine("\n==============\n");

 69 

 70             XmlDocument xd2 = new XmlDocument();

 71             xd2.Load(file2);

 72 

 73             XmlDsigC14NTransform t2 = new XmlDsigC14NTransform(true); //true mean inclue comment

 74 

 75             t2.LoadInput(xd2);

 76             Stream s2 = t2.GetOutput() as Stream;

 77             XmlTextReader xtr2 = new XmlTextReader(s2);

 78             MemoryStream ms2 = new MemoryStream();

 79             XmlTextWriter xtw2 = new XmlTextWriter(ms2, System.Text.Encoding.UTF8);

 80             xtw2.WriteNode(xtr2, false); //false mean not copy default properties

 81 

 82             xtw2.Flush();

 83             ms2.Position = 0;

 84             StreamReader sr2 = new StreamReader(ms2);

 85             string str2 = sr2.ReadToEnd();

 86             Console.WriteLine(str2);

 87 

 88             if (str1 == str2)

 89                 Console.WriteLine("Files cannonically equivalent");

 90             else

 91                 Console.WriteLine("Files Not canonically equivalent");

 92         }

 93 

 94         private static bool XMLExactlyExceptEncoding(string file1, string file2)

 95         {

 96             FileStream fs1 = new FileStream(file1, FileMode.Open);

 97             FileStream fs2 = new FileStream(file2, FileMode.Open);

 98             StreamReader sr1 = new StreamReader(fs1);

 99             StreamReader sr2 = new StreamReader(fs2);

100 

101             string s1 = sr1.ReadToEnd();

102             string s2 = sr2.ReadToEnd();

103             sr1.Close();

104             sr2.Close();

105             fs1.Close();

106             fs2.Close();

107             return (s1==s2);

108         }

109 

110         private static bool XMLExactlySame(string file1,string file2)

111         {

112             FileStream fs1 = new FileStream(file1, FileMode.Open);

113             FileStream fs2 = new FileStream(file2, FileMode.Open);

114 

115             if (fs1.Length != fs2.Length)

116                 return false;

117             else

118             {

119                 int b1 = 0;

120                 int b2 = 0;

121 

122                 while ((b1 = fs1.ReadByte()) != -1)

123                 {

124                     b2 = fs2.ReadByte();

125                     if (b1 != b2)

126                     {

127                         fs1.Close();

128                         fs2.Close();

129                         return false;

130                     }

131                 }

132                 fs1.Close();

133                 fs2.Close();

134                 return true;

135             }

136         }

137 

138         private static void WriteXMLbyXmlTextWrite()

139         {

140             string caseID = "0001";

141             string result = "Pass";

142             string whenRun = "10/09/2014";

143             XmlTextWriter xtw = new XmlTextWriter(@"..\..\Results1.xml", System.Text.Encoding.UTF8);

144             xtw.Formatting = Formatting.Indented;

145             xtw.WriteStartDocument();

146             xtw.WriteStartElement("Results");

147             xtw.WriteStartElement("result");

148             xtw.WriteAttributeString("id", caseID);

149             xtw.WriteStartElement("passfaill");

150             xtw.WriteString(result);

151             xtw.WriteEndElement();

152             xtw.WriteStartElement("whenRun");

153             xtw.WriteString(whenRun);

154             xtw.WriteEndElement();

155             xtw.WriteEndElement();

156             xtw.WriteEndElement();

157             xtw.Close();

158         }

159 

160         private static void UpdateXMLByXSLT(string tcPath)

161         {

162             XslTransform xst = new XslTransform();

163             xst.Load(@"..\..\testCasesModifier.xslt");

164             xst.Transform(tcPath, @"..\..\testCasesModifier.xml");

165             Console.WriteLine("Done. New XML file is 'testCasesModifier.xml'");

166         }

167 

168         private static void VerifyByXsdSchema(string tcPath)

169         {

170             XmlSchemaCollection xsc = new XmlSchemaCollection();

171             xsc.Add(null, @"..\..\testCases.xsd");

172             XmlTextReader xtr = new XmlTextReader(tcPath);

173             XmlValidatingReader xvr = new XmlValidatingReader(xtr);

174             xvr.ValidationType = ValidationType.Schema;

175             xvr.Schemas.Add(xsc);

176             xvr.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

177             while (xvr.Read()) ;

178 

179             Console.WriteLine("If no error message then XML is valid");

180         }

181 

182         private static void ValidationCallBack(object sender, ValidationEventArgs ea)

183         {

184             Console.WriteLine("Validation error: " + ea.Message);

185             Console.ReadLine();

186         }

187 

188         public static void DisplayInfo(DataSet ds)

189         {

190             foreach (DataTable dt in ds.Tables)

191             {

192                 Console.WriteLine("\n==========================================");

193                 Console.WriteLine("Table= " + dt.TableName + "\n");

194                 foreach (DataColumn dc in dt.Columns)

195                     Console.Write("{0,-14}", dc.ColumnName);

196                 Console.WriteLine("\n------------------------------------------");

197                 foreach (DataRow dr in dt.Rows)

198                 {

199                     foreach(object data in dr.ItemArray)

200                         Console.Write("{0,-14}", data.ToString());

201                     Console.WriteLine();

202                 }

203                 Console.WriteLine("\n==========================================");

204             }

205             foreach (DataRelation dr in ds.Relations)

206             {

207                 Console.WriteLine("\n\nRelations:");

208                 Console.WriteLine(dr.RelationName+"\n\n");

209             }

210         }

211 

212         private static void ParseByDataSet(Utility.Suite suite, string tcPath)

213         {

214             DataSet ds = new DataSet();

215             ds.ReadXml(tcPath);

216 

217             foreach (DataRow row in ds.Tables["testcase"].Rows)

218             {

219                 Utility.TestCase tc=new Utility.TestCase();

220                 tc.id = row["id"].ToString();

221                 tc.bvt = row["bvt"].ToString();

222                 tc.expected = row["expected"].ToString();

223 

224                 DataRow[] children = row.GetChildRows("testcase_inputs"); //relation name

225                 tc.arg1=(children[0]["arg1"]).ToString();

226                 tc.arg2=(children[0]["arg2"]).ToString();

227 

228                 suite.cases.Add(tc);

229             }

230             DisplayInfo(ds);

231         }

232 

233         private static void ParseByXmlSerializer(string tcPath)

234         {

235             XmlSerializer xs = new XmlSerializer(typeof(SerializerLib.Suite));

236             StreamReader sr = new StreamReader(tcPath);

237             SerializerLib.Suite suite = (SerializerLib.Suite)xs.Deserialize(sr);

238             sr.Close();

239             suite.Display();

240         }

241 

242         private static void ParseByXPathDocument(Utility.Suite suite, string tcPath)

243         {

244             System.Xml.XPath.XPathDocument xpd = new XPathDocument(tcPath);

245             XPathNavigator xpn = xpd.CreateNavigator();

246             XPathNodeIterator xpi = xpn.Select("/suite/testcase");

247 

248             while (xpi.MoveNext())

249             {

250                 Utility.TestCase tc = new Utility.TestCase();

251                 tc.id = xpi.Current.GetAttribute("id", xpn.NamespaceURI);

252                 tc.bvt = xpi.Current.GetAttribute("bvt", xpn.NamespaceURI);

253 

254                 XPathNodeIterator tcChild = xpi.Current.SelectChildren(XPathNodeType.Element);

255                 while (tcChild.MoveNext())

256                 {

257                     

258                         if (tcChild.Current.Name == "inputs")

259                         {

260                             XPathNodeIterator tcSubChild = tcChild.Current.SelectChildren(XPathNodeType.Element);

261                             while (tcSubChild.MoveNext())

262                             {

263                                 if (tcSubChild.Current.Name == "arg1")

264                                     tc.arg1 = tcSubChild.Current.Value;

265                                 else if (tcSubChild.Current.Name == "arg2")

266                                     tc.arg2 = tcSubChild.Current.Value;

267                             }

268                         }

269                         else if (tcChild.Current.Name == "expected")

270                             tc.expected = tcChild.Current.Value;

271 

272                 }

273                 suite.cases.Add(tc);

274             }

275         }

276 

277         private static void ParseByXMLDocument(Utility.Suite suite, string tcPath)

278         {

279             XmlDocument xd = new XmlDocument();

280             xd.Load(tcPath);

281 

282             //get all <testcase> nodes

283             XmlNodeList nodeList = xd.SelectNodes("/suite/testcase");

284             foreach (XmlNode node in nodeList)

285             {

286                 Utility.TestCase tc = new Utility.TestCase();

287                 tc.id = node.Attributes.GetNamedItem("id").Value;

288                 tc.bvt = node.Attributes.GetNamedItem("bvt").Value;

289 

290                 XmlNode n = node.SelectSingleNode("inputs");

291                 tc.arg1 = n.ChildNodes.Item(0).InnerText;

292                 tc.arg2 = n.ChildNodes.Item(1).InnerText;

293                 tc.expected = node.ChildNodes.Item(1).InnerText;

294 

295                 suite.cases.Add(tc);

296             }

297         }

298 

299         private static void ParseByXMLTextReader(Utility.Suite suite, string tcPath)

300         {

301             XmlTextReader xtr = new XmlTextReader(tcPath);

302             xtr.WhitespaceHandling = WhitespaceHandling.None;

303             xtr.Read(); //read xml declaration, move to tag<suite>

304 

305             while (!xtr.EOF)

306             {

307                 if (xtr.Name == "suite" && !xtr.IsStartElement()) break;

308                 while (xtr.Name != "testcase" || !xtr.IsStartElement())

309                     xtr.Read(); //move to tag<testcase>

310 

311                 Utility.TestCase tc = new Utility.TestCase();

312                 tc.id = xtr.GetAttribute("id");

313                 tc.bvt = xtr.GetAttribute("bvt");

314                 xtr.Read(); //move to tag <inputs>

315                 xtr.Read(); //move to tag <arg1>

316                 tc.arg1 = xtr.ReadElementString("arg1");

317                 tc.arg2 = xtr.ReadElementString("arg2");

318                 xtr.Read(); //move to tag <expected>

319                 tc.expected = xtr.ReadElementString("expected");

320                 //current tag is </testcase>

321                 suite.cases.Add(tc);

322 

323                 xtr.Read(); //current tag is <testcase> or </suite>

324             }

325             xtr.Close();            

326         }

327     }

328 }

329 

330 namespace SerializerLib

331 {

332     using System.Xml.Serialization;

333 

334     [XmlRootAttribute("suite")]

335     public class Suite

336     {

337         [XmlElementAttribute("testcase")]

338         public TestCase[] items;

339         public void Display()

340         {

341             foreach(TestCase tc in items)

342             {

343                 Console.WriteLine(tc.id + " " + tc.bvt + " " + tc.inputs.arg1 + " " + tc.inputs.arg2 + " " + tc.expected);

344             }

345         }

346         

347     }

348 

349     public class TestCase

350     {

351         [XmlAttributeAttribute()]

352         public string id;

353         [XmlAttributeAttribute()]

354         public string bvt;

355         [XmlElementAttribute("inputs")]

356         public Inputs inputs;

357         public string expected;

358 

359     }

360 

361     public class Inputs

362     {

363         public string arg1;

364         public string arg2;

365     }

366 }

367 

368 namespace Utility

369 {

370     public class TestCase

371     {

372         public string id;

373         public string bvt;

374         public string arg1;

375         public string arg2;

376         public string expected;

377     }

378 

379     public class Suite

380     {

381         public System.Collections.ArrayList cases = new System.Collections.ArrayList();

382         public void Display()

383         {

384             foreach (TestCase tc in cases)

385             {

386                 Console.WriteLine(tc.id + " " + tc.bvt + " " + tc.arg1 + " " + tc.arg2 + " " + tc.expected);

387             }

388         }

389     }

390 }
View Code

 

你可能感兴趣的:(软件测试)