PART – 02
RECORD
“录制”是
QTP的一个最基本的功能,
测试人员在什么都不会的情况下,通过录制,就能完成一个简单的线性测试脚本。方便,快捷。但是带来的问题是,很多人在接触自动化的时候,也就了解到了自动化是靠的“录制”而成。尤其是开发,或是不懂自动化的测试领导。瞬间你个
自动化测试人员的高大上的光环消失。(一把眼泪一把鼻涕的血泪史啊)
OK,言归正传,录制其实能说的不多,就和录音一样,点击录制,然后进行你的测试,然后,一段脚本生成,简单快捷。但是建议大家尽量不要使用录制,尽量手动添加对象到对象库,然后拖动至专家视图,进行编辑。
关于优缺点
使用纯录制,会有以下,问题:
漏步骤。对一些识别的不好的控件,QTP会显示出现无法录制的情况,后来回放失败,还得一个个查是少了哪个步骤。
对象凌乱。如果你在一个页面上分两次录制,有可能出现 object 、object_2、object_3 的情况,其实属性都一样,其实都是一个东西,但是却记录了很多多余的分支。
名称过长。有的网页的标题很长,录制下来的脚本会把脚本拉的很长,比如录制51testing首页的一个控件后,脚本为:Browser(“51Testing软件测试网-中国
软件测试人的精神家园”).Page(“51Testing软件测试网-中国软件测试人的精神家园”).WebElement(“今日热点”).Click
控件不明确。有时候开发图省事,不会对每个控件做很详细的属性描述,造成脚本出现大量WebEdit1、WebEdit2、WebEdit3…… WebEdit20之类的现象,如果使用录制,你会发现你的脚本几乎没有可读性而言,必须一个个控件重新定位才能确认。
当然了,也不是没有优点:
简单
支持低级录制
综上所述,建议大家手动编写脚本。
然后看一下关于录制的相关设置:
在 Tools 下的 Web Event Recording Configuration 可以对录制的等级进行设置,但是只对于BS架构的系统才能产生作用。
Basic等级下,是不会对鼠标在某对象上停留2秒的情况录制出效果的。
在Options中还有些其他设置,根据自己的需要进行录制设置。
#Fabric#
Python知名开源自动化部署模块Fabric,强烈推荐给各位!(运维,
测试…均可以用它实现无比具有想象力的任务)他主要用于对设备/服务器批量执行任务(同时更换500台服务器的密码、同时更新或者重启500台虚拟机)~安装和使用也极其方便,没有什么中间代码,没有架构,没有内幕!
或许对于批量自动化部署而言,这是一个很大很大的福音。
我们来看一个VPSee提供的案例:
#!/usr/bin/python # -*- coding: utf-8 -*- from fabric.api import * import string from random import choice import socket import paramiko env.user = 'root' env.password = 'root' env.hosts = [ 'grid00', 'grid01', 'grid02', 'grid03', 'grid04', 'grid05'] @task @parallel def passwd(user, passwd=False): with settings(hide('running', 'stdout', 'stderr'), warn_only=True): if isup(env.host): if not passwd: passwd = genpass() sudo("echo -e '%s\n%s' | passwd %s" % (passwd, passwd, user)) def genpass(length=10): return ''.join(choice(string.ascii_letters + string.digits) for _ in range(length)) def isup(host): print 'connecting host: %s' % host timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(1) up = True try: paramiko.Transport((host, 22)) except Exception, e: up = False print '%s down, %s' % (host, e) finally: socket.setdefaulttimeout(timeout) return up |
深圳市的士查询软件(gogo查的后台服务器)
1、现有版本总结
热点区域信息是根据过去半年的历史数据计算得出,短期内属于固定信息,不用做任何改变。现在所用的gogo查的版本中,查询热点区域所用的API,是先在servlet中计算出用户选择区域周围的区域ID,构造出
SQL查询语句,最后从postgresql中读取所需的热点区域信息。
SQL语句如下:
Select regionno from sztable.hotregioninfo where dayofweek=’”+ dayofweek+”’ and hour = ‘”+hour+”’ and regionno in “+sBuilder.toString()+”order by amount desc limit ”+return_region_num+”; |
具体操作可在XGO API程序中看到。
数据库中所存的热点信息,共有800多W条,在SQL查询中需要耗时至少2~3秒,查询效率低下,导致用户体验下降。故在此采用Redis解决查询较慢的问题。
2、热点区域postgresql转Redis
Redis数据库设计:结合原有数据以及查询需求(需要求周边区域中前N大),采用Redis中有序集合的数据结构。用“星期:时间”字符串作为key,共有(7*24=168)个;用相应区域号及在该区域成功打车的次数作为value中的memeber和score。
将热点区域信息从postgresql中导入redis:程序代码在PostToRedis中,ToRedis为程序入口。直接运行即可将数据从postgresql中以1中设计格式导入redis。注:由于读取数据量较大,可能会导致计算机为
java分配的内存空间不够用,应在运行前进行相应设置(Xms)。
3、查询过程
模拟用户查询操作,采用的模式为:用户提交坐标点及第几天、时间,在serrvlet中计算出坐标点所在区域号,根据半径计算出要查询的范围内所有的区域ID,并写入到Redis有序集合T1(临时,只对本次查询有效,查询结束之后即将该集合销毁)中,然后将T1与之前已经存好的168个key、value中相应时间段的集合求交集。Eg:现在为周三,上午十点钟,就与key为3:10的集合求交集,交集结果按照降序排列,将前N区域号提取出来,并根据将区域号转为坐标的算法得到输出结果。
需要注意的是,每次查询在redis中新增加的key,在本次查询结束之后都要进行销毁或者设置存活时间,使系统能够较快的释放掉该key所占用的内存空间,减少累加查询导致过多无效key存在,一定程度上缓解服务器压力。
热点区域查询的API,在程序包HotRegionRedis中。
4、存在弊端
每次查询都要向redis中写入新的数据集合,虽然redis声称每秒中可支持10W次写入操作,但在既有写又有读、高并发的情况下会导致Redis性能下降。不过在相当一段时间内,这种模式可以满足需求。
5、建议
建议之后将热点区域中分区方法改进,结合Geohash算法。(由于要求前N大,暂时无法避免查询操作时向Redis中写入数据)。
某产品每次重启Tomcat都会收到CPU告警信息,重启阶段CPU使用率可以达到80%~90%以上,会持续一段时间回降(具体时间没有考察)。应产品方要求,对该问题进行分析定位。
因线上产品不能随便重启,问题定位阶段使用的是同规格的云主机QA19,该环境上有和线上一致的应用程序,且重启tomcat时,也会有CPU飙高的现象。
负载高的原因:
重启的时候对资源使用情况进行监控,并通过top-H+jstack分析消耗CPU过高的线程堆栈信息。
通过监控重启时的资源使用情况,在qa19这台机器上,重启一次,CPU飙高的持续时间约为50-60s左右。
通过top-H+jstack定位消耗CPU过高的线程,发现有三个:
1.springapplicationContext在web容器中加载过程消耗的资源:(部分堆栈信息) "main" prio=10 tid=0x000000004166f800 nid=0x100f runnable [0x00007fbf42987000] java.lang.Thread.State: RUNNABLE at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206) at org.apache.catalina.startup.Catalina.start(Catalina.java:595) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414) |
2.两个编译线程:
"C2CompilerThread1"daemonprio=10tid=0x00007fec48001800nid=0x13c4runnable java.lang.Thread.State:RUNNABLE "C2CompilerThread0"daemonprio=10tid=0x00000000407c1000nid=0x13c3runnable java.lang.Thread.State:RUNNABLE |
尝试的解决方法:
helloJava的两篇文章中给出了两种配置方法:见:http://hellojava.info/?p=195以及http://hellojava.info/?p=201
尝试加上-XX:+TieredCompilation,期望借助多层编译来缓解这个问题:
在tomcatjvm参数中增加该配置项,资源监控CPU飙高持续时间降低到45s左右,比原来少了10s+,略有效果
尝试加一个-XX:CICompilerCount参数来试试,这个值默认是2,也就是说2个c2的编译线程来进行编译:
因为QA19和线上tomcat应用服务器都是2个核的云主机,所以默认值2应该是最优值,尝试把该值改成1or4,没有起到优化效果。
存在问题:
对于QA19性能测试环境来说,重启后没有其他请求引入,但是线上环境重启后会不断有请求过来,所以CPU飙高的时间会持续时间更长。
对于性能测试环境,重启之后的进行第一次并发测试,前期负载同样会很高,如下图:
同样,在测试开始后通过top-H+jstack分析堆栈信息,分析得到两个原因:
启动各种各样的线程进行处理请求,如AJP线程、和数据通信的线程、和ActiveMQ通信的线程等,会短时间内耗费一些资源
另外,测试刚启动时,"C2CompilerThread1"该线程耗费资源过多,会一段时间内持续在40%~80%的CPU消耗
测试时,增加-XX:+TieredCompilation该参数,对比资源使用情况如下:
并发50个线程时,增加参数之前(左图)和增加参数后(右图)
并发100个线程,增加参数前(左图)和增加参数后(右图)
结论:
可以看出即便有流量引入,-XX:+TieredCompilation该参数也是起到了一定作用,使得飙高的CPU尽快回落。
前段时间,老板要求每天包括晚上要在不同的压力下,且不断重复地运行smoke
test.但是晚上我们不可能就自己动手让我们的
QTP的运行,而且就算是白天也不可能做到在某一个时间点上,自己手动来运行
自动化测试。
那该怎么办呢?可以考虑用Window自带的Schedule来定时触发我们的QTP。但是schedule是无法直接去打开QTP或者去运行VBS,那又该怎么办?我是用下的解决方法与大家共享:
Schedule -> Bat -> VBS -> QTP主函数 -> VBScripts.具体代码如下:
Bat:
------------------------------------
taskkill /im EXCEL.EXE /f taskkill /im wscript.exe /f taskkill /im QTPro.exe /f taskkill /im QTAutomationAgent.exe /f ping -n 3 127.1>nul start C:\AutoTest\TA_AutomationTest\C955\3_QTPScript\0_MainScript\LaunchLoopTest.vbs **************************************************************************** |
LaunchLoopTest.vbs:
----------------------
Dim qtApp Dim qtTest Dim qtResultsOpt Dim GenerateDateTime,TestResult,BakTestResult GenerateDateTime =Replace(FormatDateTime(Date(),2),"/","_") & "-" & Replace(FormatDateTime(Time(),3),":","_") '自定义一个获取当前时间的字符串 TestResult = "C:\AutoTest\TA_AutomationTest\1_Report\ExcelReport\Test_Result.xls" '获得测试结果 BakTestResult = "C:\AutoTest\TA_AutomationTest\1_Report\ExcelReport\Test_Result" & GenerateDateTime & ".xls" Set qtApp = CreateObject("QuickTest.Application") ' 建立QTP的应用对象 qtApp.Launch ' Start QuickTest qtApp.Visible = True ' 让QTP运行过程可见 ' 设置当运行过程中如果出错,抓图。 qtApp.Options.Run.ImageCaptureForTestResults = "OnError" ' 快速运行。 qtApp.Options.Run.RunMode = "Fast" qtApp.Options.Run.ViewResults = False qtApp.Open "C:\AutoTest\TA_AutomationTest\C955\3_QTPScript\0_MainScript\MainScript2", True ' 以只读的方式开打开QTP主函数 ' 为Test设置运行 Set qtTest = qtApp.Test Set qtResultsOpt = CreateObject("QuickTest.RunResultsOptions") ' 建立测试结果 qtResultsOpt.ResultsLocation = "C:\AutoTest\TA_AutomationTest\1_Report\" & GenerateDateTime ' 建立起QTP自动的测试结果路径 'qtResultsOpt.ResultsLocation = "D:\temp2\res1" qtTest.Run qtResultsOpt ' 运行QTP主函数 qtTest.Close ' 关闭主函数 qtApp.Quit ' 退出 Set qtResultsOpt = Nothing ' 释放对象 Set qtTest = Nothing Set qtApp = Nothing Set fso = CreateObject("Scripting.FileSystemObject") fso.MoveFile TestResult, BakTestResult '备份当前运行完脚本后的测试结果 Set fso = Nothing |
图中的 All 栏显示所以的测试,Failed 栏显示没有通过的测试。强大吧,GHUnit。你可以向 GHUnitSampleTest 添加新的测试,比如:
- (void)testSimpleFail { GHAssertTrue(NO, nil); } |
我们可以向 Tests 添加更多测试类,只要该类是继承自 GHTestCase,且其中的测试方法都是无参无返回值且方法名字是以 test 为前缀即可。
OCMock
下面我们来添加 OCMock。
1,我们只能以静态库的方式来添加 OCMock。在 GHUnitTest 目录下新建 Libraries 目录,该目录是与 Tests 目录平级的。下载静态库文件,解压头文件至该目录下。
文件下载:头文件 libOCMock.a ,framework 文件:OCMock framework ,打开下载好的 ocmock-1.77.dmg,拷贝其中的‘Release/Library/Headers/OCMock’ 目录至 Libraries 下。最终目录结构如下:
2,在 GHUnitTest 工程中新建名为 Libraries 的 group,导入libOCMock.a 和目录 OCMock,注意 target 是 Tests。
3,设置 Tests 的 Build Setting。让 Libray Search Paths 包含 $(SRCROOT)/Libraries:
在 Header Search Paths 中增加 $(SRCROOT)/Libraries,并选中 Recursive 选择框。
4,编写 OCMock 测试。向 Tests 工程中添加名为 OCMockSampleTest 的 Objective C class。其内容如下:
OCMockSampleTest.h #import <GHUnitIOS/GHUnit.h> @interface OCMockSampleTest : GHTestCase @end OCMockSampleTest.m #import "OCMockSampleTest.h" #import <OCMock/OCMock.h> @implementation OCMockSampleTest // simple test to ensure building, linking, // and running test case works in the project - (void)testOCMockPass { id mock = [OCMockObject mockForClass:NSString.class]; [[[mock stub] andReturn:@"mocktest"] lowercaseString]; NSString *returnValue = [mock lowercaseString]; GHAssertEqualObjects(@"mocktest", returnValue, @"Should have returned the expected string."); } - (void)testOCMockFail { id mock = [OCMockObject mockForClass:NSString.class]; [[[mock stub] andReturn:@"mocktest"] lowercaseString]; NSString *returnValue = [mock lowercaseString]; GHAssertEqualObjects(@"thisIsTheWrongValueToCheck", returnValue, @"Should have returned the expected string."); } @end |
XCode 内置了 OCUnit
单元测试框架,但目前最好用的测试框架应该是 GHUnit。通过 GHUnit + OCMock 组合,我们可以在 iOS 下进行较强大的单元测试功能。本文将演示如何在 XCode 4.2 下使用 OCUnit, GHUnit 和 OCMock 进行单元测试。
OCUnit
在 XCode 下新建一个 OCUnitProject 工程,选中 Include Unit Tests 选择框,
OCUnit 框架则会为我们自动添加 Unit
Test 框架代码:
XCode 在 OCUnitProjectTests.m 中为我们自动生成了一个 Fail 的测试:
- (void)testExample { STFail(@"Unit tests are not implemented yet in OCUnitProjectTests"); } |
让我们来运行 Test,看看效果:
从图中的红色下划线部分可以看出,测试没有通过,符合预期。我们只要像类 OCUnitProjectTests 一样编写继承自 SenTestCase 类的子类,在其中添加形式如:- (void) testXXX(); 的测试函数既可,注意必须是一个无参无返回类型且名称是以 test 为前缀的函数。
Monkeyrunner为Andriod SDK 嫡亲的
测试工具,功能还是很强大的,但Andriod的测试技术发展比较晚,所以目前国内的教程和例子比较少,很多功能没有发掘出来。
Monkeyrunner的例程google下可以有很多,这里就不在重复了,下面说说大家可能遇到的几个问题,及解决方案。
1. 点击button,选择输入焦点,只能靠坐标来定位,一旦换手机,坐标完全失效了。 解决方案a: 通过device.getProperty("display.width"),device.getProperty("display.height")得到你调试手机的像素,在新的手机中,通过这2个参数的比例关系,可以得到在新手机的X,Y坐标点。
解决方案b:通过view
server查询ID来定位,这种方法是最好的,肯定不会错。但很多手机上view server不
工作,即使被rooted了(可以通过hierarchyviewer.bat来确认view server是否工作). 破解过程有点下复杂,大家可以参考这里,还是可以破解的。http://blog.apkudo.com/tag/viewserver/
from com.android.chimpchat.hierarchyviewer import HierarchyViewer from com.android.monkeyrunner.easy import By from com.android.hierarchyviewerlib.device import ViewNode easy_device.locate(By.id('id/main_button')) easy_device.touch(By.id('id/main_button'), 'downAndUp') |
2. 测试结果的检查中,用图片来比较精确度不高。
很多
测试用例的检查结果中,我们希望同时检查app的界面是不是我们期望的,但通知栏的电池或者弹出个通知消息不好比较,容易导致结果比较失败。
解决方案a:通过OCR技术,可以获取到图片里的文字。python里面有https://code.google.com/p/pytesser/,当然这个是cpython的,monkeyrunner用的是jython, 无法直接调用cpython的模块,OCR里面
java的开源模块很多,jython直接调用java非常方便。
解决方案b:还 是通过view server得到界面上内容
hierarchy_viewer = device.getHierarchyViewer() view_node = hierarchy_viewer.findViewById('id/prompt_text_view') text = view_node.namedProperties.get('mText').toString() |
相信大家对于qtp中的控件的识别都绞尽脑汁了吧。有时间没有必要对所有类型的控件都纠结的。比如一定情况下的webelement控件。
由于开发的框架千差万别,就拿我们公司的框架来说,webelement的操作没有必要去考虑,因为只是由于架构中布局的考虑才有的。
甚至有些webtable类型的控件也是如此。
如下图的 正常用户操作要单击左侧menu中的企业业务才能看到外发加工的业务,进而找到外发加工业务双击才能进入外发加工业务的操作界面,而我们可以根据
控件识别的原理不需要对webelement进行考虑 只需要3层识别思路即可:代码形式如下:
Browser(xxx).Page(xxx).Frame(xxx).Link(“外发加工").Click
版权声明:本文出自 ftdtest 的51Testing软件测试博客:http://www.51testing.com/?15001542
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。
windows 下
方法是:使用Oracle InstantClient连接oracle数据库
1 下载相应的程序,如是10204的instantclient-basic-win32-10.2.0.4.zip (34,742,358 bytes)
或者instantclient-basic-win32-10.2.0.3-20061115.zip
WIN64位系统
2 将Oracle Instatnt Client解压。如,至D:\test\instantclient_10_2
3 环境变量配置: "控制面板"-"系统"-"高级"-"环境变量"-"系统变量"添加
NLS_LANG = AMERICAN_AMERICA.ZHS16GBK(或SIMPLIFIEDCHINESE_CHINA.ZHS16GBK) TNS_ADMIN = D:\test\instantclient_10_2 LD_LIBRARY_PATH = D:\test\instantclient_10_2 SQLPATH = D:\test\instantclient_10_2 Path变量结尾添加;D:\test\instantclient_10_2 |
4 在D:\test\instantclient_10_2中用添加如下内容的文件,文件名为tnsnames.ora
5 可以下载单独的Oracle SDK 和Oracle SQL PLUS到安装目录中,解压即可运行
附ORA文件内容与格式
tnsnames.ora #D:/instantclient_10_2/tnsname.ora ORCL = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST =192.168.0.47)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = dedicated) (SERVICE_NAME = mydb1) ) ) |
如果执行完以上步骤之后报错:
ORA_12705:Cannot access NLS data files orinvalid environment specified的错误
则执行NLS_LANG = AMERICAN_AMERICA.ZHS16GBK(或SIMPLIFIEDCHINESE_CHINA.ZHS16GBK)
的时候替换另一种字符集
linux下
1、 去官网下载安装包
比如对应11gr2的
oracle-instantclient11.2-basic-11.2.0.1.0-1.i386.rpm oracle-instantclient11.2-devel-11.2.0.1.0-1.i386.rpm oracle-instantclient11.2-sqlplus-11.2.0.1.0-1.i386.rpm |
2、 copy到linux上执行安装
rpm -ivh XXX.rpm
3、 配置环境变量
编辑vi .bashrc,追加
export ORACLE_HOME=/usr/lib/oracle/11.2/client export TNS_ADMIN=$ORACLE_HOME/network/admin export NLS_LANG='simplified chinese_china'.ZHS16GBK export LD_LIBRARY_PATH=$ORACLE_HOME/lib export PATH=$ORACLE_HOME/bin:$PATH |
手动创建目录$ORACLE_HOME/network/admin
并在这个目录下创建编辑文件tnsnames.ora
添加链接串
ORCL = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.9.76)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = orcl) ) ) |
4、 执行命令source .bashrc生效修改内容,测试连接sqlplus
5、 如果出现sqlplus: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory
则安装相应包即可
LTest基本对
接口测试的基本思路是:将接口请求及对应的返回值记录下来当作
测试用例,便可回归测试接口。这里涉及到2个内容:
1. 记录请求与返回值,录入或者录制接口,这里可以用mock来解决。
2. 根据记录结果,执行测试用例。
初步的设计如下:
LTest-Mock,基于Http协议的mock,能分析和录制Http协议上的API。如下: