时间有点晚了,我这里就直接拿出几个最关键的一方
第一,将对象库转换成XML文件,并从中提取出对象字符串,我们输入 的可能仅仅是按钮名称,但需要从中取得对象的整个父对象。
TestDllFilePath=FrameworkPath+"Test_DotNetDll\QTPBuildObjectLayer.dll" Set FileOperation= DotNetFactory.CreateInstance("System.IO.File") Set DirectoryOperation= DotNetFactory.CreateInstance("System.IO.Directory") Set ObjectBuild= DotNetFactory.CreateInstance("QTPBuildObjectLayer.BuildObject",TestDllFilePath) Set XMLFileExport=CreateObject("Mercury.ObjectRepositoryUtil") Set TestDataDictionary=CreateObject("Scripting.Dictionary") 这里是前提,需要用不对劲这些外部dll。或者通过dotnetfactory创建,直接高用基于.net的方法
第二,处理对象库及转换成XML.
'FunctionName:BuildObject 'Description:convert object name to string, eg. convert "Login" to window("Main").Winbutton("Login"), description program is supported 'FunctionType:Function Utility , referenced by ActionEntry Function BuildObject(ObjectName) If left(ObjectName,3)="Dsc" Then BuildObject=Dsc_Object(ObjectName) 'reserved Else RepositoriesNumTemp=1 For RepositoriesNumTemp=1 to RepositoriesCollection.Count RepositoryExportToXMLFile RepositoriesNumTemp ObjectFound = ConvertToObjectLayer(ObjectName) If ObjectFound <> "" Then BuildObject = ObjectFound Exit for End If Next End If End Function 'FunctionName:LoadRepositories 'Description:if Repositories_Name give a repository,then add it to current actions,else 'FunctionType: Function Utility,referenced by ActionEntry funcion Sub LoadRepositories(RepositoriesName) TestRepositoriesFilePath=TestRepositoriesPath+RepositoriesName If RepositoriesCollection.Find(TestRepositoriesFilePath)=False Then RepositoriesCollection.Add(TestRepositoriesFilePath) else RepositoriesCollection.Remove(TestRepositoriesFilePath) RepositoriesCollection.Add(TestRepositoriesFilePath) end if End Sub 'FunctionName:RepositoryExportToXMLFile 'Description :Export all repositorys to xml files. 'Function Type:Utility Function,referenced by build Object Sub RepositoryExportToXMLFile(RepositoryIndex) If FileOperation.Exists(TempXMLFilePath) Then FileOPeration.Delete(TempXMLFilePath) End If XMLFileExport.ExportToXML (FrameworkFolderPath+RepositoriesCollection.Item(RepositoryIndex)),TempXMLFilePath End Sub 'FuncitonName:ConvertToObjectLayer 'Description:Find object name in temp.xml file and recombine to a string like windows("test").winbutton("hello") 'Function:Function Utilities ,referenced by BuildObject Function ConvertToObjectLayer(ObjectName) ObjectArray=ObjectBuild.FilePathObjectName(TempXMLFilePath,ObjectName) If ObjectArray<>"" Then ObjectArray=Split(ObjectArray,"@") ConvertToObjectLayer=ObjectArray(Ubound(ObjectArray)) ELSE ConvertToObjectLayer="" End If End Function
上面可以 看到高有季buildobjeectt方法 ,这个其实是net写的dll.具体 代码如下,这里千万不能如错,为了考虑以后兼容,我在这里返回的是数组。原则QTP对象库中是不要出现两个同名的对象。这个地方是千万不能出错的。为了简单和效率就用了linq to xml.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.XPath; using System.Xml.Xsl; using System.Xml.Linq; namespace QTPBuildObjectLayer { public class BuildObject { XNamespace NameSpace = "http://www.mercury.com/qtp/ObjectRepository"; public string FilePathObjectName(string FilePath, string LogicName, string ObjectType = "") { string ParentNode = ""; string ChildNode = ""; string BuildObjectString = ""; String ObjectList = ""; try { if (FilePath == null || LogicName == null) { ObjectList = "Please input right FilePath or LogicName"; return ObjectList.ToString(); } XDocument test = XDocument.Load(FilePath); var Query = from c in test.Descendants(NameSpace + "Object") where ((ObjectType == "") ? (c.Attribute("Name").Value == LogicName) : (c.Attribute("Name").Value == LogicName && c.Attribute("Class").Value == ObjectType)) select new { IsChildObject = c.Parent.Name.Equals(NameSpace + "ChildObjects"), LogicNameClass = c.Attribute("Class").Value //ChildObjectsElementName = c.Attribute("Name").Parent.Parent.Name, //ParentAttributionName = c.Attribute("Name").Parent.Parent.Parent.Attribute("Name").Value, //ParentAttributionValue = c.Attribute("Name").Parent.Parent.Parent.Attribute("Class").Value }; foreach (var Item in Query) { ChildNode = ""; ChildNode = Item.LogicNameClass + "(\"" + LogicName + "\")"; if (Item.IsChildObject) { ParentNode = ParentNode + BuildParentNode(FilePath, LogicName, Item.LogicNameClass); } BuildObjectString = ParentNode + ChildNode; ObjectList = ObjectList + "@" + (BuildObjectString); } return ObjectList; } catch (Exception exception) { ObjectList = exception.ToString(); return ObjectList; } } public string BuildParentNode(String FilePath, string LogicName, String LogicNameClass) { string ParentNode = ""; XDocument ParentObject = XDocument.Load(FilePath); try { var Query1 = from b in ParentObject.Descendants(NameSpace + "Object") where (b.Attribute("Name").Value == LogicName) && (b.Attribute("Class").Value == LogicNameClass) select new { ParentIsChildObject = b.Parent.Parent.Name.Equals(NameSpace + "ChildObjects"), ParentAttributionName = b.Parent.Parent.Attribute("Name").Value, ParentAttributionClass = b.Parent.Parent.Attribute("Class").Value }; foreach (var Item1 in Query1) { ParentNode = Item1.ParentAttributionClass.ToString() + "(\"" + Item1.ParentAttributionName + "\")."; if (Item1.ParentIsChildObject) { LogicName = Item1.ParentAttributionName; LogicNameClass = Item1.ParentAttributionClass; ParentNode = ParentNode + BuildParentNode(FilePath, LogicName, LogicNameClass); } // break; } return ParentNode; } catch (Exception) { return "BuildChildObject Failed"; } } } }
下面也是比较关键的,写了一大堆 东西就是为了实现 一个功能,把转换后的对象字符串、测试数据与对应的事件关联起来,即将读取到的window("aa").edit("b") 及111111 set拼接在一起执行,然后找到对应的方法并执行,这里每一个set.click.doubleclick都是作为 action部分的,每个事件一个方法,如果执行失败就截图并记录即可。
'FunctionName: ExecuteActionSteps 'Description: Execute all actions from this function 'FunctionType:Framework core partion, referenced by Utility Function library,ActionEntry function Function ExecuteActionStpes(strKeyWords,strObjectName,strParameter,strRepositoriesName) If strKeyWords="" Then Reporter.ReportEvent micFail,"Function ActionEntry","Business_Function is null" Exit function End If Environment("DefinedActionName")=strKeyWords If strRepositoriesName <> "" Then LoadRepositories RepositoriesName End If If strObjectName <>"" Then If ucase(left(strObjectName,4))="DSC_" Then strObject=DespritionObject(strObjectName) else strObject=BuildObject(strObjectName) End if If strObject="" OR strObject="Not Found" Then Reporter.ReportEvent micFail,"ObjectString:"+strObjectName,"Build object failed,please check your entry or object is described correctly" Exit function End If If strParameter = "" Then Eval(Trim(strKeyWords)+"("+strObject+")") else TestParameter=ReOrganizeParameter(strParameter) Eval(Trim(strKeyWords)+"("+strObject+","+TestParameter+")") End If Else If strObjectName="" and strParameter="" Then Eval(Trim(strKeyWords)) else If strObjectName="" Then TestParameter=ReOrganizeParameter(strParameter) Eval(Trim(strKeyWords)+"("+TestParameter+")") End If End If End If End Function
根据eval的结果,自动跳转到action方法部分。以下仅为一个,示例,所以有的均可参照这种方法。其它的类似就不一一重复
'FunctionName:Enter_Value_In_Field 'Descriptions:Enter vlaue in edit box or text box etc. 'Input Parameter:Object String,input parameter and if value is encryped flag 'FunctionType: Framework core functions, referenced by execute action steps Function Enter_Value_In_Field(strObject,strParameter,IsEncryped) Enter_Value_In_Field="FAIL" If strObject.exist(10) Then strObject.set "" If Ucase(IsEncryped)="YES" Then EncypParameter=Crypt.Encrypt(strParameter) strObject.SetSecure EncypParameter else strObject.set strParameter End If Enter_Value_In_Field="PASS" call LogAndCaptureImage(strObject,"Enter_Value_In_Field","PASS","Object:"+strObject.Tostring+" executed successfully") else Enter_Value_In_Field="FAIL" call LogAndCaptureImage(strObject,"Enter_Value_In_Field","FAIL","Object:"+strObject.Tostring+" Not Found") End If End Function
最后就是执行的结果需要进行截图,并记录运行每一步的结果
'FunctionName:LogAndCaptureImage 'Descriptions:If Function parameter contain object name, log action execute status and capture img ,if object is null,log execute status 'Input Parameter:strObjectName,ReportName,ReportStatus,ReportDetails 'Output Parameter:None 'FunctionType:Global function, referenced by all actions Function LogAndCaptureImage(ObjectName,ActionStep,ReportStatus,ReportDetails) ImageFilePath=Environment("FrameworkPath")+"Test_Result\"+Environment("DefinedTestName")+"\"+cstr(Environment("DefinedTestIteration"))+"_Image" FormattedCurrentDateTime=year(Date)&month(date)&day(date)&hour(now)&minute(now)&second(now) ReportStep=ActionStep ImageFileFullPath="" If Not IsEmpty(ObjectName) and IsObject(ObjectName) Then ReserveObject=split(trim(Replace(ObjectName.Tostring,"["," "))," ") ReserveObjectName=ReserveObject(Lbound(split(ObjectName.Tostring," "))) ObjectString=BuildObject(ReserveObjectName) If Ubound(split(ObjectString,")."))>0 Then TempArray=split(ObjectString,").") TempObject="set ObjectToCapture="+TempArray(0)+")" ELSE TempObject="set ObjectToCapture="+ObjectString End If Execute TempObject If DirectoryOperation.exists(ImageFilePath) = "False" Then DirectoryOperation.CreateDirectory(ImageFilePath) End If ImageFileFullPath=ImageFilePath+"\"+FormattedCurrentDateTime+".png" If ObjectToCapture.exist(5) and Environment("ImageCaptureLevel") <> "FailedOnly" Then ObjectToCapture.CaptureBitmap ImageFileFullPath,true ObjectToCapture.CaptureBitmap ImageFileFullPath,true If ReportStatus="PASS" Then If Environment("ImageCaptureLevel") <> "FailedOnly" Then Reporter.ReportEvent micPass,ReportStep,ObjectName.Tostring+"Finished", ImageFileFullPath else 'Reporter.ReportEvent micPass,ReportStep,ReportDetails+": "+"<img src='"+ImageFilePath+"\"+FormattedCurrentDateTime+".png"+"' />" Reporter.ReportEvent micPass,ReportStep,ReportDetails End if call GenerateReport(ReportStep,"PASSED",ReportDeatils,ImageFileFullPath) else Reporter.ReportEvent micFail,ReportStep,ReportDetails,ImageFileFullPath call GenerateReport(ReportStep,"FAILED",ReportDeatils,ImageFileFullPath) End If Else If ReportStatus="PASS" Then Reporter.ReportEvent micPass,ReportStep,ReportDetails call GenerateReport(ReportStep,"PASSED",ReportDeatils,"") else Reporter.ReportEvent micFail,ReportStep,ReportDetails call GenerateReport(ReportStep,"FAILED",ReportDeatils,"") End If End if End If End Function
最后一步是压缩成ZIP文件将结果发送至指定邮箱。这个功能多上有很多,这里就不详细介绍了。
'FunctionName:ZipFile 'Description:Zip a file to *.ZIP 'InputParameter:Source file path,desination file path 'FunctionType:Framework core function Function ZipFile(SourceFolder,ZipFilePath) Set Fso=createobject("Scripting.FileSystemObject") for each files in Fso.GetFolder(SourceFolder).Files If lcase(right(files,4))=".zip" Then Fso.DeleteFile files.path,True End If Next set File=Fso.CreateTextFile(ZipFilePath,true) File.Write "PK"& Chr(5) & Chr(6) & String(18, Chr(0)) File.Close Set objShell=CreateObject("Shell.Application") Set objSource=objShell.NameSpace(SourceFolder) Set objFolderItem=objSource.Items() Set objTarget=objShell.NameSpace(ZipFilePath) intOptions=256 objTarget.CopyHere objFolderItem,IntOptions Do wait 0.5 Loop Until objTarget.Items.Count >0 Set File=Nothing Set objShell=Nothing Set WScript=Nothing End Function 'FunctionName:SendMail 'Description:SendMail to specify user and specify server 'InputParameter:useraccount,userpassword,serveraddress,sendto,mailsubject,mailbody,attachment 'FunctionType:Framework Core function Function SendMail(UserAccount,UserPassword,SendTo,MailSubject,MailBody,Attachment) NameSpace="http://schemas.microsoft.com/cdo/configuration/" Set Email=CreateObject("CDO.Message") Email.From=UserAccount Email.To=SendTo Email.Subject=MailSubject Email.TextBody=MailBody If Attachment<>"" Then If FileExists(Attachment) Then Email.AddAttachment Attachment End If End If AccountInfo=split(UserAccount,"@",2,1) With Email.Configuration.Fields .item(NameSpace&"sendusing")=2 .item(NameSpace&"smtpserver")="smtp."+AccountInfo(1) .item(NameSpace&"smtpserverport")=25 .item(NameSpace&"smtpauthenticate")=1 .item(NameSpace&"sendusername")=AccountInfo(0) .item(NameSpace&"sendpassword")=userpassword .Update End With Email.Send Set Email=nothing End Function
再补充几个功能,进入节点,和退出QTP自带report结点
'FunctionName:EnterNode 'Description:insert a node,then all event will be logged under this node 'InputParameter:NodeName---TestInteration or ActionInteration;NodeContent,Node description 'OutPutParameter:Node 'FunctionType:Reporting module,Referenced by LogAndCaptureImage '@Description Create a Node ,then all reporter event will under this node,this function must work together with ExitNode Public Function EnterNode(ByRef NodeName, ByRef NodeContent) Set DiscriptionNodeData=CreateObject("Scripting.Dictionary") DiscriptionNodeData("Status")=MicDone DiscriptionNodeData("PlainTextNodeName")=NodeName DiscriptionNodeData("StepHtmlInfo")=NodeContent DiscriptionNodeData("DllIconIndex")=210 DiscriptionNodeData("DllIconSelIndex")=210 DiscriptionNodeData("DllPath")=Environment("ProductDir")+"/bin/ContextManager.dll" intContext=Reporter.LogEvent("User",DiscriptionNodeData,Reporter.GetContext) Reporter.SetContext intContext End Function 'FunctionName:ExitNode 'Description:Exit current node 'InputParameter:None 'OutputParameter:Node 'FunctionType:Reporting Module,referenced by LogAndCaptureImage '@Description Exit current node Public Function ExitNode() Reporter.UnSetContext Set DiscriptionNodeData=Nothing End Function
相关推荐
压缩包中的"project"和"自动化框架开发"可能包含了具体的项目实践和框架实现,而"RelevantCodes"可能是一些相关代码示例,可以帮助学习者深入理解QTP自动化测试的实现细节。"SAFFRON框架"则可能是一个具体的框架实例...
本压缩包包含了两份珍贵的资源:《QTP自动化测试实践.pdf》和《QTP自动化测试进阶.pdf》,它们分别针对QTP的基础运用和高级技巧进行了深入讲解,对于理解和掌握QTP自动化测试具有极大的帮助。 《QTP自动化测试实践....
QTP自动化轻量级测试框架则是基于QTP构建的一种简化版测试架构,旨在提高测试效率,降低维护成本,同时保持测试的灵活性和可扩展性。 1. **测试数据与测试脚本分离**: 测试数据与测试脚本分离是该框架的核心特点...
《精通QTP:自动化测试技术领航》(余杰 赵旭斌) [高清扫描版] 《精通QTP:自动化测试技术...第5章和第6章讲解了设计模式和自动化测试框架的内容,这两章内容是QTP测试技术精华的浓缩,如QTP设计模式和自动化测试框架。
在本讲中,我们将对QTP(QuickTest Professional)自动化测试进行深入的总结,这是...视频资源"第30讲-QTP自动化测试视频总结【QTP自动化测试视频.flv】"应包含对这些概念的详细解释和实例演示,建议观看以加深理解。
第5章和第6章讲解了设计模式和自动化测试框架的内容,这两章内容是QTP测试技术精华的浓缩,如QTP设计模式和自动化测试框架。 另外,《精通QTP:自动化测试技术领航》在第1章至第4章精心设置了习题,帮助读者巩固已...
线性自动化框架是自动化测试的第一种类型,使用一种顺序执行测试用例的方式进行测试。线性自动化框架简单易用,但不能满足复杂的测试需求。 八、自动化框架在测试中的应用 自动化框架在测试中扮演着非常重要的角色...
在“QTP自动化框架脚本示例”中,我们可以通过一系列的VBS(Visual Basic Scripting Edition)脚本来理解并学习如何构建一个有效的自动化测试框架。 1. **Control.vbs** 和 **ObjectControl.vbs**: 这两个文件...
- **QTP自动化测试工程师**:已有一定QTP基础,希望深入学习QTP并掌握更多高级功能的测试工程师。 - **资深测试工程师**:对多种测试技术和工具有所了解,希望通过本次培训进一步提升自动化测试技能。 - **没有实际...
**QTP(QuickTest Professional)**,现在被称为UFT(Unified Functional Testing),是HP公司推出的一款功能强大的自动化测试工具,尤其适用于企业级的软件功能测试。QTP以其易用性、自动化能力以及对多种应用程序...
本文主要针对那些希望学习或正在学习自动化测试的朋友,通过QTP自带的flight示例,逐步解析从工具操作到自动化框架构建的全过程。 首先,了解自动化测试的基础概念至关重要。自动化测试是指利用专门的软件工具,对...
- 自动化框架构建:QTP支持自定义函数库和测试框架,便于团队协作和维护。 总之,QTP汉化工具包是为了提升中文用户的使用体验,使其能够更高效地进行自动化测试。了解QTP的基本概念、工作原理以及如何正确使用汉化...
- **《自动化测试解决方案》**:概述了自动化测试的整体框架和技术路线。 - **《采购通自动化测试总体设计》**:提供了更为具体的自动化测试策略和技术实现细节。 - **《采购通功能设计说明书》**:详细描述了被测...
它主要用于功能测试和回归测试,尤其在Web、桌面应用以及移动应用的自动化测试领域有广泛的应用。QTP能够通过录制、回放以及脚本编辑的方式实现对应用程序的自动化测试,极大地提高了测试效率。 EMOS(Enterprise ...
1. 学习QTP自动化测试的起点: 学习QTP或其他自动化测试工具时,首先需要理解自动化测试的本质,即录制功能并不足够,需要深入理解自动化测试的基础知识。这包括: - 阅读工具的官方文档以获取基础信息。 - 熟悉...
9. **软件自动化测试工具**:Quick Test Professional(QTP)是功能强大的UI自动化测试工具,NUnit是.NET环境下的单元测试框架,而LoadRunner则用于性能测试和负载测试。 **第三篇 项目案例篇** 10. **自动化测试...
【自动化工具与框架实践】——探索QTP自动化测试 QTP,全称为QuickTest Professional,是一款功能强大的自动化测试工具,由HP(现为Micro Focus)公司开发,主要用于软件功能自动化测试。本篇主要介绍QTP的基本使用...
Selenium WebDriver是一个强大的开源自动化测试框架,适用于Web应用程序。它支持多种编程语言,包括Python,使得测试工程师能够利用熟悉的语言进行测试脚本的编写。相较于其他商业自动化测试工具,如QTP,Selenium...