﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-大话人生-随笔分类-自动化测试</title><link>http://www.cnitblog.com/stomic/category/8438.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 07 Jul 2015 16:19:26 GMT</lastBuildDate><pubDate>Tue, 07 Jul 2015 16:19:26 GMT</pubDate><ttl>60</ttl><item><title>[转载]关键字驱动自动化测试 </title><link>http://www.cnitblog.com/stomic/archive/2015/07/07/90143.html</link><dc:creator>大话人生</dc:creator><author>大话人生</author><pubDate>Tue, 07 Jul 2015 10:57:00 GMT</pubDate><guid>http://www.cnitblog.com/stomic/archive/2015/07/07/90143.html</guid><wfw:comment>http://www.cnitblog.com/stomic/comments/90143.html</wfw:comment><comments>http://www.cnitblog.com/stomic/archive/2015/07/07/90143.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/stomic/comments/commentRss/90143.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/stomic/services/trackbacks/90143.html</trackback:ping><description><![CDATA[<div><h1> <span style="font-size:16.0pt;line-height:150%;font-family:黑体;font-weight:normal;">第一章<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size:16.0pt;line-height:150%; font-family:黑体;Times new roman&quot;;Times new roman&quot;;font-weight:normal;">前言</span></h1> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt;">为 了提高测试效率和准确性，越来越多的测试工作引入了自动化测试的思想和方法，随着自动化测试工具的发展，自动化测试更加容易实现更高效。实践证明，软件自 动化测试技术帮助软件开发和测试人员在更短的时间内开发出更高质量的产品，通过代替频繁重复的手工测试从而节省了大量的时间开支。同时，自动化测试技术也避免了手工测试出现的人为错误，完成了许多手工测试无法实现的工作。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt;">自动化测试相较于手动测试有许多明显的优势，执行高效率、测试数据覆盖面大、结果可信。但同时自动化测试也存在着一些限制。简单的录制</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">/</span><span style="font-size: 14pt;">回放测试工具本省无法提供高效的测试。依靠捕捉产生脚本的维护需要耗费大量的时间。在项目需求不稳定或页面频繁变动的阶段，自动化测试的效率将非常低下。</span></p> <p style="text-indent:21.0pt;line-height:15.0pt"> <span style="font-size: 14pt;">面对自动化测试的这种尴尬，关键字驱动的自动化测试可有效地提高自动化测试脚本的维护效率。关键字驱动的自动化测试搭建了一个自动化测试框架，测试框架脚本与业务、数据分离，节省了大量对脚本的维护工作。本文对关键字驱动的自动化测试做具体介绍。</span></p> <h1> <span style="font-size:16.0pt;line-height:150%;font-family:黑体;font-weight:normal;">第二章<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size:16.0pt;line-height:150%; font-family:黑体;Times new roman&quot;;Times new roman&quot;;font-weight:normal;">自动化测试工具存在的问题</span></h1> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">基本的录制</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">/</span><span style="font-size: 14pt; font-family: 宋体;">回 放自动化测试具有简单易用、快速上手的特点，但在实际应用过程中存在很多问题。最常见的一个问题是对程序界面进行测试时，一旦界面有任何改动，都需要我们 去手工修改已录制的相应测试脚本，或者重新进行一次录制。这需要消耗很大的工作量，尤其对于程序中各模块都要使用的公共程序部分（如登陆页面），他的改动 会引起大量脚本的返工。如在使用</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">Rational Robot</span><span style="font-size: 14pt; font-family: 宋体;">录制的点击按钮操作的脚本：测试工具通过按钮的名字、显示文本来识别这个按钮。可以想象，当其中任何一个部分发生变化时都会对脚本造成影响，维护如此的脚本将很可能花费大量成本。</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">另一个问题是移植风险大。被测试软件转换平台，或转变自动化测试工具都可能造成测试用例被破坏，很可能要对现有脚本进行大量修改或重新录制。因此转换平台或转换工具可能对自动化测试带来毁灭性影响。</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">&nbsp;<wbr></span></p> <h1> <span style="font-size:16.0pt;line-height:150%;font-family:黑体;font-weight:normal;">第三章<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr></span></span><span style="font-size:16.0pt;line-height:150%;font-family:黑体;Times new roman&quot;;Times new roman&quot;;font-weight:normal;">自动化测试的发展</span></h1> <h2>3.1<span style="font-family:宋体;">自动化测试框架的发展</span></h2> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt;">一 个自动化测试框架就是一个由假设、概念以及为自动化测试提供支持的实践的集合。自动化测试框架可以减少测试脚本实现和维护的成本，使测试人员把精力集中在 测试用例的设计上。自动化测试框架的好坏直接影响到自动化测试的成功与否。一个优秀的自动化测试框架应该满足以下特点：</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">1)</span> <span style="font-size: 14pt;">测试框架与被测应用程序独立。虽然测试的应用程序不一样，但被测应用程序之间却会有相同的地方，测试框架应聚焦在不同测试应用程序中共同的部分，把与具体应用程序有关的部分从框架中移除。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">2)</span> <span style="font-size: 14pt;">测 试框架应易于扩展、维护。测试框架应被高度模块化，这样可以提高框架的维护性。各个模块之间相互独立，对模块内部的修改不应该影响其他模块。除此之外，系 统应该有充足、详细的文档，与软件开发一样，这也是必不可少的。设计文档可以帮助开发人员扩展、维护测试框架，而使用文档则可以告诉用户要怎么使用该框 架。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">3)</span> <span style="font-size: 14pt;">测试脚本所使用的测试语言应该是与框架独立的。不同的测试框架可能在不同的应用领域有不同的表现，有些适用于</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">Java</span><span style="font-size: 14pt;">应用程序的测试，</span> <span style="font-size: 14pt;">有些可能适用于</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">Web</span><span style="font-size: 14pt;">应用程序的测试，如果测试脚本所采用的语言是私有的、与测试框架绑定的，那么当需要从一个测试框架迁移到另外一个测试框架时，所有的测试脚本都需要重写。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">4)</span> <span style="font-size: 14pt;">测 试框架不应该让框架的复杂性影响到测试人员。在大多数情况下，测试人员就是测试人员而不是开发人员，甚至有的时候，他们不是专业的测试人员，可能只是具有 很少软件开发经验的某个应用领域的专家。对于这些使用者来说，测试框架的使用要简单、测试语言要易于理解，这样可以使他们专注于业务相关内容的编写。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 0cm;text-indent:28.0pt;line-height:21.0pt"> <span style="font-size: 14pt;">基于界面的软件自动化测试框架和工具的发展大致经历了三个阶段：</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 0cm;text-indent:28.0pt;line-height:21.0pt"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">1</span><span style="font-size: 14pt;">）简单的录制／回放：由工具录制并记录操作的过程和数据形成脚本，通过回放来重复人工操作的过程。在这种模式下数据和脚本混在一起，几乎一个测试用例对应一个脚本，维护成本很高。而且即使界面的简单变化也需要重新录制，脚本可重复使用的效率低。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 0cm;text-indent:28.0pt;line-height:21.0pt"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">2</span><span style="font-size: 14pt;">）数据驱动</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">&nbsp;<wbr></span><span style="font-size: 14pt;">（</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">data driven</span><span style="font-size: 14pt;">）的自动化测试：从数据文件读取输入数据，通过变量的参数化，将测试数据传入测试脚本，不同的数据文件对应不同的测试用例。在这种模式下数据和脚本分离，脚本的利用率、可维护性大大提高，数据的覆盖率也较高，但受界面变化的影响仍然很大。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 0cm;text-indent:28.0pt;line-height:21.0pt"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">3</span><span style="font-size: 14pt;">）关键字驱动（</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">keyword driven</span><span style="font-size: 14pt;">）的自动化测试：关键字驱动测试是数据驱动测试的一种改进类型，它将测试逻辑按照关键字进行分解，形成数据文件，关键字对应封装的业务逻辑。</span> <span style="font-size: 14pt;">主要关键字包括三类：被操作对象（</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">Item</span><span style="font-size: 14pt;">）、操作（</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">Operation</span><span style="font-size: 14pt;">）和值（</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">value</span><span style="font-size: 14pt;">），依据不同对象还有其他对应参数。关键字驱动的主要思想是：脚本与数据分离、界面元素名与测试内部对象名分离、测试描述与具体实现细节分离。数据驱动的自动化测试框架在受界面影响方面，较数据驱动和录制</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">/</span><span style="font-size: 14pt;">回放有明显的优势，可根据界面的变化更新对应的关键字对象，而不用重新录制脚本。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 0cm;text-indent:28.0pt;line-height:21.0pt"> <span style="font-size: 14pt;">关键字驱动的自动化测试系统与数据驱动的系统相比，主要的不同有两点：第一点是数据文件 的设计方法不同，数据驱动系统中数据文件存储的是测试输入数据，脚本中仍然存在业务逻辑，这样业务的变化会引起脚本的更改，而关键字驱动系统数据文件的设 计将业务和测试输入数据都集成在数据表格中，虽然设计复杂，但当业务发生变化时，无需更改测试所用的脚本，从而提高了测试的效率。第二点是与数据驱动系统 相比，由于关键字驱动系统中数据文件的设计包含了业务信息，因此，将测试所进行的操作封装为关键字支持脚本。由动作封装的关键字支持脚本不包含任何的数据和业务信息，其重用性得到了极大的增强。</span></p> <h2>3.2<span style="font-family:宋体;">自动化测试脚本的发展</span></h2> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 0cm;text-indent:28.0pt;line-height:21.0pt"> <span style="font-size: 14pt;">相应地，软件测试自动化脚本的类型也依据脚本框架的演进在不断发展，从低到高的发展层次是：</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 21.0pt;text-indent:-21.0pt;line-height:21.0pt;"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">1)<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size: 14pt;">线性脚本：通过录制直接产生的线性执行的脚本，类似于宏录制。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 21.0pt;text-indent:-21.0pt;line-height:21.0pt;"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">2)<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size: 14pt;">结构化的脚本：具有顺序、循环、分支等结构的脚本。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 21.0pt;text-indent:-21.0pt;line-height:21.0pt;"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">3)<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size: 14pt;">共享的脚本：可以被多个测试用例使用，被其它脚本调用的脚本。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 21.0pt;text-indent:-21.0pt;line-height:21.0pt;"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">4)<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size: 14pt;">数据驱动的脚本：数据和流程控制分离的脚本，通过读入数据文件来驱动流程进行的脚本。</span></p> <p style="margin-top:12.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left: 21.0pt;text-indent:-21.0pt;line-height:21.0pt;"> <span style="font-size: 14pt; font-family: Verdana, sans-serif;">5)<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr>&nbsp;<wbr></span></span> <span style="font-size: 14pt;">关键字驱动的脚本：脚本、数据、业务分离，数据和关键字在不同的数据表中，通过关键字来驱动测试业务逻辑。关键字驱动脚本的特点是它描述一个测试事例做什么</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">,</span> <span style="font-size: 14pt;">而不是如何做，测试脚本调用测试用例再具体执行。</span></p> <p style="text-indent:21.0pt">&nbsp;<wbr></p> <h1> <span style="font-size:16.0pt;line-height:150%;font-family:黑体;font-weight:normal;">第四章<span style="font:7.0pt &quot;Times new roman&quot;">&nbsp;<wbr></span></span> <span style="font-size:16.0pt;line-height:150%;font-family:黑体;Times new roman&quot;;Times new roman&quot;;font-weight:normal;">关键字驱动的自动化测试框架</span></h1> <h2>4.1<span style="font-family:宋体;">基本原理</span></h2> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt;">关键字驱动的自动化测试框架是对数据驱动的逻辑扩展，</span><span style="font-size:14.0pt">用关键字的形式将测试逻辑封装在数据文件中，测试工具只要能够解释这些关键字即可对其应用自动化，</span><span style="font-size: 14pt;">它的核心思想可以概括为三个分离。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">1</span><span style="font-size: 14pt;">）界面元素名与测试内部对象名的分离</span> <span style="font-size: 14pt;">在被测应用程序和录制生成的测试脚本之间增加一个抽象层，它可以将界面上的所有元素映射成相对应的一个逻辑对象，测试针对这些逻辑对象进行，界面元素的改变只会影响映射表，而不会影响测试。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">2</span><span style="font-size: 14pt;">）测试描述与具体实现细节的分离，把测试描述和测试的具体实现细节分离开来。测试描述只说明软件测试要做什么以及期待什么样的结果，而不管怎样执行测试或怎样证实结果。这样做是因为测试的实现细节通常与特定的平台以及特定的测试执行工具有着密切的联系。这种分离使得测试描述对于应用实现细节是不敏感的，而且有利于测试在工具和平台间的移植。</span></p> <p style="text-indent:28.0pt;line-height:15.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">3</span><span style="font-size: 14pt;">）脚本与数据的分离</span> <span style="font-size: 14pt;">最后，可以把测试执行过程中所需的测试数据从脚本中提取出来，在运行时测试脚本再从数据存放处读取预先定制好的数据，这样脚本和数据可以独立维护。</span></p> <p style="text-indent:25.9pt;line-height:15.0pt"> <span style="font-size: 14pt;">以上这三个分离各司其职、互相独立，最大程度地减少相互之间的影响。从关键字驱动的思想可以看出，该种测试框架不仅实现了将数据和脚本相分离，而且实现了测试逻辑和数据的分离，大大提高了脚本的复用度和维护性，从而更大限度地实现了测试工具的自动化。</span></p> <p style="text-indent:25.9pt;line-height:15.0pt"> <span style="font-size: 14pt;">例如在一个登陆页面输入用户名，用一个测试表（表格</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">1</span><span style="font-size: 14pt;">）来表示：</span></p> <div align="center"> <table style="width:317.35pt;margin-left:-12.7pt;border-collapse:collapse;border: none;" border="1" cellpadding="0" cellspacing="0" width="423"> <tbody> <tr style="height:28.9pt"> <td style="width:88.15pt;border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="118"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">窗口</span></p> </td> <td style="width:71.5pt;border:solid windowtext 1.0pt; border-left:none;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="95"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">对象</span></p> </td> <td style="width:70.35pt;border:solid windowtext 1.0pt; border-left:none;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="94"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">行为</span></p> </td> <td style="width:87.35pt;border:solid windowtext 1.0pt; border-left:none;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="116"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">参数</span></p> </td> </tr> <tr style="height:28.9pt"> <td style="width:88.15pt;border:solid windowtext 1.0pt; border-top:none; padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="118"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">LoginPage</span></p> </td> <td style="width:71.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="95"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">UserID</span></p> </td> <td style="width:70.35pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="94"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">InputText</span></p> </td> <td style="width:87.35pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:28.9pt" nowrap="nowrap" width="116"> <p style="text-align:center;text-indent:0cm;page-break-after:avoid" align="center"> <span style="font-size: 11pt; font-family: 宋体;">&#8220;admin&#8221;</span></p> </td> </tr> </tbody> </table> </div> <p style="text-align:center" align="center"> <span style="font-family:黑体;"> 图表</span>  1 <span style="font-family:黑体;"> 登陆测试表</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">这个测试表的含义是在</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">LoginPage</span><span style="font-size: 14pt; font-family: 宋体;">窗口的</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">UserID</span><span style="font-size: 14pt; font-family: 宋体;">文本框中输入&#8220;</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">admin</span><span style="font-size: 14pt; font-family: 宋体;">&#8221;。其中</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">InputText</span><span style="font-size: 14pt; font-family: 宋体;">是关键字，当测试程序读取它的时候，就会调用相应的处理函数，处理脚本动作。</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: Verdana, sans-serif;">&nbsp;<wbr></span></p> <h2>&nbsp;<wbr><span style="font-family:宋体;">关键字驱动测试模型</span></h2> <p style="text-align:center;text-indent:0cm;page-break-after:avoid" align="center"> <span> <img alt="[转载]关键字驱动自动化测试" title="[转载]关键字驱动自动化测试" height="435" width="554" /></span></p> <p style="text-align:center" align="center"> <span style="font-family:黑体;"> 图</span>  1 <span style="font-family:黑体;"> 关键字驱动模型</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">测 试首先由初始脚本开始，把高层测试表传递给高层驱动器，高层驱动器在处理这些表的过程中，遇到中层测试表就调用中层驱动器，中层驱动器处理中层表。当低层 驱动器处理低层表的时候，他试着使应用与测试保持同步。当低层驱动遇到某一成员的关键字指令时，它调用相应的函数模块来处理关键字的动作指令。所有这些元 素都要依靠映射表中的信息，踏实自动化模型和应用间的桥梁。</span></p> <h3><span style="font-size:15.0pt;line-height:173%;font-family:宋体;font-weight:normal;"> 应用映射表</span></h3> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">映射表是关键字驱动自动化测试中的关键组件之一。映射表是对应用中的每一个对象定义一套命名规范，并利用映射表把这些名字和自动化工具识别的对象名联系起来，是工具能准确定位和操纵对象，我们的脚本只需进行单点维护。</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">映射表的建立有许多种，简单的就是 通过自动化测试工具进行自动捕获，将捕获的对象信息存储于指定的数据表格或数据库之中。如果是自动捕获可以分类记录尽可能多的对象的属性，使得测试脚本更 方便地标识对象。另一种就是采用人工录入，即对于自动化软件测试需要用到的对象信息采用手工识别的方式录入数据文件或数据库之中。这种方式通常是挑选最能 达到测试效果的一组对象属性即可。对于结构复杂的软件可以根据软件的不同层次或是软件界面的不同区域划分对象库。例如对于窗口空间，我们可以将窗口命名为 上下左右主几个部分，将位于不同窗口区域的控件信息保存到相应的窗口名称之下，这样当软件升级或者是</span><span style="font-size: 14pt; font-family: Verdana, sans-serif;">GUI</span><span style="font-size: 14pt; font-family: 宋体;">界面发生变化时，对于增加的窗口或者是控件，只需要使用测试工具捕获其标识属性，并人工填充到映射表内即可。这样就为测试脚本提供了对象识别的仓库。</span></p> <h3><span style="font-size:15.0pt;line-height:173%;font-family:宋体;Times new roman&quot;;Times new roman&quot;;font-weight:normal;"> 成员函数</span></h3> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">成员函数是实现用户对界面对象操作指令的函数，一个成员对象的类型对应一个成员函数库。例如对以一个文本框对象，可对它进行多种操作：输入文本、验证文本框的值等，实现这些操作行为的函数就被放在文本框的成员函数库中。一般的测试工具都提供了这样的函数。</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">成员函数相当于在应用和自动化工具之间提供了一个隔离层，如果没有这个隔离层，自动化工具本身的改变会影响到已有的脚本。有了隔离层，当测试工具发生变化时，可以在成员函数库中增加一段修补代码来适应变化。</span></p> <h3><span style="font-size:15.0pt;line-height:173%;font-family:宋体;Times new roman&quot;;Times new roman&quot;;font-weight:normal;"> 测试表和核心驱动程序</span></h3> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">测试表分低层、中层、高层。低层测试表指定了测试的每一步指令语句，这些指令都是直接作用在界面对象上的，是无法再锌粉的指令。中层测试表把低层表组装起来执行任务，形成测试用例。高层测试表把中层表组装起来，利用循环完成不同的中层测试，形成测试集。</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">例如打开网页、登陆、关闭页面这三个动作可以用三个低层表来表示（如表），每个表定义了实现相应动作的具体步骤，所以低层表示又叫做步骤表。低层表中使用了映射表中定义的对象名，和成员函数库定义的底层关键字库。</span></p> <p style="text-indent:21.0pt">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p> <div align="center"> <table style="width:355.1pt;border-collapse:collapse;border:none;" border="1" cellpadding="0" cellspacing="0" width="473"> <tbody> <tr style="height:18.35pt"> <td style="width:76.1pt;border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="101"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">窗口</span></p> </td> <td style="width:119.9pt;border:solid windowtext 1.0pt; border-left:none;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="160"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">对象</span></p> </td> <td style="width:77.05pt;border:solid windowtext 1.0pt; border-left:none;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="103"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">行为</span></p> </td> <td style="width:82.05pt;border:solid windowtext 1.0pt; border-left:none;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="109"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">参数</span></p> </td> </tr> <tr style="height:18.35pt"> <td style="width:76.1pt;border:solid windowtext 1.0pt; border-top:none; padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="101"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">LoginPage</span></p> </td> <td style="width:119.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="160"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">UserIDField</span></p> </td> <td style="width:77.05pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="103"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">InputText</span></p> </td> <td style="width:82.05pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="109"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">&#8220;admin&#8221;</span></p> </td> </tr> <tr style="height:18.35pt"> <td style="width:76.1pt;border:solid windowtext 1.0pt; border-top:none; padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="101"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">LoginPage</span></p> </td> <td style="width:119.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="160"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">PasswordField</span></p> </td> <td style="width:77.05pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="103"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">InputText</span></p> </td> <td style="width:82.05pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="109"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">&#8220;123&#8221;</span></p> </td> </tr> <tr style="height:18.35pt"> <td style="width:76.1pt;border:solid windowtext 1.0pt; border-top:none; padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="101"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">LoginPage</span></p> </td> <td style="width:119.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="160"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">SubmitButton</span></p> </td> <td style="width:77.05pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="103"> <p style="text-align:center;text-indent:0cm;" align="center"> <span style="font-size: 11pt; font-family: 宋体;">Click</span></p> </td> <td style="width:82.05pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.35pt" nowrap="nowrap" width="109"> <br /></td> </tr> </tbody> </table> </div> <p style="text-align:center" align="center"> <span style="font-family:黑体;"> 图表</span>  2 <span style="font-family:黑体;"> &#8220;登陆&#8221;步骤表</span></p> <p style="text-indent:28.0pt"><span style="font-size: 14pt; font-family: 宋体;">这个&#8220;登陆&#8221;动作的低层表可能出现在&#8220;验证正确登陆&#8221;，&#8220;验证错误登陆&#8221;和&#8220;验证空白登陆&#8221;等中层用例表中，这些中层表合起来构成了&#8220;验证权限&#8221;高层表。</span></p> <span style="font-size: 14pt; font-family: 宋体;">对应以上这三个测试表，核心数据驱动引擎相应地分成高层、中层、低层驱动器。高层驱动循环读取高层表的每条记录，遇到中间表的关键字，就把这个表传递给中层驱动器，依次类推直至到达低层表，低层驱动器来完成最后的执行。</span></div><img src ="http://www.cnitblog.com/stomic/aggbug/90143.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/stomic/" target="_blank">大话人生</a> 2015-07-07 18:57 <a href="http://www.cnitblog.com/stomic/archive/2015/07/07/90143.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QTP自动化测试框架的基础知识</title><link>http://www.cnitblog.com/stomic/archive/2014/01/14/89211.html</link><dc:creator>大话人生</dc:creator><author>大话人生</author><pubDate>Tue, 14 Jan 2014 08:12:00 GMT</pubDate><guid>http://www.cnitblog.com/stomic/archive/2014/01/14/89211.html</guid><wfw:comment>http://www.cnitblog.com/stomic/comments/89211.html</wfw:comment><comments>http://www.cnitblog.com/stomic/archive/2014/01/14/89211.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/stomic/comments/commentRss/89211.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/stomic/services/trackbacks/89211.html</trackback:ping><description><![CDATA[<p>1. 什么是自动化测试框架?</p>
<p>假定你有一个活，需要构建许多自动化测试用例来测试这个应用程序。当你对这个应用程序完成自动化测试后，你对自己创建脚本应该有什么期望吗？你难道不想要-</p>
<ul><li>脚本应该按照预期的来执行而且没有发生任何问题</li><li>脚本和流程应该会被很容易的理解</li><li>脚本是容易维护的</li></ul>
<p>所有以上观点需要一个合适的自动化测试框架才能被实现</p>
<p><strong>一个自动化测试框架是一个规范或者是约束，你需要让测试脚本遵从一些规则来完成上面提到的3点内容</strong>，这些规则或者纲要如下，比如</p>
<ul><li>指定一些目录结构用来存储对应的测试用例，函数库，对象库和数据表格</li><li>决定数据表格格式，比如数据表个应该怎么组织，脚本是怎么访问这些数据表格的</li><li>遵循正确的代码标准，并且要在代码里有备注，以便别人能看懂你的代码</li><li>尽可能把一些能复用的代码封装成为函数，以便在发生变化的时候只需要修改很少的一部分</li></ul>
<p>在创建测试脚本的时候始终遵循你设置的准则，这样可以创建一个包含所有你曾经有针对性的功能的自动化测试框架</p>
<p>框架的类型分别如下：</p>
<p>2. 在QTP使用的不同类型的框架</p>
<p><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141438206583.png" /></p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">&nbsp;</p>
<p>3. QTP里的线性框架</p>
<p>线性框架是你一步一步在测试流程里写测试脚本。在这样的框架类型中，你不需要创建任何函数，所有的测试步骤都是从上到下线性的顺序来写。假如你有一个测试用例，它是按照 Login-&gt;Create-&gt;Order-&gt;Logout的流程来走，那么测试脚本就会按照如下图所写一样：</p>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141016192679.png" /></p>
<p style="margin-left: 60px">3.1 在线性框架里的组件和工作流</p>
<p style="margin-left: 60px">以下图形展示了关于QTP线性框架的组件和典型的工作流</p>
<p style="margin-left: 90px">&nbsp;<img alt="" src="http://images.cnitblog.com/blog/588942/201401/141442029708.png" /></p>
<p style="margin-left: 60px">在这里每个测试用例都有它自己的对象库并且脚本里的数据都是hardcode</p>
<p style="margin-left: 60px">&nbsp;</p>
<p style="margin-left: 60px">3.2 线性框架的优势：</p>
<ul><li style="margin-left: 60px">不需要自动化的专业知识，你只需要录制和回放的方法就能用来创建脚本</li><li style="margin-left: 60px">快速和容易的方式来创建测试脚本</li><li style="margin-left: 60px">由于脚本是按照从上到下的顺序来写的，所以框架流程理解起来比较容易</li></ul>
<p style="margin-left: 60px">3.3 线性框架的缺点：</p>
<ul><li style="margin-left: 60px">重用代码的唯一方式是不断的复制和粘贴，从而导致大量冗余的代码</li><li style="margin-left: 60px">由于脚本里数据都是hardcode，同一个测试用例不能被不同的测试数据所驱动</li><li style="margin-left: 60px">由于代码在许多地方都是重复的，所以一旦有地方发生变化就需要修改很多地方</li></ul>
<p>4. 关于QTP的模块框架</p>
<p>模块框架就是把所有的测试用例首先要分析下找出可以复用的流程的一个方法。然后把所有可以复用的流程放进函数里封装起来存储在外部文件中，当需要的时候可以在脚本里调用这些函数。考虑以下2个测试用例。</p>
<p>a)Login&gt;Create Order&gt;Logout.</p>
<p>b)Login&gt;Search Order&gt;Logout.</p>
<p>在这里登录和登出是可以复用的流程。那么这些流程就被封装起来保存在外部函数库里。测试脚本应该看起来像这样</p>
<p style="margin-left: 30px">&nbsp;<img alt="" src="http://images.cnitblog.com/blog/588942/201401/141445585338.png" /></p>
<p style="margin-left: 30px">4.1 模块框架的组件和工作流</p>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141447226587.png" /></p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">为了可以使用外部库文件里的函数，库文件首先需要和测试用例关联起来。这样测试用例就可以调用库文件里的函数了</p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">4.2 模块框架的优点：</p>
<ul><li style="margin-left: 30px">由于复用的函数只需要创建一次，测试脚本就只需要调用所需要的函数，而不需要重新再写一遍函数里的内容，那么创建起来就快一点</li><li style="margin-left: 30px">由于代码的复用，创建测试用例所花的功夫也会缩短</li><li style="margin-left: 30px">如果复用的函数里发生任何改变，只需要改变一个地方就会影响到调用它的所有测试用例，因此维护起来也会很容易</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">4.3 模块框架的缺点：</p>
<ul><li style="margin-left: 30px">由于脚本里的数据还是hardcode，所以还是不能实现不同的测试数据运行同一个脚本</li><li style="margin-left: 30px">需要花费额外的时间来分析测试用例识别出那些是可以复用的</li><li style="margin-left: 30px">创建和维护函数库需要好的编程知识</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p>5. QTP的数据驱动框架</p>
<p style="margin-left: 30px">在数据驱动框架里，测试脚本里的数据不在是hard-code。相反，数据是被存储在一些外部文件里。测试脚本需要首先连接到外部数据源，然后从数据源里解析这些数据。大部分时间，我们一般都会使用Excel表格用来存储数据。其它的经常使用的外部数据源是：文本文件，XML文件，数据库以及一个外部文件以上的组合</p>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141450282361.png" /></p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">5.1 数据驱动框架的组件和流程</p>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141451361897.png" /></p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">5.2 数据驱动框架的优点：</p>
<ul><li style="margin-left: 30px">由于数据与测试脚本是分离的，可以实现同一个脚本用不同的数据可以运行多次</li><li style="margin-left: 30px">测试数据的更改不会影响到测试脚本，反之亦然</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">5.3 数据驱动框架的缺点：</p>
<ul><li style="margin-left: 30px">连接到数据源并读取里面的数据是需要额外的努力和相关专业的知识</li><li style="margin-left: 30px">需要用额外的时间来选择使用那种外部数据源，并且要决定外部数据源里的数据应该怎么被存储或是组织</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p>&nbsp;6. QTP的关键字驱动框架</p>
<p>在关键字驱动框架里，你可以创建一些关键字以及相关联的一些方法和函数。然后你创建一个函数库，它里面包含一个读取关键字的逻辑，然后调用相关的动作。</p>
<p>关键字驱动框架有许多不同的形式，其中一个解释如下：</p>
<p style="margin-left: 30px">6.1 关键字驱动框架的组件</p>
<ul><li>数据表格或者Excel表格包含了关键字和需要执行特定流程或者动作的步骤</li></ul>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141454148458.png" /></p>
<ul><li>一个函数库里包含一些函数，这些函数可以读取Excel里每行数据，然后把他转换为QTP可以识别的格式（也就是QTP脚本），然后最终执行它。比如，函数库读取Excel里的第一行数据，然后把他转化为----Browser(&#8220;Title&#8221;).Page(&#8220;Title&#8221;).WebEdit(&#8220;UserName&#8221;).Set &#8220;user1&#8221;</li><li>对象库在这个框架里不是必须的，如果你不想用对象库的话，可以用描述性编程</li></ul>
<p style="margin-left: 30px">6.2 关键字驱动框架的工作流</p>
<p style="margin-left: 30px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141455410174.png" /></p>
<p style="margin-left: 30px">6.3 关键字驱动框架的优点：</p>
<ul><li style="margin-left: 30px">关键字和函数库变成完全通用的，因此对于不同的应用可以很容易的被重用</li><li style="margin-left: 30px">所有复杂的逻辑都添加到函数库里了。一旦库文件被准备好，在Excel表格里写测试脚本将变得很容易</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">6.4 关键字框架的缺点：</p>
<ul><li style="margin-left: 30px">需要花很多时间在初始化创建函数库上，关键字驱动框架的优势只有在它被长时间使用的时候才能被充分体现出来</li><li style="margin-left: 30px">创建复杂的关键字函数库需要很强的编程技术</li><li style="margin-left: 30px">对于新人想快速理解框架是有点困难</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p>7. QTP的混合框架</p>
<p>混合框架的意思是上面提到的一些框架的组合，基于需求，你可以合并以上框架的任何功能来组合成你需要的混合框架的版</p>
<p>有许多不同的方式来创建混合框架。让我们一起看看混合框架中其中一种的结构和工作流程</p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">7.1 关键字驱动框架的组件</p>
<ul><li style="margin-left: 30px">驱动脚本：它是一个VBS脚本文件，他是运行测试脚本的入口点</li><li style="margin-left: 30px">批处理表格：批处理表格包含了有已经自动化的所有测试用例列表，并且还包含一个叫做Execute的列名，它的值是"Yes"和"No".驱动脚本会读取这个表格，然后执行被标记为"Yes"的测试用例</li></ul>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141459182200.png" /></p>
<ul><li style="margin-left: 30px">每个测试用例是被分割成不同的业务流程。因此当这个用例包含的业务流程都被执行时候，这个用例才算被完全的执行</li></ul>
<p style="margin-left: 60px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141500107671.png" /></p>
<ul><li style="margin-left: 30px">上面所说的是构成混合框架的主要组件，像函数库，数据表，对象库，配置文件等其它一般的组件也是混合框架的一部分</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">7.2 混合框架的工作流</p>
<p style="margin-left: 30px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141501149391.png" /></p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">7.3 混合框架的优点：</p>
<ul><li style="margin-left: 30px">这个框架最大优点就是你可以用到其他框架最好的功能</li></ul>
<p style="margin-left: 30px">7.4 混合框架的缺点：</p>
<ul><li style="margin-left: 30px">该框架是非常复杂的，需要具备很好的编程知识和经验来从头到尾的构建混合框架</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p>8. QTP的业务流程测试(BPT)框架</p>
<p>把测试用例分成多个流程，每个流程都用业务流程组件(Business process component)来脚本化的一个框架。当一个具体的测试用例所包含的组件都已经准备好以后，你可以在QC里按照你们的业务逻辑来连接这些组件从而组成一个BPT的测试用例，然后就可以执行它</p>
<p style="margin-left: 30px">8.1 BPT框架的组件：</p>
<ul><li style="margin-left: 30px">应用程序区域：它作为一个容器用来存储业务流程组件和其他相关的项，比如函数库，对象库等等。</li><li style="margin-left: 30px">业务流程组件：就像Action和函数是用来存储可以复用的脚本一样，BPT框架有业务流程组件，该组件包含了一个动作所对应的脚本</li><li style="margin-left: 30px">以上提到的2个组件在BPT框架里是非常有用的，而其它就是一些标准的组件，比如函数库，对象库，数据表等等。这些所有组件组成了BPT框架</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">8.2 BPT框架的工作流</p>
<p style="margin-left: 30px"><img alt="" src="http://images.cnitblog.com/blog/588942/201401/141503139869.png" /></p>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">8.3 BPT框架的优点：</p>
<ul><li style="margin-left: 30px">BPT可以让非技术业务专家可以使用业务组件快速创建测试用例</li><li style="margin-left: 30px">许多功能，比如组件链接&amp;数据参数化，这些都是来自BPT内置的功能。有了这些功能，你不需要花费额外的时间来写实现这些功能的代码</li></ul>
<p style="margin-left: 30px">&nbsp;</p>
<p style="margin-left: 30px">8.4 BPT框架的缺点</p>
<ul><li style="margin-left: 30px">BPT框架只能在QC里使用</li><li style="margin-left: 30px">如果你想为了你的测试脚本用BPT框架，需要为该框架支付额外的费用</li></ul><img src ="http://www.cnitblog.com/stomic/aggbug/89211.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/stomic/" target="_blank">大话人生</a> 2014-01-14 16:12 <a href="http://www.cnitblog.com/stomic/archive/2014/01/14/89211.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]使用Visual Studio 2010 Coded UI Test 制作能自动安装/卸载UI应用的程序</title><link>http://www.cnitblog.com/stomic/archive/2012/12/04/86813.html</link><dc:creator>大话人生</dc:creator><author>大话人生</author><pubDate>Tue, 04 Dec 2012 09:42:00 GMT</pubDate><guid>http://www.cnitblog.com/stomic/archive/2012/12/04/86813.html</guid><wfw:comment>http://www.cnitblog.com/stomic/comments/86813.html</wfw:comment><comments>http://www.cnitblog.com/stomic/archive/2012/12/04/86813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/stomic/comments/commentRss/86813.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/stomic/services/trackbacks/86813.html</trackback:ping><description><![CDATA[<div><p>前言</p> <p>Coded UI Test是Visual Studio 2010对于Testing  Project(测试工程)提供的关于UI自动化测试的框架，支持Win32/Web/WPF等UI的自动化测试，在介绍它之前，先简单介绍一下持续集  成。大家如果对持续集成不感兴趣的话，可以直接跳到第3节。</p> <p>&nbsp;</p> <p><span style="background-color:#888888;">1：持续集成</span></p> <p>持续集成由软件工程大师Martin  Fowler提出，他对技术集成下的定义是：持续集成是一种软件开发实践，即团队开发成员经常集成它们的工作，通常每个成员每天至少集成一次，也就意味着  每天可能会发生多次集成。每次集成都通过自动化的构建（包括编译，发布，自动化测试)来验证，从而尽快地发现集成错误。</p> <p>按照持续集成的思想，代码可以也应该能够在一天里可以多次通过&#8220;构建&#8221;，从而能在一天之内提供多个可供测试的版本。</p> <p>这里面讲的构建不单单是代码的编译通过，它应该包含下面的步骤：</p> <ul><li>所有最新代码从配置管理工具中取出.</li><li>所有的代码从干净的状态开始编译。</li><li>将编译结果链接并部署，以备执行。</li><li>执行部署的应用并运行测试套件。</li></ul> <p>如果上述所有操作没有任何错误，没有人工干预，并通过了所有测试，才认为这是一次成功的构建。</p> <p>对于第4步而言，如果应用程序是一个需要安装到桌面的UI应用，那么就需要保证它可以成功的部署，这样才能提供可以测试的环境。</p> <p>&nbsp;</p> <p><span style="background-color:#888888;">2：我的持续集成实践</span></p> <p>我公司使用敏捷开发，使用CruiseControl进行代码控制，当代码被Check In 后，  会自动编译，并生成一个压缩后的exe文件，然而而当需要测试该exe文件时，需要手工从文件服务器下载，然后手工卸载已有的程序，再运行该exe安装新  的程序，确保安装后的程序/服务正确运行后，方能进行软件的测试。</p> <p>也就是说，我们已经实现了前三步的自动化，而最后一步，由于涉及UI界面、服务卸载，一直没有能够自动化，这其中的一个难点就是该exe是一个较庞  大且复杂的压缩程序，在安装时可以使用十分灵活多样的配置，每一样配置都会导致不同的安装结果，如果要把所有常用的安装方式自动化，编程的代价比较大。</p> <p>在了解了Visual Studio 2010提供的Coded UI test功能后，以上问题初步得以解决，从而在技术层面，使用较小的C#代码就完成了UI界面安装、服务卸载等问题，从而将上述第四步与前面的三步串联起来，初步满足了持续集成的要求。</p> <p>最后形成的大致步骤是</p> <p>1：开发人员提交代码</p> <p>2：编译服务器开始编译，并在文件服务器上生成installer，并发出通知</p> <p>3：C#程序去文件服务器下载installer，拷贝至测试服务器</p> <p>4：C#程序卸载测试服务器上的原程序/服务</p> <p>5：C#程序根据测试需要/测试参数安装installer，直到完成部署进行</p> <p>6：C#程序调动自动化脚本(QTP/SilkTest/Seleium)，进行自动化测试</p> <p>7：检查测试结果</p> <p>第3-6步都是由一个C#程序完成的，下面我主要介绍一下第5步，也就是软件自动安装的实现原理，在掌握了自动安装之后，第4步，也就是软件的自动卸载也就同样得到解决了。</p> <p>&nbsp;</p> <p><span style="background-color:#888888;">3: Coded UI test使用</span></p> <p>Coded UI Test是对UI进行的测试，使用方法和很多支持UI自动化测试的工具（QTP、SilkTest）一样，都支持UI的录制、回放、识别、断言，与这类工具相比，它主要还有如下的好处：</p> <p>1：基于.Net framework，且同时支持Win32/Web/WPF，利于代码的扩展和复用</p> <p>2：可以编译成exe文件，脱离Visual Studio运行。</p> <p>3：除了支持Web/Win应用外，还支持WPF（很多自动化工具对WPF的支持并不是太好）。</p> <p>&nbsp;</p> <p><span style="background-color:#33cccc;">3.1 录制一个Coded UI test测试</span></p> <p>一个复杂的installer，除了有复杂的安装配置之外，UI界面往往也比较复杂，在不了解Coded UI  test这个办法之前，如果专门为installer写一个控制安装程序会是一件比较费时费力的工作，特别是当这个installer有多个设置窗口和控  件时。而使用Coded UI test则可以非常轻松的解决这些问题，代码也便于扩展。</p> <p>&nbsp;</p> <p>下面以notepad++这个大家常用的小工具的安装来说明如果建立一个Coded UI Test（由于我的Visual Studio  2010是英文版的，所以只能提供英文截图和英文名称），在进入下文之前，建议大家再实际下载、运行一下notepad++的安装程序，体验它每一个窗口  的功能，以及支持的多种参数设置，并思考如果不使用自动化工具，如何编程实现程序的安装。</p> <p>我在示例中使用的版本是5.9.6，大家可以去其官方主页<a href="http://notepad-plus-plus.org/%E4%B8%8B%E8%BD%BD5.9.6">http://notepad-plus-plus.org/</a>&nbsp;下载5.9.6的版本npp.5.9.6.Installer.exe。</p> <p>&nbsp;</p> <p>下面是具体的步骤</p> <p>1：打开Visual Studio 2010，新建一个类型是Test的工程，如下图</p> <p>2：删掉自动生成的第一个默认类</p> <p>3：右击工程，选择Add，然后选择Coded UI Test，这时会弹出一个窗口，在此选择第一项&#8220;录制一个新测试&#8221;，点击OK按钮<img alt="使用Visual Studio 2010 Coded UI Test 制作能自动安装/卸载UI应用的程序" src="http://static.open-open.com/lib/uploadImg/20120207/20120207224352_237.png" height="382" width="669" /></p> <p><img alt="使用Visual Studio 2010 Coded UI Test 制作能自动安装/卸载UI应用的程序" src="http://static.open-open.com/lib/uploadImg/20120207/20120207224352_984.png" height="303" width="481" /></p> <p>4：此时，在窗口的右下角会弹出一个名为Coded UI Test Builder的窗口，点击第一个红色圆形按钮后，便可以进行一个UI测试的录制，如下图</p> <p><img alt="使用Visual Studio 2010 Coded UI Test 制作能自动安装/卸载UI应用的程序" src="http://static.open-open.com/lib/uploadImg/20120207/20120207224352_578.png" height="61" width="224" /></p> <p>5：在资源管理器中运行notepad++的安装程序，任意设置安装参数，逐个点击Next按钮，最后直至安装完成。</p> <p>6：点击窗口右下侧Coded UI Test  Builder窗口中第4个按钮，在弹出的窗口中将方法名称修改为DoInstall，然后点击Add and  Generate按钮，稍等片刻后，整个程序便会生成了，这时可以关闭Coded UI Test Builder窗口。</p> <p>7：生成后的工程结构如下图所示：</p> <p><img alt="使用Visual Studio 2010 Coded UI Test 制作能自动安装/卸载UI应用的程序" src="http://static.open-open.com/lib/uploadImg/20120207/20120207224352_428.png" height="350" width="410" /></p> <p>&nbsp;</p> <p>其中CodedUITest1.cs是测试类，而UIMap.uitest则包含了notepad++每个窗口的声明，以及安装的具体步骤，例如DoInstall的主体部分便是具体的每一步操作：</p> <div><pre><span style="color:#008000;">//</span><span style="color:#008000;"> Click 'OK' button</span> Mouse.Click(uIOKButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">40</span>, <span style="color:#800080;">10</span>));<span style="color:#008000;">//</span><span style="color:#008000;"> Click '&amp;Next &gt;' button</span> Mouse.Click(uINextButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">40</span>, <span style="color:#800080;">7</span>));<span style="color:#008000;">//</span><span style="color:#008000;"> Click 'I &amp;Agree' button</span> Mouse.Click(uIIAgreeButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">40</span>, <span style="color:#800080;">7</span>));<span style="color:#008000;">//</span><span style="color:#008000;"> Click '&amp;Next &gt;' button</span> Mouse.Click(uINextButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">40</span>, <span style="color:#800080;">7</span>));<span style="color:#008000;">//</span><span style="color:#008000;"> Click '&amp;Next &gt;' button</span> Mouse.Click(uINextButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">40</span>, <span style="color:#800080;">7</span>));<span style="color:#008000;">//</span><span style="color:#008000;"> Select 'Create Shortcut on Desktop' check box</span> uICreateShortcutonDeskCheckBox.Checked = <span style="color:#0000ff;">this</span>.DoInstallParams.UICreateShortcutonDeskCheckBoxChecked;<span style="color:#008000;">//</span><span style="color:#008000;"> Click '&amp;Install' button</span> Mouse.Click(uIInstallButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">40</span>, <span style="color:#800080;">10</span>));<span style="color:#008000;">//</span><span style="color:#008000;"> Clear '&amp;Run Notepad++ v5.9.6' check box</span> uIRunNotepadv596CheckBox.Checked = <span style="color:#0000ff;">this</span>.DoInstallParams.UIRunNotepadv596CheckBoxChecked;<span style="color:#008000;">//</span><span style="color:#008000;"> Click '&amp;Finish' button</span> Mouse.Click(uIFinishButton, <span style="color:#0000ff;">new</span> Point(<span style="color:#800080;">41</span>, <span style="color:#800080;">6</span>));</pre></div> <p>&nbsp;</p> <p>8：如果现在按F5，程序无法运行，原因是这段代码里没有运行notepad++安装程序的代码，只是假设安装程序已经运行了，所以我们要在第一个Click动作前面加上下面的代码</p> <div><pre><span style="color:#0000ff;">string</span> installer = <span style="color:#800000;">@"</span><span style="color:#800000;">c:\share\npp.5.9.6.Installer.exe</span><span style="color:#800000;">"</span>; ApplicationUnderTest InstallerWindow = pplicationUnderTest.Launch(installer);</pre></div> <p>现在再按F5试试？应该可能运行一个完整的安装了。</p> <p>&nbsp;</p> <p>程序说明：</p> <p>1：在录制第一个操作时，系统已经自动将每一个涉及到的UI界面及其包含的元素加以识别，并记录每一次的操作（点击、键入等），当生成代码时，会把这些东东全部输出下来。</p> <p>要想查看每一个界面元素的定义，大家可以选择任意一个元素，然后按F12，查看它的声明，并进一步查看它所成的窗口的定义。</p> <p>例如第一个被点击的按钮uIOKButton,它位于UIInstallerLanguageWindow中，而UIInstallerLanguageWindow则是依靠SearchProperties属性具体定位的。</p> <p>&nbsp;</p> <p>2：我们点击按钮、选中CheckBox，对应的操作就是Mouse.Click或者某CheckBox.Checked，如果我们有复杂的安装需求，可以按照这样的思路进行定制。</p> <p>&nbsp;</p> <p>3：在实际的安装或者参数的设置时，往往有某些控件不可见/不可用，只有满足了某种条件才会可见/ 可用。就象本文的例子中，对于正在进行安装的窗口，其Next按钮是不可用的，见下图：</p> <p><img alt="使用Visual Studio 2010 Coded UI Test 制作能自动安装/卸载UI应用的程序" src="http://static.open-open.com/lib/uploadImg/20120207/20120207224353_560.png" height="399" width="513" /></p> <p>该按钮会在安装完成后可用，如果程序在这时要点击这个Next按钮，会导致程序报错，这时怎么办呢？</p> <p>按照很多人的编程习惯，往往会用sleep(5)来解决，但这也有问题，不同的计算机性能不同， 在一台计算机上设置好的时间，在另外一台上可能过短，如果把时间设足够长，又会导致效率下降。<br /> Coded UI Test提供了一系列方法处理这类问题，如下：</p> <div><pre>WaitForControlCondition（）:控件满足某种条件后再往下执行 WaitForControlEnabled（）:控件有效后再往下执行 WaitForControlExist（）:控件可以被找到后再往下执行 WaitForControlNotExist（）:控件不存在时再往下执行 WaitForControlPropertyEqual（）:控件的某个属性等于等值后再往下执行 WaitForControlPropertyNotEqual（）:控件的某个属性不等于等值后再往下执行 WaitForControlReady（）:控件准备就序后再往下执行</pre></div> <p>&nbsp;</p> <p>这样，对上同样例子中的倒数第二行代码，在程序安装时，由于要花费一定的时间，uIRunNotepadv596CheckBox所处的窗口还没有   显现，uIRunNotepadv596CheckBox自然还无效，因此，对于性能较的计算机，执行到这句话时可能出错，为了保险，可以在之前增加一行  代码：</p> <div><pre>uIRunNotepadv596CheckBox. WaitForControlReady（）;</pre></div> <p>然后再执行后面的：</p> <div><pre>uIRunNotepadv596CheckBox.Checked = <span style="color:#0000ff;">this</span>.DoInstallParams.UIRunNotepadv596CheckBoxChecked;</pre></div> <p>就可以保证该控件是在有效的情况下执行后面的操作了。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <p>&nbsp;</p> <p>4：控件的名称、窗口的名称都是程序自动生成的，如果觉得命名不好，可以用Visual Studio 提供的重构-改名功能进行替换。</p> <p>&nbsp;</p> <p>5：程序的入口是public void CodedUITestMethod1()，默认是无参数的，如果需要在安装中设置复杂的参数，以及把安装程序的路径传递进去，可以在此增加参数，然后把参数传递到具体的执行方法DoInstall()</p> <p>&nbsp;</p> <p><span style="background-color:#00ccff;">3.2 让程序脱离Visual Studio执行</span></p> <p>以上的代码只能Visual Studio中运行，要想让它脱离Visual Studio也能运行，需要做如下操作。</p> <p>1：增加一个类，假设名称是TestMagager，加入如下代码</p> <div><pre><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">void</span> Init() {     <span style="color:#0000ff;">if</span> (!Playback.IsInitialized)     {         Playback.Initialize();     } }</pre></div> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <p>2：新建另一个工程（可以是Windows,也或以是类库），引用上述的测试工程，然后在代码先中调Init()，然后直接调用安装的主程序，如下：</p> <div><pre>TestMagager.Init();  CodedUITest1 t = <span style="color:#0000ff;">new</span> CodedUITest1(); t.CodedUITestMethod1();</pre></div> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <p>3：这个新建的工程编译成功后，理论上调用上述的代码可以进行软件的安装，但此时会报错误，提示所需要的DLL文件不存在，其原因是：</p> <p>对于Test类工程，Visual Studio 可以找到依赖的DLL文件，然而被引用由其它的程序调用后，便不能找到这些文件，只要手工把它们拷贝到一个统一的目录，然后引用到新建的工程就可以了，这些文件是：</p> <div><pre>Microsoft.VisualStudio.QualityTools.CodedUITestFramework.dll Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll Microsoft.VisualStudio.QualityTools.UnitTestFramework.xml Microsoft.VisualStudio.TestTools.TestSettings.Common.dll Microsoft.VisualStudio.TestTools.TestSettings.dll Microsoft.VisualStudio.TestTools.UITest.CodeGeneration.dll Microsoft.VisualStudio.TestTools.UITest.CodeGeneration.xml Microsoft.VisualStudio.TestTools.UITest.Common.dll Microsoft.VisualStudio.TestTools.UITest.Common.xml Microsoft.VisualStudio.TestTools.UITest.Extension.dll Microsoft.VisualStudio.TestTools.UITest.Extension.IE.Communication.Interop.dll Microsoft.VisualStudio.TestTools.UITest.Extension.IE.dll Microsoft.VisualStudio.TestTools.UITest.Extension.MSAA.dll Microsoft.VisualStudio.TestTools.UITest.Extension.Uia.dll Microsoft.VisualStudio.TestTools.UITest.Extension.xml Microsoft.VisualStudio.TestTools.UITest.Framework.dll Microsoft.VisualStudio.TestTools.UITest.Playback.dll Microsoft.VisualStudio.TestTools.UITest.Recorder.dll Microsoft.VisualStudio.TestTools.UITesting.dll Microsoft.VisualStudio.TestTools.UITesting.dll</pre></div> <p>&nbsp;</p> <p>在Visual Studio的安装目录下搜索，可以找到这些文件，它们分别存储在\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies和</p> <p>\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies目录下，把它们拷到一个目录中，然后在应用中全部引用，便可以运行新建的这个工程了。</p> <p>&nbsp;</p> <p><span style="background-color:#00ccff;">3.3 示例程序</span></p> <p>Coded UI Test程序地址是：<a href="http://files.cnblogs.com/gannan/demo.rar">点击这里</a></p> <p>解压缩后，一共有两个文件夹，第一个是Coded UI Test工程，第二个是Winform对它的调用。</p> <p>因为偷懒，所有Project的文件全是系统默认的，生成的代码也没有重构，Coded UI  Test工程用硬代码的方式运行Notepad++的安装程序(c:\share\  npp.5.9.6.Installer.exe),建议大家以参考代码结构为主，自己动手来建立一个类似的运行程序。</p> <p>如果大家真的要运行示例程序，需要c:\share\ npp.5.9.6.Installer.exe这个程序存在,而且在安装Visual Studio 2010时，安装对测试工程的支持。</p> <p>最后再说明，我已经把英文Visual Studio 2010的dll文件拷贝到了WindowsFormsApplication1的bin\debug目录下，并且在XP环境下测试通过。</p> <p>使用上面的思路，还可以实现程序的自动卸载。</p> <p>&nbsp;</p> <p>后记：按照上述方法，我实现了几个应用程序（包括服务）的自动安装、卸载，从而实现了上文提到的自动部署、测试，初步实现持续集成。<br /> <br /> 转自：<a href="http://www.cnblogs.com/gannan/archive/2012/02/07/2341961.html" target="_blank">http://www.cnblogs.com/gannan/archive/2012/02/07/2341961.html</a></p></div><img src ="http://www.cnitblog.com/stomic/aggbug/86813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/stomic/" target="_blank">大话人生</a> 2012-12-04 17:42 <a href="http://www.cnitblog.com/stomic/archive/2012/12/04/86813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QTP对象识别机制 </title><link>http://www.cnitblog.com/stomic/archive/2011/11/05/76279.html</link><dc:creator>大话人生</dc:creator><author>大话人生</author><pubDate>Sat, 05 Nov 2011 06:55:00 GMT</pubDate><guid>http://www.cnitblog.com/stomic/archive/2011/11/05/76279.html</guid><wfw:comment>http://www.cnitblog.com/stomic/comments/76279.html</wfw:comment><comments>http://www.cnitblog.com/stomic/archive/2011/11/05/76279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/stomic/comments/commentRss/76279.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/stomic/services/trackbacks/76279.html</trackback:ping><description><![CDATA[<div><p><span style="font-size: small;"><span style="font-family: 宋体;">测试对象模型是一大组对象类型或类，比如</span></span>WebElement、WebList，QTP用这些对象类型和类来表示Web页面中的对象。每个测试对象类都有一个可以唯一标识对象的属性列表以及可以录制的方法，这个属性列表和方法列表是可以设置的，见图：</p> <p><img src="http://pic002.cnblogs.com/img/wanglin1809/201002/2010022311280057.jpg" alt="" height="322" width="457" />&nbsp;&nbsp;&nbsp; <img src="http://pic002.cnblogs.com/img/wanglin1809/201002/2010022311304266.jpg" alt="" /></p> <p>在Object Identification对话框中设置的属性录制完后都可以在Object Repository中查看。属性的具体分类见下一小节。</p> <p>&nbsp;</p> <p><span style="font-size: small;"><span style="font-family: 宋体;">QTP里的对象分两个概念，一个是Test Object（简称TO）测试对象，一个是Runtime Object（简称RO）运行时对象。</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">这两个概念从字面上不大好理解，也容易混淆。</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">但从实际作用上来看，应该说TO就是是仓库文件里定义的仓库对象，RO是<span style="color: #000000;">被<span style="color: #000000;">测试</span>软</span>件的实际对象。</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">QTP识别对象，一般是要求先在对象仓库文件里定义仓库对象，里面存有实际对象的特征属性的值。</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">然后在运行的时候，QTP会根据脚本里的对象名字，在对象仓库里找到对应的仓库对象，</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">接着根据仓库对象的特征属性描述，在被测试软件里搜索找到相匹配的实际对象，最后就可以对实际对象进行操作了。</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">仓库对象TO一般在录制/编写脚本时加入仓库文件，它不仅可以在录制编写时进行修改，</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">也可以在运行过程中进行动态修改，以匹配实际对象。</span></span></p> <p>和TO、RO相关的几个函数有：<br />　　GetTOProperty():取得仓库对象的某个属性的值<br />　　GetTOProperties():取得仓库对象的所有属性的值<br />　　SetTOProperty():设置仓库对象的某个属性的值<br />　　GetROProperty():取得实际对象的某个属性的值</p> <p>理解了TO的含义，你就可以自由的用SetTOProperty()定义TO，以灵活的操作RO</p> <p>比如有个测试任务，窗口上有很多待检查的记录，每条记录右边都有一个Check按钮，用来检查各条记录。<br />记录个数不定，所以Check按钮个数也就不定，只有一个Edit显示记录个数。<br />我们要对每条记录进行检查，也就是要点击每个Check按钮。<br />但是Check按钮个数不定，不好录制，而且个数可能也很多（上百个），即使能一一录制，那也很麻烦。</p> <p>那我有一个好办法，只录制一个按钮对象，它设有两个特征属性 label=OK, index=0<br />然后用下面的脚本，就可以完成测试<br />buttonNum = CInt(JavaWindow("Test").JavaEdit("Record Num").GetROProperty("value"))<br />For buttonIndex = 0 to buttonNum - 1<br />  JavaWindow("Test").JavaButton("Check").SetTOProperty("index", buttonIndex)<br />  JavaWindow("Test").JavaButton("Check").Click<br />Next</p> <p>或者窗口上有New、Modify、Delete、Check等好几个按钮，要把这几个按钮一一按过去<br />我在对象仓库里只设置一个按钮对象AnyButton，label特征属性值填任意值，然后用下面脚本执行测试<br />JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "New")<br />JavaWindow("Test").JavaButton("AnyButton").Click</p> <p>JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "Modify")<br />JavaWindow("Test").JavaButton("AnyButton").Click</p> <p>JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "Delete")<br />JavaWindow("Test").JavaButton("AnyButton").Click</p> <p>JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label", "Check")<br />JavaWindow("Test").JavaButton("AnyButton").Click</p> <p><span style="font-size: small;">&nbsp;</span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">脚本描述定义访问对象</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">如果Web对象没有被添加到对象库中，或者通过该Web对象的标识QTP无法识别,即对象库中没有该对象，那么可以用另一种方式：在脚本中用描述性编程来定义访问对象</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">常规语法为：</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">TestObject("PropertyName1:=PropertyValue1","PropertyName2:=PropertyValue2"...)+具体操作</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">如</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">Dim buttonIndex</span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">buttonIndex = 1<br /></span></span></p> <p><span style="font-size: small;"><span style="font-family: 宋体;">JavaWindow("Test").JavaButton("label:=check","index:="+CStr(buttonIndex)).Click</span></span></p> <p><span style="font-size: small;">&nbsp;</span></p> <h2><span style="color: #993366;">属性详解（转载）</span></h2> <p><span style="color: #000000;"><span style="color: #000000;">QTP</span>通过三类属性来识别对象：</span></p> <p><span style="color: #000000;">a）Mandatory;</span></p> <p><span style="color: #000000;"> b）Assistive; <br /></span></p> <p><span style="color: #000000;">c) Ordinal identifiers。</span></p> <p><span style="color: #000000;">大部分情况下，通过对象的一些特定属性值就可以识别对象（类型a）。这些属性可以通过Tools-&gt;Object Identification 定义。每个测试对象类拥有一系列用于唯一确定对象的属性，这就是在这个<span style="color: #000000;">Object</span> Identification里查看。比如我看了一下WebEdit空间的识别方式，发现它就是通过type，name和html tag来识别。</span></p> <p><span style="color: #000000;">在这里列出了所有QTP能识别的控件，以及控件的识别方式。你可以给他添加X、Y坐标进行识别。或更明显的，列表中的信息，不按名称识别，而是按ID识别。这个修改可以解决一些问题，想动手试试，但是不知道从何下手&#8230;&#8230;</span></p> <p><strong><span style="color: #000000;">1. Smart Identification:</span></strong></p> <p><span style="color: #000000;">智能识别机制主要工作于测试脚本运行时(对象允许智能识别为真)，当对象 库中对象的强制属性（或辅助属性）与被测应用程序中对应对象的属性不一致时，智能识别机制将会启动。其主要原理为：先选择某个基本属性进行比较，若对象多 于一个，再继续添加属性筛选；若添加的对象属性造成无对象匹配，则淘汰该属性，应用该方法直至找到唯一对象并对该对象执行操作。(若所有属性的添加或淘汰 都无法识别唯一对象，QTP将应用ordinal identifier去识别对象。)</span></p> <p><span style="color: #000000;">以上是原话，然后我的理解是：比如要识别页面上的一个webedit控 件，然后这个空间有那么多的属性，qtp会根据他的属性，然后从objectidentification里的强制属性和辅助属性里找，假如一致，就可以 识别到他就是identification机制里定义的webedit了，假如还是识别不到，就用智能识别。再不行，就用index。</span></p> <p><span style="color: #000000;">在界面中可看到各种标准Windows控件对应的对象识别方法，例如，对 于Dialog控件，使用的是&#8220;is child window&#8221;、&#8220;is  ownedwindow&#8221;、&#8220;nativeclass&#8221;和&#8220;text&#8221;这四个控件对象的属性来区别出一个唯一的Dilalog控件对象。可以单击 &#8220;Add/Remove&#8221;按钮，选择更多的控件属性来唯一识别控件。</span></p> <p><span style="color: #000000;">以下这篇帖子有部分qtp官方文档的原话，我觉得理解起来更加权威些：<br />When you run a test, QuickTest searches for the object that matches the<br />description it learned (without the ordinal identifier). If it cannot find any<br />object that matches the description, or if it finds more than one object that<br />matches, QuickTest uses the Smart Identification mechanism (if enabled) to<br />identify the object. In many cases, a Smart Identification definition can help<br />QuickTest identify an object, if it is present, even when the learned<br />description fails due to changes in one or more property values. The test<br />object description is used together with the ordinal identifier only in cases<br />where the Smart Identification mechanism does not succeed in narrowing<br />down the object candidates to a single object.</span></p> <p><span style="color: #000000;">The Object Identification dialog box also enables you to configure new<br />user-defined classes and map them to an existing test object class so that<br />QuickTest can recognize objects from your user-defined classes when you<br />run your test.</span></p> <p><span style="color: #000000;">智能识别可是在三个层面设置可是启用：</span></p> <p><span style="color: #000000;">a. 类，即Object Identification对话框中</span></p> <p><span style="color: #000000;">b. 对象，即Object Repository对话框中</span></p> <p><span style="color: #000000;">c. 测试中，即Run Testing对话框中<br /></span></p> <p>&nbsp;</p> <p><span style="color: #000000;"><strong>2. Ordinal Identifier:</strong><a href="http://hi.baidu.com/iooc/blog/index/2"><br /></a></span></p> <div><span style="color: #000000;">QTP除了可以获取到被测对象的主属性、辅助属性值外，还可以获取到 被测对象的Ordinal Identifier值。当QTP发现有多个对象具有相同的主属性值、辅助属性值而无法对它们进行唯一识别时，  Ordinal Identifier会获取每个对象的序列值，以将它们区别开来。</span></div> <div><span style="color: #000000;">由于序列值是一个相对值，任何页面的变更都有可能导致这些值发生改变，因此，只在主属性与辅助属性无法唯一识别对象的情况下，QTP才会获取该序列值。</span></div> <div><span style="color: #000000;">在运行测试脚本时，如果使用对象的属性值以及Smart Identification机制都无法唯一识别应用程序中的对象，才会使用到序列值。如果QTP可以通过<span style="color: #000000;">其它</span>属性值对对象进行识别，则会忽略序列值。</span></div> <div><span style="color: #000000;">QTP可以使用以下类型的ordinal identifiers来识别对象：</span></div> <div><span style="color: #ff0000;"><strong>Index</strong></span><span style="color: #000000;"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></span><span style="color: #000000;">表示对象在程序代码中的出现顺序，这个顺序是相对于其它具有相同属性的对象而言的。</span></div> <div><span style="color: #000000;"><strong><span style="color: #ff0000;">Location</span></strong><strong><span style="color: #ff0000;">&nbsp;&nbsp;</span></strong>表示对象在窗口、Frame或对话框中出现的顺序，这个顺序是相对于其它具有相同属性的对象而言的。</span></div> <div><span style="color: #ff0000;"><strong>CreationTime</strong></span><span style="color: #000000;">（仅适用于Browser对象） 表示Browser对象打开的顺序，这相顺序是相对于其它已打开的具有相同属性的对象而言的。</span></div> <div><span style="color: #000000;">一般情况下，Ordinal Idenfifier类型适用于所有类。在Object Identification窗口，通过Ordial identifier下拉框，可以选择其它类型。</span></div> <div><span style="color: #000000;">注：QTP在录制脚本时，如果通过主属性与辅助属性已能够唯一识别对 象，则不会获取对象的ordinal identifier顺序值。你可以在脚本录制完成后，在Object Properties或Object  Repository对话框中使用Add/Remove操作，手动添加顺序值。</span></div> <h2>&nbsp;</h2>  <h2><span style="color: #993366;">QTP中设置共享对象库（转载）</span></h2> <p>很多时候我们总是<span style="color: #000000;">觉得管理<span style="color: #000000;"><span href="http://www.3atesting.com/bbs/tag.php?name=QTP">QTP</span></span>的<span style="color: #000000;"><span href="http://www.3atesting.com/bbs/tag.php?name=%BD%C5%B1%BE">脚本</span></span>比较烦.因</span>为除了要对代码的管理之外，还要保证QTP对象库的完整．每一个用例脚本的生成，同时又都会生成一个对象库．那么是不是可以做一个公共的对象库来给各个用例脚本调用呢？接下来，我们就来实现共享对象库的应用．　　<strong><br /></strong></p> <p><strong>第一步：把需要加到共享对象库中的各个用例脚本的对象库，分别导出成．tsr文件．</strong><br />　　操作方法:先用QTP打开已经<span href="http://www.3atesting.com/bbs/tag.php?name=%C2%BC%D6%C6">录制</span>完毕的脚本后，选择Resources－－＞ Object Repository ．<br />　　然后file--&gt;export Local Objects导出tsr文件</p> <p><strong>第二步：把需要加入到共享对象库中的各个用例脚本的对象库，合并对象及对象属性，形成一个大的共享对象库．</strong>（可选）<br />　　操作 方法:打开Resources－－＞Object Repository  Manager．找到Tools菜单，然后选择打开ObjectRepository  mergetool.选择两个要合并的对象库文件，进行对象合并．一次只能合并两个．所以如果这里你要合并多个对象库文件的话，先合并两个后，保存成一个 新的．tsr文件．然后再重复上面的操作，选择这个新的．tsr文件和另一个准备好的对象库合并．合并的时候，你会发现，在两个对象库文件中，相同的对象 合并成一个，不同的对象，全部被完整增加进去．然后形成一个大的对象库．现在只要保存这个共享对象库．如果以后有新增的对象，可以重复上述操作．</p> <p><strong>第三步：调用上面保存好的共享对象库．给新的脚本使用．</strong><br /><strong>　　</strong>在任意test中，都可以依照操作步骤：Resources－－＞Associate Repository．选择上面保存好的共享对象库的．tsr文件．加入到Associate Repository中．</p> <p>　　完成这一步后，其实整个共享对象库的操作已经完成．你在对象库中可以看到以后的对象．在录制新脚本的时候，如果对象已经存在，就不会再被记录，只有在这个对象库中没有的对象才会被记录进去．回放脚本，对象识别成功．</p><p><br /></p><p><div>二、QTP操作对象的原理&nbsp; <br />&nbsp;&nbsp;QTP为用户提供了两种操作对象的接口，一种就是对象的封装接口，另一种是对象的自身接口。&nbsp; <br />&nbsp;&nbsp;对象的自身接口是对象控件本身的接口，只要做过软件开发，使用过控件的人应该很清楚。&nbsp; <br />&nbsp;&nbsp;对象的封装接口是QTP为对象封装的另一层接口，它是QTP通过调用对象的自身接口来实现的。 <br /><br /><br /><br />&nbsp;<br /><br /><br />&nbsp;<br />&nbsp;&nbsp;两种接口的脚本书写格式的差别在于：&nbsp; <br />&nbsp;&nbsp;自身接口需要在对象名后面加object再加属性名或方法名，&nbsp; <br />&nbsp;&nbsp;封装接口就不用在对象名后面加object。&nbsp; <br />&nbsp;&nbsp;具体格式如下：&nbsp; <br />&nbsp;&nbsp;对实际对象的操作：&nbsp; <br />&nbsp;&nbsp;对象.object.自身属性&nbsp; <br />&nbsp;&nbsp;对象.object.自身方法()&nbsp; <br />&nbsp;&nbsp;对象.GetROProperty("封装属性")&nbsp; <br />&nbsp;&nbsp;对象.封装方法()&nbsp; <br />&nbsp;&nbsp;对仓库对象的操作：&nbsp; <br />&nbsp;&nbsp;对象.GetTOProperty("封装属性")&nbsp; <br />&nbsp;&nbsp;对象.GetTOProperties()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8217;获取所有封装属性的值&nbsp; <br />&nbsp;&nbsp;对象.SetTOProperty("封装属性",&nbsp;"封装属性值")&nbsp; <br />&nbsp;&nbsp;比如操作JavaEdit对象，通过QTP封装的封装接口，脚本如下：&nbsp; <br />&nbsp;&nbsp;设置JavaEdit的内容：&nbsp; <br />&nbsp;&nbsp;JavaDialog("Add&nbsp;NE").JavaEdit("NE&nbsp;Name").Set&nbsp;"NE1"&nbsp; <br />&nbsp;&nbsp;读取JavaEdit的内容：&nbsp;&nbsp;&nbsp;&nbsp;msgbox&nbsp;JavaDialog("Add&nbsp;NE").JavaEdit("NE&nbsp;Name").GetROProperty("value")&nbsp; <br />&nbsp;&nbsp;如果通过JavaEdit的自身接口，脚本如下：&nbsp; <br />&nbsp;&nbsp;设置JavaEdit的内容：&nbsp; <br />&nbsp;&nbsp;JavaDialog("Add&nbsp;NE").JavaEdit("NE&nbsp;Name").object.setText("NE1")&nbsp; <br /><br /><br /><br />&nbsp;<br /><br /><br />&nbsp;&nbsp;读取JavaEdit的内容：&nbsp; <br />&nbsp;&nbsp;Msgbox&nbsp;JavaDialog("Add&nbsp;NE").JavaEdit("NE&nbsp;Name").object.getText()&nbsp; <br />&nbsp;&nbsp;QTP执行JavaEdit().Set语句时，是通过执行JavaEdit().object.setText()来实现的。&nbsp; <br />&nbsp;&nbsp;QTP执行JavaEdit().GetROProperty("value"),是通过执行JavaEdit().object.getText()来实现的。&nbsp; <br />&nbsp;&nbsp;JavaEdit对象的封装接口Set()和GetROProperty("value")，是QTP封装JavaEdit对象的自身接口setText()和getText()而得来的。&nbsp; <br />&nbsp;&nbsp;对象的封装接口是QTP使用的缺省接口，我们录制出来的脚本都是使用封装接口，大家用的也都是封装接口。&nbsp; <br />&nbsp;&nbsp;但是封装接口不如自身接口丰富，因为QTP只是封装了部分常用的自身接口嘛。&nbsp; <br />&nbsp;&nbsp;所以我们在需要时，可以绕过封装接口，直接调用对象的自身接口。&nbsp; <br />&nbsp;&nbsp;不过有些自身接口不够稳定，在实践中偶尔会出现问题，但是概率很少。&nbsp; <br />&nbsp;&nbsp;封装接口有相应功能的话，就尽量用封装接口吧！&nbsp; <br />&nbsp;&nbsp;理解了封装接口和自身接口的原理，我们就可以更加灵活的操作对象了。&nbsp; <br />&nbsp;&nbsp;但是我们怎么知道对象都有哪些封装接口和自身接口呢？&nbsp; <br />&nbsp;&nbsp;其实很简单，用对象查看器（Object&nbsp;Spy）查看对象，在查看窗口里有列出这些接口，包括属性和方法。&nbsp; <br />&nbsp;&nbsp;窗口中间有选择栏让你选择Run-time&nbsp;Object或者Test&nbsp;Object，&nbsp; <br />&nbsp;&nbsp;当你选择Runtime&nbsp;Object时，它显示的就是对象的自身接口（自身的属性和方法）&nbsp; <br />&nbsp;&nbsp;当你选择Test&nbsp;Object时，它显示的就是对象的封装接口（封装的属性和方法）&nbsp; <br />&nbsp;&nbsp;（注意：GetROProperty访问的是实际对象的封装接口，GetTOProperty访问的是仓库对象的封装接口，&nbsp; <br />&nbsp;&nbsp;两者访问的都是对象的封装接口，即Object&nbsp;Spy窗口里选Test&nbsp;Object时显<br /><br /><br /><br />&nbsp;<br /><br /><br />示的属性。&nbsp; <br />&nbsp;&nbsp;不要以为GetROProperty访问的是自身接口，即Object&nbsp;Spy窗口里选Run-time&nbsp;Object时显示的属性。&nbsp; <br />&nbsp;&nbsp;QTP里的Test&nbsp;Object/Run-time&nbsp;Object的概念太容易让人混淆了！&nbsp; <br />&nbsp;&nbsp;它既用来区分仓库对象和实际对象，又用来区分对象的封装接口和自身接口。）&nbsp; <br />&nbsp;&nbsp;明白了这些，你还等什么呢？快拿起对象查看器，看看对象都有哪些封装接口和自身接口，肆意的操作它，玩弄它吧！&nbsp; <br />&nbsp;&nbsp;比如执行&nbsp; <br />&nbsp;&nbsp;JavaDialog("Add&nbsp;NE").JavaEdit("NE&nbsp;Name").object.setVisible(false)&nbsp; <br />&nbsp;&nbsp;哈哈，你的JavaEdit对象就当场消失不见了！！！&nbsp; <br />&nbsp;&nbsp;你可以拿这个做恶作剧，指着这个窗口逼问开发人员，JavaEdit对象哪去了？&nbsp; <br />&nbsp;&nbsp;开发人员肯定瞪大眼睛看着这个窗口，当场翘掉！！！</div><br /></p></div><img src ="http://www.cnitblog.com/stomic/aggbug/76279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/stomic/" target="_blank">大话人生</a> 2011-11-05 14:55 <a href="http://www.cnitblog.com/stomic/archive/2011/11/05/76279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[分享] 在WIN2003安装TD8，问题汇总</title><link>http://www.cnitblog.com/stomic/archive/2009/11/26/62844.html</link><dc:creator>大话人生</dc:creator><author>大话人生</author><pubDate>Thu, 26 Nov 2009 04:40:00 GMT</pubDate><guid>http://www.cnitblog.com/stomic/archive/2009/11/26/62844.html</guid><wfw:comment>http://www.cnitblog.com/stomic/comments/62844.html</wfw:comment><comments>http://www.cnitblog.com/stomic/archive/2009/11/26/62844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/stomic/comments/commentRss/62844.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/stomic/services/trackbacks/62844.html</trackback:ping><description><![CDATA[<div class=date>&nbsp;</div>
<table style="TABLE-LAYOUT: fixed; WIDTH: 100%">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <p>　　不知道，为什么这类软件做的这么不易用，安装的时候会报出这样那样的问题，而在安装手册中又不曾提及。也许这就是用户体验和易用性的问题。MS的软件在现在能达到这样一个垄断的程度，除了MS本身的一些营销手段宣传策略以外，我想最关键的就是软件比较人性化，为用户去考虑，服务于用户。在安装TD8的过程中感慨就比较多了，还好我工作经验不算差，否则我很难想象把这样一件看似简单的安装软件的事情交给一个刚出校门的人，会发生什么。</p>
            <p>　　废话不说了，这里我贴两篇文章，基本可以解决TD8在安装过程中遇到的问题。同时也提供给遇到此类问题的人，希望在你搜到这篇文章的时候可以对你有所帮助。</p>
            <p><font size=5><strong>第一篇 2003如何安装TD</strong></font></p>
            <p>引用链接：<a href="http://bbs.testfocus.com.cn/showtopic-955.aspx"><u><font color=#0000ff>http://bbs.testfocus.com.cn/showtopic-955.aspx</font></u></a></p>
            <p>一直不推崇TD在windows2003上安装，但由于一个项目要求，必须安装在windows2003上，遇到了很多问题，在不懈努力下终于解决。在解决问题的过程，我有一种很微妙的心理变化，遇到问题，没有慌张、没有急迫，从容的找寻办法，但解决掉一个问题后，也没有太多的喜悦。做IT这个行业久了，总会遇到各种问题，高手也会被各种细微的问题给绕晕，长时间里培养了一种从容。工作中的从容和不懈。<br><br>第一个问题：2003的IIS是手工启动的。启动后，不显示td的初始界面，但在其他机器上，通过网络浏览没有问题。<br><br>解决方法.修改win2003的IIS的TDBIN的属性，开始－管理工具－Internet信息服务(IIS)管理器中，本地计算机-网站-默认网站-TDBIN，右键菜单属性-HTTP头&#224;【MIME类型】，点【新建】按钮，填扩展名为ini，MIME类型为text/*，继续新建扩展名分别为：lld、dll、ocx、 xco、exe、adt、adm、xxx，MIME类型都填为text/*。<br><br>第二个问题：安装过程中，提示用户名密码错误，无法进行下面安装，原因数据执行保护DEP不允许该程序执行。解决方法：右击&#8220;我的电脑&#8221;选择&#8220;属性&#8221;&#224;性能【设置】&#224;数据执行保护，选择选项：为除下列选定程序之外的所有程序和服务启动DEP（U），点击【添加】按钮，找到TD安装程序中的bin目录下：checku.exe,添加上即可。<br><br>第三个问题：安装程序完成，登陆时出现&#8220;The RPC server is unavailable&#8221;，The RPC server is unavailable.翻译过来就是&#8220;RPC（远程过程调用）服务不可行。&#8221;它指的是&#8220;权限不够&#8221;的意思。导致这个错误的原因有很多<br><br>1. RPC服务未启动。解决：控制面板-管理工具-服务-&#8220;Remote Procedure Call(RPC)&#8221;，启动一下（自动），服务状态&#8220;启动&#8221;；<br><br>2. 本身操作系统有问题缺少远程过程调用补丁。解决：更新操作系统。<br><br>3.服务器端IIS没装。解决：安装IIS。以2000系统为例，控制面板-添加删除程序-添加删除windows组件-&#8220;Internet 信息服务(IIS)&#8221;打一下勾，下一步&#8230;&#8230;<br><br>4.TD服务未启动。此种情况比较复杂，需要尝试不同的解决方案，先到TD所在的那台机器上，点右键的testdirector checker，看看出错提示，对症下药。<br><br>以下几种可以结合起来尝试：<br><br>启动一下TD。到TD所在的那台电脑上，在系统栏右边有个小图标，鼠标移上去，点右键&#8220;Start TestDirector&#8221;；<br><br>清空IE的cookies、History、缓存；删掉TD2000_80目录，重新下载一次插件；<br><br>把 http://IP/tdbin/start_a.htm 改为 http://计算机名/tdbin/start_a.htm<br><br>TD服务器装了多个版本的TD，兼容性问题；请卸载其中一个版本，重装TD；<br><br>第四个问题：MSIE7.0无法访问testdirector8.0，提示：&#8220;Microsoft Internet Explorer : 4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1; .NET CLR.3.0.04131.06) is not supported&#8221;。原因：testdirector8.0不支持MSIE7.0的问题，解决：　在安装目录一般为C:\Inetpub\TDBIN下找到Start_a.htm文件，用记事本打开，即看到了文件源代码，找到fMSIE3456参数，修改在|| (ua.lastIndexOf('MSIE 6.0') != -1)后黏贴|| (ua.lastIndexOf('MSIE 7.0') != -1)，保持即可。打开IE7.0再次访问，下载插件，安装插件，没有问题了。</p>
            <div class=t_msgfont>
            <p>&nbsp;</p>
            <p><strong><font size=5>第二篇 <strong>WIN2003下安装TD问题总结</strong></font></strong></p>
            <p>引用链接：<a href="http://itcat.it.com.cn/articles/285177.htm"><u><font color=#0000ff>http://itcat.it.com.cn/articles/285177.htm</font></u></a></p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp; 倒霉的我，在win2003下安装Test Director，遇到了种种问题。前提是，这个win2003系统非干净的系统，是英文版，在此之前，配置了几个测试站点。<br>&nbsp;&nbsp;&nbsp;&nbsp; 在干净的win2003中文版系统下，安装TD，除了出现问题一外，其他正常。<br><br>问题一：<br>&nbsp;&nbsp;&nbsp; 安装过程中，提示用户名密码错误，无法进行下一步的安装，原因数据执行保护DEP不允许该程序执行。解决方法：右击&#8220;我的电脑&#8221;选择&#8220;属性&#8221;性能【设置】数据执行保护，选择选项：为除下列选定程序之外的所有程序和服务启动DEP（U），点击【添加】按钮，找到TD安装程序中的bin目录下/或者是C:\Program Files\Common Files\Mercury Interactiver 的checku.exe,添加上即可。</p>
            <p>问题提示见图</p>
            <p><img height=237 alt="" src="http://www.cnitblog.com/images/cnitblog_com/stomic/T4.gif" width=360 border=0><br><br><br>问题二：<br>&nbsp;&nbsp;&nbsp;&nbsp; 安装到50%左右，提示无法找到路径，创建虚拟目录失败。</p>
            <div forimg="1"><img class=blogimg height=98 alt="" src="http://www.cnitblog.com/images/cnitblog_com/stomic/T5.gif" width=222 border=0 small="0"></div>
            <p><br>&nbsp;&nbsp;&nbsp;&nbsp; 我的解决办法：重装IIS。<br><br>问题三：重装IIS，居然也会报错"Error Writing Encrypted Data to the Web Services Configuration Database." ，点击重试是可以继续安装，但IIS站点是不能启动的。<br><br>&nbsp;&nbsp;&nbsp;&nbsp; 在微软支持网站上查了，原因是在写入machinekeys文件夹时出问题：This error occurs because of incorrect (corrupt) information. If this is a new installation of IIS 5.0, the corrupt information is located in the following folder: <br>%Windir%\Documents and Settings\ <br><br>If you are re-installing IIS, the corrupt information is located in the following folder: <br>%Windir%\Profiles\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys <br><br>&nbsp;&nbsp;&nbsp;&nbsp; 解决：先把原IIS卸载，再把machinekeys删除，文件夹所在%Windir%\Profiles\All Users\Application Data\Microsoft\Crypto\Rsa\，重新安装IIS就可以了。<br>&nbsp;&nbsp;&nbsp;&nbsp; 为了安全起见，我的处理办法不是直接把原machinekeys文件夹删除，而是rename这个文件夹为machinekeys1，以作备份。<br><br>&nbsp;&nbsp;&nbsp;&nbsp; 在IIS成功安装后，DEP也允许checku.exe执行，TestDirecotr就可以成功安装了。<br><br>注：<br>1、在win2003下安装Test Directo装过程中，会出现关于TD_DIR文件夹共享权限的问题，如图</p>
            <div forimg="1">
            <p><img class=blogimg height=98 alt="" src="http://www.cnitblog.com/images/cnitblog_com/stomic/T6.gif" width=222 border=0 small="0"></p>
            <p><br>如果遇到此问题，解决办法很简单，把已经生成的TD_DIR文件夹手工设置成共享，并把当前系统的管理员帐号添加进去，具有&#8220;控制权&#8221;。<br><br>2、当遇到IE打开TD出现空白页时，请把TD站点添加至IE的可信任站点中。</p>
            </div>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/stomic/aggbug/62844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/stomic/" target="_blank">大话人生</a> 2009-11-26 12:40 <a href="http://www.cnitblog.com/stomic/archive/2009/11/26/62844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QTP实现自动化原理(转)</title><link>http://www.cnitblog.com/stomic/archive/2009/09/09/61315.html</link><dc:creator>大话人生</dc:creator><author>大话人生</author><pubDate>Wed, 09 Sep 2009 03:50:00 GMT</pubDate><guid>http://www.cnitblog.com/stomic/archive/2009/09/09/61315.html</guid><wfw:comment>http://www.cnitblog.com/stomic/comments/61315.html</wfw:comment><comments>http://www.cnitblog.com/stomic/archive/2009/09/09/61315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/stomic/comments/commentRss/61315.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/stomic/services/trackbacks/61315.html</trackback:ping><description><![CDATA[<p><span>以下为个人的一些理解，而要查看官方的请查看</span><span><font face="Times New Roman">QTP</font></span><span>帮助或网上查找。</span> </p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>QTP</font></span><span>主要采用的是使用</span><span><font face="Times New Roman">GUI</font></span><span>模拟人的操作。它在模拟人的操作时会记录操作的对象及所做的操作和顺序，然后在回放时按记录顺序操作这些对象。而在这个模拟的过程中，最重要的莫过于界面对象（控件）的识别，那</span><span><font face="Times New Roman">QTP</font></span><span>是怎么做的呢？下面就举一个小例子来说明：</span></font></p>
<p><font size=3><span>比如我们要<a onclick="javascript:tagshow(event, '%B2%E2%CA%D4');" href="javascript:;" target=_self><u><strong>测试</strong></u></a>内网论坛</span><span><a href="http://172.16.1.3:8080/bbs/index.php"><font face="Times New Roman">http://172.16.1.3:8080/bbs/index.php</font></a></span><span>用正确的用户名和密码是否能成功登录。登录界面如下：</span></font></p>
<p><font size=3><span><a href="http://www.51testing.com/batch.download.php?aid=13500" target=_blank><img src="http://www.51testing.com/attachments/2009/03/130986_200903111914271axiv.jpg" border=0></a></span></font></p>
<p>&nbsp;</p>
<p><span><font size=3>测试步骤大概如下：</font></span></p>
<p><span><span><font face="Times New Roman"><font size=3>1.</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></font></span></span><span><font size=3>要先识别用户名输入框、密码输入框、登录按钮控件</font></span></p>
<p><span><span><font face="Times New Roman"><font size=3>2.</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></font></span></span><span><font size=3>在用户名输入框中输入正确的用户名</font></span></p>
<p><span><span><font face="Times New Roman"><font size=3>3.</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></font></span></span><span><font size=3>在密码输入框中输入正确的密码</font></span></p>
<p><span><span><font face="Times New Roman"><font size=3>4.</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></font></span></span><span><font size=3>点击登录按钮</font></span></p>
<p><span><span><font face="Times New Roman"><font size=3>5.</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></font></span></span><span><font size=3>验证是否登录成功，要验证是否成功登录，那就得知道成功登录与失败登录的区别。成功登录后的页面如下：</font></span></p>
<p><span><a href="http://www.51testing.com/batch.download.php?aid=13501" target=_blank><img src="http://www.51testing.com/attachments/2009/03/130986_200903111916121xklp.jpg" border=0></a></span></p>
<p>&nbsp;</p>
<p><span><font size=3>我们可以通过验证红色框中的内容或验证绿色框中的内容来标识登录是否成功，然后记入测试报告。</font></span></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>以上只是一个小例子，从中可以看出识别对象是一个很重要的问题也是一个很困难的问题，毕竟现在的控件类型越来越多（包括第三方插件或自己开发或定义的控件）。那</span><span><font face="Times New Roman">QTP</font></span><span>是怎么来识别对象的呢，下面通过讲解</span><span><font face="Times New Roman">QTP</font></span><span>识别以上小例子中的控件的方法来说明一下：</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>首先，</span><span><font face="Times New Roman">QTP</font></span><span>是通过记录控件的属性来标识对象的（当然具体用哪一些属性，</span><span><font face="Times New Roman">QTP</font></span><span>是有默认的，也可以配置）。假设</span><span><font face="Times New Roman">QTP</font></span><span>使用&#8220;</span><span><font face="Times New Roman">html tag</font></span><span>&#8221;和&#8220;</span><span><font face="Times New Roman">name</font></span><span>&#8221;属性来识别对象，</span><span><font face="Times New Roman">QTP</font></span><span>是怎么处理的呢？请先看下图：</span></font></p>
<p>&nbsp;</p>
<p><font size=3><span><span><font face="Times New Roman"><a href="http://www.51testing.com/batch.download.php?aid=13502" target=_blank><img src="http://www.51testing.com/attachments/2009/03/130986_200903111916122msb7.jpg" border=0></a></font></span></span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>在使用</span><span><font face="Times New Roman">QTP</font></span><span>录制时，</span><span><font face="Times New Roman">QTP</font></span><span>会把对象存储到对象库中。而对象是按如上图的方式存储于对象库中。即，</span><span><font face="Times New Roman">QTP</font></span><span>会默认给录制的对象取一个名字（这个名字可以自己改，只要在脚本中使用到此对象时保持和此名字一样就可以了），然后把识别此对象的属性和属性值存储到对象库中，我们可以先把识别对象的属性集合认为是一个属性包，接着就是把识别此对象的属性包与定义的对象名进行关联，也叫做对象映射。这样一个对象就存入对象库了。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>接着来说明</span><span><font face="Times New Roman">QTP</font></span><span>是如何调用这个对象的。例如，在&#8220;用户名输入框&#8221;中输入&#8220;</span><span><font face="Times New Roman">a</font></span><span>用户&#8221;，伪代码如下：</span></font></p>
<p><font size=3><span><font face="Times New Roman">WebEdit(&#8220;</font></span><span>用户名输入框</span><span><font face="Times New Roman">&#8221;).Set &#8220;a</font></span><span>用户</span><span><font face="Times New Roman">&#8221;</font></span></font></p>
<p><span><font size=3>现在分析一下这个语句：</font></span></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>首先，</span><span><font face="Times New Roman">QTP</font></span><span>会通过&#8220;<span>用户名输入框</span>&#8221;这个名字到对象库的对象名中查找，会找到以下这个对象名：</span></font></p>
<p>&nbsp;</p>
<p><font size=3><span><span><font face="Times New Roman"><a href="http://www.51testing.com/batch.download.php?aid=13503" target=_blank><img src="http://www.51testing.com/attachments/2009/03/130986_200903111916123aWlj.jpg" border=0></a></font></span></span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>然后通过找到的对象名，找到对象名映射的属性包，如下图：</span></font></p>
<p>&nbsp;</p>
<p><font size=3><span><span><font face="Times New Roman"><a href="http://www.51testing.com/batch.download.php?aid=13504" target=_blank><img src="http://www.51testing.com/attachments/2009/03/130986_200903111916124Icw9.jpg" border=0></a></font></span></span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>接着</span><span><font face="Times New Roman">QTP</font></span><span>就会通过这个属性包来匹配页面上的控件的属性，如果在页面上找到一个唯一与此属性包匹配的控件，那</span><span><font face="Times New Roman">QTP</font></span><span>就会认为此控件为要找的控件。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>然后</span><span><font face="Times New Roman">QTP</font></span><span>根据&#8220;</span><span><font face="Times New Roman">WebEdit</font></span><span>&#8221;来确定控件的类型，并调用</span><span><font face="Times New Roman">QTP</font></span><span>对于此类控件内置的操作方法&#8220;</span><span><font face="Times New Roman">Set</font></span><span>&#8221;把&#8220;</span><span><font face="Times New Roman">a</font></span><span>用户</span><span>&#8221;赋予了控件</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>至于<a onclick="javascript:tagshow(event, '%C6%E4%CB%FB');" href="javascript:;" target=_self><u><strong>其他</strong></u></a>控件的识别和操作，基本原理和上面一样。检验登录是否成功，也是通过比对登录成功后的页面特有的控件的属性值来判断。</span></font></p>
<p><font size=3><span><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>QTP</font></span><span>还提供描述性编程，从而可以不使用对象库，如在&#8220;用户名输入框&#8221;中输入&#8220;</span><span><font face="Times New Roman">a</font></span><span>用户&#8221;，可以使用以下伪代码：</span></font></p>
<p><font size=3><font face="Times New Roman"><span>WebEdit(&#8220;</span><span>Html tag:=INPUT<span>&#8221;,&#8221;</span>Name=username<span>&#8221;).Set &#8220;a</span></span></font><span>用户</span><span><font face="Times New Roman">&#8221;</font></span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>细心的朋友可能已经发现，上面只是把识别对象的属性包中的属性和属性值按一定规则直接写到了&#8220;</span><span><font face="Times New Roman">WebEdit()</font></span><span>&#8221;的括号内了。这时</span><span><font face="Times New Roman">QTP</font></span><span>将不通过对象库，而是直接使用括号内的属性和属性值到页面上去找匹配项。然后操作与使用对象库的操作一样。</span></font></p>
<p><font size=3><span><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span></span><span>当然，</span><span><font face="Times New Roman">QTP</font></span><span>还提供了一些其他的功能，比如参数化，划分模块（</span><span><font face="Times New Roman">Action</font></span><span>）呀。但最重要的还是对象的识别。本次到此结束，希望对大家理解自动化能有所帮助。</span></font></p>
<img src ="http://www.cnitblog.com/stomic/aggbug/61315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/stomic/" target="_blank">大话人生</a> 2009-09-09 11:50 <a href="http://www.cnitblog.com/stomic/archive/2009/09/09/61315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>