我不在办公室就在星巴克,我不在星巴克就在去星巴克的路上

发布新日志

  • TestComplete 5+ 与 Borland Starteam 的整合【出自Terry Young】

    2008-02-04 10:35:16

    原著者: Terry Young

    Borland 出品的 StarTeam,是个版本控制软件 (Source Control)。

    如果你的团队是用 Borland Delphi 开发软件的,也有可能正在利用 Starteam 来作为版本控制的。

    TestComplete 自从版本 5 以内,亦支援使用 StarTeam 来控制测试项目档案的版本的。

    不过,就连国外的网站也偶尔看到有人问:‘我的本机上已经安装了 StarTeam Client 了,为何在 TestComplete 的 Tools > Options > Source Control 里面仍未见有 StarTeam 可供选择呢?’

    如需要将 TestComplete 和 StarTeam 整合,你是需要在机上安装 Borland StarTeam SCC Integrations 的。可以在以下官方网址下载 (页内找一找 SCC 这个便是):

    http://www.borland.com/downloads/download_starteam_integrations.html

    安装之后,或需要重新启动。

    再启动 TestComplete 之后,就可以在 Options 里面选择了。

    - 完 -

  • TestComplete 5 / 6 的选项设置介绍【 出自Terry Young 】

    2008-02-02 16:39:24

    原著者: Terry Young

    适合程度: 初学至进阶

    博客:   http://www.51testing.com/?20638

     

    读完此文章之后,读者应该学会:

    1.      Tools > Customize Keyboard 的用途

    2.      Tools > Default Project Properties… 的用途和影响

    3.      Project > Properties的用途和影响

    4.      Tools > Options 的用途和影响

     

    本文章不是将所有设置都介绍,而是针对一些值得一提的设置,属于经验之谈。无论你是测试员或者是需要为队伍统一一下一些设置,希望你会觉得本文章有点用。

     

    Tools > Customize Keyboard

    不知道有多少人像我一样,是个键盘怪癖者,学习任何软件都特爱学习快捷键,希望键不离手,不希望被鼠标操作拖慢效率。就正如很多从事图像设计的高手也很熟练  Photoshop 等等工具内的快捷键一样。

     

     

    Tools > Customize Keyboard 就是自定义快捷键设置的地方。各种功能都会在此纪录其目前的快捷键 (Current key)

     

    你可以赋以新的快捷键,直接在 Press new shortcut key 里面键入你的快捷键组合便可,但需要留意 Shortcut currently used by 看看你所键的快捷键是否已经被另一功能使用。

     

    例如下图,笔者的个人喜好之一就是将 Code Explorer 赋以快捷键。这样的话,在编写代码时键不离手就可以很快得到代码方面的基本帮助。

     

     

    不过,笔者也同时建议不要将已经存在的快捷键更改,尤其是如果你知道不一定会在同一台电脑操作或者你的电脑不只是固定一人操作的话,以免因为不统一而一时不习惯。

     

    另外,Tools > Options 内有一部份是设置全局快捷键的,就算 TestComplete 不是当前的画面也可以用的,但这些键不是在 Customize Keyboard 里面设置的。文章后面会有介绍。

     

    Tools > Default Project Properties…

     

    Default Project Properties 的设定,就是影响你目前及将来建立的 Project 里面的 Properties 的设定。

     

     

    首先值得一提的就是 Project > General > Character encoding

    如果你所做的测试开发,会使用一般亚洲语言 (中文 [ 繁体 / 简体 ]、日文、韩文等),或者处理一些已国际化 (i18n) 或者本地化 (l10n) 的测试对像,你或需要设置成 UTF-8 或者 UTF-16,避免代码乱码的问题。

     

    当你有已经存在的单元档案后才转换 Encoding 的话,TestComplete 会在当你下次编辑并且保存单元档案时对档案进行转换。

     

    唯独 TestComplete 6 则多了个 Auto 的选择,是不会对已经存在的档案进行转换。不过如无特别原因,笔者不建议使用。

     

    UTF-16 應該注意它和你連接外部的版本控制工具的兼容。相信如果你明白你的測試項目是有 UTF-16 的需求的話,你應該是個高手的了,可以參考一下幫助文件。

     

     

     

    另一个值得一提的是 Project > Playback 的选项。

     

    根据帮助文件所说明,Error Dialog 是只会对 Delphiscrīpt 的单元起作用的。它是当回放脚本时遇到错误时是否弹出提示窗口要求测试员是否终止回放的。

     

    如果你的测试对像可能存在一些效能上的问题,笔者建议你调整一下右面那四种时间上的设置。尤其 Auto-wait timeout, ms 的设置,预设是 10000 (10 ),笔者目前的习惯是调整成 30000 的。Key-pressing delay, ms 我也习惯从预设的 0 改为 20

     

    On unexpected window 主要是控制回放时遇到未预期的窗口时应该怎么处理。

     

    On overlapping window 是控制当回放是遇到被其他窗口覆盖正要操作的窗口是是否理会那前面的窗口。

     

    Project > Properties

     

     

    Project > Properties 基本上就是和 Tools > Default Project Properties 里面的设置一样的,但只是对当前的 Project 起作用。

     

    Tools > Options

     

     

    上图这部份是设置 Global Shortcuts (全局快捷键) 的,就算 TestComplete 不是当前的画面也可以用的,但这些键不是在 Customize Keyboard 里面设置的。

     

    笔者建议记一下,用得多就容易习惯的了。

     

    另外也提示一下,如果你的测试对像正好也有全局快捷键的话,留意一下有没有发生冲突,你是可以在这里更改的。更改时也留意有没有和 Customize Keyboard 里面的设置有冲突。

     

     

    上图这部份里面,可以设置预设的脚本编程语言。笔者用 VBscrīpt 的。

     

     

    上图这部份是设定 Visualizer,可以设置脚本在录制或者回放时,是否保存抓图。

    这个抓图功能很好,尤其当实际运行脚本后测试出错误时,你就有抓图可以利用它作为向开发组提供错误报告的有力证据 (呵呵,测试报告是讲求证据的)

     

    笔者也建议按 Configure,适度调节抓图的图像格式。预设的 BMP 实在会是很大的,笔者就试过,刚开始的项目,代码不多,经过几次运行之后,所有抓图加起来就已经超过 3MB 了。所以笔者都习惯都会转成 JPG,已经很足够。

     

    录制或者运行后,你回顾代码就会发现代码旁边的图示,按下去就可以浏览抓图了,而且,多次运行的抓图都有纪录的。右按图示的话,是有菜单提供给你去一次过或逐个清除抓图的,不一定要到我的电脑去删除。

     

    深入一点的话,笔者会建议,测试组具体进行录制和尝试运行的电脑,不需要抓图,因为主要都只是进行测试代码开发和试行的工作;最好设置另一台独立的电脑,是专门独立负责正式运行测试组的完成品,这台电脑的硬盘空间最好是足够有余的。

     

     

    也留意 Engines > Log > Images > Configure 里面同样有图像格式的设置,也是例行地转为 JPG 比较化算。这些图片是纪录在脚本运行后所生成的测试报告 (Logs) 里面的。

     

    (TestComplete 6+ only)

     

    TestComplete 6 多了个 Name Mapping 的选项。管理者应该深思熟虑决定并且为队伍统一设置。

     

    主要就是 TC 6 增强了代码编辑介面的 Code Completion 功能,可以将 Name Mapping 生成的 Aliases (物件别名) <SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-f

  • 介绍 TestComplete 的 LLP (Low-Level Procedures)【从Terry Young转载】

    2008-02-02 16:32:49

    原著者: Terry Young

    适合程度: 初学至进阶

     http://www.51testing.com/?20638

     

    读完此文章之后,读者应该认识:

    1.      LLP (Low-Level Procedures) 是什么、它的原理、录制以及编辑的基本方法。

     

    LLP 是什么?

    LLP (Low-Level Procedures) 实际上可能比较少机会用,但好奇心强烈的你,难免也按捺不住想知道它是什么。它是低层次的键盘和鼠标的纪录方式。

     

    首先要说我们一般所录制的脚本,它的原理是识别测试对像的控件,录制对控件上键盘和鼠标的动作,回放时就是以这个原理摹拟动作的。

     

    LLP 则是低层次、座标式的纪录方式。它是不识别控件的。它只会纪录鼠标 (点击,移动和滚轮) 和键盘的动作事件,以及事件之间的时间间距。

     

    也因为此,录制后未经修改的情况,回放时的速度是和录制时的速度一样的。

     

    有什么情况可以利用 LLP ? 比如要测试图像软件或者一些基于鼠标 / 画笔的绘制动作,就适宜利用 LLP 了。一些以 Flash 作为平台的互动程序,或者也可以利用 LLP 的,不过笔者就未曾深入探究过了。

     

    对于 Rational Robot 有认识的人士,TestComplete LLP 可以说是类似 Robot 内的 VU 吧。不过,TestComplete LLP 在录制后是提供一个可视化的介面来编辑动作的,而不是从编写代码的层面去修改。

     

     

    如果你的侧边栏未有 LLP 的话,可以在 Project 右按 > Add > New Item 来建立,如上图。

     

    TestComplete LLP 的录制方式

    TestComplete 的工具列按 Record 按钮,所弹出的小窗口内可以选择录制方式。

     

     

     

    前者是基于整个荧幕作为座标基础去录制动作的座标;后者是基于窗口的,需要拖拉动作拖至对像窗口才开始录制。

     

    如果你的测试对像固定是全屏的话,或者你的动作牵涉多个窗后的话,应该选择 Screen Coordinates 比较适合。不过,在另一台机回放的话,要留意电脑荧幕的解像度是否吻合。管理者应该预先为此安排好。

     

    如果你的测试的动作只是对一个窗口的话,可以考虑使用 Window Coordinates 的。

     

    LLP 录制后的编辑

     

     

    录制完成后,首先会自动建立一个函数,Screen Coordinates 录制的话,就是生成一句 LLCollection1.LLP1.Execute 的语句,也就是执行LLP1 这个低层次动作纪录了,如上图。

     

    然后,自己再编辑一下何时调用这函数便可。

     

     

    而当你打开 LLCollection1 LPP1 的话,就会看到一个可视化的编辑画面,里面详细纪录了 Event (鼠标和键盘的动作)Parameters (鼠标的座标或者键盘的 CharCode、以及 Delay, ms (动作与动作之间相隔的时间 [微秒])

     

    点击一行就可以进行微调编辑。

     

    如果编辑鼠标动作,可以看到,它能纪录四种鼠标动作,分别是 Mouse Down, Mouse Up, Mouse Move Mouse Wheel (滚轮)

     

    如果编辑键盘动作,可以看到,它纪录了 Key Up Key Down 两种动作。

     

    你还可以对一个或多个动作进行拖拉或者剪贴删除,以编辑动作的次序,或者贴进另一个 LLP 内。

     

    右按介面的话,有几个值得提及的功能。

     

     

     

    Add Event 是手工地加插鼠标或者键盘的动作。

     

    如果你如上图一样,预先选择多个动作,Expand/Shrink Time for Selected Events… 是可以批次调整动作执行的时间间距的。

     

     

    以上图为例,假设我原本录制花了大概 1 分钟完成,以以上的设置,就是将所有动作缩短到 10 秒内完成,而每个动作所需要的时间是 Evenly 平均分配的。假如有 10 个动作,也就是每个动作相隔 1 秒了。记住,如要缩短,就要推断一个合理的值,否则,你的测试对像也可能未能及时反应过来而间接导致一些不必要的错误。

     

    另外,如果你选择的动作包含鼠标动作的话,你可以用Shift Coordinates for Selected Events… 来批次将座标的 xy 中心点移动。

     

     

    以上图为例,就是批次向右水平移动 100 pixels (像素),及向上垂直移动 100 pixels

    假设原本的第一个动作是 Mouse Down X: 150, Y: 250 的话,编辑后就会变成 Mouse Down X: 250, Y: 150 了。

     

    是否需要动用到这些功能是很视乎实际情况和需要的。如果过程时间不长的话,还不如重新录制再回放。如果只是测试对像介面上的少许改动,手工地批次编辑则可能更快。

  • TestComplete 的项目组织和脚本回放介绍【从Terry Young转载】

    2008-02-02 16:30:16

     原著者: Terry Young

    适合程度:初学者

    http://www.51testing.com/?20638

     

    笔者注:看到很多文章,在术语的翻译上,尤其对没有正式汉化或者国际化的国外软件,都存在着翻译不统一的情况。笔者则通常会在文章中第一次出现的英文字眼附上中文翻译,但其后会以英文字眼为准。

     

    读完此教程后,读者应该学会:

    1.        TestComplete 内主要六种回放,范围由小至大分别是

    1.1         Run Current Routine (执行函式)

    1.2         Run scrīpt (执行脚本)

    1.3         Run Manual Test (执行手工测试)

    1.4         Project Test Items 里面的 Run Focused Item (执行当前选择的测试物件)

    1.5         Run Project (执行项目)

    1.6         Run Project Suite (执行专案)

    2.        TestComplete 内测试项目的架构

    3.        透过 Test Items 来组织测试单元 (Units) 的串连回放

     

    正文:

    Run Current Routine

    下图是 Run Current Routine 的方法,在 Sub Main 任何一个范围上右按,选择 Run Current Routine 便会执行 Main 这个函式。

    根据图内的代码的话,结果会是先出现 “Hello.” MsgBox,然后呼叫AnotherFunction 继而出现 “Hello World!” MsgBox


    Run scrīpt

    透过下图所显示,在工具列上的按钮可以执行 Run scrīpt, Run Project 或者 Run Project Suite

    按照下图的代码,如果执行 Run scrīpt,会先运行左边栏的 “scrīpt” 内的 Main Routine (启始函式)

     

    scrīpt Main Routine,可以按照下图来设置。

    如果设置成 AnotherFunction,执行 Run scrīpt 就只会出现 “Hello World!” 这个结果。

    如果设置成 Main,执行 Run scrīpt 就会先出现 “Hello.”,再出现 “Hello World!”

     


    Run Manual Test

    Manual Test 是手工测试,可以在 Project 右按来建立,主要就是纪录一些人手操作的步骤。

    Run Manual Test 就是回放一个一个的画面显示每个人手操作步骤,测试员人手执行实际动作后可回到 TestComplete 去选择适合的按钮来纪录结果。

    Run Project

    执行 Run Project,是会执行 Project Test Items

    如下图的设置的话,Project 的第一个 Test Item 就是执行 Unit1 AnotherFunction 这个函式。

    右按介面,透过 New Item 可以陆续加上更多 Test Items,甚至用 New child item 来分层次地加上 Test Items

    Test Items 不单可以是 scrīpt (脚本),还可以是 Manual Test (手工测试)

     

    如下图的设置的话,执行 Run Project 的结果就是出现 “Hello World!”,然后出现 ManualTest1 的手工测试脚本,测试员完成手工测试后,继续运行自动测试而出现 ”Goodbye”,然后出现 “Hello.” “Hello World!”


    在此处,分层次的主要是为了方便启动或者屏蔽某一项测试范围。如下图。你还可以直接拖拉或者透过右按来移动项目。

     

    这里通常就是管理者组织很多复杂脚本的地方。

     

    通常,测试队伍可以陆续建立很多 Function (函式) 甚至 Unit (单元),每个 Unit 或者 Function 通常都有自己的录制起点和终点。而管理者,透过测试计划 Test Plans 和用例 Test Cases 等等设计文件和辅助文件引导下,可以在这里组织 Unit 来实现计划的。

     

    因此,其实没有必要透过代码编写多个 Call 函式来实现多个脚本组合运行的。反而,使用 Call 函式更适合去呼叫一些经过代码重构 (Refactorization) 后可以循环再用或者共用的函式的。

     

    Run Focused Item

    同样在 Project Test Items 介面内,你可以透过右按来执行 Run Focused Item,将目前选取的项目运行。如根据下图的设置,是不会运行的,因为,事前已经将 ProjectTestItem2 屏蔽了。

    Run Project Suite

    Project Suite 同样有 Test Items 的设置。此处所谓的 Test Items,其实就是指 Projects,如下图,就是指 Windows 专案下 Notepad 这个项目。

    一个专案 (Project Suite) 可以有多个项目 (Projects) 的。这个例子中则只有一个。如果出现多个,你是可以同样地在 Test Items 内设置 Projects 的次序先后和屏蔽状态。

    执行 Run Project Suite 的话,就会先运行 Notepad 这个 Project,也就会根据 Notepad Project Test Items 的设置来运行了。

  • TestComplete: 对Manual Test 的介绍 【从Terry Young 转载】

    2008-02-02 16:26:54

    原著者: Terry Young   http://www.51testing.com/?20638

    适合程度: 初学至进阶

     

    读完此文章之后,读者应该学会:

    1.      Manual Test 的应用范围和一些启发

    2.      Manual Test 的建立和修改

    3.      Manual Test 的回放和运行

    4.      Manual Test Run Project 内的串连运行

    5.      TestComplete 6 Manual Test 的增强,Manual Test TC5 TC6 的升级

     

    TestComplete Manual Test 是什么?

    TestComplete Manual Test,是用来建立一个个画面 (有点像安装软件过程一个一个的画面一样),每个画面其实就是手工测试的步骤描述和预期结果。在回放时,它就会一个个画面展现在测试员面前。测试员按照画面内所描述的步骤进行手工测试,步骤完成了,就回到 TestComplete 这个画面,决定是通过还是不合格。测试员可以在每个步骤加入备注形容具体的结果。到整个 Manual Test 回放完成了, TestComplete 一样会生成一个测试报告 (Log) 的。

     

    Manual Test 的应用

    Manual Test,顾名思议就是手工测试的意思。

    你或者会问:‘咱们用这 TestComplete 不是为了实现自动化测试? 那这手工测试的功能是不是有点本末倒置了?

     

    其实,很多人都已经知道,一个测试对像里面并不是所有地方都适合实施自动化的测试的。

     

    有哪些地方适合利用 TestComplete Manual Test ? 笔者来分享一下构想和经验。

     

    对于一些逻辑性很强而且复杂的测试或者变数很多的测试,要开发一个覆盖率可靠的自动化脚本作回归测试之用,并非一朝一夕可以完成的。那么,不妨先建立一个 Manual Test。况且,未建好自动化脚本之前,你的队伍还不一样是要做些手工测试来应付目前的需求,对不?

     

    那么,这边有人已经按照 Manual Test 进行手工测试,那边就有人开始构想自动化的可能,继而开发自动化测试脚本。

     

    Manual Test 是可以利用作为无工具测试和自动化测试之间的过渡桥。假使真的可以自动化了并且完成了,原本的 Manual Test 也可以被取代了。

     

    又或者,有些测试项目根本不值得或者不需要自动化的,是不会带来有价值的回报或者会严重加重维护的负担的话,管理者适宜将此类测试纳入手工测试的工作里面。

     

    Manual Test 的建立

    如果你目前已经存在的项目并未包括 Manual Test 的话,你可以右按 Project > Add > New Item,选择 Manual Test 来建立。

     

    TestComplete 6 的左边栏组织得更好,所有手工测试项目都在 Manual Test 这个目录之下,不如 TestComplete 5 一样保存在 Project 这一层,感觉上直观得多。

     

    Manual Test 的编辑

     

    利用 Test steps 的按钮,你可以增加,移除或者移动每个步骤。

     

    步骤的根层适合作为本次测试的介绍,以及描述一些事前准备功夫;最好可以把所有不涉及预期结果的内容都写进去。例如上图。

     

    上图右面就是所选择步骤的编辑介面。值得一提的是 Test descrīption Test notes and comments 似乎对输入中文字有问题。但你最主要去编写的步骤内容会是写在中间的 Test instructions,这才是编写 Manual Test 的核心部份之一,而且可以保存成一个个 HTML 档案,或者导入一些已经存在的 HTML 档案的。

     

    由于是 HTML 格式,你可以加插图像,或者加入超连结指向其他文件以辅助测试员之用。

     

     

    以上例子就是 Step1 的编辑画面和内容。

     

    每个步骤应该能给测试员一些步骤指示,和预期结果。

     

    如果你步骤过于复杂,牵涉很多变数,或者预期结果比较长的话,右可以利用超连结指向具体的档案供测试员参考。或者可以来得简单点,留给测试员思考和判断的空间。这完全是测试设计者去决定了。

     

    Manual Test 的回放和运行、TC 6 内的增强,以及升级问题

     

    单独运行一个 Manual Test,就透过左边栏上右按 > Run Manual Test 吧。

     

     

     

    管理者亦可以在 Project > Test Items 里面加插这 Manual Test,那么,Run Project 或者 Run Project Suite 也可以包括这个 Manual Test 的,如上图。

     

    以下是运行 Manual Test 的过程。

      

    正如之前所说,手工测试一开始时,最好可以给测试员描述一下测试起点在哪,应该有什么设置和环境等等;是不牵涉预期结果,也不预期测试员要报告通过或者不合格的一种描述。

     

     

    留意,除了 Success, Fail Stop 之外,工具列上还有个双箭头按钮,就是 Skip (跳过) 的意思。

     

    以下是按了 Fail 之后出现的画面,会要求测试员输入对不合格的描述。

    此时可以 Continue 继续下一步测试,或者 Try Again 继续尝试目前的步骤,或者 Stop 终止整个手工测试。

     

     

    由以上画面中圈着的可见,TestComplete 6 最主要增强的地方,就是有实时抓图的能力,会纪录在测试完成后的报告内

     

    另外,笔者亦试过了,TC5 TC6 所生成的 Manual Test 档案并没有不兼容的问题的,可以交替来用。

     

  • 数据池(DATAPOOL)专题【转载】

    2008-01-26 23:57:47

    数据池在rational测试中是使用率很高,同时它也充分体现了自动化测试的优势。通过使用数据池,可以通过简单的脚本完成大量数据的测试,缩短测试时间、提高测试效率和测试质量。下面将介绍数据池的概念、创建以及在GUI、VU脚本中的应用。
        数据池(DATAPOOL)用于存储测试数据,在脚本中插入数据池命令并增加相关的控制命令后,在脚本回放时就可以自动从数据池中取出数据,完成多组测试数据的测试。
    (一)数据池(DATAPOOL)创建
    1、启动Rational TestManager;
    2、Tools>Manage>Datapool,点击New…,输入数据池名称点“确定”;
    3、在打开的Data Type Specification中添加字段定义;
    字段定义说明:
    Name:字段名称
    Type:数据类型
    Sequence:次序,包括Random(随机)、Sequential(连续)、Unique(唯一)
    Repeat:数据重复次数
    Length:数据长度
    Decimals:小数位数
    Interval:间隔,相邻两个数据的间隔数
    Mininum:最小值
    Maxinum:最大值
    Seed:Sequence设为Random时,Seed输入不同的数据,生成不同的随机数
    4、在设置好字段后,在No. of records to genarete:中输入要生成的记录数,然后点击Genarete Data 即可生成数据,或者点击SAVE按钮,关闭当前窗口,然后点击manage datapools>edit>edit datapool data,直接手工输入数据;
    5、这样就完成了数据池的创建,还可以执行数据池的编辑、改名、删除、导入、导出等操作;
    6、数据池有数据生成能力,但是不具备数据的计算能力。这种情况下可以利用其他工具(如EXCEL)生成数据,并保存为csv(逗号分割文件)格式,然后在manage datapools中导入;
    (二)、
    1、数据池在GUI脚本中的应用
    这是计算器测试的例子,在GUI中使用数据池需要手工编码,robot不能自动生成,在手工编码时可以参考Robot的在线帮助。
    '$Include "sqautil.sbh"

    Sub Main
        Dim Result As Integer
        dim x as integer
        dim num1 as string
        dim num2 as string
        dim sum as string

       
        'Initially Recorded: 2003-7-18  8:51:18
        'scrīpt Name: 计算器-2

        StartApplication "C:\WINNT\system32\calc.exe"
       
        dp=SQADatapoolOpen("jsq"
    '打开数据池,jsp为数据池的名称,这个数据池是预先按照上述规范做好的

        for x=1 to 5
    Call SQADatapoolFetch(dp)
    '从数据池中读取记录
        Call SQADatapoolValue(dp,1,num1)
        Call SQADatapoolValue(dp,2,num2)
    Call SQADatapoolValue(dp,3,sum)
    '将从数据池中读取的数据赋予相应变量
        Window SetContext, "Caption=计算器", ""
        InputKeys num1 &"{+}"& num2 &"{ENTER}"
       
        Result = LabelVP (CompareNumeric, "Text="& sum &".", "VP=Alphanumeric;Value="& sum &"."
       
        next
       
        Call SQADatapoolClose(dp)
        '关闭数据池
        Window CloseWin, "", ""

    End Sub

    2、数据池在VU脚本中的应用
       VU脚本中的数据池可以通过录制自动产生,如果不能自动产生可以手工编码加入。

       以下录制在Google上搜索的脚本,数据池时录制时自动产生的:
      #include <VU.h>
    {

    push Timeout_scale = 200; /* Set timeouts to 200% of maximum response time */
    push Think_def = "LR";
    Min_tmout = 120000;       /* Set minimum Timeout_val to 2 minutes          */
    push Timeout_val = Min_tmout;

    DP1 = datapool_open("googlw";
    datapool_fetch(DP1);
                
    push Think_avg = 0;

    www_google_com = http_request ["googlw001"] "www.google.com:80",
       HTTP_CONN_DIRECT,
       "GET / HTTP/1.1\r\n"
       "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, applicat"
       "ion/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, ap"
       "plication/x-shockwave-flash, */*\r\n"
       "Accept-Language: zh-cn\r\n"
       "Accept-Encoding: gzip, deflate\r\n"
       "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR"
       " 1.1.4322)\r\n"
       "Host: www.google.com\r\n"
       "Connection: Keep-Alive\r\n"
       "Cookie: PREF=ID=6011af2d9ae9ecc9:TB=2:TM=1079509149:LM=1079509149:S=Bbt"
       "iwXYs9ldWNF0T\r\n"
       "\r\n";
    set Server_connection = www_google_com;

    http_header_recv ["googlw002"]  302;    /* Moved Temporarily */

    http_nrecv ["googlw003"]  100 %% ;      /* Internally Generated */

    {
      string SgenRes_001[];
      SgenRes_001 = http_find_values("RedirectPrefix", HTTP_REDIRECT_PREFIX, 2);
      CHECK_FIND_RESULT(SgenRes_001,"RedirectPrefix","/intl/zh-CN/")
    }

    set Think_avg = 190;

    /* Keep-Alive request over connection www_google_com */
    http_request ["googlw004"]
       "GET " + SgenRes_001[0] + " HTTP/1.1\r\n"
       "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, applicat"
       "ion/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, ap"
       "plication/x-shockwave-flash, */*\r\n"
       "Accept-Language: zh-cn\r\n"
       "Accept-Encoding: gzip, deflate\r\n"
       "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR"
       " 1.1.4322)\r\n"
       "Host: www.google.com\r\n"
       "Connection: Keep-Alive\r\n"
       "Cookie: PREF=ID=6011af2d9ae9ecc9:TB=2:TM=1079509149:LM=1079509149:S=Bbt"
       "iwXYs9ldWNF0T\r\n"
       "\r\n";

       { string SgenURI_003; }
       SgenURI_003 = _reference_URI; /* Save "Referer:" string */


    http_header_recv ["googlw005"]  200;    /* OK */

    http_nrecv ["googlw006"]  100 %% ;      /* 1407 bytes */

    {
      string SgenRes_002[];
      SgenRes_002 = http_find_values("hl", HTTP_HREF_DATA, 1);
      CHECK_FIND_RESULT(SgenRes_002,"hl","zh-CN")
    }

    {
      string SgenRes_003[];
      SgenRes_003 = http_find_values("ie", HTTP_HREF_DATA, 1);
      CHECK_FIND_RESULT(SgenRes_003,"ie","UTF-8")
    }

    {
      string SgenRes_004[];
      SgenRes_004 = http_find_values("oe", HTTP_HREF_DATA, 1);
      CHECK_FIND_RESULT(SgenRes_004,"oe","UTF-8")
    }

    {
      string SgenRes_005[];
      SgenRes_005 = http_find_values("lr", HTTP_FORM_DATA, 3);
      CHECK_FIND_RESULT(SgenRes_005,"lr","lang_zh-CN")
    }
    set Think_avg = 6228;

    /* Keep-Alive request over connection www_google_com */
    http_request ["googlw007"]
            "GET /search?q="
         + http_url_encode(datapool_value(DP1, "q"))+
         "&ie="
         + SgenRes_003[0] +
         "&oe="
         + SgenRes_004[0] +
         "&hl="
         + SgenRes_002[0] +
         "&btnG="
         + http_url_encode(datapool_value(DP1, "btnG"))+
         "&lr="
         + SgenRes_005[0] +
         " HTTP/1.1\r\n"
       "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, applicat"
       "ion/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, ap"
       "plication/x-shockwave-flash, */*\r\n"
       "Referer: " + SgenURI_003 + "\r\n"
       /* "Referer: http://www.google.com/intl/zh-CN/" */
       "Accept-Language: zh-cn\r\n"
       "Accept-Encoding: gzip, deflate\r\n"
       "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR"
       " 1.1.4322)\r\n"
       "Host: www.google.com\r\n"
       "Connection: Keep-Alive\r\n"
       "Cookie: PREF=ID=6011af2d9ae9ecc9:TB=2:TM=1079509149:LM=1079509149:S=Bbt"
       "iwXYs9ldWNF0T\r\n"
       "\r\n";

       { string SgenURI_004; }
       SgenURI_004 = _reference_URI; /* Save "Referer:" string */


    http_header_recv ["googlw008"]  200;    /* OK */

    http_nrecv ["googlw009"]  3145;         /* 3145/4855 bytes */

    http_nrecv ["googlw010"]  1630;         /* 4775/4855 bytes */

    http_nrecv ["googlw011"]  100 %% ;      /* Last 80 of 4855 bytes */

    http_disconnect(www_google_com);

    pop [Think_def, Think_avg, Timeout_val, Timeout_scale];

    }

    DATAPOOL_CONFIG "googlw"        OVERRIDE DP_NOWRAP DP_SEQUENTIAL DP_SHARED
    {
            EXCLUDE, "btnG", "string", "Google鎼滅储";
            EXCLUDE, "q", "string", "软件测试\";
    }

    以下是全部手工编写的使用数据池的VU脚本:
    #include <VU.h>
    {
    push Timeout_scale = 200; /* Set timeouts to 200% of maximum response time */
    push Think_def = "LR";
    Min_tmout = 120000;       /* Set minimum Timeout_val to 2 minutes          */
    push Timeout_val = Min_tmout;
    DP1 = datapool_open("test");   //打开数据池

    ser=sqlconnect("server","sa","8888","192.168.1.12","sqlserver");
    set Server_connection = ser;
    push Think_avg = 0;

    for (i=0; i<10; i++)
    {
       datapool_fetch(DP1); //移动指针到下一记录
       sqlexec ["sql_1000"] "TestDB..test " +datapool_value(DP1, "q");
    }
    sqldisconnect (ser);
    datapool_close (DP1);   //关闭数据池
    }

    DATAPOOL_CONFIG "test"  DP_SEQUENTIAL DP_SHARED DP_WRAP
    {
            INCLUDE, "q", "string", "8";
    }

        GUI中的数据池只能手工编码修改,VU中的数据池可以通过edit――datapool infoermation进行配置。此菜单在GUI脚本下为灰色不可操作。
  • Rational中DataPool的介绍与实际应用-续(2)【转载】

    2008-01-26 23:56:14

    二.性能测试脚本自动建立测试datapool

    在robot中tools->session record options, 设置Generator页面general的use datapool选项,才能在产生datapool.

    一般录制性能测试脚本,遵循如下步骤:

    第一.         设置录制Session选项

    第二.         启动录制对话

    第三.         启动客户端程序

    第四.         产生脚本

    第五.         关闭客户端程序

    第六.         停止录制

     

    设置选项:

    1.录制方法(method): api, network,proxy,custom四种选项设置

       通过分析要测试的软件架构来选择录制的方法,下边的表格提供参考:

    Situation

    Api

    NetWork

    Proxy

    The client application access secure data from a Web server

    Required

     

     

    The Client Application access data from a web server

    Recommended

    Fist Alternate

    Second alternate

    The client application accesses objects on a DCOM Server

    Required

     

     

    The client application access an oracle8 database or oracle arrays.

    Required

     

     

    The client application access an Oracle database.(For network and proxy recording, supply the name of the oracle database,)

    Recommended

    First alternate

    Second alternate

    The client application is not installed on the local computer

     

    Recommended

    Alternate

    The client application is not running on Windows NT4, Windows XP, or Windows 2000

     

    Recommended

    Alternate

    You want to record traffic from multiple client applications that reside on different commputers

     

    Recommended

    Alternate

    You want to record traffic between multiple,specific clent and server computers.

     

     

    Recommended

    Neither the client nor the serer computer is on same network segment  as  the  local computer

     

     

    Required

    An Ethernet controls network traffic, and neither the client nor the server application is installed on the computer

     

     

    required

    The client application accesses a TUXEDO Server

    Recommended

    Alternate

     

    “On-the-wire” recording support is lacking

    Recommended

     

    Alternate

    Api recording is not functioning properly

     

    Recommended

    Alternate

    FDDI,ATM,or other hight-speed networks are used

     

     

    Recommended


    备注:上图参考rational robot user’s guide,

          NetWork录制方式必须安装Rational网络驱动才能生效

          安装方法:

    1.     开始-〉设置-〉网络和拨号连接

    2.     点本地连接

    3.     点安装,选择协议,点添加

    4.     点选者从磁盘安装

    5.     打开安装目录C:\Program Files\Rational\Rational Test\driverw2k(安装rational的目录),选者inf文件,确定

    6.     选择ethernet 或者 token ring都可以

     

    2.Generator Filtering

      Filtering

    (1).设置autoFiltering使robot生成脚本时自动选择可用协议,下边协议选者列表可用

     特别说明DCOM是一种独占的协议,不能和其他协议共存

           如果后台是SQLSERVER,选择SQLSERVER,如果后台是ORACLE,选择ORACLE协议。根据软件实现方式,选择不同的协议。

               (2). 设置Manual Protocol Filtering使robot生成脚本时手工选择协议

    3.Generator Per Protocol

      只能对在generator Filtering选择的部分协议(http,iiop,Oracle,Tuxedo,和dcom)起作用。

  • Rational中DataPool的介绍与实际应用-续(1)【转载】

    2008-01-26 23:55:03

    第一步:创建名字为dp的datapool,假如字段name,password并自动生成数据,然后把测试用例中各种数据输入dp中

    第二步:录制功能测试脚本,脚本如下:

     

    Sub Main

        Dim Result As Integer

     

        'Initially Recorded: 2004-4-24  10:59:24

        'scrīpt Name: Five

        StartApplication "xxx"

       

        Window SetContext, "Caption=登陆", ""

        InputKeys "sa"

        EditBox Click, "ObjectIndex=1", "Coords=34,9"

        InputKeys "sa"

        PushButton Click, "Text=登陆"

       

        Window SetContext, "Caption=登陆;Class=#32770", ""

        PushButton Click, "Text=确定"

       

    End Sub

     

    第三步:循环读出datapool数据,进行自动化测试,脚本如下

     '$Include "sqautil.sbh"

     

    Sub Main

        Dim Result As Integer

        Dim dp_id as Long

        Dim dp_Result as Long

       

        Dim strName as String

        Dim strPassWord as String

      

        'Initially Recorded: 2004-4-24  10:30:51

        'scrīpt Name: Four

     

        StartApplication "xxx"

        Window SetContext, "Caption=登陆", ""

        dp_id = SQADatapoolOpen ("dp", FALSE, SQA_DP_SEQUENTIAL, FALSE)

       

    dp_Result = SQADatapoolFetch (dp_id)

       

         while dp_Result <>  sqaDpEOF

       

               dp_Result = SQADatapoolValue (dp_id, "name", strName)

               dp_Result = SQADatapoolValue (dp_id, "password", strPassWord)

               dp_Result = SQADatapoolFetch (dp_id)

             

               InputKeys strName

               EditBox Click, "ObjectIndex=1", "Coords=34,9"

               InputKeys strPassWord

               PushButton Click, "Text=登陆"

       

               Window SetContext, "Caption=登陆;Class=#32770", ""

               PushButton Click, "Text=确定"

        wend

     

        dp_Result = SQADatapoolClose (dp_id)

       

    End Sub

     

    第四步: 加入执行成功和失败的result信息并写入Result report中,和必要的除错处理。对脚本进行优化。加入BASELINE设置(对于测试基线有两种思路,一种是文件处理,采用文件类型为文本文件或者EXCEL或者WORD,读取DATAPOOL测试数据和文件内容对比,检测测试数据是否在文件中存在,当然这里的测试基线考虑的不够周全,你可以定制规则,逐步完善,一种是直接从数据库中读取数据进行对比,用数据库作为baseline来避免以后增加测试用例后改动baseline文件,当然这么做跟测试理论不合,应该把预期输出保存到特定文件中作为baseline,这个留给你自己动手来改进)。

    脚本如下:

    '$Include "sqautil.sbh"

     

    Sub Main

        Dim Result As Integer

        Dim dp_id as Long

        Dim dp_Result as Long

       

       

        Dim strMessage as String

        Dim vSText as string

       

        Dim cnn As object

        Dim Rst As object

      Dim strLink As String

        Dim strSql As String

       

        Dim strName as String

        Dim strPassWord as String

      

        'Initially Recorded: 2004-4-24  10:30:51

        'scrīpt Name: Four

       

        strLink = "连接字符串"

       

        Set cnn = CreateObject("ADODB.Connection")

        Set Rst = CreateObject("ADODB.Recordset")

        cnn.Open strLink

        Rst.CursorLocation = 0

        Rst.LockType = 1

        Rst.CursorType = 2

       

       

         On Error Goto Last

         StartApplication "xxx"

       

         Window SetContext, "Caption=登陆", ""

        

         dp_id = SQADatapoolOpen ("dp", FALSE, SQA_DP_SEQUENTIAL, FALSE)

       

         dp_Result = SQADatapoolFetch (dp_id)

        

         if (dp_Result = 0) then

              while dp_Result <>  sqaDpEOF

       

                    dp_Result = SQADatapoolValue (dp_id, "name", strName)

                    dp_Result = SQADatapoolValue (dp_id, "password", strPassWord)

                    dp_Result = SQADatapoolFetch (dp_id)

              

                   

                        

                    InputKeys strName

                    EditBox Click, "ObjectIndex=1", "Coords=34,9"

                    InputKeys strPassWord

                    PushButton Click, "Text=登陆"

                   

                    strMessage = "用户名:" + strName + "; 密码:" + strPassWord 

                   

                    strSql = "select * from login where name = "" " + strName + " "" and password = """ + strPassWord + """"

                    Rst.open strSql, cnn

       

       

                    Window SetContext, "Caption=登陆;Class=#32770", ""

                    ‘这个函数是作为插入验证点,验证点为窗体提示信息,没有用window image来作为验证点,是因为无法把该脚本进行模块化,存入shl文件中,将来多平台使用。

                    SQAGetProperty  "Label", "Text", vSText

                                 

                   

                    ‘如果rst.RecordCount返回值为1,说明此用户在数据库中存在

                    ‘测试用例分为成功,失败的测试用例,失败的测试用例中即使数据

    ’错误,但有预期输出就是成功的用例,所以写入result report中的信

    ‘息分为三种,成功,失败,预期失败,对于程序中有不是预期的窗

    ‘体,用程序自动关闭掉,继续执行,这里安全的做法做标志然后关

    ‘闭整个软件,重新启动软件,测试脚本从失败处继续执行

                         if Rst.RecordCount= 1 then

                            if (vSText="登陆成功") then

                               PushButton Click, "Text=确定"

                               SQALogMessage sqaPass, "测试数据为" + strMessage + "的测试用例执行成功", "项目名称"

                            else

                               '出现异常窗体,该用例测试失败

                               SQALogMessage sqaFail, "测试数据为" + strMessage + "的测试用例执行失败", "项目名称"

                               SQAGetProperty "Window", "Text", vSText  

                               SQALogMessage sqaFail, "出现错误窗体:"+ vSText, "项目名称"

                               Window CloseWin, "Caption=" + vSText, ""

     

                            end if  

                         else

                            if (vSText="登陆失败") then

                               '数据错误,用例执行失败,软件功能正常

                               PushButton Click, "Text=确定"   

                               SQALogMessage sqaFail, "测试数据为" + strMessage + "的测试用例执行失败但软件功能正常", "项目名称"

                            else

                               '出现异常窗体,该用例测试失败

                               SQALogMessage sqaFail, "测试数据为" + strMessage + "的测试用例执行失败", "项目名称"

                               SQAGetProperty "Window", "Text", vSText  

                               SQALogMessage sqaFail, "出现错误窗体:"+ vSText, "项目名称"

                               Window CloseWin, "Caption=" + vSText, "" 

                            end if  

                         end if

                   

              wend

       

              dp_Result = SQADatapoolClose (dp_id)

        else

             SQALogMessage sqaFail, "数据池打开失败", "项目名称"

        end if

     

    Last:

          SQALogMessage sqaFail, "测试脚本发生异常,测试脚本执行失败", "项目名称"    

     

       

    End Sub

     

     

    总结:

          上边脚本是对登陆功能测试自动化初步优化后的代码,后边还要做的是脚本模块化,函数话,功能分切。脚本过大不容易维护,把其中连接数据库,处理datapool功能写成函数提供其他工程使用。其实也可以把测试数据存入文本文件,word,excel等文件中,然后读出处理模拟datapool功能,但开发脚本工程量大。datapool提供自动生成数据功能和能够和工程结合是它的优点,但很困难多个工程共享datapool。

  • Rational中DataPool的介绍与实际应用【转载】

    2008-01-26 23:53:06

    本文对datapool进行简单介绍的同时结合实际功能测试性能测试的来讲界使用datapool。希望对广大的软件测试人员有帮助。由于写作

    DataPool是一种测试数据集,在测试脚本回放的时候提供给脚本的变量。datapool可以由rational产品robot或TestManager创建,下边的表格列举出在robot和testmanager中可以对datapool执行的操作:

    操作 Robot TesrManager
    在测试脚本中自动建立datapool

     

    创建测试脚本兵产生自动数据

    修改vu脚本中的datapool设置

     

    修改datapool字段定义并修改测试数据

    创建并修改数据类型

     

    管理datapool比如改名或者拷贝

     

    倒入倒出数据

     

    倒入数据

     

    备注:rational中datapool有两种文件:txt和csv文件,创建datapool成功后会保存在

    盘符:\工程文件目录\TestDatastore\DefaultTestscrīptDatastore\TMS_Datapools文件夹下

    测试数据保存在有csv扩展名的文本文件中,所有字段信息保存在后缀名为spc的文件中,该文件由testmanager管理。

    datapool有两种创建方法,一种是在testmanager中建立,一种robot录制vu脚本时自动建立同名datapool,只有在robot中tools->session record options, 设置Generator页面general的use datapool选项,才可以生效。下边分别介绍这两种创建和使用方法:

    一.

    建立datapool:

      1.启动Rational TestManager;

    2.Tools>Manage>Datapool,点击New…,输入数据池名称点“确定”;

    3.在打开的Data Type Specification中添加字段定义;(字段定义说明见后)

    4.生成数据Generate Data(产生大量数据,这里默认产生100个数据)

    5.修改其中的数据Edit DataPool data

    其中字段定义说明:

    1) Name 指的是数据池列标题名它与测试脚本中变量相一致。如果你改变了数据池列名,也必须保证测试脚本中的变量做相应的改变;如果你不是在Rational测试环境下建立的数据池然后导入它,TestManager自动给数据池列分配缺省的名称。也必须保证测试脚本中的变量与其相一致。你可以用ime给datapool字段起多字节的名字

    2) Type 标准的或用户定义的数据类型都按名称向数据池列提供其值。犹如建立数据库,先建立字段名,后改动类型。

    制定数据池列的数据类如下操作:

    a、选择标准类型或已存在的用户定义数据类型,点击当前显示的数据类型名称,然后从列表中选择新的数据类型。

    b、可以选择rational中的标准的数据类型。

    c、如果想自定义一个类型名称而不是进行选择,在用户定义数据类型前输入星号,如:*MyData;

    d、建立新的用户定义数据类型,输入数据类型名称(不要带*),然后点击Return。在你点击了Yes确定你想要建立用户定义的数据类型,

      例如:建立新的column,输入列名,输入DemoType(自定义类型),保存。这时会出现数据类型属性编辑对话框(我向Descrīption中输入描述信息,确定按钮不可用,可能是rational的bug,不知道告诉ratioanl有没有奖励),确定,出现另一个数据类型属性编辑界面,输入测试数据,退出。选中该行生成数据,testmanager会自动创建你输入的数据。

    e、建立新的用户定义数据类型。

    3) Sequence 数据类型的值的顺序被写入数据池列中。只要从中进行选择即可:-Random-随机向数据池列中写入数字和字母的值。-Sequential-顺序写出,如0,1,2,3,... Sequential仅仅支持数字值(包括日期和时间) 和生成的用户定义的日期类型。当你选择数字类型,必须确定其最大和最小的范围,间隔必须大于0;-Unique即其中的值是唯一的。也可定义最大最小值。

    4) Repeat 即出现在数据池列的时间,Repeat不能为0。要想设置有符号的整数和用户定义的数据类型的唯一性,设置Reapeat为1。当定义唯一值时,确定生成的数在你定义的范围之内。

    5) Length 数据池列中存在的最大的数。这个长度包括小数点和负号。

    6) Decimals 定义最大的浮点数的小数位,最大的设置是6位。

    7) Interval 如果你在数据池列中设置了间隔,那么将按照你设置的顺序,而顺序变化。最小的间隔是1,最大的间隔是999999在数字数据类型下选择了Sequence,并定义了最大和最小范围,间隔必须大于0。这设置仅仅在数字设置时有效。

    8) Minimum 确定数字最小值这设置仅仅在数字设置时有效。

    9) Maximum 确定数字最大值这设置仅仅在数字设置时有效。

    10) Seed 是Rational Test为了计算随机值的数。相同的种子数产生相同的随机数,要改变随机顺序,改变种子数。

    11) Data File 用户定义的数据类型的路径,这个路径是自动付给你的,不能进行修改。数据类型文件存放在你的项目文件中的Data Type目录,不能进行直接修改。

    4、 在设置好字段后,在No. of records to genarete:中输入要生成的记录数,然后点击Genarete Data 即可生成数据,或者点击SAVE按钮,关闭当前窗口,然后点击manage datapools>edit>edit datapool data,直接手工输入数据;

    5、 这样就完成了数据池的创建,还可以执行数据池的编辑、改名、删除、导入、导出等操作;

    6、 数据池有数据生成能力,但是不具备数据的计算能力。这种情况下可以利用其他工具(如EXCEL)生成数据,并保存为csv(逗号分割文件)格式,然后在manage datapools中导入;

    实际应用:

        开发部最近提出对现有软件系统的登陆功能进行测试。测试工程师设计测试用例,在实际工作中发现登陆系统版本基本稳定,而且功能孤立,界面在将来的版本中变化的可能性不大,所以决定测试自动化,减少人工重复劳动,提高测试效率。

    测试工程师开始利用黑盒测试方法等价类法,因果分析法,边界值法等方法设计测试用例,开发功能测试脚本,用datapool(数据池中的数据是设计测试用例的时候用到的输入值)保存测试数据。 登陆界面需要输入用户名,密码,在数据池中建立两个字段username,password。Datapool中的数据和测试用例中输入数据相一致

  • Robot手工编写GUI脚本如何获取对象识别方法和属性【转载】

    2008-01-26 23:51:51

    以计算器为例,下面的脚本是键盘输入“1+1=”,然后关闭计算器。
    Sub Main
        Dim Result As Integer

        StartApplication "C:\WINNT\system32\calc.exe"
       
        Window SetContext, "Caption=计算器", ""
        InputKeys "1{+}1{ENTER}"
        Window CloseWin, "", ""

    End Sub
       
        Robot提供了获取对象识别方法和属性的利器――Inspector。通过Robot tools-Inspector..打开。现在使用SQAGetProperty命令获取1+1的结果值,并通过msgbox显示该值。
        鼠标左键按住Inspectot工具栏上的“Select Objcet”按钮,然后选择计算器的结果放开鼠标左键。Inspectot中显示出对象的识别方法,鼠标左键点击工具栏上的“Copy recognition String”按钮拷贝识别方法,属性值通过选择Inspector左下角窗口中的Text属性,然后鼠标左键点击工具栏上的“Copy”按钮拷贝属性。修改后的脚本如下:
    Sub Main
        Dim Result As Integer
        Dim sum as Variant

        StartApplication "C:\WINNT\system32\calc.exe"
       
        Window SetContext, "Caption=计算器", ""
        InputKeys "1{+}1{ENTER}"
       
        Result = SQAGetProperty ("Type=Label;ObjectIndex=1", "Text", sum)
        msgbox sum
       
        Window CloseWin, "", ""

    End Sub

        VU脚本是类C语言,区分大小写。所以在获取识别方法和属性值时最好的方法就是使用Inspector。
        自己编写脚本时,还有一个要注意的问题是窗口上下文,窗口上下文不正确会导致回放时找不到对象。上面的脚本中Window SetContext, "Caption=计算器", ""下面的操作都是在这个窗口上进行的。编写脚本时一定注意看一下窗口上下文是否正确。
        也可以在识别方法中指定窗口上下文,如Result = SQAGetProperty ("Type=Label;ObjectIndex=1", "Text", sum)可以改成Result = SQAGetProperty ("\;Type=Window;Caption=计算器;\;Type=Label;ObjectIndex=1", "Text", sum),第一个“\”代表桌面,“Type=Window;Caption=计算器”是计算器窗口,第二个“\”代表“Type=Window;Caption=计算器”和“Type=Label;ObjectIndex=1”是父子关系。这两个命令的效果完全一样。 

  • robot函数实例讲解(二)【转载】

    2008-01-26 23:50:45

    Rational Robot中提供了一个文件操作命令,语法如下:
    Open filename$ [For mode] [Access access] [lock] As [#] filenumber% [Len = reclen]
    这里我们把它的语法分为两部分,因为这个文件操作命令有两种文件操作模式,一种是顺序文件,一种是随机文件。

    下边是对顺序文件操作的语法:
    Open filename$ [??For [Input |Output |Append] As [#]filenumber [Len = buffersize]
    参数说明:
    说明:

      (1)参数filename$表示要打开的文件名,文件名可以包含有驱动器和目录

      (2)Input Output 和Append用于设置顺序文件的打开方式。其中,Input表示从打开的文件中读取数据。以这种方式打开文件时,文件必须存在,否则会产生错误。Output表示向打开的文件中写入数据。以这种方式打开文件时,文件中原有的数据将被覆盖,新的数据将从文件开始写入。如果文件不存在,则创建一个新文件。Append表示向打开的文件中添加数据。以这种方式打开时,文件中原有的数据将被保留,新的数据将从文件为开始添加。如果文件不存在,则创建一个新文件。

      (3)As[#]filenumber 子句用于为打开的文件指定文件号.对文件进行读写操作时,要用文件号表示该文件.文件号是介于1~511之间的整数,既可以是数字,又可以是变量.也可以省略不用.

      (4)当在文件与程序之间拷贝数据时,Len=buffersize子句指定缓冲区的字符数.

    例子:
    Open “c:\test.dat" For Output As 1
    Open “c:\test.dat" For Output As 1
      这两句代码在c盘所在目录下创建了一个名为test.dat的文本文件,分配文件号为1.
    Open “c:\test.dat"??For Input As [#]filenumber  这条语句是从文本文件中读取数据.
    Open App.Path + "\test.dat" For Append As [#]filenumber?? 这条语句则是向文本文件中添加数据
    随机文件的操作:
      操作随机文件之前,首先必须定义用于保存数据项的记录类型.该记录是用户自定义数据类型,他们是随机文件中存储数据的基本结构.例如:

    Type Student
     No As Integer
     Name As String * 20
     age As Integer
    End Type

    Dim Stud As Student ‘定义一个可以存放学生材料的变量
      随机文件中,所有的数据都将保存到若干个结构为Student类型的记录中, 而从随机文件中读出的数据则可以存放到变量Stud中.之后我们就可以打开并读写文件了.

    随机文件的操作语法格式:
    Open filename For Random as [#]filenumber Len = Reclength
      说明:
      (1)参数filename 和filenumber 分别表示文件名或文件号.
      (2)关键字Random 表示打开的是随机文件
      (3)Len子句用于设置记录长度,长度由参数Reclength指定.Reclength的值必须大于0,而且必须与定义的记录结构的长度一致.计算记录长度的方法是将记录结构中每个元素的长度相加.例如前面声明的Student的长度应该是2+20+2=24字节.
    打开一个记录类型为Student 的随机文件的方法是:
    Open "c:\Student.txt " For Random As #1 Len = 25

    这里还有一种文件操作方式二进制文件,下边是他的语法格式:
    Open pathname For Binary As [#]filenumber
      说明:
      (1) 参数filename 和filenumber 分别表示文件名或文件号.
      (2)关键字Binary 表示打开的是二进制文件
      (3)对于二进制文件,不能指定字节长度.每个打开的二进制文件都有一个自己的指针,文件指针是一个数字值,指向下一次读写操作的文件中的位置.二进制文件中的每个”位置”对应一个数据字节,因此,有n个字节的文件,就有1到n个位置.

      我们可以用Seek()函数返回当前的文件指针位置(即下一个要读写的字节 );用Loc()函数返回上一次读写的字节位置,除非用Seek语句移动了指针,Loc()返回值总比Seek()的小1.我们来看下面的例子:
    Open “路径:\student.txt” for Binary as #1? ? 该语句用二进制的方式打开了student.txt文件.

    二)写文件
      1、 顺序文件
      写顺序文件我们可以用Write # 和Print #语句向一个已经打开的文件中写入数据.
      下面是他们的格式和说明:

      Print # 的语法格式:

      Print # 文件号,变量列表

      例如,将文本框中的文本写到文件中,代码如下:

    Open "file.txt" For Output As #filenum

    Input #filenum, text1.text

      Write # 语句的语法格式:

    Write # 文件号,变量列表

      说明:用Write # 语句写入的信息便于以后用Input #语句来读取数据,因为Write #语句自动将写入到文件中的信息用逗号分开,并为字符串数据加上双引号.例如:

    Open "student.txt" For Output As #filenum

    Write #filenum, "张三", "初一年级", 14
    Write #filenum, "李四", "职业高中", 18

      2、 随机文件

      向随机文件中写入数据,使用Put #语句.语法格式如下:

    Put [#] FileNum ,[RecNum],UserType

      说明:

      (1) FileNum 是要打开的文件号;RecNum是要写入的记录号,若省略,则再上一次用Get 和Put语句所读写过的记录的后一条记录中写入,如果没有执行过Get 和Put语句,就从第一条记录开始

      (2)UserType 是包含要写入数据的用户自定义的数据类型变量.例如:我们向前面的student.txt文件中的第5个记录写入数据,可用这些语句:

    stud.No = 0301
    stud.Name = “王武”
    stud.Age =20
    Put #1 ,5,stud

      如果要插入的数据不只一两条的话,首先要确定文件和每条记录的长度,这样就可以计算出文件中究竟有多少条记录.我们可以用Lof()函数返回文件的长度,Len()函数返回每个记录的长度,计算文件中的记录个数可以用文件的长度除以给个记录的长度.示例如下:

    Nextrec= (Lof(1)\Len(UserType))+1

    Put #1,Nextrec,UserType

      3、二进制文件

      下面是以二进制方式写入文件的语句格式及其说明:

      格式:

    Put [#]fileNumber ,[Pos], Var

      功能: 用二进制方式,从文件的中指定的位置开始写入,所给变量长度的数据

      说明:

      (1)FileNumber是以二进制方式打开的文件号.

      (2)Pos用来指定写操作发生时的字节位置,若省略,则使用当前文件指针位置.

      (3)Var是用来存放写入的数据的变量.该语句会自动根据var变量包含的字节长度写入文件,如果Var是一个可变长度的字符串变量,则传送的字节数等于Var中目前的字节数.

      使用方法可参考二进制文件的读操作.
    用Excel做Datapool实现Rational Robot 功能测试的一个实例
    Rational Robot是一个比较通用的软件测试工具。她主要通过录制(自动或手工)脚本用于功能测试和性能测试

    在手工修改Robot录制的GUI脚本时,经常用到Datapool这一概念,由于Rational自带的Datapool工具只能支持2000行的数据池纪录,而且编辑不是很方便。现用比较方便的Excel作为数据源,实现自动测试的功能。

    前提条件:OS系统中已经安装Office。

    [源码]

    '$include "sqautil.sbh"
    Sub Main
        Dim Result As Integer
        dim excel as Object
        dim book as Object
        dim worksheet as Object
        dim s_name as String
        dim s_pass as String
        dim count as Integer

        'Initially Recorded: 2004-4-2  :16:55
        'scrīpt Name: AUT_1_Login
       
        Window SetContext, "Caption=Program Manager", ""
        StartBrowser "C:\Program Files\Internet Explorer\IEXPLORE.EXE", "WindowTag=WEBBrowser"
       
       
        '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        'Initiliaze excel
        on error resume next
        Set excel = GetObject(,"excel.application")
        if(excel Is Nothing) then
            Set excel = CreateObject("excel.application")
            if(excel Is Nothing) then
                MsgBox "Couldn't find Excel!"
                Exit Sub
            End if
        End if
       
        '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

        Set book = excel.Workbooks.Open("Your Book1.xls")
        Set worksheet = book.Worksheets("Your Excel sheet's name")
           
        For count=1 To 2
        s_name = worksheet.Cells(1,count).value
        s_pass = worksheet.Cells(2,count).value
        'print s_name,s_pass
       
        Window SetContext, "Caption=Web应用系统 - Microsoft Internet Explorer", ""
        Browser SetFrame,"Type=HTMLFrame;HTMLId=mainframe",""
        Browser NewPage,"HTMLTitle=Title",""
        EditBox Click, "Type=EditBox;Name=userAccount", "Coords=26,10"
        InputKeys s_name &"{TAB}"&s_pass
        PushButton Click, "Type=PushButton;HTMLText=登录"
       
        Window SetTestContext, "Caption=Web应用系统 - Microsoft Internet Explorer", ""
        Browser SetFrame,"Type=HTMLFrame;HTMLId=mainframe",""
       
        Window SetTestContext, "Caption=Microsoft Internet Explorer", ""
        Result = LabelVP (CompareProperties, "Text=输入错误,请重新输入!", "VP=Object Properties;ExpectedResult=FAIL")
        Window ResetTestContext, "", ""
         
        Next count

        'Quit Excel'''''''''''''''''''''
        excel.Quit
        Set excel = Nothing
       
        Window CloseWin, "", ""
       
    End Sub

    数据池(DATAPOOL)应用技巧――如何生成定制数据

    数据池可以按一定的规则生成测试数据列,但是它不能直接生成定制的数据。下面介绍使用数据池生成定制数据的一种方法:

        测试数据要求:数据由用户和产品数据组成,依次为用户名、用户密码、产品ID、产品价格。用户名和用户密码一一对应,产品ID和产品价格一一对应。要求用户数据和产品数据随机组合,生成大量测试数据。
    数据生成过程:
    1、从数据库中用Select语句分别从用户表和产品表中检索出用户数据和产品数据,检索结果分别存为CSV文件,文件名为user.csv和product.csv;

    2、在Testmanager中新建DATAPOOL,命名为testdata,插入两个字段,TYPE选择“Read from File”,分别选择上一步生成的CSV文件,Sequense按需要选择;

    3、按“Generate Data”按钮生成数据,close关闭窗口;

    4、“Edit Datapool Data”查看生成的数据,可以看到只有两列数据,关闭窗口;

    5、Manage Datapools窗口上点击“Import”按钮,选择测试项目目录中的..\TestDatastore\DefaultTestscrīptDatastore\TMS_Datapools\ testdata.csv(上一步生成的数据池的CSV文件),输入新的DATAPOOL名afterdata,按“确定”按钮;

    6、打开afterdata查看生成的数据,数据为4列,数据成功生成。

    Rational Robot如何测试帮助c++程序员识别自定义或则第三方控件

    大家都知道Rational Robot利用Delphi Enabler支持识别Delphi第三方控件和自定义控件,但是识别C++程序中遇到的第三方控件呢?我将在下边介绍识别他的方法,希望对大家有所帮助。

    SQA Object Testing Control

    如果你测试软件是vb编写的,那么利用SQA Object Testing Control: (SQAOTE32.ocx)来获得控件信息很对你来说很熟悉,通过它可以获取到软件运行时候的控件信息和方法。Robot可以根据提供的信息建立强壮的脚本,验证那些方法或功能是否正确,也就是最后的验证点。
    如果你的c或则c++程序中包含自定义或者第三方的ActiveX(ocx)控件,你可以同样把这个控件放到每一个包含第三方控件或者用到自定义控件的窗体上。
    安装Rational TeamTest或者Robot,Object Testing Control (SQAOTE32.ocx)会默认安装到系统目录system32中:C:\WINNT\system32\sqaote32.ocx.。

    添加Rational ActiveX Test Control

      如果想让ActiveX Test Control起作用,需要在VC中设置ActiveX可用。以下用MFC举例
    第一.建立工程,设置ActiveX控件可用
          
    第二.在有第三方控件的地方添加Rational ActiveX Test Control
    有一个窗体中包含MSTreeView,运行Rational Robot利用object properties来抓取MSTreeView属性,Rational Robot无法识别该对象(对象为UNKNOW)。添加SQA Object Testing Control(右键插入ActiveX控件,出现下图窗体)。

    添加Rational ActiveX Test Control后窗体上出现一个robot的图标,你不用在代码中做任何处理就可以使用他。SQA Object Testing Control是个不可见控件,运行软件后他不会显示在窗体上。

        
         
    再没有添加SQA Object Testing Control的时候Robot只能识别这个控件的通用属性,添加后Robot可以识别自定义控件或者插件的大部分属性。


    注意
    如果用到得自定义控件继承自MFC或者用APIS实现,即使添加SQA Object Testing Control控件Robot也无法有效的工作。那么定义该对象继承相近的类别。
    方法1:运行的时候当用Object properties识别对象为unknow的时候,在出现的对话框中定义无法识别控件到相近的基类中。
    方法2:打开robot,Tools->General Options,切换到object mapping页面。选择基类,然后添加无法是别的控件到该类中。
    这样做可以识别该控件的通用类别属性。

    总结:针对无法识别自定义和第三方控件建议添加Rational ActiveX Test Control,通过他能使Robot识别对象的大多数属性,帮助Robot建立强壮的脚本。

    Rational Robot SQABasic数据库操作相关命令 


    SQLClose 功能函数
    断开由SQLOpen确定的与ODBC数据源连接。
    SQLClose ( connection& )
    语法: 参数 解释
    connection& 由SQLOpen返回的一个长整型的名称参数。
    注解:
    返回的是一个变量。成功返回0并连接随后关闭或断开。如果连接不正常,返回-1。

    This example opens the data source named "SblTest," gets the names in the ODBC data sources, and closes the connection.
    Sub main
    ' Declarations
    '
    Dim outputStr As String
    Dim connection As Long
    Dim prompt As Integer
    Dim datasources(1 To 50) As Variant
    Dim retcode As Variant
    Dim action1 as Integer
    Dim qualifier as String

    prompt = 5
    ' Open the datasource "SblTest"
    connection = SQLOpen("DSN=SblTest", outputStr, prompt:=5)

    action1 = 1 ' Get the names of the ODBC datasources
    retcode = SQLGetSchema(connection:=connection,action:=1, qualifier:=qualifier, ref:=datasources())
    ' Close the datasource connection
    retcode = SQLClose(connection)

    End Sub

    SQLError功能函数
    可以用来接收做ODBC函数调用时发生的多条错误的详细信息。为最近ODBC函数调用和连接返回错误信息。
    SQLError ( destination() )
    语法: 参数 解释
    destination() 两维数组的每行包含一个错误。名称参数是必要的,必须是变量的数组。

    注解
    没有返回值。域: 1) 表示ODBC错误类型/下级分类的字符串, 2)表示数据源错误编码的数字值, 3)表示错误的文本信息。

    如果没有错误从先前的ODBC函数调用发生,则0被返回到调用者数组的(1,1)里。如果数组不是2维的或不支持上面提到的三个域,则一个错误信息被返回到调用者数组的(1,1)里。

    SQLError Example
    This example forces an error to test SQLError function.
    sub main
    ' Declarations
    Dim connection As long
    Dim prompt as integer
    Dim retcode as long
    Dim errors(1 To 3, 1 To 10) as Variant
    Dim outputStr as String
    ' Open the datasource
    connection = SQLOpen("DSN=SBLTESTW;UID=DBA;PWD=SQL",outputStr,prompt:=3)
    ' force an error to test SQLError select a nonexistent table
    retcode = SQLExecQuery(connection:=connection,query:="select * from notable ")
    ' Retrieve the detailed error message information into the errors array
    SQLError destination:=errors
    retcode = SQLClose(connection)
    end sub


    SQLExecQuery Function
    在SQLOpen确定的连接上执行一个SQL语句。
    SQLExecQuery ( connection& , query$ )
    语法: 参数 解释
    connection& 指定参数、必须。长整形、由SQLOpen返回。
    query$ 包含一个有效SQL语句的字符串,返回值是个变量。
    注解:
    对于SQL SELECT返回结果集的栏数目;对于UPDATE, INSERT, 或 DELETE返回受语句作用的行的数目。任何其它SQL语句返回0。如果函数在指定数据源不能执行此查询,或如果连接不可用,则返回为负的错误编码。

    如果SQLExecQuery被调用但连接上还有一些未处理结果,则这些等待结果被新的结果所代替。

    SQLExecQuery Example
    This example performs a query on the data source.
    Sub main
    ' Declarations
    '
    Dim connection As Long
    Dim destination(1 To 50, 1 To 125) As Variant
    Dim retcode As long
    Dim outputStr as String
    Dim query as String
    ' open the connection
    connection = SQLOpen("DSN=SblTest",outputStr,prompt:=3)
    '
    ' Execute the query
    query = "select * from customer"
    retcode = SQLExecQuery(connection,query)
    '
    ' retrieve the first 50 rows with the first 6 columns of each row into
    ' the array destination, omit row numbers and put column names in the
    ' first row of the array
    '
    retcode = SQLRetrieve(connection:=connection,destination:=destination,columnNames:=1,rowNumbers:=0,maxRows:=50, maxColumns:=6,fetchFirst:=0)

    ' Get the next 50 rows of from the result set
    retcode = SQLRetrieve(connection:=connection,destination:=destination,columnNames:=1,rowNumbers:=0,maxRows:=50, maxColumns:=6)
    ' Close the connection
    retcode = SQLClose(connection)
    End Sub


    SQLGetSchema功能函数
    返回各类信息,包括数据源可用的信息,当前用户ID、表格名称、表格列的名称和类型、及其它数据源/数据库相关信息。
    SQLGetSchema (connection& , action% , qualifier$ , ref() )
    语法: 参数 解释
    connection& 由SQLOpen返回的一个长整形。
    action% 必需项。
    qualifier$ 必需项。
    ref() 动作请求的对应的结果的变量数组,必须有一个数组即使仅一个参数的一维数组。返回值是一个变量。

    注解:
    返回一个负数表示一个错误。如果请求信息不能被访问或连接不能用,将返回-1。目标数组必须适当地定制以支持动作或错误返回。动作2和3不是普遍被支持的。动作4返回所有表格并不支持权限使用。不是所有数据库产品和ODBC驱动支持所有动作。
    动作对应解释表:
    动作 具体注释说明
    1 现有可用数据源列表(dimension of ref() is one)
    2 当前连接上的数据库列表(不支持)
    3 当前连接上数据库的所有者列表(不支持)
    4 指定连接上的表格列表
    5 由合法用户指定表格的栏列的列表(ref() 必须2维)。返回列栏名称和SQL数据类型。
    6 当前连接使用者的用户ID
    7 当前数据库的名称
    8 当前连接的数据源的名称。
    9 数据源使用的DBMS的名称(例如Oracle)。
    10 数据源的服务器名称
    11 数据源表示拥有者的术语
    12 数据源表示表格的术语
    13 数据源表示合法用户的术语
    14 数据源表示过程的术语


    SQLGetSchema Example
    This example opens the data source named "SblTest," gets the names in the ODBC data sources, and closes the connection.
    Sub main
    ' Declarations
    '
    Dim outputStr As String
    Dim connection As Long
    Dim prompt As Integer
    Dim datasources(1 To 50) As Variant
    Dim retcode As Variant
    Dim action1 as Integer
    Dim qualifier as String

    prompt = 5
    ' Open the datasource "SblTest"
    connection = SQLOpen("DSN=SblTest", outputStr, prompt:=5)

    action1 = 1 ' Get the names of the ODBC datasources
    retcode = SQLGetSchema(connection:=connection,action:=1, qualifier:=qualifier, ref:=datasources())
    ' Close the datasource connection
    retcode = SQLClose(connection)

    End Sub

    SQLOpen 功能函数
    建立一个到在connectStr里指定的ODBC数据源的连接并返回一个连接ID,并将完全的连接字符串赋予outputStr变量。如果连接不可用,返回ODBC错误的负数。
    SQLOpen ( connectStr$ [ , outputStr$] [ , prompt%] )
    语法: 参数 解释
    connectStr$ 指定参数,必须参数。
    outputStr$ 可选
    prompt% 可选。Prompt指定何时驱动对话框出现。可选项:
    1 对话框永远出现
    2 说明不够充分以建立连接时打开驱动对话框
    3 同2,对话框内容为灰色,不能修改
    4 对话框不出现,连接不成功,则返回一个错误
    注解:
    关于connectStr的内容描述在ODBC微软程序员参考手册。典型字符串形式为"DSN=datasourcename; UID=myid; PWD=mypassword"。返回长型long型。
    当prompt缺省时,SQLOpen使用2作为默认值。

    SQLOpen Example
    This example opens the data source named "SblTest," gets the names in the ODBC data sources, and closes the connection.
    Sub main
    ' Declarations
    '
    Dim outputStr As String
    Dim connection As Long
    Dim prompt As Integer
    Dim datasources(1 To 50) As Variant
    Dim retcode As Variant
    Dim action1 as Integer
    Dim qualifier as String

    prompt = 5
    ' Open the datasource "SblTest"
    connection = SQLOpen("DSN=SblTest", outputStr, prompt:=5)

    action1 = 1 ' Get the names of the ODBC datasources
    retcode = SQLGetSchema(connection:=connection,action:=1, qualifier:=qualifier, ref:=datasources())
    ' Close the datasource connection
    retcode = SQLClose(connection)

    End Sub


    SQLRequest功能函数
    建立一个由connectionStr指定数据源的连接,执行包含在query内的SQL语句,返回请求的结果到ref()数组里,并关闭连接。
    SQLRequest( connectionStr$ , query$ , outputStr$ , prompt% , columnNames% , ref() )
    语法: 参数 解释
    connectionStr$ 必需项。
    query$ 必需项
    outputStr$ 包含完整连接字符串。
    prompt% Prompt指定何时驱动对话框出现。一个整数。(查看SQLOpen).
    columnNames% 0或非0的一个整数。当columnNames为非0,栏列名称作为ref()数组的第一行被返回。如果columnNames缺省,默认值为0。
    ref() 必需项,2维变量数组。
    注解:
    在连接不能被建立、查询不能用、或其它错误的情况下,返回一个负数。在请求成功情况下返回正数或受影响的行数。其它SQL语句返回0。
    参数是必需的参数。结果为变量。

    SQLRequest Example
    This example will open the datasource SBLTESTW and execute the query specified by query and return the results in destination
    Sub main
    ' Declarations
    '
    Dim destination(1 To 50, 1 To 125) As Variant
    Dim prompt As integer
    Dim retcode as Variant
    Dim query as String
    Dim outputStr as String

    ' The following will open the datasource SBLTESTW and execute the query
    ' specified by query and return the results in destination
    '
    query = "select * from class"
    retcode = SQLRequest("DSN=SBLTESTW;UID=DBA;PWD=SQL",query,outputStr,prompt,0,destination())
    End Sub

    SQLRetrieve 功能函数
    在由connection指定的连接上获取待定查询结果并将结果返回到destination()数组里。
    SQLRetrieve( connection& , destination() , maxColumns% , maxRows% , columnNames% , rowNumbers% , fetchFirst% )
    语法:
    参 数 解 释
    connection& 长型long
    destination() 2维变量数组
    maxColumns% 整形,可选参数,用来指定在查询中取回的栏列数目
    maxRows% 整形,可选参数,用来指定在查询中取回的行的数目
    columnNames% 整形,可选参数,默认为0
    rowNumbers% 整形,可选参数,默认为0
    fetchFirst% 整形,可选参数,默认为0
    注解:
    返回值是结果集的行的数目或请求的最大行。如果函数不能在指定连接上获得结果,返回-1。如果没有发现数据,函数返回0。
    参数是必需参数。返回变量。
    如果maxColumns或maxRows被缺省,数组大小被用来确定获得的行列的最大数目,并返回整个结果集是一个尝试。通过再次使用SQLRetrieve和把fetchFirst设置为0,额外行可以被获得。如果maxColumns指定比结果中可用的更少的列,SQLRetrieve抛弃右边结果列只到结果与指定大小相适合。
    当columnNames是非0,数组的第1行将放置数据库计划(database schema)指定的列名称。 当 rowNumbers是非0,行数目返回到destination()的第1列。SQLRetrieve将清空用户的数组来获得结果。
    当fetchFirst 是非0,它将结果重新配置到第一行,前提是如果数据库支持此功能。如果数据库不支持此功能,结果设置 –1错误被返回。
    如果结果集有比可以被destination()数组包含还多的行或比用maxRows请求还多的行,用户可以重复调用SQLRetrieve只到返回值为0为止。

    SQLRetrieve Example
    This example retrieves information from a data source.
    Sub main
    ' Declarations
    '
    Dim connection As Long
    Dim destination(1 To 50, 1 To 125) As Variant
    Dim retcode As long
    Dim query as String
    Dim outputStr as String
    connection = SQLOpen("DSN=SblTest",outputStr,prompt:=3)
    '
    ' Execute the query
    query = "select * from customer"
    retcode = SQLExecQuery(connection,query)

    ' retrieve the first 50 rows with the first 6 columns of each row into
    ' the array destination, omit row numbers and put column names in the
    ' first row of the array

    retcode = SQLRetrieve(connection:=connection,destination:=destination, columnNames:=1,rowNumbers:=0,maxRows:=50, maxColumns:=6,fetchFirst:=0)

    ' Get the next 50 rows of from the result set
    retcode = SQLRetrieve(connection:=connection,destination:=destination,columnNames:=1,rowNumbers:=0,maxRows:=50, maxColumns:=6)
    ' Close the connection
    retcode = SQLClose(connection)
    End Sub


    SQLRetrieveToFile 功能函数
    在connection指定的连接上获取待定查询结果并存储到destination指定的文件。
    SQLRetrieveToFile( connection& , destination$ , columnNames% , columnDelimiter$ )
    语法: 参数 解释
    connection& 必需项,long
    destination$ 必需项,包含用来存储结果的文件和路径的字符串。
    columnNames% 整型,非0时,文件首行将存储数据库计划指定的栏列名称。如果缺省,默认为0。
    columnDelimiter$ 每行内界定域用的字符串。如果缺省,tab键用来分隔域。
    注解:
    成功完成操作情况下,返回值是结果集的行数目。如果函数不能在指定连接上获得结果,返回-1。
    参数是必需参数。返回变量。

    SQLRetrieveToFile Example
    This example opens a connection to a data source and retrieves information to a file.
    Sub main
    ' Declarations
    '
    Dim connection As Long
    Dim destination As String
    Dim retcode As Long
    Dim query as String
    Dim outputStr as String
    Dim filename as String
    Dim columnDelimiter as String
    '
    ' Open the connection
    connection = SQLOpen("DSN=SblTest",outputStr,prompt:=3)
    ' Execute the query
    '
    query = "select * from customer"
    retcode = SQLExecQuery(connection,query)
    ' Place the results of the previous query in the file named by
    ' filename and put the column names in the file as the first row.
    ' The field delimiter is %
    '
    filename = "c:\myfile.txt"
    columnDelimiter = "%"
    retcode = SQLRetrieveToFile(connection:=connection,destination:=filename, columnNames:=1,columnDelimiter:=columnDelimiter)

    retcode = SQLClose(connection)
    End Sub

    转载请注明信息来自51testing

  • robot函数实例讲解(一)【转载】

    2008-01-26 23:47:22

    功能说明:出现一个提示对话框,N秒后消失,比如说:提示等待一个窗口阿,有时候这个窗口没了,我也不知道脚本运行到什么地方了,提示一下挺好,也方便其他测试员修改,而且,也不影响无人值守的操作

    例子:SQAMsgbox "test","title",5

    Global iTime as Integer

    Declare Function TimedDlgFunc(id As String, Action As Integer, Suppvalue As Long) As Integer

    Declare Function SQAMsgBox(sMsgText as String, Optional vMsgCaption as Variant, Optional vTimeOut as Variant) as Integer


    Function TimedDlgFunc(id As String, Action As Integer, Suppvalue As Long) As Integer
        Static StartTime
        Dim EndTime
        Dim vTimeoutvalue as Variant

        Select Case Action
            Case 1      'Dialog box Initialization
                    StartTime = Timer

                    If StartTime + iTime >= 86400 Then
                            StartTime = 86400 - StartTime - iTime
                    End If
                    TimedDlgFunc = 1

            Case 2      'Button pushed or any control changed (except typing in text or combo box)
                Select Case Suppvalue
                    Case 1
                        DlgEnd -1
                    Case 2
                        DlgEnd 0
                    Case Else
                        TimedDlgFunc = 0
                End Select

            Case 3      'Change in text or combo box contents
                    TimedDlgFunc = 1

            Case 4      'Change of control focus
                    TimedDlgFunc = 1

            Case 5      'Idle state (return 0 to prevent this being continually called)
                    EndTime = Timer
                    If (EndTime - StartTime) >= iTime Then
                            DlgEnd -1
                    End If
                    vTimeoutvalue = Format(iTime - (EndTime - StartTime), "#.#")
                    DlgText DlgControlID("txtTimevalue"), CStr(vTimeoutvalue)
                    TimedDlgFunc = 1
        End Select

    End Function


    Function SQAMsgBox(sMsgText as String, Optional vMsgCaption as Variant, Optional vTimeOut as Variant) as Integer
        Dim Result as Integer
        Dim TotalTime As Integer
        Dim sCmdText as String   
        Dim sTimeoutText as String
        Dim vvalue as Variant

       
        If IsMissing(vMsgCaption) Then
            vMsgCaption = "SQAMsgBox"
        End If
        If IsMissing(vTimeOut) Then
            vTimeOut = 20       'seconds
        End If

        sTimeoutText = "Timeout: "
       
    '-----
        Begin Dialog dlgMsgBox 200, 80, vMsgCaption, .TimedDlgFunc
            GroupBox 5, 2, 190, 40, "", .grpMsgTxt
            Text 15, 11, 175, 25, sMsgText, .txtMsgText
            Text 15, 47, 180, 20, sCmdText, .txtCmdText
    '--------------
            Button 20, 60, 40, 14, "&OK", .btnOK
            Button 140, 60, 40, 14, "&Cancel", .btnCancel
            Text 78, 63, 30, 10, sTimeoutText, .txtTimeText
            Text 108, 63, 20, 10, vTimeout, .txtTimevalue
        End Dialog
    '-----

        Dim TimedDlg As dlgMsgBox
        iTime = CInt(vTimeOut)
        Result = Dialog(TimedDlg)
       
        If Result = 2 Then
            SQAMsgBox = sqaFail
        Else
            SQAMsgBox = sqaPass
        End If   
       
    End Function

    关于Recognition
    一共分为Recognition, ParentRecognition, FullRecognition
    1. To find the recognition method of the currently active window:
    Result=SQAGetProperty(".\","Recognition",value)
    Returned value:
    Type=Window;Name=frmMain
    抓出来的是当前窗口的一些信息

    2. To find the immediate parent of the tree view item Bach:
    Result=SQAGetProperty("Name=treMain;\;ItemText=Bach","ParentRecognition",value)
    Returned value:
    Type=TreeView;Name=treMain
    抓出来的是树型结构的父结点的信息

    3. To find the complete object path of the tree view item Bach, beginning with the desktop and ending with the target object itself:
    Result=SQAGetProperty("Name=treMain;\;ItemText=Bach","FullRecognition",value)
    Returned value:
    Type=Window;Name=frmMain;\;Type=TreeView;Name=treMain;\;Type=TVItem;ItemText=Bach
    抓出来的是树型结构中指向该控件的全部路径

    Rational Robot中自动进行100次操作
    Rational Robot中的SQA Basic与Basic语言极为类似,下面是一个for循环的例子,其中cstri()函数把整数转换成字符串。
    Sub Main
        Dim Result As Integer
        Dim i As Integer
        ……
      
         'begin of for loop
         for i=1 to 100 step 1
         ……
         InputKeys cstr(i*3) '这个地方设置输入值为I*3.
         ……
        next
        'end of for loop
        ……
    End Sub

    使用Rational Robot录制自动测试GUI脚本,在点击一个按钮以后,出现的结果可能有多种,可能会出现一个含“确定”按钮的对话框,也可能出现一个标题为”Title abcd”的窗体,可以使用SQAWaitForPropertyvalue方法来判断出现的属性,或者使用SQAWaitForObject来判断出现何种窗体,下面是两个对可能出现的属性进行判断的例子。

    1).2秒内假若出现确定对话框,点击确定按钮,否则打印"确定按钮未出现" :
    '等待2秒直到确定按钮出现.
    Result = SQAWaitForPropertyvalue("Text=(O)确定", "Enabled",TRUE, 2000)
    If Result <> sqaSuccess Then
    print "确定按钮未出现"
    Else  
        PushButton Click, "Text=(O)确定"   
    End If

    2).2秒内假若出现标题为"Title abcd" 的窗体,打印"出现标题为Title abcd的窗体" ,否则打印"未出现标题为Title abcd的窗体" :
    '等待2秒直到标题为Title abcd的窗体出现.
    Result = SQAWaitForPropertyvalue("Caption=Title abcd", "Enabled",TRUE, 2000)
    If Result <> sqaSuccess Then
    PushButton Click, "Text=(O)确定"
    print "出现标题为Title abcd的窗体"
    Else  
        print "未出现标题为Title abcd的窗体"
    End If


    说明:
    1).Result是一个Integer型变量;

    2).SQAWaitForPropertyvalue:顾名思义,指的是等待一个属性被指定值之前暂停执行。SQAWaitForPropertyvalue("Text=(O)确定", "Enabled",TRUE, 2000)表示等待2秒直到确定按钮出现,如果2秒内未出现,则返回sqlfalse,出现则返回sqlsuccess;

    3).SQA Basic中<>表示不等于;

    4).另外,可以用SQAWaitForObject来判断出现出现的对象类型:
    Result = SQAWaitForObject("Type=PushButton;Text=OK", 2000)
    If Result = sqaSuccess Then
         ...          ' add the rest of the actions/tests here
    End If

    识别控件
    需要相应的enabler,你现在测试的程序是delphi开发的应用软件,那么就要加载相应的delphi enabler!

    extension manager里边加入了delphi enabler,但是这个还是不能识别出delphi开发中用到的第三方控件或则其他控件!其实这里选择只是个打开使用真正的delphi enabler的开关,真正的delphi其实是一个sqasrvr.pas的单元文件,这个单元文件是识别控件的核心。

    ratitonal 2003里边的test enabler安装选项中包含delphi enabler,但是它需要你本机上安装delphi,才会把delphi enabler安装到你的机器上。否则不会出现。

    假如安装成功后,会在开始菜单中rational菜单下,rational test菜单下出现个delphi enabler(具体什么名字忘记了)的菜单项,通过它可以调用一个执行文件。
    执行文件的功能就是把sqasrvr.pas自动放到工程文件的头。

    delphi 工程文件只有加载了这个delphi enabler(核心 sqasrvr.pas)才会让robot识别,当然前提是你的extension manager中delphi选择了。

    Robot手工编写GUI脚本如何获取对象识别方法和属性

    以计算器为例,下面的脚本是键盘输入“1+1=”,然后关闭计算器。
    Sub Main
        Dim Result As Integer

        StartApplication "C:\WINNT\system32\calc.exe"
       
        Window SetContext, "Caption=计算器", ""
        InputKeys "1{+}1{ENTER}"
        Window CloseWin, "", ""

    End Sub
       
        Robot提供了获取对象识别方法和属性的利器――Inspector。通过Robot tools-Inspector..打开。现在使用SQAGetProperty命令获取1+1的结果值,并通过msgbox显示该值。
        鼠标左键按住Inspectot工具栏上的“Select Objcet”按钮,然后选择计算器的结果放开鼠标左键。Inspectot中显示出对象的识别方法,鼠标左键点击工具栏上的“Copy recognition String”按钮拷贝识别方法,属性值通过选择Inspector左下角窗口中的Text属性,然后鼠标左键点击工具栏上的“Copy”按钮拷贝属性。修改后的脚本如下:
    Sub Main
        Dim Result As Integer
        Dim sum as Variant

        StartApplication "C:\WINNT\system32\calc.exe"
       
        Window SetContext, "Caption=计算器", ""
        InputKeys "1{+}1{ENTER}"
       
        Result = SQAGetProperty ("Type=Label;ObjectIndex=1", "Text", sum)
        msgbox sum
       
        Window CloseWin, "", ""

    End Sub

        VU脚本是类C语言,区分大小写。所以在获取识别方法和属性值时最好的方法就是使用Inspector。
        自己编写脚本时,还有一个要注意的问题是窗口上下文,窗口上下文不正确会导致回放时找不到对象。上面的脚本中Window SetContext, "Caption=计算器", ""下面的操作都是在这个窗口上进行的。编写脚本时一定注意看一下窗口上下文是否正确。
        也可以在识别方法中指定窗口上下文,如Result = SQAGetProperty ("Type=Label;ObjectIndex=1", "Text", sum)可以改成Result = SQAGetProperty ("\;Type=Window;Caption=计算器;\;Type=Label;ObjectIndex=1", "Text", sum),第一个“\”代表桌面,“Type=Window;Caption=计算器”是计算器窗口,第二个“\”代表“Type=Window;Caption=计算器”和“Type=Label;ObjectIndex=1”是父子关系。这两个命令的效果完全一样。

    SQABasic头文件包含一系列的声明,头文件可以应用到

    一.声明共有或则全局常量,变量和用户定义类型

    二.声明自定义sub,procedures和function

    头文件中的声明可以应用到任何模块(脚本或者类库文件)。用’$include关键字,放在模块开始的地方-例如:

         ’$include “global.sbh”

    SQABasic头文件类型

    Sqabasic支持两种头文件类型:

    一.头文件保存在sqabasic路径。不用指定任何路径信息就可以在本工程或者其他工程中应用他们

    二.工程头文件可以保存在TMS_scrīpt文件夹中。不用指定任何路径信息就可以在同一个工程中处理。

    这两种SQABasic头文件都有同样的扩展名- .sbh

    库文件


    库文件包含一个或者更多供procedure从其它文件调用的sub,procedure和function。

    一.SQABasic库文件(扩展名为.sbl或则.rec)

    注意,.rec文件可以作为脚本文件或者库文件,但是.sbl只能被用作库文件。

    二.动态连接库文件(扩展名.dll)

    下边的表格这几种类库文件不同的总结:


    .sbl
    .rec
    .dll

    位置
    SQABasic路径
    当前工程文件中Datastore(文件夹 TMS_scrīpt)
    TMS_scrīpt/dll文家夹或则其他位置

    范围
    在SQABasic路径中,对所有工程文件都可用
    对同一个工程所有脚本可用
    依靠位置

    验证点
    不支持
    支持标准的robot验证点
    支持自定义验证点


    任何.rec文件都能作为库文件。不管怎样,如果一个.rec文件作为脚本(可以从robot中直接运行或者用callscrīpt命令),他必须有一个main过程。

    在SQABasic库文件中声明过程


    如果在SQABasic过程中有一个自定义的过程,你声明类文件的方法同样适用声明过程。

    下边的例子是在sqabasic库文件中(mylib.sbl)声明一个自定义过程(mysub):

         Declare Sub MySub Basiclib “MyLib”( arg1 as string,arg2 as integer)

    一.关键字basiclib,表示过程mysub在一个sqabasic库文件中

    二.库文件的名字“mylib”,这里不需要写扩展名(.sbl或者.rec)

    备注:basiclib关键字特指.sbx库文件的声明(和.dll库文件相对),这里不需要也不推荐带有.sbx扩展名的声明。


    什么地方声明SQABasic库文件

    可以在任何位置声明SQABasic库文件

    一.在脚本或者其他库文件,仅在模块中应用过程

    二.头文件中,用道的模块

    库文件包含不需要指定的例程或者’include头文件

    在dll文件声明过程文件


    如果在dll文件的自定义过程,声明过程同样可以声明dll文件。

    下边是dll文件中(mydll.dll)声明自定义过程(mysub)的例子:

           declare sub mysub lib “mydll”(byval arg1 as string,Byval arg2 as integer)

    一.声明中加入Lib关键字,表示声明的过程在dll文件中(相对于.sbl或者.rec sqabasic库文件)

    二.库文件名字(mydll),跟随库指定的名称

    三.参数声明通常包括关键字byval(参数声明包括任何关键字)


    如果编译位置在sqabas32路径或在系统路径的库文件(.dll),你不用特别声明路径。如果库文件不再sqabas32或者在系统路径,你需要制定路径,比如

           Declare Sub MySub Lib “E:MyDll”  (byval arg1 as string,Byval arg2 as integer)

    在什么地方声明dll文件


    你可以声在任何为指声明dll文件:

    1.脚本或者sqabasic库文件,要用过程的模块

    2.头文件,任何模块指定的头文件

    SQABasic路径


    Sqabasic路径是robot保存和寻找sbl库文件和头文件的地方,用户在robot中也可以定义。

    一旦你在robot中指定sqabasic路径,这个路径是固定的。不管怎样,robot自动设置sqabasic路径,当下列条件是真的时候:

               i.仍没有明确在robot中定义sqabasic

             ii.已经在rational Aministrator建立新的工程和数据仓库

            iii.打开最近创建的工程和数据仓库

    当上边所有条件为真的时候,robot自动在新工程和数据仓库中设置sqabasic路径到下列位置:

    [NewProject][NewDatastore]DefaultTestscrīptDatastoreTMS_scrīptSQABas32

    设置步骤:

    1)点Tools->General Options

    2)点Preferences页面

    3)在SQABasic路径中输入路径

    Rational test早期版本没有提供菜单选项来设置sqabasic路径 – 参阅sqa common directory片断

    指导使用头文件和库文件


    推荐下边使用库文件方法:

    a)自定义函数或者过程应该使用有同样文件名字的头文件(.sbh)和库文件(.sbl),比如DataFunctions.sbh和DataFunctions.sbl。这个过程和函数在头文件中定义(指定声明头文件)和在库文件中定义。看下边的例子

    b)分离头文件(参阅常量头文件)用于包含常量,变量和用户定义类型用于脚本或者库文件调用。头文件用同样的文件名字后边附加_x或则_C(附加是早期命名规定)。注意包含常量和变量的头文件必须加入到声明头文件和库文件之前。(DataFunctions.sbh和DataFunctions.sbl),比如’include “DateFunctions_c.sbh”。这样做很容易维护。

    c)通过分类或者程序把相关的函数放在同一个库里,例如,把所有日期相关的函数放到DataFunctions.sbh/sbl,或者把所有的函数加入为特定程序开发的函数库中(比如AppName.SBH/SBL)


    d)函数是在库文件中子程序的的首选方式,处分过程的结果对于调用脚本是不相关的。函数应该返回一个值,或者适当的,数据可以通过变量或者数组返回。在后边的例子中,函数返回的结果表示成果或者失败。


    e)库文件中的所有得函数和子程序必须有“注释“,包含这个过程的目的和用途::

    请看下边的例子。


    f)库文件的注释有合理的解释,通过读注释可以知道过程的逻辑


    g)如果开发和维护robot库文件是集中管理的方式,那么你可以加入到’$include 所有库文件到global.sbh头文件中,这样做对所有头文件都有用。这可以加入缺省的脚本模板。作为选择,测试人员在每个脚本中可以选择或者包含需要的库文件。

    转载请注明信息来源51testing

  • Rational robot 识别对象的方法【转载】

    2008-01-26 23:45:54

    当时看到这个问题,想到两个的解决方法一个是利用对象的方法,赋值,编写程函数,输入列和行,然后由这个函数处理,这样做直接,高效率,还有一个思路是利用坐标定位然后输入数据,也是便写函数,具体计算由函数处理,这种方法虽然不能做到通用,但简单实用。

    按照第一个思路开始行动,因为那位朋友测试的软件用delphi开发,其中gird是个第三方控件,这里我用TDBGrid来代替他的第三方控件做到问题简单化,先把实际问题解决,自己动手做了个程序,用ADO连接数据库,利用DataGrid显示数据,来模拟实际情况。录制脚本如下:

    Sub Main

        Dim Result As Integer

     

        'Initially Recorded: 2004-4-22  23:01:19

        'scrīpt Name: First

       

    StartApplication """C:\Documents and Settings\Administrator\桌面\T\Project1.exe"""

       

        Window SetContext, "Caption=Form1", ""

        GenericObject DblClick, "Class=TDBGrid;ClassIndex=1", "Coords=168,27"

        InputKeys "good"

        GenericObject Click, "Class=TDBGrid;ClassIndex=1", "Coords=369,33"

        Window CloseWin, "", ""

     

    End Sub

    用过delphi的人都知道TstringGrid有个Cell属性,我们可以利用robot函数SqaSetPropertycell赋值完成上边要的功能,首先用robot来的gui insertobject properties来抓取对象TDBGrid的属性,这样做是因为函数SqaSetProperty只能对robot抓取道的属性起作用,也就是说即使有cell属性,robotobject properties抓取不到这个属性,我们也无法实现前边的想法。用object properties抓取TDBGrid的属性后发现,只抓取到了部分属性,根本没有可以利用的cell属性,怎么办,利用delphi enabler来做一次看是否可以得到更多的属性,我把sqasrv.pas(其实delphi enabler的核心就是这个delphi单元文件)加入到工程文件中,重新编译(可能编译的时候有一些问题,我遇到的问题是Unit 'oleAuto' is deprecated,$WARN UNIT_DEPRECATED ON/OFF编译开关,就可以解决了),重新录制脚本如下:(这回TDBGrid的属性基本都抓取到了)。

     

    Sub Main

        Dim Result As Integer

     

        'Initially Recorded: 2004-4-22  23:38:55

        'scrīpt Name: Second

        StartApplication """C:\Documents and Settings\Administrator\桌面\T\Project1.exe"""

       

        Window SetContext, "Name=Form1;Type=Form", ""

        GenericObject DblClick, "Name=DBGrid1;Type=CustomGrid", "Coords=93,30"

        InputKeys "jack"

        GenericObject Click, "Name=DBGrid1;Type=CustomGrid", "Coords=338,26"

        Window CloseWin, "", ""

     

    End Sub

     

    可是仍然没有我们要的cell属性,只有columns属性,没有我需要的cell属性,怎么办?于是研究delphiTDBGrid的源代码发现TDBGrid继承的TcustomGrid中有HideEditUpdateEdit等方法,说明在输入数据的时候TDBGird在后台是生成了一个输入文本框,焦点改变后这个文本框自动消失把数据输入到TDBGrid。这样我们只要能给这个EDITTEXT属性赋值同样可以实现,因为TDBGrid没有CELL属性,不能直接利用SQASetProperty函数给cellfocus属性赋值,只能利用点击这个cell来赋予它焦点,因为只有焦点在这个cell上后才会出现浮动的文本框,修改上边的脚本:

     

    Sub Main

        Dim Result As Integer

        Dim Var as String

        'Initially Recorded: 2004-4-22  23:38:55

        'scrīpt Name: Second

        StartApplication """C:\Documents and Settings\Administrator\桌面\T\Project1.exe"""

       

        Window SetContext, "Name=Form1;Type=Form", ""

        GenericObject DblClick, "Name=DBGrid1;Type=CustomGrid", "Coords=93,30"

       

           

        Result = SQASetProperty ("Name=;Type=CustomGrid;Index=1", "Text", "Mr.")

        Result = SQAGetProperty("Name=;Type=CustomGrid;Index=1", "Text", VAR)

        GenericObject Click, "Name=DBGrid1;Type=CustomGrid", "Coords=338,26"

       

           

        if Result = 0 then

           MsgBox "Hello"

        End if

        GenericObject Click, "Name=DBGrid1;Type=CustomGrid", "Coords=338,26"

        'Window CloseWin, "", ""

     

    End Sub

    虽然赋值成功,但是datagrid无法显示你需要的数据(这里需要研究一下),因为时间的缘故,就用第二种方式坐标的方式来实现,考虑多平台共享使用,写SetGridFocus函数,思路这样得到tdbgrid对象,得到其中column的属性宽高,计算坐标(这些都在函数内部实现),其中移动有个固定值24是追踪tdbgrid代码中defaultHeight24

    最后代码如下:

    Sub SetGridFocus(strObject as String, strCol as String, strRow as String, strValue as String)

      

       Dim iResult as Integer

       Dim iCount as Integer

       Dim ColWidth() as integer

       Dim iWidth as Integer

      

       Dim strColPos as Integer

       Dim strRowPos as Integer

       Dim strCor as String

      

       Dim iTemp as integer

      

       strColPos = 0

       strRowPos = 0

       iTemp = 0

      

       SQAGetProperty strObject ,"Columns.Count", iCount

      

       if iCount <> 0  then

          Redim ColWidth(iCount - 1)

         

          While iTemp < iCount

             iResult = SQAGetProperty (strObject, "Columns.Items(" + CStr(iTemp) +").Width",iWidth)

             ColWidth(iTemp) = iWidth

             iTemp = iTemp + 1

         wend

         

       End if

          strColPos = 20

          if CInt(strCol) <> 1 then

              for iTemp = 1 to CInt(strCol)-1

                    strColPos = strColPos+ ColWidth(iTemp-1)

              next iTemp         

          End if         

         

          for iTemp = 1 to CInt(strRow)

             strRowPos = 24 +strRowPos

          next iTemp

         

         

         

       strCor = "Coords=" & strColPos &","+CStr(strRowPos)

      

      

       GenericObject Click, strObject, strCor

       InputKeys strValue

       stop

       strCor = "Coords=" & strColPos &","+CStr(strRowPos + 24)

       GenericObject Click, strObject, strCor  

      

      

    End Sub

     

    上编写的还有很多疏漏的地方,对于浮动文本框赋值成功,却无法改动tdbgrid中的值没有深入研究,该函数在实际应用中还有个小问题,没有做到很完全“周到“ ,下回有时间改正。

    备注:

    最后我把代码进行优化和扩展,开发了针对grid的相关函数,下边是其中之一

    //得到列数

    Function GetColCount(sGridRecogStr as String) as Integer

        Dim Result as Integer

        Dim vValue as Variant

        Dim sLogMessage as String

        Dim sErrorMessage as String

     

        grdGetRowCount = -1

     

        Result = SQAGetProperty(sGridRecogStr, "Column.Count", vValue)

        If Result = sqaSuccess Then

            GetRowCount = CInt(vValue)

        Else

            sLogMessage = "无法得到Grid的列数

            sErrorMessage = "[" & CStr(Result) & " = " & Error(Result) &"]"

            SQALogMessage sqaFail, sLogMessage, sErrorMessage

        End If

       

    End Function

     

    就到这里吧。

  • Rational 识别 Delphi TDBGrid的解决方法【转载】

    2008-01-26 23:44:40

    当时看到这个问题,想到两个的解决方法一个是利用对象的方法,赋值,编写程函数,输入列和行,然后由这个函数处理,这样做直接,高效率,还有一个思路是利用坐标定位然后输入数据,也是便写函数,具体计算由函数处理,这种方法虽然不能做到通用,但简单实用。

    按照第一个思路开始行动,因为那位朋友测试的软件用delphi开发,其中gird是个第三方控件,这里我用TDBGrid来代替他的第三方控件做到问题简单化,先把实际问题解决,自己动手做了个程序,用ADO连接数据库,利用DataGrid显示数据,来模拟实际情况。录制脚本如下:

    Sub Main

        Dim Result As Integer

     

        'Initially Recorded: 2004-4-22  23:01:19

        'scrīpt Name: First

       

    StartApplication """C:\Documents and Settings\Administrator\桌面\T\Project1.exe"""

       

        Window SetContext, "Caption=Form1", ""

        GenericObject DblClick, "Class=TDBGrid;ClassIndex=1", "Coords=168,27"

        InputKeys "good"

        GenericObject Click, "Class=TDBGrid;ClassIndex=1", "Coords=369,33"

        Window CloseWin, "", ""

     

    End Sub

    用过delphi的人都知道TstringGrid有个Cell属性,我们可以利用robot函数SqaSetPropertycell赋值完成上边要的功能,首先用robot来的gui insertobject properties来抓取对象TDBGrid的属性,这样做是因为函数SqaSetProperty只能对robot抓取道的属性起作用,也就是说即使有cell属性,robotobject properties抓取不到这个属性,我们也无法实现前边的想法。用object properties抓取TDBGrid的属性后发现,只抓取到了部分属性,根本没有可以利用的cell属性,怎么办,利用delphi enabler来做一次看是否可以得到更多的属性,我把sqasrv.pas(其实delphi enabler的核心就是这个delphi单元文件)加入到工程文件中,重新编译(可能编译的时候有一些问题,我遇到的问题是Unit 'oleAuto' is deprecated,$WARN UNIT_DEPRECATED ON/OFF编译开关,就可以解决了),重新录制脚本如下:(这回TDBGrid的属性基本都抓取到了)。

     

    Sub Main

        Dim Result As Integer

     

        'Initially Recorded: 2004-4-22  23:38:55

        'scrīpt Name: Second

        StartApplication """C:\Documents and Settings\Administrator\桌面\T\Project1.exe"""

       

        Window SetContext, "Name=Form1;Type=Form", ""

        GenericObject DblClick, "Name=DBGrid1;Type=CustomGrid", "Coords=93,30"

        InputKeys "jack"

        GenericObject Click, "Name=DBGrid1;Type=CustomGrid", "Coords=338,26"

        Window CloseWin, "", ""

     

    End Sub

     

    可是仍然没有我们要的cell属性,只有columns属性,没有我需要的cell属性,怎么办?于是研究delphiTDBGrid的源代码发现TDBGrid继承的TcustomGrid中有HideEditUpdateEdit等方法,说明在输入数据的时候TDBGird在后台是生成了一个输入文本框,焦点改变后这个文本框自动消失把数据输入到TDBGrid。这样我们只要能给这个EDITTEXT属性赋值同样可以实现,因为TDBGrid没有CELL属性,不能直接利用SQASetProperty函数给cellfocus属性赋值,只能利用点击这个cell来赋予它焦点,因为只有焦点在这个cell上后才会出现浮动的文本框,修改上边的脚本:

     

    Sub Main

        Dim Result As Integer

        Dim Var as String

        'Initially Recorded: 2004-4-22  23:38:55

        'scrīpt Name: Second

        StartApplication """C:\Documents and Settings\Administrator\桌面\T\Project1.exe"""

       

        Window SetContext, "Name=Form1;Type=Form", ""

        GenericObject DblClick, "Name=DBGrid1;Type=CustomGrid", "Coords=93,30"

       

           

        Result = SQASetProperty ("Name=;Type=CustomGrid;Index=1", "Text", "Mr.")

        Result = SQAGetProperty("Name=;Type=CustomGrid;Index=1", "Text", VAR)

        GenericObject Click, "Name=DBGrid1;Type=CustomGrid", "Coords=338,26"

       

           

        if Result = 0 then

           MsgBox "Hello"

        End if

        GenericObject Click, "Name=DBGrid1;Type=CustomGrid", "Coords=338,26"

        'Window CloseWin, "", ""

     

    End Sub

    虽然赋值成功,但是datagrid无法显示你需要的数据(这里需要研究一下),因为时间的缘故,就用第二种方式坐标的方式来实现,考虑多平台共享使用,写SetGridFocus函数,思路这样得到tdbgrid对象,得到其中column的属性宽高,计算坐标(这些都在函数内部实现),其中移动有个固定值24是追踪tdbgrid代码中defaultHeight24

    最后代码如下:

    Sub SetGridFocus(strObject as String, strCol as String, strRow as String, strValue as String)

      

       Dim iResult as Integer

       Dim iCount as Integer

       Dim ColWidth() as integer

       Dim iWidth as Integer

      

       Dim strColPos as Integer

       Dim strRowPos as Integer

       Dim strCor as String

      

       Dim iTemp as integer

      

       strColPos = 0

       strRowPos = 0

       iTemp = 0

      

       SQAGetProperty strObject ,"Columns.Count", iCount

      

       if iCount <> 0  then

          Redim ColWidth(iCount - 1)

         

          While iTemp < iCount

             iResult = SQAGetProperty (strObject, "Columns.Items(" + CStr(iTemp) +").Width",iWidth)

             ColWidth(iTemp) = iWidth

             iTemp = iTemp + 1

         wend

         

       End if

          strColPos = 20

          if CInt(strCol) <> 1 then

              for iTemp = 1 to CInt(strCol)-1

                    strColPos = strColPos+ ColWidth(iTemp-1)

              next iTemp         

          End if         

         

          for iTemp = 1 to CInt(strRow)

             strRowPos = 24 +strRowPos

          next iTemp

         

         

         

       strCor = "Coords=" & strColPos &","+CStr(strRowPos)

      

      

       GenericObject Click, strObject, strCor

       InputKeys strValue

       stop

       strCor = "Coords=" & strColPos &","+CStr(strRowPos + 24)

       GenericObject Click, strObject, strCor  

      

      

    End Sub

     

    上编写的还有很多疏漏的地方,对于浮动文本框赋值成功,却无法改动tdbgrid中的值没有深入研究,该函数在实际应用中还有个小问题,没有做到很完全“周到“ ,下回有时间改正。

    备注:

    最后我把代码进行优化和扩展,开发了针对grid的相关函数,下边是其中之一

    //得到列数

    Function GetColCount(sGridRecogStr as String) as Integer

        Dim Result as Integer

        Dim vValue as Variant

        Dim sLogMessage as String

        Dim sErrorMessage as String

     

        grdGetRowCount = -1

     

        Result = SQAGetProperty(sGridRecogStr, "Column.Count", vValue)

        If Result = sqaSuccess Then

            GetRowCount = CInt(vValue)

        Else

            sLogMessage = "无法得到Grid的列数

            sErrorMessage = "[" & CStr(Result) & " = " & Error(Result) &"]"

            SQALogMessage sqaFail, sLogMessage, sErrorMessage

        End If

       

    End Function

     

    就到这里吧。

  • Rational Robot 常用语句【转载】

    2008-01-26 23:43:12

    1.        验证点语句

    AnimateControlVP, CalendarVP, CheckBoxVP, CheckedListBoxVP, ClipboardVP, ComboBoxVP, ComboEditBoxVP, ComboListBoxVP, DataGridVP, DataWindowVP, DateTimeVP, EditBoxVP, FileVP, GenericObjectVP, GroupBoxVP, HeaderVP, HotKeyControlVP, HTMLVP, HTMLActiveXVP, HTMLDocumentVP, HTMLHiddenVP, HTMLImageVP, HTMLLinkVP, HTMLTableVP, IPAddressVP, JavaCanvasVP, JavaListViewVP, JavaMenuVP, JavaObjectVP, JavaPanelVP, JavaPopupMenuVP, JavaSplitPaneVP, JavaSplitterVP, JavaTableVP, JavaTableHeaderVP, JavaTreeVP, JavaWindowVP, ListBoxVP, ListViewVP, ModuleVP, PagerVP, ProgressBarVP, PSGridVP, PSMenuVP, PSNavigatorVP, PSPanelVP, PSSpinVP, PSTreeHeaderVP, PSTreeVP, PushButtonVP, RadioButtonVP, RebarVP, RegionVP, RichEditVP, ScrollBarVP, SpinControlVP, StatusBarVP, TabControlVP, ToolbarVP, TrackbarVP, TreeViewVP, WebSiteVP, WindowVP,

     

    2.        获取/设置对象属性语句

    SQAGetPropertySQASetProperty

     

    3.        数据池语句

    SQADatapoolOpen, SQADatapoolFetch, SQADatapoolValue, SQADatapoolRewind, SQADatapoolClose,

     

    4.        日志语句

    SQALogMessage

     

    5.        等待延迟语句

    Delayfor SQAWaitForObject SQAFindObject, SQAWaitForPropertyValue

     

    6.        字符串相关语句

    GetFieldLeftLenInstr, InstrB, Mid, MidB, Right, Str, Strcomp, Option Compare, Trim, LTrim, RTrim,

     

    7.        调用程序语句

    StartApplication SQAShellExecute

     

    8.        调用其他脚本语句

    CallCallscrīpt

     

    9.        输入/输出语句

    Open Close Get Put

     

    10.     错误处理语句

    On Error, Error, Resume, GoTo, Erl

     

    11.     常用控制语句

    If…Then, Select…Case, Do…Loop, For…Next, While…Wend, Stop, Exit Goto, On…Goto

     

    12.     交互语句

    MsgBox InputBox PasswordBox

  • Rational Robot项目移植[转载]

    2008-01-26 23:42:02

    前言:曾经在2004年培训Rational Robot的过程中,南航的学员问了我一个问题就是Rational Robot的项目移植的问题, 因为Rational可以创建本地项目和共享项目两种,共享项目有利于团对协作,但是本地项目就涉及到一个问题如何做到项目移植,把项目拷贝到另外一个地方之后就可以出现不能使用的问题,在后来的我还在网上遇到一个网上的朋友问我同样类似的问题,就是他们总公司在台湾,但是项目拷贝发到台湾之后就出现不能使用的现象。

    正文:

    [原创]Rational Robot项目移植

        RationalRobot可以创建两种类型的项目,本地项目和共享项目!那怎么样把项目进行移植呢,下边介绍两种方法!
        方法一:
        在Rational Administrator中
        - 创建新的项目
        - 创建新的测试数据仓库
        - 在数据仓库向导最后一步选择已经存在的数据仓库
        - 选择旧的数据仓库
        方法二:
        - 拷贝整个项目
        - 更新下列路径
         <project>\<project>.rsp
         <project>\TestDatastore\project.dat
         <project>\TestDatastore\datastore.dat
         <project>\TestDatastore\DefaultTestscrīptDatastore\project.dat
         <project>\TestDatastore\DefaultTestscrīptDatastore\datastore.dat
         <project>\TestUsersAndGroups\project.dat
         <project>\TestUsersAndGroups\datastore.dat
         <project>\TestDatastore\TMS_TestscrīptSources\*.rtxml
       
         注意:你还要修改Robot Menu Tools->General Option->Presferences->SQABasic Path
         如果你想移植项目,那么就要修改这个路径!

    转载请注明出处:www.51testing.com

  • 使用Robot连接SQL的例子

    2008-01-26 23:40:32

    这是使用Robot连接TestDirector数据库的一个例子。
        首先在控制面板的ODBC中新建一个DSN,选择SQL Server连接,名字是td_test(这个可以自己随便取),连接服务器选择你TD库保存的DB服务器名称。连接你想要查询的库名,我这里是gpt_gogs_db,登录名是td,密码tdtdtd(在TD中新建一个project时,数据库默认所有者为td,密码为tdtdtd),这里仅两不要使用权限过大的用户,因为在脚本中是要明文写入密码的。最后测试一下数据源。

    开始编写脚本了:
    ======================================================================
    Sub Main
        Dim Result As Integer
        Dim connect as long
        Dim outputstr,query as string
        Dim out(1 to 2,1 to 16) as variant      
        '这里定义一个二维数组,第一维表示数据库中查询结果中的列,第二维表示查询结果中的行,可以看到这里可以一次查询并存储两行两列
        dim retcode as variant
        dim i as integer
        'Initially Recorded: 2005-7-18  22:16:12
        'scrīpt Name: sqltest
        connect = SQLOpen("DSN=td_test;UID=td;PWD=tdtdtd",outputstr)
        '注意这里各个参数和等号及等号后面赋值是紧跟着的,没有空格,因为如果有空格的话连接的时候连空格也算上
        '这样的话连接的时候就会提示选择DSN或是输入用户名,密码
       
        query = "select bg_bug_id,bg_status from bug where bg_subject='113'"
        '最好在查询分析器中执行一下这条语句
       
        call SQLExecquery(connect,query)
       
        call SQLRetrieve(connect,out())
       
        msgbox out(1,1)
        msgbox out(2,1)
        msgbox out(1,2)
        msgbox out(2,2)
        '显示保存的结果
    '    next
       
        call sqlclose(connect)
        

    End Sub
    =================================================================================
    这里尤其注意那个设置二维数组的地方,这个二维数组可以一次存储多个查询结果,其结构就类似SQL Server中查询分析器查询后的结果。

    如果我生明了两个二维数组即可保存不同的查询结果。

    其读取查询内容的函数也应该重点看看。

    如果想要返回不同的查询语句结果,应该这样写:
    =================================================================================
    Sub Main

        Dim Result As Integer

        Dim connect as long

        Dim outputstr,query1,query2 as string

        Dim out1(1 to 2,1 to 1) as variant

        Dim out2(1 to 2,1 to 1) as variant     

        '这里定义一个二维数组,第一维表示数据库中查询结果中的列,第二维表示查询结果中的行,可以看到这里可以一次查询并存储两行两列

        dim retcode as variant

        dim i as integer

        'Initially Recorded: 2005-7-18  22:16:12

        'scrīpt Name: sqltest

        connect = SQLOpen("DSN=td_test;UID=td;PWD=tdtdtd")

        '注意这里各个参数和等号及等号后面赋值是紧跟着的,没有空格,因为如果有空格的话连接的时候连空格也算上

        '这样的话连接的时候就会提示选择DSN或是输入用户名,密码

        query1 = "select bg_bug_id,bg_status from bug where bg_subject='113'"

        '最好在查询分析器中执行一下这条语句

    query2 = "select bg_bug_id,bg_severity from bug where bg_subject='113'"

    '不同的查询语句

        call SQLExecquery(connect,query1)  

    call SQLRetrieve(connect,out1())

    '执行完查询语句后赋值给一个二维数组,切记!

        call SQLExecquery(connect,query2)

        call sqlretrieve(connect,out2()) 

        msgbox out1(1,1)

        msgbox out1(2,1)

        msgbox out2(1,1)

        msgbox out2(2,1)

        '显示保存的结果

    '    next

        call sqlclose(connect)

    End Sub

  • 使用Robot输入清单

    2008-01-26 23:38:21

    制作一份模拟真实情况的预算文件通常需要输入大量的清单和子目,采用手工输入的话不仅浪费时间而且可重复性不强,本篇文章介绍如何使用Robot的DataPool和for循环对清单进行输入,并探索了两种方法的优缺点。

        从事建筑行业的人都知道清单的输入格式,在这里我也简单介绍一下。 

        十二位的清单格式:

        两位专业号+两位章号+两位节号+三位小节号+三位流水号,如01 01 01 001 001(为了从视觉上看到不同位的意义,我把一个标准的清单用空格分隔开了,正常的清单号是没有空格分隔的)。不同专业、章、节、小节可以组合出不同的清单,最后一位流水号起到区分同一清单的作用,即为010101001001与010101001002是同一清单,只是用户流水号不同,因为一份预算书中不允许有完全相同的清单出现。

        作为自动化输入大量清单我首先想到的就是使用Robot的DataPool。从EXCEL制作大量清单并保存为CSV文件,导入到DataPool中进行循环输入。但这里我遇到一个问题:保存为CSV格式后清单号的第一个0被抹掉了(直接在CSV文档中输入010101001001,保存后第一个0还是会被清除),这样导入到DataPool后清单号都变成十一位了,这不是标准清单!解决办法就是手工在DataPool中添加,但对于大量保存在DataPol中的清单这样的修改是不可行的。于是只能放弃。

        另一种办法就是使用循环,将清单号如上面的格式拆分,分别对专业、章、节、小节、流水号进行循环,最后再组合成为一个标准的清单输入。但这里还有一个小问题,如我对三位小节号从1循环到10,最后怎样让其输出格式为001~010。其实很简单,使用format函数。简单代码如下:


    Sub Main
        Dim Result As Integer
        Dim zhuan,zhang,jie,liu as integer
        Dim qing as string
       
        'Initially Recorded: 2006-11-15  21:35:34
        'scrīpt Name:     
            
        for jie = 1 to 5
            for liu = 1 to 5
          
             qing = "01" + "01" + "01" + Cstr(format(jie,"000")) + Cstr(format(liu,"000"))
             InputKeys qing
             InputKeys "{DOWN}"
       
            next liu
        next jie

    End Sub

        这是一个再简单不过的循环语句,但是效果却很不错。由此可见我们不见得非要采用“高新技术”解决所有问题,最适用最简单的方法就是最好的。

    本文出自51testing博客,转载请注明出处
    原始链接:http://blog.51testing.com/?5939

  • [转]浅谈软件测试自动化解决方案

    2008-01-13 22:48:49

     

    【摘要】 测试是软件开发的一个重要环节。本文论述了软件测试自动化测试的实施。从自动测试的好处. 影响软件测试自动化实施的因素产生原因等几个方面出发.总结软件自动化测试的方案。

    【关键字】软件测试  软件自动化测试

    软件测试自动化,已经成为国内软件工程领域一个众所周知的课题;不言而喻,软件测试从业者都意识到软件测试这项工作走向成熟化、标准化的一个必经之路就是要实施自动化测试。也许您认为实施自动化测试不是必须,也许您认为测试的思想是开展该工作的精髓、而工具只是辅助,那么我要告诉你我的想法:从计算机这一庞大学科发展至今,它最根本的意义是解决人类手工劳动的复杂性,成为替代人类某些重复性行为模式的最佳工具;我们不可推翻测试思维在测试工作中的指导思想地位,但如何将思想转化成可操作的方案,本文也许会给您一些启示。

    以前听过北京中软的一个业内专家讲一句话,觉得挺经典:凡是说既是科学又是艺术的学科,就是说明它是不成熟的学科!他将软件工程和建筑行业做类比,让我们深深体会到软件工程走向成熟化的任重与道远。而软件测试,更是一个新兴的领域,虽然近几年得到了快速发展,也随着该领域从业者数量的与日俱增,培养了一批高级的人才;但是依然有多少企业和个人工作在迷茫中:这种困惑是因为工程师们手中的测试工作与理想的测试模式造成的强烈反差,这种无奈是因为他们和开发人员一样的努力却有不同的待遇,这种迷茫是因为测试工作者不知道这个领域里是否还有自己的发展空间和人生价值的体现!笔者认为:如今的软件测试行情,正处在群雄逐鹿的混战岁月,每个人、每个有测试部门或从事测试业务的企业,都该发扬百花齐放、百家争鸣的精神,多多借鉴国内外先进的测试经验,参考业界流行的行业标准,找到适合自己团队的测试方法和模式,创造更大的社会价值,发挥更大的人生价值。

    •  实施软件测试自动化的理由分析

    首先,测试人员的工作比以往任何时候都更加困难,因为公司和组织希望以更快的速度和更低的成本开发出高质量的应用程序。

    此外,在很多项目中,测试人员的所有任务实际上都是手动处理的,而实际上,有很大一部分重复性强的测试工作,是可以独立开来自动实现的。

    还有,在大型项目中测试团队和其他的团队之间没有足够的合作,无法促进彼此的工作。

    最后,从个人角度来说,测试人员通常很难花费大量时间来学习新技能;这是目前国内测试从业者的现状,太多的企业为了节约成本而将刚刚走出校门的毕业生作为测试工程师,他们每日做着繁忙的重复工作,又基于自身技能的不深,虽怀博览群书的心愿却不知从何出入手。所谓光阴似箭,因为一转眼我们就说到未来的5年、10年后,我们这些技能不深的测试工程师能做什么呢?而软件测试自动化,也是未来测试工程师或即将成为测试工程一项强有力的工作技能。可以说,实施测试自动化是软件行业一个不可逆转的趋势,如果在这个领域走在了前列,无论从企业的核心竞争力还是个人的工作技能来说,都有巨大的优越性,而国内众多的软件厂商也的确在纷至沓来的着手开展着这项工作。

    • 当然国内软件测试自动化实施现状分析

    随着众多具有了一定优秀实施自动化测试经验的企业陆续出现,也伴随着很多组织对这项工作依然是丈二的和尚-摸不着头脑。对当前国内软件企业实施或有意向实施测试自动化时面临的主要问题,按实施的不同层次来说:

    ——干脆认为测试自动化是个遥不可及的事情,我们这样的小公司不必实施,人员、资金、资源都不足,以后再说吧!

    ——热血沸腾的实施测试自动化,购买了工具,推行了新的测试流程;几个月后,工具放在那里成了共享资源,测试流程又涛声依旧,回到原来的模式。

    ——公司实施了自动化测试;然而开发与测试之间,甚至与项目经理之间矛盾重重,出了事情不知如何追究责任;虽然还在勉强维持的自动化测试,但实施的成本比手工测试增加了,工作量比从前更大了,从而造成项目团队人员怨声载道,更怀念起那段手工测试的悠闲岁月,唉!那一场风花雪月的事,既然要结束又何必开始…——自动化测试实施相对比较成功,但或多或少还有些问题,比如工具选择不准确,培训不到位,文档不完备,人员分配不合理,脚本可维护度不高等等,造成一种表面上的自动化测试流程,是一幅空架子,如同山间竹笋,嘴尖皮厚腹中空。

    • 国内软件测试自动化实施不成功原因分析

    ——公司高层意识不到软件测试自动化的重要性;殊不知,其他竞争对手们都大张旗鼓的开展这方面研究和策划的时候,自己还对此持漠视态度,等到整个行业都提高到一个新的层次,那时再着手做,可能就是热锅上的蚂蚁了。

    ——所谓凡事预则立,不预则废。一个软件企业实施测试自动化,绝对不是拍脑袋说干就能干好的,它不仅涉及测试工作本身流程上、组织结构上的调整与改进,甚至也包括需求、设计、开发、维护及配置管理等其他方面的配合。

    ——软件开发是团队工作,在这一领域要尤其注重以人为本;所以人员之间的配合、测试组织结构的设置非常重要,每个角色一定要将自己的责任完全担负起来,这也是减少和解决前述团队矛盾的必要手段。——对开展自动化测试的监督和评估相当重要,也包括对工作产品的检查和人员的考核。一定要将自动化测试全面深入的贯彻到测试工作中,不能敷衍了事,不能做表面工作。这项工作在CMM三级里规范的很好,只可惜我们的很多公司对CMM真的只是“过级”!

    •  正确认识国内未实施软件测试自动化的根源

    目前国内的软件公司,很多还是处于获取资本的原始积累阶段,我们不能说公司领导完全不重视测试,而是测试整体行业都没有被重视起来,这是其一;其二是公司高层有更需要重视的环节,例如寻找客户签订单,或者开发,这些是直接关系公司存亡的命脉性东西。

    即便企业重视测试,如果公司做一番比较全面的评估(在后续的测试自动化引入入条件里,再详细说明),也不一定非要实施自动化测试。笔者认为一些中小软件公司在大刀阔斧推行自动化测试之前,在测试流程管理、测试缺陷流程、测试人员技能培训等方面做工作,这样可以用比较少的成本投入来获取相对较大且长期的收益回报。

    最后,针对普通测试工程师的一些建议,在这样的公司里,其实有着很多意想不到的优越性:

    (一)这样的公司测试如果不正规,那么你就有更大更多的发挥空间。

    (二)你可以单独学习自动化测试技术,自己先试着应用到日常工作的软件项目中。

    (三)你可以直接和开发人员沟通,甚至向他们学习开发技术,这对将来的自动化测试中开发脚本很有好处。

    (四)每个优秀测试工程师的成长都是个循序渐进的过程。我遇到很多测试界的新手向我发牢骚,很惭愧我没有什么可以告诫他们的,只是希望这样的新人克服浮躁情绪,稳扎稳打练好基本功,想成为优秀的测试专家,就要经历这个阶段。

    •  软件测试自动化的引入条件

    如果你的测试部门有意向引入自动化测试,那么首先要从思想上统一认识。

    自动化测试能大大降低手工测试工作,但决不能完全取代手工测试。完全的自动化测试只是一个理论上的目标,实际上想要达到 100% 的自动化测试,不仅代价相当昂贵,而且操作上也是几乎不可能实现。一般来说,一个 40-60% 的利用自动化的程度已经是非常好的了,达到这个级别以上将过大的增加测试相关的维护成本。

    测试自动化的引入有一定的标准,要经过综合的评估,绝对不能理解成测试工具简单的录制与回放过程。实际上,从实现成熟度来说,自动化测试分五个级别:

    级别

    说明

    优点

    缺点

    用法

    一级

    录制和回放 自动化的测试脚本能够被自动的生成,而不需要有任何的编程知识 拥有大量的测试脚本,当需求和应用发生变化时相应的测试脚本也必须被重新录制 当测试的系统不会发生变化时,实现小规模的自动化

    二级

    录制、编辑和回放 减少脚本的数量和维护的工作 需要一定的编程知识;频繁的变化难于维护 回归测试时,用于被测试的应用有很小的变化

    三级

    编程和回放 确定了测试脚本的设计,在项目的早期就可以开始自动化的测试 要求测试人员具有很好的软件技能,包括设计、开发 大规模的测试套件被开发、执行和维护的专业自动化测试

    四级

    数据驱动的测试 能够维护和使用良好的并且有效的模拟真实生活中数据的测试数据 软件开发的技能是基础,并且需要访问相关的测试数据 大规模的测试套件被开发、执行和维护的专业自动化测试

    五级

    使用动作词的测试自动化 测试用例的设计被从测试工具中分离了出来 需要一个具有工具技能和开发技能的测试团队 专业的测试自动化将技能的使用最优化的结合起来

    自动化测试能提高测试效率,快速定位测试软件各版本中的功能与性能缺陷,但不会创造性的发现测试脚本里没有设计的缺陷。测试工具不是人脑,要求测试设计者将测试中各种分支路径的校验点进行定制;没有定制完整,即便事实上出错的地方,测试工具也不会发觉。因此,制订全面、系统的测试设计工作是相当重要的。

    自动化测试能提高测试效率,但对于周期短、时间紧迫的项目不宜采用自动化测试。推行自动化测试的前期工作相当庞大,将企业级自动化测试框架应用到一个项目中也要评估其合适性,因此决不能盲目的的应用到任何一个测试项目中,尤其不适合周期短的项目,因为很可能需要大量的测试框架的准备和实施而会被拖跨。

    实施测试自动化必须进行多方面的培训,包括测试流程、缺陷管理、人员安排、测试工具使用等。如果测试过程是不合理的,引入自动化测试只会给软件组织或者项目团队带来更大的混乱;如果我们允许组织或者项目团队在没有关于应该如何做的任何知识的情况下实施自动化测试,那将肯定会以失败告终。如果软件企业有意向实施自动化测试,那么应该具备什么样的条件才可以引入自动化测试呢,才可以最大可能的减少引入风险,并能够可持续性的开展下去呢?

    •  对企业自身现状的评估分析

    第一,从企业规模上来说,没有严格限制。无论公司大小,都需要提高测试效率,希望测试工作标准化,测试流程正规化,测试代码重用化。所以第一要做到的,就是企业从高层CTO开始,直到测试部门的任何一个普通工程师,都要树立实施自动化测试的坚定决心,不能抱着试试看的态度。一般来说,一个这样的软件开发团队可以优先开展自动化测试工作:测试-开发人员比例合适,比如1:1到1:1.5;开发团队总人数不少于10个。当然,如果你的公司只有三五个测试人员,要实施自动化测试绝非易事;不过可以先让一个、两个测试带头人首先试着开展这个工作,不断总结、不断提高,并和层层上司经常汇报工作的开展情况,再最终决定是否全面推行此事。

    第二,从公司的产品特征来说,一般开发产品的公司实施自动化测试要比开发项目的公司要优越些。原因很简单,就是测试维护成本和风险都小。产品软件开发周期长,需求相对稳定,测试人员可以有比较充裕的时间去设计测试方案和开发测试脚本;而项目软件面向单客户,需求难以一次性统一,变更频繁,对开发、维护测试脚本危害很大,出现问题时一般都以开发代码为主,很难照顾到测试代码。但决不是说做项目软件的公司不能实施自动化测试,当前国内做项目的软件公司居多,有很多正在推行CMM等级标准,这是好事情;只要软件的开发流程、测试流程、缺陷管理流程规范了,推行自动化测试自然水到渠成。

    第三,说说标准化的开发和管理流程。不管是CMM还是ISO,不管是开发流程、测试流程还是缺陷管理流程,这里不能一一阐述,可以参考RUP(Rational Unified Process, Rational 统一过程),可以参考很多业界文献,我只说明一点,也是我们IT从业人员甚至任何从业人员一个很好的工作原则:

    1. 把你想做的写下来(计划管理)
    2. 按照你写下来的去做(行为管理)
    3. 把做的事情记录下来(报告管理)
    4. 出现的问题要设法解决(跟踪管理)

    在测试流程里,这几个要点都一一有所落实;如果你的软件开发团队据此开发软件,那么完全具备实施自动化测试的条件。当然,也许一些公司的测试管理比较混乱,出了问题不知道谁负责,测试人员或开发人员整日碌碌却无为,软件缺陷不胜枚举,那么笔者认为还是首先从管理角度来规范一下公司的开发流程和测试流程吧!

    第四,从测试人员个人素质和角色分配来说,除了有一个CTO级人物做后盾外,还应该有个具有良好自动化测试背景和丰富自动化测试经验的测试主管,不仅在技术方面,更重要的是在今后的自动化测试管理位置起着领导的作用。还要有几个出色的开发经验良好的测试人员,当然也可以是开发工程师,负责编写测试脚本、开发测试框架;他们不需要对产品业务了解深刻,但要具有将软件业务逻辑转化成可测试逻辑的分析能力,属于自动化测试设计者。还有一些测试执行者,他们要对软件产品业务逻辑相当熟练,配合测试设计者完成设计工作,并在执行自动测试时,敏锐的分析和判断软件缺陷。如果你的测试团队具有这样的人员角色雏形,那么具备了实施自动化测试的又一条件。综合分析上述四个条件,企业可以决定是否推行自动化测试;但是为了减少实施风险,我们还要预测到其他潜在的风险,做好事先解决思路。

    •  对企业推行自动化测试的风险分析

    其一是资金风险。虽然你的公司具备实施自动化测试的条件,但如果企业效益不好,还是先扭亏为盈吧。一款正版的测试工具价格庞大,企业要首先考虑资金是否允许购买正版的测试工具软件,所以进行测试工具的成本估算,以及引入自动化测试后组织结构调整等方面的成本估算是很必要的。如果你的公司处在如同前面所言的自动化测试试验阶段,可以使用试用版测试工具。当然具有实力的公司可以按照自身的工作流程自主开发测试工具,本文不考虑这种情况。其二是自动化测试对软件功能类型的切入点的风险。企业开发的产品业务和功能是否需要自动化测试,包括白盒自动化测试、功能自动化测试和性能自动化测试。比如一些公司开发单机版软件,只需要做功能测试,那便不必考虑第三种;有的公司开发简单界面之类的软件,例如搜索引擎,也可不必考虑第二种;而大多数国内公司开发的软件,由于各种原因,一般都不考虑第一种。也有可能公司开发的软件特殊性很强,市场上根本没有支持它的自动化测试工具,此时要另辟蹊径。这种评估相当重要,要根据自身的产品功能特征来综合评估。针对不同阶段采用自动化测试的种种优势,我引用一个表格供读者参考:

    测试阶段

    描       述

    备    注

    单元测试/组件测试

    这个测试工作通常是开发人员的职责,很多不同的方法能够被使用,比如"测试先行",它是一个测试框架,开发人员在编写代码前编写不同的单元测试,当测试通过时,代码也被完成了。 通过使用正式的单元测试,不仅能够帮助开发人员产出更加稳定的代码,而且能够是软件的整体质量更加的好。

    集成测试

    这里的测试工作集中在验证不同的组件之间的集成上。 这种类型的测试通常是被测试系统的更加复杂测试的基础,大量的边缘测试被合并以制造出不同的错误处理测试。

    系统测试

    这种测试是通过执行用户场景模拟真实用户使用系统,以证明系统具有被期望的功能。 这里不需要进行自动化的测试。安装测试、安全性测试通常是有手工完成的,因为系统的环境是恒定不变的。

    其它两种非常重要的测试

    回归测试

    回归测试实际上是重复已经存在的测试,通常如果是手工完成的化,这种测试只在项目的结尾执行执行一到两次。 这里完全有潜力应用自动化的测试,你能够在每次构建完成后执行自动化的回归测试,以验证被测试系统的改变是否影响了系统的其他功能。

    性能测试

    性能测试包括以下不同测试形式:

    - 负载测试

    - 压力测试

    - 并发测试

    -.....

    如果没有自动化的测试工具,你将不能执行通过模拟用户的负载实现的高密集度的性能测试。

    其三是软件自动化测试切入方式的风险。正如前面所言,一定要记住将自动化测试与手工测试结合起来使用,不合理的规划会造成工作事倍功半。首先,对于自动化测试率的目标是 10/90 (10% 的自动化测试和 90% 的手工测试)。当这些目标都实现了,可以将自动化测试的使用率提高。对于何种测试情况下引入自动化测试,何时依然采用手工测试,我们分开阐述。

    一般这样的测试条件下使用自动化测试:

    1. 项目没有严格的时间压力
    2. 具有良好定义的测试策略和测试计划(知道要测试什么,知道什么时候测试)
    3. 对于自动化测试你拥有一个能够被识别的测试框架和候选者
    4. 能够确保多个测试运行的构建策略
    5. 多平台环境需要被测试
    6. 拥有运行测试的硬件
    7. 拥有关注在自动化过程上的资源

    如下条件下是宜采用手工测试:

    1. 没有标准的测试过程
    2. 没有一个测试什么、什么时候测试的清晰的蓝图
    3. 在一个项目中,你是一个新人,并且还不是完全的理解方案的功能性和或者设计
    4. 你或者整个项目在时间的压力下
    5. 在团队中没有资源或者具有自动化测试技能的人
    6. 没有硬件

    其四是企业软件的开发语言风险。当前业界流行的测试工具有几十种,相同功能的测试工具所支持的环境和语言各不相同,这里笔者总结了当前国际上流行的几个软件测试工具生产厂商及一些主要IDE产品,读者可根据参考网址去了解列举工具和更多工具的详细资料。

    生产厂商

    工具名称

    测试功能简介

             

    网址链接

    Mercury

    Interactive

    Corporation

    winrunner 功能测试

        http://www.mercury.com/us/products/         

    Loadrunner 性能测试
    QuickTest Pro 功能测试
    Astra LoadTest 性能测试
    testdirector 测试管理

    IBM

    Rational

    Rational robot 功能测试和性能测试

       http://www-900.ibm.com/cn/software/rational/                      

    products/index.shtml

    Rational xde tester 功能测试
    Rational testmanager 测试管理
    Rational purifyplus 白盒测试
    compuware corporation QARun 功能测试     http://www.compuware.com/products/
    QALoad 性能测试
    QADirecto 测试管理
    DevPartner  Studio Professional Edition 白盒测试
    Segue software SilkTest 功能测试     http://www.segue.com/products/index.asp
    SilkPerformer 性能测试
    SilkCentral  Test/Issue Manager 测试管理
    Empirix e-Tester 功能测试

        http://www.empirix.com/Empirix

        /Web+Test+Monitoring/Testing+Solutions

        Integrated+Web+Testing.html

    e-Load 性能测试
    e-Monitor 测试管理
    parasoft Jtest Java 白盒测试   http://www.parasoft.com/jsp/products.jsp?itemId=12
    C++test C/C++白盒测试
    .test .NET 白盒测试
    RadView WebLOAD 性能测试   http://www.radview.com/products/index.asp
    WebFT 功能测试
    MicroSoft Web Application Stress Tool 性能测试

      http://www.microsoft.com/technet/archive/itsolutions/

      intranet/downloads/webtutor.mspx

    Quest Software Benchmark Factory 性能测试   http://www.quest.com/benchmark_factory/
    Minq Software PureTes 功能测试   http://www.minq.se/products/

    其五还要做时间估算。在评估完前面几项指标后,需要估算实施测试自动化的时间周期,以防止浪费不必要的时间,减少在人员、资金、资源投入上的无端消耗。虽然到测试自动化步入正轨以后,会起到事半功倍的效果,但前期的投入巨大,要全面考虑各种因素,明确实施计划并按计划严格执行,才能最大限度降低风险。

    其六是工作流程变更风险。测试团队乃至整个开发组织实施测试自动化,或多或少会因为适应测试工具的工作流程,带来团队的测试流程、开发流程的相应变更,而且,如果变更不善,会引起团队成员的诸多抱怨情绪;所以应该尽量减少这种变更,并克服变更中可能存在的困难。

    其七是人员培训与变更风险。简单而言,就是测试团队人员的培训具有风险性,例如每个角色的定位是否准确,各角色人员对培训技能的掌握程度是否满意,尤其实施途中如果发生人员变更等风险,都要事先做出预测和相应的处理方案。

    一个企业或软件团队实施测试自动化,会有来自方方面面的压力和风险,但是凭借团队成员的聪明才智和公司高层的大力支持,事先做好评估,做好风险预测,那么可以告诉你一个激动人心的消息:你的团队成功引入了测试自动化!有了测试自动化,我们即可享受它带来的超凡价值和无穷魅力:我们的测试工作变得更简单、更有效,我们工作在一个专家级的团队里,因此我们每天都在享受这种成功的喜悦!关于本文:本文主要分析当前国内软件企业的测试团队现状,并从管理角度分析测试团队实施软件测试自动化时所应考虑的问题,并从几个角度分析实施的风险,最终才可以成功引入自动化测试。在后续文章里,会结合实例讲述如何具体实施测试工作的自动化。感谢我的好朋友pcl 和王威的大力支持,并在百忙中无怨无悔的为文章批点、建议;作者本人才疏学浅,文中难免有欠深刻、全面的地方,望大家批评指正,也希望同行朋友们多多补充、交流

  • 软件错误跟踪处理流程(转载)

    2008-01-06 19:59:21

    软件错误跟踪处理流程

    2007-01-18 09:04:15 / 个人分类:软件缺陷管理

    大型本地化软件测试需要进行充分的测试准备,需要科学的测试流程管理。为了跟踪和控制测试质量,便于管理测试发现的Bug,需要为每一个测试项目配置一个专用缺陷跟踪数据库,以便报告、查询、分类、跟踪、处理和验证错误。

    为了保证发现和报告的错误质量,需要首先由经验丰富的测试人员,在缺陷跟踪数据库中对新发现的错误进行确认,如果确实属于错误,再由错误修复工程师进行修复处理。

    1、软件错误的状态

    新错误(New):测试中新报告的软件缺陷。 更多新信息(New More Info):错误修复工程师认为报告的错误信息不完整,要求错误报告者添加更准确的错误信息。 打开 (Open):错误被确认并分配给相关错误修复工程师处理。 拒绝(Declined):拒绝修改缺陷。包括两种情况: 拒绝-不是错误(Declined-Not Bug):报告的错误不术语错误。 拒绝-重复(Declined-Duplicated):以前已经报告过这个错误,需要指出已经报告过的错误标识编号。 修正(Fixed):错误修复工程师已完成修正,等待测试人员验证。 重新打开(Reopen):没有正确修复的错误,需要进一步修复。 延期(Deferred):不在当前版本修复的错误,以后的版本修复。包括两种情况: 延期-下个版本(Deferred –Next Build):本项目的下一个新版本修复。 延期-下个主要版本(Deferred –Next Main Release):本项目不修复,本软件下一个项目的版本修复。 关闭(Closed):错误已被修复。  
    K;TjPtV!}^.}I14953851Testing软件测试网6HVH'_3n7u^
     2、Bug管理的一般流程

    测试人员提交新的错误入库,错误状态为New。

    高级测试人员验证错误,如果是重复报告的错误,则设置为Declined-Duplicated状态,并指出与哪个已经报个错误重复(注明标识编号ID#)。否则,如果确认是错误,分配给相应的修复工程师,设置状态为Open。如果不是错误,则拒绝,设置为Declined-Not Bug状态。

    错误修复工程师查询状态为Open的错误,如果因为错误的信息不完全,没法重现错误,则设置状态为New More Info;如果不是错误,则设置状态为Declined-Not Bug;如果是错误则修复,设置状态为Fixed。对于当前版本不能解决,准备本项目的下一个新版本处理的错误,要留下处理注释,设置错误为Deferred –Next Build状态。如果只能在软件的下个新项目才能解决,要留下处理注释,设置错误为Deferred –Next Main Release状态。

    对于不能解决和延期解决的错误,不能由软件修复工程师自己决定,一般要通过某种会议(评审会)通过才能认可。

    测试人员查询状态为Fixed的错误,然后验证错误是否已修复,如果已经修复,设置错误的状态为Closed,如没有解决置状态为Reopen。

    下面以一个错误的处理过程为例,给出一般的处理流程图。

    51Testing软件测试网iEwW2y'{!MN K
    51Testing软件测试网*fdbo+Y)Jz
     3、软件错误流程管理要点

    为了保证错误的正确性,需要有丰富测试经验的测试人员验证和确认发现的错误是否是真正的错误,测试步骤是否准确、简洁、可以重复。 软件错误的确认并不总是轻而易举的事情。由于对软件设计具体要求的不了解,对测试报告的个别软件错误,可能无法确认是否属于真正的软件错误,本地化服务商需要与软件供应商交流并确认。 每次对错误的处理都要保留处理信息,包括处理者姓名,时间,处理方法,处理步骤,错误状态,处理注释等。 对错误的拒绝不能由程序员单方面决定,应该由项目经理,测试经理和设计经理共同决定。 对错误延期处理不能由本地户服务商决定,应该由软件供应商决定。 错误修复后必须由报告错误的测试人员验证后,确认已经修复,才能关闭错误。

422/3<123>
Open Toolbar