测试交流天地

发布新日志

  • 用QTP的描述性编程高亮显示任意对象

    2011-07-24 09:52:05

    这里运用描述性编程实现高亮显示计算器中的0到9的按钮对象
    把以下代码拷到QTP中,点“运行”,看看效果。
    注:本程序windows XP下的计算器演示,若使用windows 2000的计算器无效。


    SystemUtil.Run "C:\WINDOWS\system32\calc.exe","","C:\WINDOWS\system32","open"
    For i =0 to 9
    HighlightAll Window("regexpwndclass:=SciCalc").WinButton("text:=" & cstr(i) )
    Next


    Sub HighlightAll(TestObject)

           Dim Parent, Desc, Props, PropsCount, MaxIndex, i, Objs
           If IsEmpty(TestObject.GetTOProperty("parent")) Then
                  Set Parent = Desktop
           Else
                  Set Parent = TestObject.GetTOProperty("parent")
           End If
           Set Desc = Description.Create
           Set Props = TestObject.GetTOProperties
           PropsCount = Props.Count - 1
           For i = 0 to PropsCount
                  Desc(Props(i).Name).Value = Props(i).Value
           Next
           Set bjs = Parent.ChildObjects(Desc)
           MaxIndex= Objs.Count - 1
           For i = 0 to MaxIndex
                  Objs.Item(i).Highlight
           Next

    End Sub

  • QTP的Test参数以及顶级Action参数的使用

    2011-07-24 09:51:06

    网上有些关于如何使用Action参数的文章,不过关于QTP的Test参数和Top-Level Action参数的使用例子几乎没有。
    有些人甚至不知道这个参数做什么用的,尤其是Test的output不知道怎么取。
    其实它是外部对象传给它的(这个外部对象可以是Quality Center,也可以是vbs这样的驱动程序)。
    以下给大家讲解一个关于QuickTest的Flight的例子。
    首先,在QTP里录制一段脚本代码如下:
    1. SystemUtil.Run "C:\Program Files\Mercury\QuickTest Professional\samples\flight\app\flight4a.exe","","C:\Program Files\Mercury\QuickTest Professional\samples\flight\app\","open"
    2. Dialog("Login").WinEdit("Agent Name:").Set Parameter("InAction1")
    3. wait 5
    4. Dialog("Login").WinEdit("Agent Name:").Type  micTab
    5. Dialog("Login").WinEdit("Password:").SetSecure "4649c633ffc8803c10097292953c6334fde3e923"
    6. Dialog("Login").WinEdit("Password:").Type  micReturn
    7. Window("Flight Reservation").Close
    8. Parameter("OutAction1") = True
    复制代码

    然后,鼠标选中Keyword View中的Action1,点右键---Action Property,在Parameters的Tab标签下,分别加入:输入参数 InAction1 ,类型String;输出参数 OutAction1,类型 Boolean。如下图。
    再然后,在QTP的菜单File--->>Settings的Parameters的Tab标签下,分别加入:输入参数 InParam1 ,类型String;输出参数 OutParam1,类型 Boolean。如下图。
    接着,鼠标还是选中Keyword View中的Action1,点右键,这次点“Action Call Properties”,在Parameter Values里进行参数化传递设置,把InParam1的值传递给InAction1,把OutAction1的值传递给OutParam1。如下图。
    以上设置完毕后,点“保存”,保存到C:\下,存为Test1好了。

    最后,在你的硬盘上新建一个vbs文件,文件内容如下:
    1. Dim qtApp ,pDefColl,pDef ,rtParams,rtParam
    2. Set qtApp = CreateObject("QuickTest.Application")
    3. qtApp.Launch
    4. qtApp.Visible = True
    5. qtApp.Open "C:\Test1"
    6. Set pDefColl = qtApp.Test.ParameterDefinitions
    7. cnt = pDefColl.Count
    8. Indx = 1
    9. While Indx <= cnt
    10.     Set pDef = pDefColl.Item(Indx)
    11.     Indx = Indx + 1
    12. Wend
    13. Set rtParams = pDefColl.GetParameters()
    14. Set rtParam = rtParams.Item("InParam1")
    15. rtParam.Value = "songfun"
    16. qtApp.Test.Run , True, rtParams
    17. MsgBox rtParams.Item("OutParam1").Value  
    复制代码


    做完这步之后,保存这个vbs文件,双击执行这个vbs文件,你会发现它自动启动了QTP,而且进行了自动测试,最后还取到了运行成功与否的布尔值。
    这就是关于Test、Top-Level Action参数使用的例子,它的参数的整个传递过程是:
    外部vbs文件 传参数给QuickTest的Test的输入参数InParam1,然后InParam1传参数到InAction1去驱动了Action1的测试,然后通过这个Action1得出了OutAction1的值,然后通过OutAction1传给OutParam1,最后再传回到vbs文件中。示例用MsgBox来打出重新传回到vbs文件中的字符串。

    [ 本帖最后由 songfun 于 2007-5-17 09:33 编辑 ]

    quicktestparam.bmp (1.83 MB)

    quicktestparam.bmp

  • 用QTP调用外部vbs读写XML的例子(一)

    2011-07-24 09:49:01

    目前,企业中对XML的应用越来越广泛,作为自动化测试的测试工程师,也应该掌握XML的读写操作。
    以下我使用XML DOM技术演示一个例子,用以读取XML指定节点的节点内容值。
    读取函数原型 GetXml strXmlPath,nodeName
    这个函数的第一个参数表示xml文件所在路径,第二个参数表示希望获取到的xml节点名,请结合下列例子看
    首先,新建一个vbs文件(取个名字叫readXml.vbs),输入代码
    1. '==================================================================
    2. '   Author  : songfun
    3. '
    4. '  Description :  Read XML
    5. '==================================================================
    6. Dim strXML

    7. GetXml "c:\search.xml","TestResult"  '这个函数的第一个参数表示xml文件所在路径,第二个参数表示希望获取到的xml节点名,请结合下列例子看
    8. MsgBox strXML


    9. Function GetXml (ByVal strXmlFilePath,ByVal xmlNodeName)
    10.         Dim xmlDoc,xmlRoot
    11.        
    12.         Set xmlDoc = CreateObject("Microsoft.XMLDOM") '创建XML DOM对象
    13.         xmlDoc.async = False  '控制加载模式为同步模式(xml树加载完毕后再执行后续代码)
    14.         xmlDoc.load strXmlFilePath        '载入xml文件
    15.         If xmlDoc.parseError.errorCode <> 0 Then
    16.                 MsgBox "XML文件格式不对,原因是:" & Chr(13) &  xmlDoc.parseError.reason
    17.                 Exit Function               
    18.         End If
    19.         Set xmlRoot = xmlDoc.documentElement       
    20.         xmlRecursion xmlRoot,xmlNodeName        '调用xml递归函数传入指定的根和节点名       
    21.         GetXml = True 'xmlRecursion (xmlRoot)
    22.        
    23. End Function

    24. Function xmlRecursion(byval xmlNode,byval strNodeName)
    25.         If xmlNode.nodeName = strNodeName And xmlNode.hasChildNodes Then
    26.                 If  xmlNode.childNodes.item(0).nodeName = "#text" Then
    27.                         strXML = strXML & xmlNode.nodeName & ":" & xmlNode.childNodes.item(0).nodeValue & Chr(13)                                               
    28.                 End If               
    29.         End If                       
    30.         If xmlNode.hasChildNodes Then
    31.                 For Each childNodeItem In xmlNode.ChildNodes
    32.                         If childNodeItem.hasChildNodes Then
    33.                                 xmlRecursion childNodeItem,strNodeName                               
    34.                         End If                       
    35.                 Next
    36.         End If       
    37. End Function
    复制代码


    接着,自己构造一个xml文件(取个名字叫search.xml),如:

    1. <?xml version="1.0" encoding="GB2312"?>

    2. <ROOT>
    3.         <TestCase>
    4.                 <TestNumberOne>1</TestNumberOne>
    5.                 <TestNumberTwo>2</TestNumberTwo>
    6.                 <TestNumberThree>+</TestNumberThree>
    7.                 <TestResult>3</TestResult>
    8.         </TestCase>
    9.         <TestCase>
    10.                 <TestNumberOne>3</TestNumberOne>
    11.                 <TestNumberTwo>2</TestNumberTwo>
    12.                 <TestNumberThree>-</TestNumberThree>
    13.                 <TestResult>1</TestResult>
    14.         </TestCase>
    15.         <TestCase>
    16.                 <TestNumberOne>3</TestNumberOne>
    17.                 <TestNumberTwo>7</TestNumberTwo>
    18.                 <TestNumberThree>*</TestNumberThree>
    19.                 <TestResult>21</TestResult>
    20.         </TestCase>
    21.         <TestCase>
    22.                 <TestNumberOne>2</TestNumberOne>
    23.                 <TestNumberTwo>5</TestNumberTwo>
    24.                 <TestNumberThree>/</TestNumberThree>
    25.                 <TestResult>0.4</TestResult>
    26.         </TestCase>       
    27. </ROOT>
    复制代码


    然后,在QTP的expert view中调用刚才写的vbs文件:
    executefile "c:\readXml.vbs"

    点“Run”,就能看到这个效果了。
    当然,如果你不用调用外部文件的方式,也可以,如下图。

    [ 本帖最后由 songfun 于 2007-5-19 13:46 编辑 ]

    qtpxml.JPG (132.46 KB)

    qtpxml.JPG

  • 在QTP中如何使用Class(类)

    2011-07-24 09:47:34

    大家知道VB是面向对象的,其中Class(类)是一个“模板”,对象是由它而创建的。类中的代码描述了从该类创建的对象的特性 (attribute) 和行为。
    虽然Class(类)不是对象,但是它的确有定义其特性 (attribute) 的设计时属性 (property) 和定义其行为的事件。
    类里的数据,是相对于类实例(也就是,由类创建的每一对象)而独立存在的。
    也就是说,它存在于程序的存活期中;而类实例中的数据只存在于对象的存活期,它随对象的创建而创建,随对象的撤消而消失。
    在编程的时候使用Class正是符合了OO(面向对象封装)的编程原则,我们在使用QTP进行自动化测试编程的时候也要时刻牢记这一原则,进行脚本设计。
    然而,如何在QTP中使用Class呢,以下是本人写的一个在QTP中使用Class的例子,大家直接把它粘贴到QTP的Expert View中就能看到效果了:)


    '****************************************************************
    Call Test

    Class Tester

            Dim mvarTesterName,mvarAge,mvarGender       
           
            Sub Class_Initialize   '构造函数
                   MsgBox  "接下来,大家欢迎新同事的到来!"
            End Sub
           
            Sub Class_Terminate  '析构函数
                    If mvarGender Then
                        MsgBox "很遗憾," & mvarTesterName & "先生脱离了测试行业!"
                    Else
                        MsgBox "很遗憾," & mvarTesterName & "女士脱离了测试行业!"
                    End If
            End Sub

            Sub Test(ByVal ProjectName)
                    MsgBox mvarTesterName & "正在加班加点的测试" & ProjectName & "呢!"
            End Sub
           
            Sub Eat(ByVal food)
                    MsgBox mvarTesterName & "正在吃" & food & "呢,好爽啊!"
            End Sub
           
            Property Let Gender(ByVal vData)
                mvarGender = vData            
            End Property
           
            Property Get Gender()
                Gender = mvarGender
            End Property
           
            Property Let Age(ByVal vData)
                mvarAge = vData
            End Property
           
            Property Get Age()
                Age = mvarAge
            End Property
           
            Property Let TesterName(ByVal vData)
                mvarTesterName = vData
            End Property
           
            Property Get TesterName()
                TesterName = mvarTesterName
            End Property
       
    End Class



    Sub Test()
            Set sb = New Tester  '创建一个对象,对象名叫somebody,它是由Tester创建出来的
            sb.TesterName = "songfun"
            sb.Age = 29
            sb.Gender = True
            sb.Eat "HagenDaz"
            sb.Test "手机"
            If sb.Gender Then
                    MsgBox sb.TesterName & "先生年方" & sb.Age
       Else
                    MsgBox sb.TesterName & "女士芳龄" & sb.Age
            End If
            Set sb = Nothing
    End Sub
    '****************************************************************

  • QTP中连接MySQL的方法(数据库验证点和ADO连接)

    2011-07-24 09:45:41

    很多朋友对于QTP中连接MYSQL束手无策,其实根本原因是默认的我们的操作系统中ODBC驱动里默认不支持开源的MySQL驱动。
    解决这个问题的方法非常简单,安装一个相关的驱动就能解决问题了。
    这里给出这个驱动程序下载地址MyODBC-3.51.11-2-win.exe
    安装完毕后,到“控制面板--管理工具--数据源ODBC--系统DSN”把它添加进来,步骤见下面截图qtpmysqsl1.JPG到qtpmysqsl5.JPG(我在本机上安装了一个Discuz论坛)。
    添加完毕后,就可以开始使用了。
    以下给出具体的实现过程
    (一)数据库验证点:
    见下面截图 qtpmysqsl6.JPG 到 qtpmysqsl9.JPG
    (二)ADO连接MySQL数据库的代码
    例子(获取论坛中的帖子主题和内容):
    1. Dim Cnn, Rst, strCnn

    2. strCnn = "DRIVER={MySQL ODBC 3.51 Driver};SERVER=localhost;DATABASE=discuz;USER=root;Option=3"
    3. Set Cnn = CreateObject("ADODB.connection")
    4. Cnn.Open strCnn
    5. Set Rst = CreateObject("ADODB.Recordset")
    6. Rst.Open "select * from cdb_posts", Cnn
    7. Rst.MoveFirst
    8. While Rst.EOF <> True
    9.     MsgBox Rst.Fields("subject") & Chr(13) & Chr(10) & Rst.Fields("message") & Chr(13) & Chr(10)
    10.     Rst.MoveNext
    11. Wend
    12. Rst.Close
    13. Cnn.Close

    14. Set Rst = Nothing
    15. Set Cnn = Nothing
    复制代码

    qtpmysqsl1.JPG (34.27 KB)

    qtpmysqsl1.JPG

    qtpmysqsl2.JPG (44.58 KB)

    qtpmysqsl2.JPG

    qtpmysqsl3.JPG (34.17 KB)

    qtpmysqsl3.JPG

    qtpmysqsl4.JPG (34.97 KB)

    qtpmysqsl4.JPG

    qtpmysqsl5.JPG (36.01 KB)

    qtpmysqsl5.JPG

    qtpmysqsl6.JPG (27.92 KB)

    qtpmysqsl6.JPG

    qtpmysqsl7.JPG (35.67 KB)

    qtpmysqsl7.JPG

    qtpmysqsl8.JPG (25.09 KB)

    qtpmysqsl8.JPG

    qtpmysqsl9.JPG (35.41 KB)

    qtpmysqsl9.JPG

  • 如何用QTP解决图片验证码(解析QuickTest文本识别机制)?

    2011-07-24 09:43:55

    大家在使用QTP进行自动化测试的过程中经常会遇到图片验证码的问题——大家所关心的就是如何解决此类问题。
    这里我们首先要去了解为什么会有图片验证码。其实验证码的本质作用就是防止有人利用工具(灌水机、注册机,当然也不小心包括了我们的自动化测试工具)恶意猜解登陆或者不停的注册和灌水的。因此如果我们完全寄希望于通过GUI识别来获取内容是不切实际的——先打好预防针,免得读者希望太大,失望更大,呵呵!
    下面说说验证码的解决思路:
    其实解决图片验证码的思路有很多,我这里主要结合QTP9.5的新特性给大家介绍其中一种解决方案,就是利用它的OCR机制抓取文本内容。
    在QTP9.5中,对象识别能力有了进一步改善,其中针对文本识别方面进行了优化,引入了ABBYY公司的OCR解决方案——这个相关的功能体现在QTP菜单的“Tools-->Options-->General--Use text recognition mechanisms in this order”里,详细内容后面会有具体介绍。
    先来看看ABBYY是何许公司,登录他们的官方网站可以看到一段相关介绍:“ABBYY是世界OCR(光学字符识别)、ICR(手写体识别)和语言软件的领航者。ABBYY 致力于人工智能(AI)和语言软件开发。提供全套文档识别,转换和数据捕获技术的产品解决方案。”如果你使用过图像文档转换的软件,一定会听说过FineReader OCR Professional ,其实它就是ABBYY公司的产品,用官方的说法就是“将通过扫描仪、MFP 或数码相机生成的图像快速转换为可编辑和可搜索的电子格式,而且识别率很高”,说白了就是可以借助它先进的OCR机制“读”出图片里的文本内容,并转换为PDF之类的文档。
    有了ABBYY这么强大的背后支持,QTP自然底气十足,那么QTP到底如何以OCR机制识别文本呢?我们首先先了解一下什么是OCR。
    打开“百度百科_OCR”,它的说明:“OCR(Optical Character Recognition,光学字符识别),是属于图型识别(Pattern Recognition,PR)的一门学问。其目的就是要让计算机知道它到底看到了什么,尤其是文字资料。 由于OCR是一门与识别率拔河的技术,因此如何除错或利用辅助信息提高识别正确率,是OCR最重要的课题,ICR(Intelligent Character Recognition)的名词也因此而产生。而根据文字资料存在的媒体介质不同,及取得这些资料的方式不同,就衍生出各式各样、各种不同的应用。”这里有个关键词:“正确率”,也就是“识别率”——既然不能够总是100%,我们自然不可能完全寄希望于通过QTP能够每次100%正确的去识别图片里的文本。尤其是“道高一尺魔高一丈”的今天,验证码加入了大量的干扰素,如扭曲、变形、错位、随机背景花纹,给OCR识别增加了很多难度——本来就不希望被软件识别到嘛。

    了解了OCR之后,我们再来看看QTP对应的这个设置。如前面所说,通过QTP菜单的“Tools-->Options”选中到“General--Use text recognition mechanisms in this order”,这里的四个选项就是对应的不同设置。我们看看帮助的描述(我做了翻译):
    =================================
    使用文本识别机制

    指定QTP在采用 “文本”或者“文本区域” 的 检查点或输出值 的步骤时,捕获文本内容所使用的文本识别机制。
    以下有三种识别方式:
    1、先使用Windows API,再使用OCR(默认)。
        指示QTP首先尝试以基于Windows API的机制从对象上直接获取文本内容。如果未获取到文本(比如,文本属于图片的一部分),QTP就会使用OCR的机制尝试获取这段文本。
        强烈建议在使用中日韩(象形文字)、英的语言环境下采用这个设置。

    2、先使用OCR,再使用Windows API。
        指示QTP首先尝试使用OCR机制从对象上去获取文本。如果未获取到文本,QTP就会以Windows API的机制去获取文本内容。

    3、仅使用Windows API方式。
        指示QTP仅采用基于Windows API的机制从对象上获取文本内容。

    4、仅使用OCR的方式。
        指示QTP仅采用基于OCR的机制从对象上获取文本内容。
        在使用Windows Vista要使用这种方式。

    =================================
    上面的内容已经解释的很明确了,接下来我们通过TextArea Output Value看看效果。

    如下图所示,QTP针对几张图片的识别效果:
    (一)、内容是51Testing的,QTP获取正确;内容是51Testing的G风格彩字,QTP获取错误(显示为IC_CHECK_PATTERN)



    (二)、内容是songfun的普通文本,QTP获取正确;内容是songfun的G风格彩字,QTP获取错误(也显示为IC_CHECK_PATTERN)




    有兴趣大家可以自己做一些图片,甚至可以用QQ的验证码图片来试验一下,看看OCR效果。
  • QTP六脉神剑之调用Java程序

    2011-07-24 09:41:33

    不少网友对于QTP调用Java程序感到束手无策,实际上要调用Java程序是非常容易的。接下来songfun老师传授给大家武林绝技之六脉神剑。在演示这个例子前,请大家先造一个java程序(我以java计算器为例,源码见下),以方便观察调用结果

    第一式:少商剑。特点:剑路雄劲,石破天惊。

    打开QTP,在QTPExpert View中输入:InvokeApplication "cmd /k cd c:\ && java Counter && exit"
    运行QTP,看看,打开了吗?

    第二式:商阳剑 特点:巧妙灵活,难以捉摸。

    C盘上新建一个bat文件,取名为runjava.bat,在文件里面输入一段文本:cmd /k "cd c:\ && java Counter && exit",然后保存下来。
    打开QTP,在QTPExpert View中输入:SystemUtil.Run "C:\runjava.bat"
    运行QTP,看看,打开了吗?

    第三式:中冲剑 特点:大开大阖,气势雄迈。

    打开QTP,在QTPExpert View中输入:
    Dim oWsh
    Set Wsh = CreateObject("WScript.Shell")
    oWsh.Exec "cmd /k cd c:\ && java Counter && exit"
    Set Wsh = Nothing
    运行QTP,看看,打开了吗?

    第四式:关冲剑 特点:以拙滞古朴取胜。

    C盘上新建一个qfl文件,取名为runjava.qfl,在文件里面输入一段文本:
    CallJava "Counter"
    Sub CallJava(ByVal strJavaName)

    Dim oWsh


    Set Wsh = CreateObject("WScript.Shell")


    oWsh.Run "cmd /k cd c:\ && java " & strJavaName & " && exit"


    Set Wsh = Nothing

    End Sub
    打开QTP,在QTPExpert View中输入:ExecuteFile "C:\runjava.qfl"
    运行QTP,看看,打开了吗?

    第五式:少冲剑 特点:轻灵婀娜,迅雷不及掩耳。

    安装QTPJava Add-in,之后在Automation—Record and Run Settings中出现了Java标签页。根据下图的内容设置即可(runjava.bat文件内容参照六脉神剑第二式)。
    javarecord.PNG

    第六式:少泽剑 特点:忽来忽去,变化精微。

    采用直接调用jar包的形式。要生成jar包,首先要确保在C盘下已经放置了Counter.java 源文件,然后通过命令行工具去编译它:
    cd \
    javac Counter.java
    jar cvf Counter.jar *.class
    执行完命令看看在C盘是否已经生成了Counter.jar文件?
    接下来解压Counter.jar文件,在C:\Counter\META-INF目录下可以找到MANIFEST.MF这个文件,用Notepad打开,在第三行空行处加入入口类的代码(蓝色字体部分):
    Manifest-Version: 1.0
    Created-By: 1.6.0_07 (Sun Microsystems Inc.)
    Main-Class: Counter
    保存完以后,回到命令行窗口处,输入命令更新jar包:
    jar umf C:\Counter\META-INF\MANIFEST.MF Counter.jar
    写完测试一下:java -jar Counter.jar
    如果计算器可以打开说明前期铺垫工作已经完成,那接下来的就是在QTPExpert View中输入:SystemUtil.Run "C:\Counter.jar"
    运行QTP,看看,打开了吗?


    当然实际上要调用Java程序的方法还有很多,这里就不一一介绍了。在下次课,songfun老师将会传授QTP独门秘笈之降龙十八掌给大家。谢谢!再见!

    附:Counter.java源码。
    import java.awt.*;
    import java.awt.event.*;
    import java.lang.*;
    import javax.swing.*;
    public class Counter extends Frame.
    {
    //声明三个面板的布局
    GridLayout gl1,gl2,gl3;
    Panel p0,p1,p2,p3;
    JTextField tf1;
    TextField tf2;
    Button b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17,b18,b19,b20,b21,b22,b23,b24,b25,b26;
    StringBuffer str;//显示屏所显示的字符串
    double x,y;//x和y都是运算数
    int z;//Z表示单击了那一个运算符.0表示"+",1表示"-",2表示"*",3表示"/"
    static double m;//记忆的数字
    public Counter()
    {
    gl1=new GridLayout(1,4,10,0);//实例化三个面板的布局
    gl2=new GridLayout(4,1,0,15);
    gl3=new GridLayout(4,5,10,15);
    tf1=new JTextField(27);//显示屏
    tf1.setHorizontalAlignment(JTextField.RIGHT);
    tf1.setEnabled(false);
    tf1.setText("0");
    tf2=new TextField(10);//显示记忆的索引值
    tf2.setEditable(false);
    //实例化所有按钮、设置其前景色并注册**
    b0=new Button("Backspace");
    b0.setForeground(Color.red);
    b0.addActionListener(new Bt());
    b1=new Button("CE");
    b1.setForeground(Color.red);
    b1.addActionListener(new Bt());
    b2=new Button("C");
    b2.setForeground(Color.red);
    b2.addActionListener(new Bt());
    b3=new Button("MC");
    b3.setForeground(Color.red);
    b3.addActionListener(new Bt());
    b4=new Button("MR");
    b4.setForeground(Color.red);
    b4.addActionListener(new Bt());
    b5=new Button("MS");
    b5.setForeground(Color.red);
    b5.addActionListener(new Bt());
    b6=new Button("M+");
    b6.setForeground(Color.red);
    b6.addActionListener(new Bt());
    b7=new Button("7");
    b7.setForeground(Color.blue);
    b7.addActionListener(new Bt());
    b8=new Button("8");
    b8.setForeground(Color.blue);
    b8.addActionListener(new Bt());
    b9=new Button("9");
    b9.setForeground(Color.blue);
    b9.addActionListener(new Bt());
    b10=new Button("/");
    b10.setForeground(Color.red);
    b10.addActionListener(new Bt());
    b11=new Button("sqrt");
    b11.setForeground(Color.blue);
    b11.addActionListener(new Bt());
    b12=new Button("4");
    b12.setForeground(Color.blue);
    b12.addActionListener(new Bt());
    b13=new Button("5");
    b13.setForeground(Color.blue);
    b13.addActionListener(new Bt());
    b14=new Button("6");
    b14.setForeground(Color.blue);
    b14.addActionListener(new Bt());
    b15=new Button("*");
    b15.setForeground(Color.red);
    b15.addActionListener(new Bt());
    b16=new Button("%");
    b16.setForeground(Color.blue);
    b16.addActionListener(new Bt());
    b17=new Button("1");
    b17.setForeground(Color.blue);
    b17.addActionListener(new Bt());
    b18=new Button("2");
    b18.setForeground(Color.blue);
    b18.addActionListener(new Bt());
    b19=new Button("3");
    b19.setForeground(Color.blue);
    b19.addActionListener(new Bt());
    b20=new Button("-");
    b20.setForeground(Color.red);
    b20.addActionListener(new Bt());
    b21=new Button("1/X");
    b21.setForeground(Color.blue);
    b21.addActionListener(new Bt());
    b22=new Button("0");
    b22.setForeground(Color.blue);
    b22.addActionListener(new Bt());
    b23=new Button("+/-");
    b23.setForeground(Color.blue);
    b23.addActionListener(new Bt());
    b24=new Button(".");
    b24.setForeground(Color.blue);
    b24.addActionListener(new Bt());
    b25=new Button("+");
    b25.setForeground(Color.red);
    b25.addActionListener(new Bt());
    b26=new Button("=");
    b26.setForeground(Color.red);
    b26.addActionListener(new Bt());

    //实例化四个面板
    p0=new Panel();
    p1=new Panel();
    p2=new Panel();
    p3=new Panel();
    //创建一个空字符串缓冲区
    str=new StringBuffer();
    //添加面板p0中的组件和设置其在框架中的位置和大小
    p0.add(tf1);
    p0.setBounds(10,25,300,40);
    //添加面板p1中的组件和设置其在框架中的位置和大小
    p1.setLayout(gl1);
    p1.add(tf2);
    p1.add(b0);
    p1.add(b1);
    p1.add(b2);
    p1.setBounds(10,65,300,25);
    //添加面板p2中的组件并设置其的框架中的位置和大小
    p2.setLayout(gl2);
    p2.add(b3);
    p2.add(b4);
    p2.add(b5);
    p2.add(b6);
    p2.setBounds(10,110,40,150);
    //添加面板p3中的组件并设置其在框架中的位置和大小
    p3.setLayout(gl3);//设置p3的布局
    p3.add(b7);
    p3.add(b8);
    p3.add(b9);
    p3.add(b10);
    p3.add(b11);
    p3.add(b12);
    p3.add(b13);
    p3.add(b14);
    p3.add(b15);
    p3.add(b16);
    p3.add(b17);
    p3.add(b18);
    p3.add(b19);
    p3.add(b20);
    p3.add(b21);
    p3.add(b22);
    p3.add(b23);
    p3.add(b24);
    p3.add(b25);
    p3.add(b26);
    p3.setBounds(60,110,250,150);
    //设置框架中的布局为空布局并添加4个面板
    setLayout(null);
    add(p0);
    add(p1);
    add(p2);
    add(p3);
    setResizable(false);//禁止调整框架的大小
    //匿名类关闭窗口
    addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent e1)
    {
    System.exit(0);
    }
    });
    setBackground(Color.lightGray);
    setBounds(100,100,320,280);
    setVisible(true);
    }
    //构造**
    class Bt implements ActionListener
    {
    public void actionPerformed(ActionEvent e2)
    {
    try{
    if(e2.getSource()==b1)//选择"CE"清零
    {
    tf1.setText("0");//把显示屏清零
    str.setLength(0);//清空字符串缓冲区以准备接收新的输入运算数
    }
    else if(e2.getSource()==b2)//选择"C"清零
    {
    tf1.setText("0");//把显示屏清零
    str.setLength(0);
    }
    else if(e2.getSource()==b23)//单击"+/-"选择输入的运算数是正数还是负数
    {
    x=Double.parseDouble(tf1.getText().trim());
    tf1.setText(""+(-x));
    }
    else if(e2.getSource()==b25)//单击加号按钮获得x的值和z的值并清空y的值
    {
    x=Double.parseDouble(tf1.getText().trim());
    str.setLength(0);//清空缓冲区以便接收新的另一个运算数
    y=0d;
    z=0;
    }
    else if(e2.getSource()==b20)//单击减号按钮获得x的值和z的值并清空y的值
    {
    x=Double.parseDouble(tf1.getText().trim());
    str.setLength(0);
    y=0d;
    z=1;
    }
    else if(e2.getSource()==b15)//单击乘号按钮获得x的值和z的值并清空y的值
    {
    x=Double.parseDouble(tf1.getText().trim());
    str.setLength(0);
    y=0d;
    z=2;
    }
    else if(e2.getSource()==b10)//单击除号按钮获得x的值和z的值并空y的值
    {
    x=Double.parseDouble(tf1.getText().trim());
    str.setLength(0);
    y=0d;
    z=3;
    }
    else if(e2.getSource()==b26)//单击等号按钮输出计算结果
    {
    str.setLength(0);
    switch(z)
    {
    case 0 : tf1.setText(""+(x+y));break;
    case 1 : tf1.setText(""+(x-y));break;
    case 2 : tf1.setText(""+(x*y));break;
    case 3 : tf1.setText(""+(x/y));break;
    }
    }
    else if(e2.getSource()==b24)//单击"."按钮输入小数
    {
    if(tf1.getText().trim().indexOf('.')!=-1)//判断字符串中是否已经包含了小数点
    {
    }
    else//如果没数点有小
    {
    if(tf1.getText().trim().equals("0"))//如果初时显示为0
    {
    str.setLength(0);
    tf1.setText((str.append("0"+e2.getActionCommand())).toString());
    }
    else if(tf1.getText().trim().equals(""))//如果初时显示为空则不做任何操作
    {
    }
    else
    {
    tf1.setText(str.append(e2.getActionCommand()).toString());
    }
    }
    y=0d;
    }
    else if(e2.getSource()==b11)//求平方根
    {
    x=Double.parseDouble(tf1.getText().trim());
    tf1.setText("数字格式异常");
    if(x<0)
    tf1.setText("负数没有平方根");
    else
    tf1.setText(""+Math.sqrt(x));
    str.setLength(0);
    y=0d;
    }
    else if(e2.getSource()==b16)//单击了"%"按钮
    {
    x=Double.parseDouble(tf1.getText().trim());
    tf1.setText(""+(0.01*x));
    str.setLength(0);
    y=0d;
    }
    else if(e2.getSource()==b21)//单击了"1/X"按钮
    {
    x=Double.parseDouble(tf1.getText().trim());
    if(x==0)
    {
    tf1.setText("除数不能为零");
    }
    else
    {
    tf1.setText(""+(1/x));
    }
    str.setLength(0);
    y=0d;
    }
    else if(e2.getSource()==b3)//MC为清除内存
    {
    m=0d;
    tf2.setText("");
    str.setLength(0);
    }
    else if(e2.getSource()==b4)//MR为重新调用存储的数据
    {
    if(tf2.getText().trim()!="")//有记忆数字
    {
    tf1.setText(""+m);
    }
    }
    else if(e2.getSource()==b5)//MS为存储显示的数据
    {

    m=Double.parseDouble(tf1.getText().trim());
    tf2.setText("M");
    tf1.setText("0");
    str.setLength(0);
    }
    else if(e2.getSource()==b6)//M+为将显示的数字与已经存储的数据相加要查看新的数字单击MR
    {
    m=m+Double.parseDouble(tf1.getText().trim());
    }
    else//选择的是其他的按钮
    {
    if(e2.getSource()==b22)//如果选择的是"0"这个数字键
    {
    if(tf1.getText().trim().equals("0"))//如果显示屏显示的为零不做操作
    {
    }
    else
    {
    tf1.setText(str.append(e2.getActionCommand()).toString());
    y=Double.parseDouble(tf1.getText().trim());
    }
    }
    else if(e2.getSource()==b0)//选择的是“BackSpace”按钮
    {
    if(!tf1.getText().trim().equals("0"))//如果显示屏显示的不是零
    {
    if(str.length()!=1)
    {
    tf1.setText(str.delete(str.length()-1,str.length()).toString());//可能抛出字符串越界异常
    }
    else
    {
    tf1.setText("0");
    str.setLength(0);
    }
    }
    y=Double.parseDouble(tf1.getText().trim());
    }
    else//其他的数字键
    {
    tf1.setText(str.append(e2.getActionCommand()).toString());
    y=Double.parseDouble(tf1.getText().trim());
    }
    }
    }
    catch(NumberFormatException e){
    tf1.setText("数字格式异常");
    }
    catch(StringIndexOutOfBoundsException e){
    tf1.setText("字符串索引越界");
    }
    }
    }
    public static void main(String args[])
    {
        new Counter();
    }
    }

  • QTP自动化测试相关资源列表[摘自TIB自动化测试工作室]

    2011-05-25 00:35:36

    TIB自动化测试工作
    网站:www.AutomationQA.com QQ:1837632674 Email:quicktest#qq.com

    QTP自动化测试相关资源列表

    网站、博客

    1、QTP专业网站

    http://www.advancedqtp.com/

    http://knowledgeinbox.com/

    http://www.learnqtp.com/

    http://relevantcodes.com/

    http://www.intellipro.co.uk/

    http://www.softwareinquisition.com/

    http://www.qtp10.com/

    2、HP官方QTP主页

    https://h10078.www1.hp.com/cda/hpms/display/main/hpms_content.jsp?zn=bto&cp=1-11-127-24^1352_4000_100__

    3、QTP第三方工具Test Design Studio的主页

    http://www.patterson-consulting.net/products/test_design_studio/Default.aspx

    4、QTP WEB测试辅助工具IE Developer Toolbar下载页面

    http://www.microsoft.com/downloads/details.aspx?familyid=e59c3964-672d-4511-bb3e-2d5e1db91038&displaylang=en

    5、QTP论坛

    SQAForums论坛上的QTP版块:

    http://www.sqaforums.com/postlist.php?Cat=0&Board=UBB20

    AdvancedQTP论坛上启动的一个QTP虚拟项目(围绕QTP附带的样例程序Flight开展):

    http://www.advancedqtp.com/forums/index.php/board,5.0.html

    6、自动化测试方面的网站

    http://www.automatedtestinginstitute.com/

    http://safsdev.sourceforge.net/

    http://www.io.com/~wazmo/qa/#test_automation

    QTP项目实战课程测试脚本下载(以Discuz论坛测试为例讲解QTP脚本设计):

    http://files.cnblogs.com/testware/QTP_Training_Scripts.rar

    相关课程:

    http://blog.csdn.net/Testing_is_believing/category/639478.aspx

    《软件自动化测试成功之道》学习资源:

    http://blog.csdn.net/Testing_is_believing/archive/2010/05/27/5628697.aspx

    QTP基础视频(《软件自动化测试成功之道》光盘视频):

    http://www.verycd.com/topics/2823906

    《QTP自动化测试进阶》一书附带的源代码,包含脚本例子、小工具:

    http://download.csdn.net/source/2473429

    ADO教程:

    http://www.w3school.com.cn/ado/index.asp

    QTP读取PDF、测试PDF

    http://files.cnblogs.com/testware/AccessingPDF.rar

    QTP认证考试题目样例:

    选择题

    http://www.softwaretestinggenius.com/categoryDetail.php?catId=147

    描述问答题

    http://www.softwaretestinggenius.com/categoryDetail.php?catId=118

    自动化测试框架

    1、《测试对象级框架 - QTestWare》

    http://blog.csdn.net/Testing_is_believing/archive/2010/01/03/5125592.aspx

    2、《QTP面向对象框架》

    http://blog.csdn.net/Testing_is_believing/archive/2009/12/19/5040680.aspx

    3、《自动化测试框架剖析》

    http://blog.csdn.net/Testing_is_believing/archive/2009/12/20/5042211.aspx

    4、《QTRunner》

    http://blog.csdn.net/Testing_is_believing/archive/2009/12/19/5037830.aspx

    5、《自动化测试框架开发5步法》

    http://blog.csdn.net/Testing_is_believing/archive/2009/12/17/5026712.aspx

    6、《QTP下基于XML+DP的关键字驱动DEMO》

    http://blog.csdn.net/Testing_is_believing/archive/2009/11/29/4900529.aspx

    7、《如何选择自动化测试框架》

    http://blog.csdn.net/Testing_is_believing/archive/2008/06/29/2595477.aspx

    8、《自动化测试框架设计指南》

    http://blog.csdn.net/Testing_is_believing/archive/2008/06/22/2576208.aspx

    9、《QTP的报告管理扩展框架 - ReporterManager》

    http://blog.csdn.net/Testing_is_believing/archive/2008/01/27/2068905.aspx

    10、《透析QTP自动化测试框架SAFFRON》

    http://blog.csdn.net/Testing_is_believing/archive/2008/08/28/2845530.aspx

    11、《Test Automation Frameworks》

    http://safsdev.sourceforge.net/FRAMESDataDrivenTestAutomationFrameworks.htm

    12、《QTP关键字驱动框架 - RelevantCodes[1]One》

    http://blog.csdn.net/Testing_is_believing/archive/2010/03/14/5378979.aspx

    13、《介绍一个QTP基础框架 - SIFL》

    http://blog.csdn.net/Testing_is_believing/archive/2010/03/16/5384390.aspx

    文章

    1、《QTP10调试时查看变量显示空白 - 补丁QTP_00591》

    http://blog.csdn.net/Testing_is_believing/archive/2010/02/28/5333934.aspx

    2、《HP发布QTP的新补丁支持FireFox3.5》

    http://blog.csdn.net/Testing_is_believing/archive/2010/01/10/5170279.aspx

    3、《QTP10的Reporter对象》

    http://blog.csdn.net/Testing_is_believing/archive/2010/01/02/5121064.aspx

    4、《QTP10的Tips.txt文件》

    http://blog.csdn.net/Testing_is_believing/archive/2009/12/13/4996879.aspx

    5、《HP发布了针对QTP 10的Web2.0 Feature Pack》

    http://blog.csdn.net/Testing_is_believing/archive/2009/11/22/4851752.aspx

    6、《QTP的智能识别(Smart Identification)过程》

    http://blog.csdn.net/Testing_is_believing/archive/2010/02/01/5277890.aspx

    7、《如何让你的QTP脚本执行效率更高》

    http://blog.csdn.net/Testing_is_believing/archive/2009/12/19/5040174.aspx

    8、《用户体验测试的自动化实现》

    http://blog.csdn.net/Testing_is_believing/archive/2008/05/27/2488303.aspx

    9、《使用QTP进行非GUI的自动化测试》

    http://blog.csdn.net/Testing_is_believing/archive/2010/03/14/5379213.aspx

    10、《QTP调用外部应用程序的4种方法》

    http://blog.csdn.net/Testing_is_believing/archive/2010/03/18/5394213.aspx

    11、stickyminds网站上关于QTP和自动化测试的一些文章:

    <p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; line-height: 1

Open Toolbar