也许很多让对ruby中的开源工具Watir,都有耳闻,也就是Ruby其实可以对Web的自动化测试有了很好的工具了。不过在做Web的自动化测试的时候,不知道有没有遇到过弹出窗口的问题,甚至有没有想过Ruby是否可以Window的应用进行一定的自动化测试呢?
如果有很简单的思路,既然ruby可以调用Window的Com接口,那我们是不是可以利用Win32api的接口,做些事情呢?我也是在网上很多大神的提醒下,开始做这方面的探索,不过我对C++简直就是抵触啊,C的话还算能接受,所以在做这方面的探讨有点班门弄斧,我想这个就算是我的学习笔记吧,也不能算是什么技术博客了。
做好准备
让ruby帮我们启动外部程序
似乎标题很清楚了,我们要迈出的第一步,就是要完成先把被测的软件启动起来,那么ruby提供了我们很简单的方法:
system 'C:\Path\To\Program.exe'
不要着急,任务是启动了,但是代码好像是阻塞在这里了,不往下执行了,ruby会等待程序一直执行下去,这可怎么办呢?
system 'start c:\Path\To\Program.exe'
Yes,这样就可以了。我们可以进行下面的步骤。
开始工作
获取主窗口
当我们启动了一个软件后,一定会有一个窗口弹出来,这个就是主窗口,如果我们要做自动化测试,那么我们下一步,就应该考虑怎么获取这个窗口。这个时候我们就需要使用一个win32api的函数了
HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);
先看看这个函数的两个参数:
- [lpClassName] 这个参数主要是用来说明寻找的主窗口的类型,一般我们寻找一般的Window窗口,设置成null就可以了,当然在ruby空是用nil表示的。
- [lpWindowName] 这个参数是用来生成窗口的Title名称的。简单地说就是窗口左上角图标旁边的的文字。还是弄不清楚,下载一个spy++,定位一下吧。
- 返回值是一个HWND,说白了,这个就是窗口的句柄。什么?句柄是什么东东,去网上查查吧。
下面的问题来了,既然我们知道有这么一个方法了,那么我们应该怎么使用ruby去调用这个方法来获取这个窗口呢?
在ruby里要使用win32api,首先你要引入win32api的库,那么
require 'win32api'
这个就必不可少了。 下面针对win32api里的函数需要做一个声明,声明方式如下:
find_window = Win32API.new 'user32' , 'FindWindow' , ['P' , 'P' ], 'L'
这里需要注意的就是,两个参数类型都是LPCTSTR类型,我们在ruby里用'P'来表示字符串的指针,而返回类型是一个句柄,这个用'L'来表示。至于这都是为什么呢,主要就是看变量的对应关系。 然后不用说了,我们声明完了,该调用了。
handle = find_window.call nil, 'Window Title'
调用的方法如上,这样我们就获得了hanle的一个句柄。
这里我要说明的一点,如果你刚刚运行一个程序,就获取主窗口可能获取的时候有问题,可能是因为窗口还没有打开就去获取。这种情况,可以用sleep等待上几秒,或者获取看看返回是否不为0,如果为了等待几秒再获取,这样的方式。
写个函数简化声明吧
def user32(name, param_types, return_value)
Win32API.new 'user32' , name, param_types, return_value
end
做点键盘操作
比方说我们打开一个记事本,那么现在我们要在记事本里输入文字,那么现在我们就要通过底层代码实现键盘操作。这个时候需要另外一个win32api函数。
void keybd_event(
BYTE keyCode,
BYTE unused,
DWORD event,
DWORD extraInfo);
这个函数是实现通过代码发送键盘事件给操作系统的。但是自己看他的说明,你会发现,他使用起来没有那么简单。这里最主要的是两个参数:
- keyCode 表示你使用的是哪个按键
- event 表示是keyup事件,还是keydown事件。说白了就是按键按下,还是按键起来。
keybd_event = user32 'keybd_event' , ['I' , 'I' , 'L' , 'L' ], 'V'
KEYEVENTF_KEYDOWN = 0
KEYEVENTF_KEYUP = 2
定义的时候,BYTE可以使用int类型,而DWORD用long类型,返回为空用"V" 然后这里定义了两种事件,就是刚才所说是按键的keyup和keydown
下面我就通过下面的方法来进行按键
"this is some text".upcase.each_byte do |b|
keybd_event.call b, 0, KEYEVENTF_KEYDOWN, 0
sleep 0.05
keybd_event.call b, 0, KEYEVENTF_KEYUP, 0
sleep 0.05
end
这样代码就会顺序在页面输入文本信息了。
激活窗口
有的时候窗口是在后侧的,不是在去前面,鼠标键盘的焦点也不在该窗口上,如果进行键盘操作的的话,可能会在其他窗口上。所以我们需要把激活,放到电脑最前面来。 这里需要win32api里面的一个函数:
BOOL SetForegroundWindow(HWND hWnd)
这里需要的函数只需要一个参数,这个参数就是窗口的句柄,返回是布尔型,如果失败返回0,成功返回1,那么可以用'L', ruby的代码就可以这么写
set_fore_window = user32 'SetForegroundWindow', ['L'], 'L'
set_fore_window.call main_window
PS: 可能该操作要进行多次,直到返回值为1为止,这里的代码比较简单,只是执行了一次
关闭窗口
打开 必有 关闭,我们打开的窗口,现在研究一下如何关闭窗口,关闭窗口。通过win32api关闭窗口,使用一个想窗口传递消息的函数:
BOOL PostMessage(
HWND window,
UINT message,
WPARAM wParam,
LPARAM lParam);
这里第一个参数不用说了,窗口的句柄,第二个参数就是消息的具体内容,后面是相关的参数。我们这里要用WM_SYSCOMMAND(0x0112)消息来发送关闭窗口,代码如下:
post_message = user32 'PostMessage' , ['L' , 'L' , 'L' , 'L' ], 'L'
WM_SYSCOMMAND = 0x0112
SC_CLOSE = 0xF060
post_message.call main_window, WM_SYSCOMMAND, SC_CLOSE, 0
具体WM_SYSCOMMAND意义,可以参看文档[http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx]
如果你用记事本的话,他可能会发送完关闭消息后,会弹出一个窗口,询问是否保存,看来我们还有工作要做啊。
定位窗口的控件
我们下面试着用鼠标,来把上面窗口上的按钮点了。不用说,要搞到页面上的控件,加入我们要点“否”的按钮。使用一个函数
HWND GetDlgItem(HWND dialog, int control);
改函数会获取对话框上的控件,control会是对话窗上按钮的ID,我们可以用spy++看到,当然一般系统对否的按钮默认就是7
get_dlg_item = user32 'GetDlgItem' , ['L' , 'L' ], 'L'
dialog = find_window.call nil, 'Steganos LockNote' )
IDNO = 7
button = get_dlg_item.call dialog, IDNO
代码很简单,先找到对话框,然后找其中的控件
获取控件坐标
找到了控件,我们需要计算出他的位置,然后把鼠标移动到相应的位置,然后执行鼠标的点击事件。 首先计算位置:
BOOL GetWindowRect(HWND window, LPRECT rectangle);
这个函数会获得控件的坐标和大小,会写入rectangle函数里,这里我们使用ruby的pack方法来设置这个值,我还是先上代码吧
get_window_rect = user32 'GetWindowRect' , ['L' , 'P' ], 'I'
rectangle = [0, 0, 0, 0].pack 'L*'
get_window_rect.call button, rectangle
left, top, right, bottom = rectangle.unpack 'L*'
在ruby里我们用'P'来作为来作为rectangle的类型,call之前先初始化,然后使用pack和unpack来分别获取坐标和长宽。 这里细节讲太细,会有很多边边角角的。不过这种用法可以直接记住,在使用的时候直接使用即可。
执行鼠标的点击事件
知道位置我们就可以计算位置,然后移动鼠标了,然后点击了。最后这一步,其实很简单了,就是多了两个方法,直接上代码来看吧:
set_cursor_pos = user32 'SetCursorPos' , ['L' , 'L' ], 'I'
mouse_event = user32 'mouse_event' , ['L' , 'L' , 'L' , 'L' , 'L' ], 'V'
MOUSEEVENTF_LEFTDOWN = 0x0002
MOUSEEVENTF_LEFTUP = 0x0004
center = [(left + right) / 2, (top + bottom) / 2]
set_cursor_pos.call *center
mouse_event.call MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
mouse_event.call MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
首先 SetCursorPos会将光标移动到指定位置,而mouse_event和我们之前的键盘输入很相近了,移动好位置,直接点击OK,大功告成。 最后这点我没有仔细分析了,因为这部分代码我觉得都可以直接写个函数,经常用了。
##小小总结 其实写了这么长,基本上在不断调用win32api而已,所以只要看看win32api,我们能在window的界面上做很多事情。
##写在最后 其实这类代码在vb中有很多,很多让写游戏插件,脚本什么的,都曾用过,网上一大堆一大堆的。可以通过借鉴vb的方法,来学习使用ruby来进行自动化测试。
相关推荐
博客还提供了Ruby的实际应用场景,如Web开发、数据处理和自动化测试。此外,博客还提供了学习资源和进阶建议,如官方文档、在线教程、实践项目和加入社区。通过这个教程,读者可以对Ruby编程有一个基本的理解,并为...
ruby入门级教程,一款很容易学,而且非常使用的软件,自动化测试的尤其可以看看
软件规模会越来越大,重复的测试工作会越来越多,自动化测试是一种趋势,一种必然, 随着企业越来越重视自己研发、重视知识产权,开源自动化测试工具越来越受到重视与使用。 Selenium 是时下很流行的面向 web 的自动...
本文从初学者的角度对自动化测试工具 Selenium 2(即 WebDriver)进行全面阐述,重点 介绍在非测试框架下使用 Selenium 进行自动化测试,因为只有掌握 Selenium 的自动化测试 原理,以后在各种测试框架下才能灵活...
自动化测试 - Python / Shell 作为一名Python开发者,根据个人的喜好和职业规划,可以选择的就业领域也非常多。 Python后端开发工程师(服务器、云平台、数据接口) Python运维工程师(自动化运维、SRE、DevOps) ...
与Ruby、Python等语言相比,Node.js更年轻、更易于没有经验的人上手使用,因此很快在世界各地的开发者中收获了一大批拥趸。在国内,Node.js在许多企业中获得了广泛应用,并取得了一系列的应用成果。然而,随着技术的...
Rubinius,JRuby,MRI入门gem install em-http-request介绍扩展名一些更高阶的Ruby项目已经合并了em-http和其他Ruby HTTP客户端: 便利类和基元的集合,以帮助解开事件代码(Ruby 1.9 + Fibers)。 -将Rack API用于...
随着时间的流逝,您会发现,其中包括:1)高度重视自动化测试,以及2)非常古怪。 欢迎!入门运行命令: ruby path_to_enlightenment.rb您应该看到如下输出: AboutAsserts#test_assert_truth has damaged your ...
它使用库来收集代码覆盖率数据,但是通过提供干净的API来过滤,分组,合并,格式化和显示这些结果,使处理结果更加容易,从而为您提供了一个完整的代码覆盖率套件,只需设置几行代码即可。 SimpleCov / Coverage...
该书是selenium-webdriver实用指南,页面排版美观,代码简洁
production目录包括 Ruby on Rails 的典型 Web 应用程序, system_tests目录包括 RSpec、Turnip 和system_tests自动化测试套件。 但是system_tests目录下的代码不依赖于生产架构。 Thease 系统测试套件描述和检查...
当前,该应用程序用于自动化从webapp抓取数据的过程。 在此项目中,我们将废弃Utorrent Webapp。 :wrench: 建于 Ruby。 使用Rubocop短绒。 终端表 野吉里 httparty :hammer_and_wrench: 入门 安装 您可以在自己...
运行Postgres实例供自动化测试使用 设置用于自动测试的消息存储数据库 配置测试套件以使用适当的Postgres凭据 运行测试 运行Postgres 使用Docker运行Postgres或从头开始安装Postgres。 自动测试期望以下默认值可以...
经MRI测试入门将其添加到您的Gemfile中: gem 'rpush' 将Rpush初始化到您的项目中。 Rails将被自动检测到。 $ cd /path/to/project$ bundle$ bundle exec rpush init创建一个应用和通知苹果推送通知服务可
运行测试自动化测试分为后端Ruby测试和前端javascript测试。 要运行后端测试... cd autotunebundle installbundle exec rake db:migrate RAILS_ENV=testbundle exec rake test 并进行前端测试cd autotunebundle ...
9.1 Grails自动化测试基础知识 111 9.2 编写测试用例 113 9.2.1 对Domain类进行测试 113 9.2.2 对Service类进行测试 116 9.2.3 对Controller进行测试 118 9.2.4 对Taglib进行测试 120 9.3 本章小结 121 第10章 部署...
matlab学生管理系统代码我的简历 投资组合 ASWATHYLAL MOHANLAL (Ashley) 425-633-0560 强大的工程专业人士,寻求软件...自动化专家 1 级,Tricentis 学院 工作经验:软件测试员(志愿者)Future of Flight Foundatio
用于徽章的fastlane插件入门该项目是插件。 要开始使用fastlane-plugin-badge ,请运行以下命令将其添加到您的项目... 关于fastlane fastlane是自动化iOS和Android应用程序Beta部署和发布的最简单方法。 要了解更多信息
文件夹结构:这些工作流示例用于自动化针对各种 Azure 服务的部署工作流,这些示例组织在同名文件夹下。 例如: /AppService/asp.net-core-webapp-on-azure.yml 用于配置和部署可随您的业务扩展的 Web 应用程序的...
测试厨房 烹饪风格 适用于云的各种Test Kitchen和Knife插件 入门 下载 双击.dmg或.msi文件以开始安装过程,或使用Linux发行版的软件包管理器。 打开一个终端,然后尝试一个临时任务。 这是一般用法: chef-run ...