日历
| |||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
| 1 | 2 | 3 | 4 | 5 | 6 | ||||
| 7 | 8 | 9 | 10 | 11 | 12 | 13 | |||
| 14 | 15 | 16 | 17 | 18 | 19 | 20 | |||
| 21 | 22 | 23 | 24 | 25 | 26 | 27 | |||
| 28 | 29 | 30 | |||||||
搜索标题
我的好友
最新留言
最新评论
统计信息
- 访问量: 7030
- 日志数: 121
- 建立时间: 2008-02-26
- 更新时间: 2008-08-20
我的最新日志
-
如何修改QTP脚本默认打开/保存的目录?
2008-8-20
By Wiston Li
QTP脚本开发,每次都要打开文件夹,却总是默认从C:\Program Files\Mercury Interactive\QuickTest Professional\Tests来找文件,
但基于框架开发的脚本,是保存在src\case里的,今天捣腾了一下,其默认的目录是可以修改的,
修改注册表:
1, HKEY_current_user\software\MI\QTP\mictest\TestsDirectory
2, HKEY_local_machine\software\MI\QTP\mictest\TestsDirectory
修改为:
D:\svn\10_QAArchitech_scrīpts\src
重启QTP,看一下,再打开文件是不是已经修改自定义的目录?是不是操作使用起来很爽。。。
节约个几秒是几秒,不要把心情弄槽。。。
-
jmeter应用指南(脚本设计、场景设置、查看监控)
2008-8-19
by jack
一直以来都希望能有一套能够基本满足常规性能测试需求,并有效产生报表的工具,用以部分替代LoadRunner的依赖。所以专门针对jmeter进行了评估和研究,在评估过程中完成了一份使用说明;经过代码研究,对jmeter进行了改进,主要是增加了linux资源监控功能和报表功能。由于时间仓促,对增加的代码只进行了单元测试。
可用于面向B/S WEB应用测试的工程师使熟悉jmeter使用,章节安排按照脚本设计、场景设置、查看监控三部分顺序组织。十四、十五两章内容是关于增进的监控和报表功能的,不适用于apache网站提供的原jmeter。
内容主要是使用上的,不涉及性能测试分析的内容。
Jmeter应用指南.pdf
(2008-08-19 11:13:16, Size: 1.45 MB, Downloads: 0) -
测试工具loadrunner扩展开发的一点感想
2008-8-13
by liangjz
最近在应用VC6,大量采用win32 api扩展Loadrunner8.0/8.2的一些外围功能,做到自动调节面向资源消耗目标的合适(临界)并发数,碰到了几个相当棘手问题。
如
(1) 在loadrunner controller design 界面上编程实现更改并发用户数
(2) 确保安全停止在运行的loadrunner但不破坏已存在结果文件,如res.lrr等等
由于没有loadrunner源代码以及很detail的介绍Loadrunner内部结构的资料,为了突破这些点,耗费了相当的力气。
如果我们换成对JMeter的外围扩展内,在一堆结构清晰的代码面前,突破这些功能难度可能陡降
经过这些天的尝试,对扩展黑盒工具的难度有一个更加清晰的认知,实践才知道水有多深
下面简单介绍下如何做到编程更改loadrunner并发数的几个思路
1)EnumWindows/GetWindowText 结合spy++,硬编码检索到窗口层次关系,获取classname=GridControl、windows caption=GridClass的控件,然后利用grid控件的行、列改写数据。
可是classname=GridControl仅仅是注册窗口时的一个友好名字,并非真正实现类。这个实现这个控件的类是什么呢? 这下卡壳了。
从安全工程师哪边拿到LookingGlass.exe、FABERTOYS(进程管理).EXE等工具,企图嗅探出ocx但未果。
其他难度、实现成本比较高、非常笨拙操控grid的方式还有: 利用IDAPro动态调试或者进程注入修改对应内存内容,这个有时间再琢磨下。
2)修改loadrunner 场景设计文件.lrs的GroupChief内容
由于loadrunner controller designed 界面大量选项,每一个选项可能都对loadrunner结果产生敏感影响。为了弄清楚每一个选项对应文件内容,很土也很管用的方法
一次只更改一个,然后对比变化,最后跟踪发现groupchief 段才是loadrunner 并发数关键所在。
lrs文件格式不是Ini 格式,是mercury自有格式,我们要做的事情就是fgets逐行读取,然后填充入自定义的数据结构(偶采用了链表)。
增加、删除修改并发数就是减少ChiefSettings所在的段,最后用fwrite将数据结构回填。
最后第二个方法成功实现需求。
不过综合权衡下,如果loadrunner升级lrs数据结构,第二种方法是相当脆弱的。
哈,要是偶遇一个mercury工具研发工程师问到grid控件实现类并把头文件和lib给我,然后彻底解决这个问题该多好啊
-
标准时间和格式化时间的转换-awk
2008-8-12
date命令和strftime函数,扩展clock、hwclockdate命令:print or set the system date and time
strftime函数:awk调用了类型为time_t的c函数库 strftime([format [, timestamp]])
功能:Formats timestamp according to the specification in format.
systime函数:同上,Returns the current time of day as the number of seconds since the Epoch systime()
譬如:毫秒级时间戳->格式化时间:echo 12879350 | awk '{print strftime("%F %T", $0)}'
格式化时间->毫秒级时间戳:date -s把当前时间设置成special time,然后 awk '{print systime()}'即可
-
使用samba的提高工作效率
2008-8-12
samba
service smb stop/start/status/etc/samba/smb.conf然后我们把下面这段写入smb.conf中;
[global]
workgroup = LinuxSir
netbios name = LinuxSir05
server string = Linux Samba Server TestServer
security = share
[linuxsir]
path = /opt/linuxsir
writeable = yes
browseable = yes
guest ōk = yes
注解:[global]这段是全局配置,是必段写的。其中有如下的几行;
workgroup 就是Windows中显示的工作组;在这里我设置的是LINUXSIR (用大写);
netbios name 就是在Windows中显示出来的计算机名;
server string 就是Samba服务器说明,可以自己来定义;这个不是什么重要的;
security 这是验证和登录方式,这里我们用了share ;验证方式有好多种,这是其中一种;另外一种常用的是user的验证方式;如果用share呢,就是不用设置用户和密码了;[linuxsir] 这个在Windows中显示出来是共享的目录;
path = 可以设置要共享的目录放在哪里;
writeable 是否可写,这里我设置为可写;
browseable 是否可以浏览,可以;可以浏览意味着,我们在工作组下能看到共享文件夹。如果您不想显示出来,那就设置为 browseable=noguest ok 匿名用户以guest身份是登录;
第二步:建立相应目录并授权;
在linux下:smbclient -L 192.168.1.101
在window下:\\192.168.1.101注意iptables stop注意修改/etc/samba/smb.conf下的host allow的IP设 -
tcpdump在服务器维护方面的使用
2008-8-12
在表达式中一般如下几种类型的关键字:
第一种是关于类型的关键字,主要包括host,net,port
例如 host 210.27.48.2, 指明 210.27.48.2是一台主机
net 202.0.0.0,指明202.0.0.0是一个网络地址
port 23 指明端口号是23。如果没有指定类型,缺省的类型是host。
第二种是确定传输方向的关键字,主要包括src,dst,dst or src,dst and src,这些关键字指明了传输的方向。
举例说明,src 210.27.48.2 ,指明ip包中源地址是 210.27.48.2 , dst net 202.0.0.0 指明目的网络地址是202.0.0.0。
第三种是协议的关键字,主要包括fddi,ip,arp,rarp,tcp,udp等类型。
还有三种逻辑运算,取非运算是not,! ;与运算是and,&& ;或运算是or ,||
example:
1. tcpdump port 23 and \( host 192.168.1.101 \) : 过滤主机192.168.1.101(不管src还是dst)且端口为23的包
2. tcpdump host 192.168.1.1: 截获所有192.168.1.1主机收到的和发出的所有的包
3. tcpdump ip host 210.27.48.1 and ! 210.27.48.2: 获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包
4. tcpdump host 210.27.48.1 and \(210.27.48.2 or 210.27.48.3 \): 截获主机210.27.48.1 和主机210.27.48.2或210.27.48.3的通信
5. 先 tcpdump 一看,信息太多。 想了想我要做的是什么,主要是想看看,局域网中访问internet那些东西,跟那些机器有连接,而且要探测不明链接。从而可以发现是否有木马,病毒一些在作怪! tcpdump dst net not 192.168.123.0/24 不监视跟网内机子的链接,过滤很多信息。迅速进入主题, 不想看发邮件的情况,一般的80网页访问,domain访问,还有要排除网内已有服务器的一些端口。
-
异常对象识别(Watir应用解决方案)
2008-8-11
5. 异常对象识别(Watir应用解决方案)
Watir基于处理,继承于web document的对象提供较好的支持方法,但相对于处理windows对象较弱. 就目前从各网站收集的对象来看, 基本上,对于在IE实例对象打开的web标准对象
能够成功识别与操作,其它的脱离当前IE窗口,打开的所有弹出框都不能正常识别。其中,弹出框对象占有异常对象识别中很大一部分。
目前碰到的弹出框, 我把他们分为三大类型:
1, Alerts 警告作用,如:sorry, 当前用户没有权限操作
2, Confirm 需要操作按钮, 如:你确认要删除当前记录?
3, Prompt+ select +confirm 需要用户输入,操作查询或点击, 最后确认, 如:Download/upload (浏览+选择文件)下面给出,上面几种弹出框watir实现识别与操作的方法,
5.1. 弹出框基于autoIT + 线程实现方式此种方法,对于第一、二种弹出框操作较有效,
因点击某个link/button等对象,而弹出的窗口(大部分弹出框可应用此种方式来实现。)1, 定义方法
def check_for_popups
autoit = WIN32OLE.new('AutoItX3.Control')
#
# Do forever - assumes popups could occur anywhere/anytime in your application.
loop do
# Look for window with given title. Give up after 1 second.
ret = autoit.WinWait('消息 -- 网页对话框', '', 1)
#ret = WinActivate("Microsoft Internet Explorer", "")
#autoit.ControlClick("Microsoft Internet Explorer", "", "[CLASS:Button; INSTANCE:1]", 2)
puts(ret)
#
# If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
if (ret==1) then autoit.Send("{Enter}") end
#
# Take a rest to avoid chewing up cycles and give another thread a go.
# Then resume the loop.
sleep(3)
end
end
2, 程序体代码ie.button(:name, "signin").click_no_wait
sleep(20)
$popup = Thread.new { check_for_popups } # start popup handler
at_exit { Thread.kill($popup) }
5.2. Call 另一ruby文件对于第二种弹出框,像安全警告点击, 并不通过操作与点击任何对象, 即呈现弹出窗口。
我尝试用3.1方法来实现,不成功。用下面方法替代:
1, 在watir/WindowHelper.rb文件中增加方法def push_security_alert_yes_cn
@autoit.WinWait "安全警报", ""
@autoit.Send "{TAB}"
@autoit.Send "{TAB}"
@autoit.Send "{SPACE}"
End2, 定义另一调用文件 tmp.rb
require 'watir/WindowHelper'
helper = WindowHelper.new
helper.push_security_alert_cn_yes
3, 在打开安全URL之前,启动调用ruby文件require 'rubygems'
require 'watir' # the watir controller
require 'win32ole'
require 'watir/WindowHelper'
Thread.new{system('ruby c:\tmp.rb')} #你定义tmp文件存放路径
ie = Watir::IE.new
ie.goto("http://www.alipay.com.cn/")
5.3. 修改框架底层此种方法,针对弹出框3.
举例一, 上传下载文件
1, 修改底层代码input_elements.rb文件,
类 FileField中, 方法set.
为了支持中文,有一句替换修改为:system("rubyw -e \"require 'win32ole'; @autoit=WIN32OLE.new('AutoItX3.Control'); waitresult=@autoit.WinWait '选择文件', '', 15; sleep 1; if waitresult == 1\" -e \"@autoit.ControlSetText '选择文件', '', 'Edit1', '#{setPath}'; @autoit.ControlSend '选择文件', '', 'Button2', '{ENTER}';\" -e \"end\"")
2, 定义方法
def save_file(filepath)
ai = WIN32OLE.new("AutoItX3.Control")
ai.WinWait("文件下载", "", 5)
ai.ControlFocus("文件下载", "", "保存(&S)")
sleep 1
ai.ControlClick("文件下载", "", "保存(&S)", "left")
ai.WinWait("另存为", "", 5)
sleep 1
ai.ControlSend("另存为", "", "Edit1",filepath)
ai.ControlClick("另存为", "", "保存(&S)", "left")
ai.WinWait("下载完毕", "", 5)
ai.ControlClick("下载完毕", "", "关闭")
end
3, 程序体代码:
ie.file_field(:name, "xlsfile").set("c:\\samenameobject.html")
#上传你所指定的文件或
ie.span(:text, "导出Excel表").click_no_wait
save_file("C:\\abc.xls")
#下载到你所指定的路径针对弹出框3, 需要用户介入查询并操作:
举例二, 中供crm中类目与客户选择的弹出框,与第一种实现方式不同在于,
用到autoit中WinActivate与ControlClick方法,
require 'rubygems'
require 'watir' # the watir controller
require 'watir/WindowHelper'
require 'win32ole'
def check_for_popups
autoit = WIN32OLE.new('AutoItX3.Control')loop do
ret = autoit.Winwait("选择 -- 网页对话框", "", 1)
puts ret
if (ret==1) then
autoit.WinActivate("[CLASS:Internet Explorer_TridentDlgFrame]", "")
autoit.Send("{TAB}")
autoit.Send("{TAB}")#autoit.Send("湖州")
#autoit.Send("{ASC 2709}")
#autoit.SendUnicode("a")
#autoit.ClipPut ("杭")
#autoit.ClipGet
#autoit.ToolTip "This is a tooltip杭州", 0, 0
#autoit.Sleep 2000
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{Enter}")autoit.WinActivate("[CLASS:Internet Explorer_TridentDlgFrame]", "")
autoit.ControlClick("选择 -- 网页对话框", "", "[CLASS:Internet Explorer_TridentLstBox; INSTANCE:2]", 2)autoit.Send("{TAB}")
autoit.Send("{Enter}")autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{TAB}")
autoit.Send("{Enter}")
end
sleep(3)
endend
ie=Watir::IE.new
ie.goto("http://10.2.6.4:5100/bin/member/signin")
#ie.goto("http://10.2.6.4:5100/")
#ie.element_by_xpath("//span[contains(text(), 'Main Road Nijmegen')]").clickie.text_field(:name, "id").set("mhl1805")
ie.text_field(:name, "password").set("zxcvbnm")ie.button(:name, "signin").click
ie.frame(:name, "left").link(:url, "http://10.2.6.4:5100/v3/help_cust.htm").clickie.frame(:name, "left").link(:text, "新签中供客户").click
# start popup handler
ie.frame(:name, "right").frame(:name, "rtop").button(:value, "选择客户").click_no_wait
sleep(20)$popup = Thread.new { check_for_popups }
at_exit { Thread.kill($popup) }
针对第三种popup window, 如果需要与用户交互,且需要输入中文时,若用autoit sendkey对待中文支持(但官方文档说支持中文输入, 网上有不少人和我遇到同样问题),尚没有找到有效方案,有待进一步跟进。
除上述弹出框需要特殊处理外,watir中也有一些扩展tag,或第三方控件需要特殊处理的,
像:
5.4. web HTML编辑器
中文站的html编辑器提供: 操作ID或name操作起来较方便直接require 'rubygems'
require 'watir' # the watir controller
require 'watir/WindowHelper'
require 'win32ole'
ie=Watir::IE.newie=Watir::IE.attach(:title, /阿里助手/)
ie.text_field(:name, "_fmo.a._0.s").set("mhl1805")
ie.document.getElementByid("_editor").contentWindow.focus()
ie.send_keys("abcsadfasfd")
但也碰到有些web页面,不提供任何ID,只能用autoIT方法来send tab实现
require 'rubygems'
require 'watir' # the watir controller
require 'watir/WindowHelper'
require 'win32ole'
ie=Watir::IE.new#ie=Watir::IE.attach(:title, /Alibaba/)
ie.goto('http://us.my.alibaba.com/product/buyoffer/post_buying_lead.htm')
ie.text_field(:name, "_fmp.bu._0.su").set("mhl1805")
ie.text_field(:name, "_fmp.bu._0.su").set("中国人")
ie.checkbox(:id, "detailDesc").set
ie.checkbox(:id, "detailDesc").focus()
ie.send_keys("\t"*9)
ie.send_keys('Hello Worldabcdef')
5.5. 对象识别其它常用TAG内置方法引用如:IE.div , ie.span, ie.cell, ie.table方法,可以实现点击操作,取值操作等.
另外提供QTP类似描述性编程,同类型对象统计:ie.buttons.each { |b| puts b.to_s }
puts ie.checkboxes.length
puts ie.links.length
puts ie.buttons.length等等对于常用的innertext属性, 在watir中已经封装到方法,可以直接引用。如:
ruby在对象识别底层,封装了innertext
实现,调用方法text即可:
如:puts ie.div(:id, "intelligentWord").link(:id, index.to_s).text最后:返回文本与源代码,用下面方法:
puts ie.text()
puts ie.html()5.6. 识别对象正则表达式支持
当然,ruby提供强大的正则表达式支持,如:属性标识正则
ie=Watir::IE.attach(:title, /Alibaba/)Ruby的正则表达式以"//"作为基本框架,表达式内容位于"/"之间。表达式返回一个RegExp的对象。
表达式的一般规则:
/a/匹配字符a。
/\?/匹配特殊字符?。特殊字符包括^, $, ? , ., /, \, [, ], {, }, (, ), +, *.
.匹配任意字符,例如/a./匹配ab和ac。
/[ab]c/匹配ac和bc,[]之间代表范围。例如:/[a-z]/ , /[a-zA-Z0-9]/。
/[^a-zA-Z0-9]/匹配不在该范围内的字符串。
/[\d]/代表任意数字,/[\w]/代表任意字母,数字或者_,/[\s]/代表空白字符,包括空格,TAB和换行。
/[\D]/,/[\W]/,/[\S]/均为上述的否定情况。关于正则其它用法,请参照《watir技术集锦》
5.7. 最后攻略总之,对于对象识别与操作,要借助于上述文档中的, 灵活运用autoit, xpath与异常对象操作方法。对于watir不支持的windows控件,想到第一个方法,就是采用第三方autoit技术,来模拟键盘或鼠标操作。
对于操作web对象,watir不支持特殊tag,除了扩展其底层代码外,只能深深研究一下xpath了.
最后,再搞不定,就只能到watir group里咨询高人了,呵呵。尚没有碰到其它更好方法。。。
-
MSXML6 SDK解析中文XML文件
2008-8-10
1.1 下载msxml6_SDK.msi安装
默认安装在C:\Program Files\MSXML 6.0\
1.2 在vc6上建立编译环境
Preprocessor 编译加入 Additional include directorie加入C:\Program Files\MSXML 6.0\inc
LINK module加入: msxml6.lib
Link Additional library path加入:C:\Program Files\MSXML 6.0\lib
1.3 解决vc6 link错误问题
msxml6.lib(msxml6_i.obj) : fatal error LNK1103: debugging information corrupt; recompile module
参见 :
All I get from Google is that VS6 doesn't work with platform SDK's later than february 2003.
必须采用release版本编译、链接才成功。(build->set active project configuration->win32 release)
1.4 汉语问题
//解决汉语问题
setlocale(LC_ALL,"chinese-simplified");
1.5 源代码
#include <objbase.h>
#include <msxml6.h>
#include <stdio.h>
#include <windows.h>
#include <stdarg.h>
#include <locale.h>
#include <AtlBase.h>
#import <msxml6.dll> raw_interfaces_only
// Macro that calls a COM method returning HRESULT value:
#define HRCALL(a, errmsg) \
do { \
hr = (a); \
if (FAILED(hr)) { \
dprintf( "%s:%d HRCALL Failed: %s\n 0x%.8x = %s\n", \
__FILE__, __LINE__, errmsg, hr, #a ); \
goto clean; \
} \
} while (0)
// Helper function that put output in stdout and debug window
// in Visual Studio:
void dprintf( char * format, ...)
{
static char buf[1024];
va_list args;
va_start( args, format );
sprintf(buf, format, args);
vsprintf(buf, format, args );
va_end( args);
OutputDebugStringA( buf);
printf("%s", buf);
}
// Helper function to create a DOM instance:
IXMLDOMDocument3 * DomFromCOM()
{
HRESULT hr;
IXMLDOMDocument3 *pxmldoc = NULL;
HRCALL( CoCreateInstance(CLSID_DOMDocument60,
NULL,
CLSCTX_INPROC_SERVER,
//__uuidof(IXMLDOMDocument),
IID_IXMLDOMDocument3,
(void**)&pxmldoc),
"Create a new DOMDocument");
HRCALL( pxmldoc->put_async(VARIANT_FALSE),
"should never fail");
HRCALL( pxmldoc->put_validateOnParse(VARIANT_FALSE),
"should never fail");
HRCALL( pxmldoc->put_resolveExternals(VARIANT_FALSE),
"should never fail");
return pxmldoc;
clean:
if (pxmldoc)
{
pxmldoc->Release();
}
return NULL;
}
int Get_nodeValue(IXMLDOMElement * pRoot , char * tagName,char *ret_text)
{
USES_CONVERSION;
IXMLDOMNodeList * pNodeList = NULL;
IXMLDOMNode * pNode = NULL;
HRESULT hr;
BSTR bstr = NULL;
hr=pRoot->getElementsByTagName(_bstr_t(tagName),&pNodeList) ;
if (FAILED(hr))
return -1;
//取第一个满足条件的
hr= pNodeList->get_item(0,&pNode);
if (FAILED(hr))
return -1;
hr=pNode->get_text(&bstr);
if (FAILED(hr))
return -1;
//dprintf("v=%s\n",W2A(bstr));
sprintf(ret_text,W2A(bstr));
return 0;
}
int main(int argc, char* argv[])
{
/*
HRESULT hr;
IXMLDOMDocument3 *pXMLDoc = NULL;
CoInitialize(NULL);
hr = CoCreateInstance(CLSID_DOMDocument60,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument3,
(void**)&pXMLDoc);
if (FAILED(hr))
{
printf("Error code: %x\n", hr);
}
*/
USES_CONVERSION;
IXMLDOMDocument3 *pXMLDom=NULL;
IXMLDOMParseError *pXMLErr=NULL;
BSTR bstr = NULL;
VARIANT_BOOL status;
VARIANT var;
HRESULT hr;
IXMLDOMElement * pRoot = NULL;
VARIANT_BOOL isHasChild=VARIANT_FALSE;
long listLen=0;
long i=0;
char ret_scrīpttext[48]={0};
char ret_steptime[48]={0};
char sz_xmlFile[]="lr.xml";
CoInitialize(NULL);
//解决汉语编码问题
setlocale(LC_ALL,"chinese-simplified");
pXMLDom = DomFromCOM();
if (!pXMLDom)
goto clean;
VariantInit(&var);
V_BSTR(&var) = SysAllocString(_bstr_t(sz_xmlFile));
V_VT(&var) = VT_BSTR;
HRCALL(pXMLDom->load(var, &status), "");
if (status!=VARIANT_TRUE) {
HRCALL(pXMLDom->get_parseError(&pXMLErr),"");
HRCALL(pXMLErr->get_reason(&bstr),"");
dprintf("Failed to load DOM from stocks.xml. %S\n",
bstr);
goto clean;
}
HRCALL(pXMLDom->get_xml(&bstr), "");
dprintf("XML DOM loaded from stocks.xml:\n%S\n",bstr);
HRCALL( pXMLDom->get_documentElement(&pRoot) ,"get_documentElement");
Get_nodeValue(pRoot,"scrīpt",ret_scrīpttext);
Get_nodeValue(pRoot,"steptime",ret_steptime);
printf("%s %d",ret_scrīpttext,atoi(ret_steptime));
/*
HRCALL(pNode->get_nodeValue(&value),"get_nodeValue");
USES_CONVERSION;
dprintf("v=%s\n",OLE2A(value.bstrVal));
SysFreeString(bstr);
*/
clean:
if (bstr) SysFreeString(bstr);
if (&var) VariantClear(&var);
if (pXMLErr) pXMLErr->Release();
if (pXMLDom) pXMLDom->Release();
CoUninitialize();
return 0;
}
Lr.Xml文件如下(notepad保存为ascii格式):
<?xml version="1.0" encoding="GB2312"?>
<root>
<scrīpt type="string">d:\工程\1.lrr</scrīpt>
<steptime>30</steptime>
</root>
-
jmeter利用http代理服务器组件录制脚本
2008-8-07
by jack
在“工作台”添加“HTTP代理服务器”

端口:
代理服务器的端口,默认8080,可自行修改,但不要与其它应用端口冲突
目标控制器:录制的脚本存放的位置,可选择项为测试计划中的线程组
分组:
对请求进行分组。“分组”的概念是将一批请求汇总分组,可以把url请求理解为组。
“不对样本分组”:所有请求全部罗列
“在组间添加分隔”:加入一个虚拟的以分割线命名的动作,运行同“不对样本分组”,无实际意义
“每个组放入一个新的控制器”:执行时按控制器给输出结果
“只存储每个组的第一个样本”:对于一次url请求,实际很多次http请求的情况,这个选项很好用,因为我们常常是不关心后面的那些请求的。
记录HTTP信息头:
录制request的head信息
添加断言:
录制时加入空的检查点(需自行填写内容)
Regex matching:
录制时加入空的正则匹配(需自行填写内容)
在浏览器中录制
启动HTTP代理服务器后,打开浏览器(IE,Firefox,Opera等),添加代理,地址填写本机ip或host name,端口填写刚刚设置的代理端口(本例中8080),在浏览器中进行正常网页浏览,即可录制下对应的http请求。IE上的设置:
-
自动化友好、干净停止loadrunner运行场景的源代码
2008-8-01
最近针对loadrunner做功能扩展,其中一个环节是:尽力正常点击stop停止,如经过处理无法停止,则干净停止loadrunner进程。
loadrunner手册有命令行方式启动wlrun.exe进程的方式,但没有停止wlrun.exe的方式。本方法用win32实现友好停止Loadrunner场景。
窗口层次关系可以用spy++察看 .
测试程序的方法,启动一个loadrunner运行场景。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <locale.h>
#include <windows.h>
#include <vdmdbg.h>
typedef struct
{
DWORD dwID ;
DWORD dwThread ;
} TERMINFO ;BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;
DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
{
HANDLE hProc ;
DWORD dwRet ;// If we can't open the process with PROCESS_TERMINATE rights,
// then we give up immediately.
hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
dwPID);if(hProc == NULL)
{
return FALSE ;
}// TerminateAppEnum() posts WM_CLOSE to all windows whose PID
// matches your process's.
EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;// Wait on the handle. If it signals, great. If it times out,
// then you kill it.
if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
dwRet=(TerminateProcess(hProc,0)?TRUE:FALSE);
else
dwRet = TRUE ;CloseHandle(hProc) ;
return dwRet ;
}
BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
{
DWORD dwID ;GetWindowThreadProcessId(hwnd, &dwID) ;
if(dwID == (DWORD)lParam)
{
PostMessage(hwnd, WM_CLOSE, 0, 0) ;
}return TRUE ;
}//MyEnumWindow 函数本身只能枚举最top-level的窗口。
//嵌套的窗口自己枚举//这里用spy++观察层次结构
//模拟用户鼠标操作停止loadrunner的过程
BOOL CALLBACK MyEnumWindow(HWND hWnd, LPARAM lParam)
{
char sz_text[MAX_PATH]={0};
int len =0;
char * p_title = NULL;
int ret;
HWND child_hWnd=NULL,dialog_hWnd=NULL,next_hWnd=NULL;
int i=0;
BOOL isFound = FALSE;
int try_time=10;
WINDOWINFO winInfo;
DWORD dwID ;
p_title=(char*)lParam;len= GetWindowText(hWnd, sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
if (strstr(sz_text,"LoadRunner"))
printf("%s\r\n",sz_text);
child_hWnd = hWnd;
if(strstr(sz_text,p_title))
{
while(1)
{
//获取子窗口
child_hWnd=GetWindow(child_hWnd, GW_CHILD);
//恶意关闭loadrunner时,窗口是否为存在?防止死循环。
if(child_hWnd!=NULL)
{
len= GetWindowText(child_hWnd, sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
if (!strcmp(sz_text,"&Start Scenario"))
{
//获取兄弟窗口
next_hWnd=GetWindow(child_hWnd, GW_HWNDNEXT);
len= GetWindowText(next_hWnd,sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
if (!strcmp(sz_text,"S&top") )
{
//找到停止的窗口
isFound =TRUE;
break;
}
}
}
else //child_hWnd!=NULL
{
break;
}
} //while
if (FALSE ==isFound )
{
//失败退出
printf("not found S&top!\r\n");
return TRUE;
}//尝试投递try_time次。
//for(i=0;i < try_time; i++)
while(1)
{//SendMessage(next_hWnd, BM_CLICK,0, 0);
PostMessage(next_hWnd, BM_CLICK,0, 0); // 这里不能用SendMessage,否则阻塞进程
dialog_hWnd = FindWindow("#32770", "LoadRunner Controller");
if (!dialog_hWnd)
{
printf("Find dialog error. ret=%d\r\n",GetLastError());
}
else
{
//if (IsWindowVisible(dialog_hWnd))
//{
len= GetWindowText(dialog_hWnd, sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
printf("GetWindowText return %s\r\n",sz_text);
//查找对话框上按纽
child_hWnd = FindWindowEx(dialog_hWnd,0,"Button","确定");
if (!child_hWnd)
{
printf("确定 button ret=%d\r\n",GetLastError());
continue;
}SendMessage(child_hWnd, BM_CLICK,0, 0);
ret = GetLastError();
if (ret)
{
printf("button error. ret=%d\r\n",ret);
}
else
{
printf("正常停止loadrunner!\r\n");
}
//经过如上处理后
printf("destroywindows\r\n");
Sleep(10);
//强行关闭loadrunner相关进程
GetWindowThreadProcessId(hWnd, &dwID) ;
TerminateApp(dwID,10);
return FALSE;
//}
} //(!prev_hWnd)
}//for
}return TRUE;
}
int stop_loadrunner()
{char sz_title[]="Mercury LoadRunner Controller ";
// char sz_title[]="S&top";
if (EnumWindows(MyEnumWindow,(long) sz_title) )
printf("failed,errno=%d",GetLastError());
}
void main(){
stop_loadrunner();
}






