欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

QTP自动化测试框架:第六章 主要方法介绍(框架功能)

程序员文章站 2022-04-16 12:14:59
...

时间有点晚了,我这里就直接拿出几个最关键的一方

 

第一,将对象库转换成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