2010年12月29日星期三

Sikuli X 之 Region类相关说明

PSMRL:指可以把模式(Pattern)、指向图像文件名的字符串或者表示纯文本的字符串(string )、匹配(Match)、区域(Region)或者位置(Location)作为参数进行传递。

PS:指可以把模式(Pattern)、指向图像文件名的字符串或者表示纯文本的字符串(string )作为参数进行传递。

applicable for Screen or Match or Screen and Match:尽管区域(Region)的所有方法可以用于显示器(Screen)类和匹配(Match)类的对象上,但是每个方法在这些类上都是合理的(例如:Screen(0).below(),find(PS).setRect(rectangle))。所以,如果提及它,就表示在应用场景中这个方法在屏幕对象或者匹配对象上使用是合理的。

Note on Multi Monitor Environments:在多于一个显示器被激活的情况下,想要对非默认屏幕(这种情况下是主显示器)上的区域进行操作,要考虑一些特殊因素。所以,在多于一个显示器的环境下开始使用Sikuli之前,要先阅读多显示器环境相关章节。

2010年12月28日星期二

Qt单实例运行

程序要求单实例运行,且如果第二次运行激活已存在的程序实例的窗口。
于是有了下面的这段代码。

QSystemSemaphore sema("sema", 1, QSystemSemaphore::Open);
sema.acquire();
QSharedMemory mem("memObject");
if (!mem.create(1)) {
HWND w = FindWindow(NULL, "Window Title");
if (w)
{
SetForegroundWindow(w);
ShowWindow(w, SW_SHOWNORMAL);
}
sema.release();
return 0;
}
sema.release();

神奇的是的Qt里,只写ShowWindow是不行的,如果窗口最小化后再从另一个实例中激活它,窗口上的控件得不到绘制。可能是Qt的消息处理函数进行了判断吧。而且必须得在ShowWindow之前调用SetForegroudWindow。

2010年12月24日星期五

Sikuli X 之 Region类

区域(Region)就是屏幕上的一个矩形部分,它由位置和维度确定。位置 (x, y) 就是它的左上角相对于屏幕左上角的距离;维度 (w, h) 就是它的宽和高。
其中 x、y、w、h是以像素为单位计算距离的整数值。

区域(Region)只知道它在屏幕上的位置和它的维度,并不知道任何它的可视内容(窗体、图片、图形、文本等)。

新的区域(Region)可以在已有的区域基础上创建:你可以在各个方向上扩展区域或者获取相信区域,直到屏幕的水平或者垂直边界。

区域(Region)上的可视内容和文本内容可以使用像find()这样的方法计算得到,find()方法在区域搜索一个给定的矩形像素模式或者文本串。区域中进行匹配的内容有一个在0到1之间的相似度,0就是没有找到,1就是找到了且它的每一个像素都与模式精确匹配。可以让find以一个最小的相似度进行搜索,这样一些形状和颜色的微小变化就可以被忽略。如果不指定其他东西,Sikuli将以最小相似度0.7进行搜索,通常的情况下这样做与预期相符。

查找(Find)操作返回一个匹配(Match),它具有一个区域(Region)拥有的所有属性和方法,可以以相同的方式使用(比如查找或点击它里面的另一个目标)。匹配(Match)包含了搜索中使用的模式的维度,它也知道模式被发现的位置以及相似度。有一个区域保存了最后一次成功的查找操作中最佳的匹配和最后一次成功的findAll()返回的所有匹配(通过getLastMatch()/getLastMatches()获取)。你可以使用wait()等待模式出现,使用waitVanish()等待模式消失,或者只是使用exists()检查一下模式是否存在,这样就不用处理异常(当模式不存在的时候,exists()返回None,而不是抛出异常)。

Sikuli X支持可视化事件驱动编程。你可以告诉一个区域来观察某些东西的出现、消失或变化。这就有可以等待一个观察结果的完成或者让它在后台运行,而你的脚本继续执行。当这些可视化事件发生时,你脚本中的处理器就会被调用。每个区域有一个观察者,每个观察者可以处理多个可视化事件。停止观察是你的责任。

你可以通过模拟鼠标和键盘行为在一个区域上操作。你可以选择在先前查找操作中计算出的区块内操作,也可以一个将被隐含查找的模式上操作。要想模拟像游戏或者图形这样的特殊应用程序中的复杂操作,有低级的鼠标和键盘操作可用。

想支持更复杂和健壮的脚本,你可以处理FindFailed异常,当查找操作失败会将会抛出它。

在同一个区域上的操作,可以使用Python的"with"语句进行分组。

Screen是继承了Region类的所有属性和访求的另一个类。通过Screen类,你可以获取屏幕维度和不同的显示器(如果你有多个显示器)。如果你不指定区域,它也给了你一个默认的区域来操作。通常在你对整个屏幕进行搜索的时候,仍需要写region.find(image),只是这里的region是整个屏幕。所以为了方便,如果只写find(image)将简单的在整个屏幕中操作(实际上是默认/主要的屏幕),而不用每次都指定默认的SCREEN。而另一面,这样做将降低搜索速度,因为在整个屏幕上查找目标是耗时的。所以,为了提升处理速度,写region.find()能把搜索限定在指定的更小的矩形内(通常是你感兴趣的应该程序的主窗体)。另外,可以使用setROI()把随后的查找操作在比整个屏幕更小的区域中。

2010年12月21日星期二

Why X? eXperimental

Sikuli X要来了,一直纳闷为什么要改成X呢,今天到LaunchPad上一逛,原来X stands for eXperimental。难道以后就这样一直eXperimental下去,一直X下去了?不管如何,准备开始跟踪这个X了。

看了Sikuli的文档,全局函数里只有几个打开关闭应用程序的函数,可是平时写代码的时候都是直接find,click的啊,难道它们不是全局函数?果然,它们都是Region对象的函数,当不指定对象直接使用这些函数的时候,默认的对象是Screen,当然,Screen类是继承自Region类的。看来就从这个重要的Region类开始吧。


2010年12月17日星期五

够酷够强的Sikuli

又见 Sikuli。自从Sikuli刚刚出来时,简单用了下,发现它真是够酷够简,后来没有再用到也就没继续关注了。现在偶然又看见了Sikuli的身影,真是够酷够强了。不仅很久以前就已经有了一些OCR的功能,而且整个IDE也更加完整了,还提供了UnitTest框架,看来确实想在界面自动化测试方面大展身手了。

再看看预告中的Sikuli X,首先是要加入文本的识别与匹配,这一功能不仅可以简化脚本的编写,对于一些文本界面元素,直接在脚本中输入文字不必非得去屏幕取图了,而且对于脚本中对目标程序的控制也更加方便,可以读取并处理界面中的文本了。此外,Sikuli脚本将允许使用import语句重用,这样就有可能通过编写不同层次的Sikuli脚本以形成一个产品的测试框架。还有就是Sikuli将会把操作限制在目标程序的窗口范围之内,这样应该可以提高效率与准确性。

仍是简单试用了一下,发现对双显示器的支持还是不够,目标程序放在主显示器,Sikuli可以匹配到目标,操作的时候却把鼠标移到了次显示器的相应坐标处。期待能在Sikuli X中解决这问题。也许Sikuli X把操作限制在目标程序 窗口范围之内的功能有助于这个问题的解决。

2010年11月8日星期一

QMessageBox点滴

QMessageBox本地化,需要使用QT自己的翻译文件,translations下的qt_zh_CN。这也告诉我们利用Qt的翻译机制本地化软件是很方便的,而且便于管理显示字符串。

QMessageBox如果不指定parent,则其图标为系统默认程序图标;如果不指定标题,则标题会取可执行文件的文件名。

2010年11月5日星期五

停用QQ号

在这些只允许娱乐的日子,连能活着都得靠幸运,何况什么隐私安全。

自从用了Win7,每次打开QQ系统都会弹出个提示框需要提升权限,因为QQ要Update。终于,某年某月某一天,照例启动QQ,授权Update后,桌面上多了一个QQ医生。我异常震惊,居然Update出一个医生,这是我绝对没有想到的事,它挑战了我的权限,我的脑子里一片空白,唯一能做就是马上把它卸载掉。

又到某年某月某一天,我无聊到打算QQ游戏一把中国象棋的时候,猛然发现下盘棋也要实名制了。在全国人民都在斗地主的时候,也得时刻记得自己的身份,这不是你的地盘,你做不了主。

这一回,它拒绝运行了。原来6亿的桌面只是别人娱乐的舞台。

2010年10月27日星期三

潜行


近来经常是伴着落网的音乐工作的,当看到VOL.220的标题时,我知道这就是我最近在寻找的词,潜行。

昨天以前公司的主管打电话来,说是准备成立一个产品研究组,问我是否愿意回去做这块儿。我还是很赞同部门作这决定的,尽管我离职时也提到了更愿意转向产品方面的工作,但是我更想踏踏实实的把现在的工作做好。
到了新的工作中,角色有一些变化,而且刚过来的一段时间先是接手了一个比较紧急的项目,所以还没有完全适应过来。现在,这个项目进入了常规化状态,又有一些新的项目即将启动,在这个时候,需要思考一下接下来的工作内容和方式。
潜行,就是给自己的状态。

说到产品研究,确实值得去做。如何将新技术运用到产品中去,给用户带来效率的提升?面对市场上充斥着的各种产品,如何体现自己的特点与优势?如何做用户需要的东西。
前段时间接手项目后,跟客户就需求文档中的某些内容进行确认与探讨,客户说,我们共同的目标是做出易用的软件产品,而不是做出仅仅符合文档的产品。而看到许多难用的产品时,有时候很是怀疑我们是否应该指望计算机或者软件来帮助我们改善生活。

就自己而言,目前对于产品,需要进行的工作有:
了解同类产品的相关情况,分析各产品的特点
了解可以改善产品的思想与技术

2010年8月9日星期一

Web与桌面的混合

AQP里一开始就讲Web与桌面的混合编程。回想一下最近做的几个项目,全都是这种模式。这样做的好处是充分利用了Web页面丰富的表现形式和桌面程序对本地资源的控制能力。

2010年7月15日星期四

Delphi 2010 使用UAC的问题


1. 不要引用XPMan单元。
2. 把Delphi 2010生成的资源文件中trustInfo节中的requestedExecutionLevel节点的level属性设置为requireAdministrator。
重新打开工具,编译;OK。

其实最好还是修改程序避免总是使用UAC。

2010年7月6日星期二

Love Explains It All

记着这些日子。

You say the words I need to hear
Dry my tears when I cry
You pull me close when I'm not near

You knows the colours of my mind
Every breath that I take
And still they say that love makes blind

And here I am 
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

I stay awake to watch you breath
So much I should have said
Somehow I tell you when you sleep
I love the silence when you're near
And i love knowing you
And every word you say i keep.

And here I am 
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

Time will pass
Time will change
Everything we know will turn to something else
Turn to something else

Time has shown
Us where to go
And still i wonder why you catch me when I fall
I guess love explains it all

Cause here I am
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

Here I am
Once again
Trying to think of what to say
And you're my friend
Knowing all of my dreams and my fears
And here we are - you and me
I guess love explains it all

Love explains it all
I guess love explains it all
Love explains it all 

2010年4月24日星期六

一个软件缺陷的来龙去脉


背景
P软件主要有两个模块C和M组成。前期发现C模块中的A组件存在问题,所以决定由另一项目组的一名开发发员W来改写A组件,暂称A'组件。
我负责修改P软件,以更换新的A'组件,同时修改若干其他问题。由于旧的A组件在M中所用的功能没有发现问题,所以我没有修改M模块。
我修改了C模块,采用新的A'组件,在未经严格测试的情况下,把P软件部署到了客户现场使用。

问题
由于A'组件未经严格测试,存在缺陷:采用A'组件生成的文件无法以普通方式打开。
而P软件通常并不以普通方式打开A'组件生成的文件,只是在C模块中采用A'生成文件,然后在M模块中通过A组件进行操作,转换为另一格式的文件。
但是在少数情况下,也需要以普通方式打开A'组件生成的文件。
很快,少数情况真的出现了,问题显露了,C模块生成的文件不能以普通方式打开。我确定了这一事实后,开始怀疑在M模块中是否能正确进行转换工作,因为P软件的C和M模块的采用的组件是不同的。
客户暴怒、技术支持愤慨,测试人员紧急测试一番,M模块工作正常,P软件工作正常。

反思
如果C和M模块的A组件被同时替换为A'组件,虽然问题不能避免,但出现问题时,不必考虑由于C和M模块中组件不一致会引起的可能性。
如果P软件经过严格测试,出现问题时,就不会考虑M模块功能是否正常,能确切知道缺陷影响的范围。
P软件对于未经严格测试的A'组件,有测试的义务,因为A'组件本身不是一个项目,只是一个开发人员写的组件。


2010年2月2日星期二

够酷够简的Sikuli


Sikuli真的够COOL,样子也真的够简陋,安装好了只有一个Editor,连个Help菜单也没有。不过这些都没关系,阻碍不了它的酷,也妨碍不了它今天0.9.7明天0.9.8的的版本更新速度。

正在开发的程序,界面主要由Flash组成,以前用的自动化测试工具还不能认出Flash中的控件,只好用取坐标的方式来编写自动化脚本了;这真是让Sikuli一显身手的地方。中午开始,把以前用AutoIt3编写的一段脚本,由Sikuli来完成,算是试用。

前两天只看到了Sikuli的四个函数:switchApp、wait、click和find。这四个函数已经够做一些事了。可是今天需要更多,于是看一下API吧,真是少得可怜,当然,毫无疑问这才叫足够简单。好了,既然是Python,import几个模块来用用,def几个函数试试,一切顺利,一小段GUI自动化测试脚本完成了。运行一下,跟之前脚本的功能一样,不过,Sikuli可是更聪明,它能知道需要的界面出来没有。

再看一下Sikuli Test API,哈哈,函数少到不到再少,只有assertExist和assertNotExist两个函数。可是测试不能只看存在不存在,如果能多几个OCR之类的函数,可能用处会更大吧。也许很快就会出现了。