总结Selenium WebDriver中一些鼠标和键盘事件的使用.docx
《总结Selenium WebDriver中一些鼠标和键盘事件的使用.docx》由会员分享,可在线阅读,更多相关《总结Selenium WebDriver中一些鼠标和键盘事件的使用.docx(11页珍藏版)》请在冰豆网上搜索。
总结SeleniumWebDriver中一些鼠标和键盘事件的使用
本文将总结SeleniumWebDriver中的一些鼠标和键盘事件的使用,以及组合键的使用,并且将介绍WebDriver中没有实现的键盘事件(Keys枚举中没有列举的按键)的扩展。
举例说明扩展Alt+PrtSc组合键来截取当前活动窗口并将剪切板图像保存到文件。
在使用SeleniumWebDriver做自动化测试的时候,会经常模拟鼠标和键盘的一些行为。
比如使用鼠标单击、双击、右击、拖拽等动作;或者键盘输入、快捷键使用、组合键使用等模拟键盘的操作。
在WebDeriver中,有一个专门的类来负责实现这些测试场景,那就是Actions类,在使用该类的过程中会配合使用到Keys枚举以及Mouse、Keyboard、CompositeAction等类。
其次,在实际测试过程中,可能会遇到某些按键没办法使用Actions、Keys等类来实现的情况。
比如通过使用Alt+PrtSc组合键来实现截取屏幕当前活动窗口的图像,在Keys枚举中,因为没有枚举出PrtSc键,所以没办法通过Action的KeyDown(Keys)来模拟按下这个动作。
再次是在自动化测试中,可能会遇到一些附件、文件上传的场景,或者是多文件上传,这些在Selenium2.0之后,可以直接使用WebElement类的sendKeys()方法来实现。
下面就分别介绍这些情况的具体使用。
鼠标点击操作
鼠标点击事件有以下几种类型:
清单1.鼠标左键点击
Actionsaction=newActions(driver);action.click();//鼠标左键在当前停留的位置做单击操作
action.click(driver.findElement(By.name(element)))//鼠标左键点击指定的元素
清单2.鼠标右键点击
Actionsaction=newActions(driver);
action.contextClick();//鼠标右键在当前停留的位置做单击操作
action.contextClick(driver.findElement(By.name(element)))//鼠标右键点击指定的元素
清单3.鼠标双击操作
Actionsaction=newActions(driver);
action.doubleClick();//鼠标在当前停留的位置做双击操作
action.doubleClick(driver.findElement(By.name(element)))//鼠标双击指定的元素
清单4.鼠标拖拽动作
Actionsaction=newActions(driver);
//鼠标拖拽动作,将source元素拖放到target元素的位置。
action.dragAndDrop(source,target);
//鼠标拖拽动作,将source元素拖放到(xOffset,yOffset)位置,其中xOffset为横坐标,yOffset为纵坐标。
action.dragAndDrop(source,xOffset,yOffset);
在这个拖拽的过程中,已经使用到了鼠标的组合动作,首先是鼠标点击并按住(click-and-hold)source元素,然后执行鼠标移动动作(mousemove),移动到target元素位置或者是(xOffset,yOffset)位置,再执行鼠标的释放动作(mouserelease)。
所以上面的方法也可以拆分成以下的几个执行动作来完成:
action.clickAndHold(source).moveToElement(target).perform();
action.release();
清单5.鼠标悬停操作
Actionsaction=newActions(driver);
action.clickAndHold();//鼠标悬停在当前位置,既点击并且不释放
action.clickAndHold(onElement);//鼠标悬停在onElement元素的位置
action.clickAndHold(onElement)这个方法实际上是执行了两个动作,首先是鼠标移动到元素onElement,然后再clickAndHold,所以这个方法也可以写成action.moveToElement(onElement).clickAndHold()。
清单6.鼠标移动操作
Actionsaction=newActions(driver);
action.moveToElement(toElement);//将鼠标移到toElement元素中点
//将鼠标移到元素toElement的(xOffset,yOffset)位置,
//这里的(xOffset,yOffset)是以元素toElement的左上角为(0,0)开始的(x,y)坐标轴。
action.moveToElement(toElement,xOffset,yOffset)
//以鼠标当前位置或者(0,0)为中心开始移动到(xOffset,yOffset)坐标轴
action.moveByOffset(xOffset,yOffset);
action.moveByOffset(xOffset,yOffset)这里需要注意,如果xOffset为负数,表示横坐标向左移动,yOffset为负数表示纵坐标向上移动。
而且如果这两个值大于当前屏幕的大小,鼠标只能移到屏幕最边界的位置同时抛出MoveTargetOutOfBoundsExecption的异常。
鼠标移动操作在测试环境中比较常用到的场景是需要获取某元素的flyover/tips,实际应用中很多flyover只有当鼠标移动到这个元素之后才出现,所以这个时候通过执行moveToElement(toElement)操作,就能达到预期的效果。
但是根据我个人的经验,这个方法对于某些特定产品的图标,图像之类的flyover/tips也不起作用,虽然在手动操作的时候移动鼠标到这些图标上面可以出现flyover,但是当使用WebDriver来模拟这一移动操作时,虽然方法成功执行了,但是flyover却出不来。
所以在实际应用中,还需要对具体的产品页面做相应的处理。
清单7.鼠标释放操
Actionsaction=newActions(driver);
action.release();//释放鼠标
键盘模拟操作
对于键盘的模拟操作,Actions类中有提供keyUp(theKey)、keyDown(theKey)、sendKeys(keysToSend)等方法来实现。
键盘的操作有普通键盘和修饰键盘(ModifierKeys,下面的章节将讲到修饰键的概念)两种:
1.对于普通键盘,使用sendKeys(keysToSend)就可以实现,比如按键TAB、Backspace等。
清单8.普通键盘模拟sendKeys(keysToSend)
Actionsaction=newActions(driver);
action.sendKeys(Keys.TAB);//模拟按下并释放TAB键
action.sendKeys(Keys.SPACE);//模拟按下并释放空格键
/***
针对某个元素发出某个键盘的按键操作,或者是输入操作,
比如在input框中输入某个字符也可以使用这个方法。
这个方法也可以拆分成:
action.click(element).sendKeys(keysToSend)。
*/
action.sendKeys(element,keysToSend);
注意除了Actions类有sendKeys(keysToSend)方法外,WebElement类也有一个sendKeys(keysToSend)方法,这两个方法对于一般的输入操作基本上相同,不同点在于以下几点:
∙Actions中的sendKeys(keysToSend)对于修饰键(ModifierKeys)的调用并不会释放,也就是说当调用actions.sendKeys(Keys.ALT);actions.sendKeys(Keys.CONTROL);action.sendKeys(Keys.SHIFT);的时候,相当于调用actions.keyDown(keysToSend),而如果在现实的应用中想要模拟按下并且释放这些修饰键,应该再调用action.sendKeys(keys.NULL)来完成这个动作。
∙其次就是当Actions的sendKeys(keysToSend)执行完之后,焦点就不在当前元素了。
所以我们可以使用sendKeys(Keys.TAB)来切换元素的焦点,从而达到选择元素的作用,这个最常用到的场景就是在用户名和密码的输入过程中。
∙第三点,在WebDriver中,我们可以使用WebElement类的sendKeys(keysToSend)来上传附件,比如element.sendKeys(“C:
\\test\\uploadfile\\test.jpg”);这个操作将test.jpg上传到服务器,但是使用:
Actionsaction=NewActions(driver);
action.sendKeys(element,“C:
\\test\\upload\\test.jpg”);
action.click(element).sendKeys(“C:
\\test\\upload\\test.jpg”);
这种方式是上传不成功的,虽然WebDriver在执行这条语句的时候不会出错,但是实际上并没有将文件上传。
所以要上传文件,还是应该使用前面一种方式。
2.对于修饰键(Modifierkeys),一般都是跟普通键组合使用的。
比如Ctrl+a、Alt+F4、Shift+Ctrl+F等等。
∙这里先解释一下修饰键的概念,修饰键是键盘上的一个或者一组特别的键,当它与一般按键同时使用的时候,用来临时改变一般键盘的普通行为。
对于单独按下修饰键本身一般不会触发任何键盘事件。
在个人计算机上的键盘上,有以下几个修饰键:
Shift、Ctrl、Alt(Option)、AltGr、Windowslogo、Command、FN(Function)。
但是在WebDriver中,一般的修饰键指前面三个。
你可以点击下面的Wiki链接去了解更多有关修饰键的信息,Modifierkey。
∙回到上面的话题,在WebDriver中对于修饰键的使用需要用到KeyDown(theKey)、keyUp(theKey)方法来操作。
清单9.修饰键方法KeyDown(theKey)、keyUp(theKey)
Actionsaction=newActions(driver);
action.keyDown(Keys.CONTROL);//按下Ctrl键
action.keyDown(Keys.SHIFT);//按下Shift键
action.keyDown(Key.ALT);//按下Alt键
action.keyUp(Keys.CONTROL);//释放Ctrl键
action.keyUp(Keys.SHIFT);//释放Shift键
action.keyUp(Keys.ALT);//释放Alt键
所以要通过Alt+F4来关闭当前的活动窗口,可以通过下面语句来实现:
action.keyDown(Keys.ALT).keyDown(Keys.F4).keyUp(Keys.ALT).perform();
而如果是对于像键盘上面的字母键a,b,c,d...等的组合使用,可以通过以下语句实现:
action.keyDown(Keys.CONTROL).sednKeys(“a”).perform();
在WebDriverAPI中,KeyDown(KeystheKey)、KeyUp(KeystheKey)方法的参数只能是修饰键:
Keys.SHIFT、Keys.ALT、Keys.CONTROL,否者将抛出IllegalArgumentException异常。
其次对于action.keyDown(theKey)方法的调用,如果没有显示的调用action.keyUp(theKey)或者action.sendKeys(Keys.NULL)来释放的话,这个按键将一直保持按住状态。
使用Robot类来操作Keys没有枚举出来的按键操作
1.在WebDriver中,Keys枚举出了键盘上大多数的非字母类按键,从F1到F10,NUMPAD0到NUMPAD9、ALT\TAB\CTRL\SHIFT等等,你可以通过以下链接查看Keys枚举出来的所有按键,EnumKeys。
但是并没有列出键盘上的所有按键,比如字母键a、b、c、d…z,一些符号键比如:
‘{}\[]’、‘\’、‘。
’、‘?
’、‘:
’、‘+’、‘-’、‘=’、、‘“”’,还有一些不常用到的功能键如PrtSc、ScrLk/NmLk。
对于字母键和符号键,前面我们已经提到可以直接使用sendKeys(“a”),sendKeys(“/”)的方式来触发这些键盘事件。
而对于一些功能组合键,如Fn+NmLk来关闭或者打开数字键,或者Alt+PrtSC来抓取当前屏幕的活动窗口并保存到图片,通过WebDriver的Keys是没办法操作的。
这个时候我们就需要用到Java的Robot类来实现对这类组合键的操作了。
2.下面就以对Alt+PrtSc为例介绍一下Robot对键盘的操作。
如代码清单10。
清单10.通过Robot发出组合键动作
/**
*
*@Description:
这个方法用来模拟发送组合键Alt+PrtSc,当组合键盘事件执行之后,屏幕上的活动窗口
*就被截取并且存储在剪切板了。
接下来就是通过读取剪切板数据转换成Image图像对象并保存到本地。
*@paramfilename:
要保存的图像的名称
*/
publicstaticvoidsendComposeKeys(StringfileName)throwsException{
//构建Robot对象,用来操作键盘
Robotrobot=newRobot();
//模拟按下键盘动作,这里通过使用KeyEvent类来获取对应键盘(ALT)的虚拟键码
robot.keyPress(java.awt.event.KeyEvent.VK_ALT);
//按下PrtSC键
robot.keyPress(java.awt.event.KeyEvent.VK_PRINTSCREEN);
//释放键盘动作,当这个动作完成之后,模拟组合键Alt+PrtSC的过程就已经完成,
//此时屏幕活动窗口就一被截取并存入到剪切板
robot.keyRelease(java.awt.event.KeyEvent.VK_ALT);
//获取系统剪切板实例
Clipboardsysc=Toolkit.getDefaultToolkit().getSystemClipboard();
//通过getContents()方法就可以将剪切板内容获取并存入Transferable对象中
Transferabledata=sysc.getContents(null);
if(data!
=null){
/***
判断从剪切板获取的对象内容是否为JavaImage类,如果是将直接转化为Image对象。
到此为止,我们就从发出组合键到抓取活动窗口,再读取剪切板并存入Image对象的过程
就完成了,接下来要做的就是需要将Image对象保存到本地。
*/
if(data.isDataFlavorSupported(DataFlavor.imageFlavor)){
Imageimage=(Image)data
.getTransferData(DataFlavor.imageFlavor);
writeImageToFile(image,fileName);
}
}
}
Robot类对键盘的处理是通过keyPress(intkeycode)、keyRelease(intkeycode)方法来实现的,其中他们需要的参数是键盘按键对应的虚拟键码,虚拟键码的值可以通过KeyEvent类来获取。
在JavaAPI中对于虚拟键码的解释如下:
虚拟键码用于报告按下了键盘上的哪个键,而不是一次或多次键击组合生成的字符(如"A"是由shift+"a"生成的)。
例如,按下Shift键会生成keyCode为VK_SHIFT的KEY_PRESSED事件,而按下'a'键将生成keyCode为VK_A的KEY_PRESSED事件。
释放'a'键后,会激发keyCode为VK_A的KEY_RELEASED事件。
另外,还会生成一个keyChar值为'A'的KEY_TYPED事件。
按下和释放键盘上的键会导致(依次)生成以下键事件:
KEY_PRESSED
KEY_TYPED(只在可生成有效Unicode字符时产生。
)
KEY_RELEASED
所以当测试中需要用到按下键盘Alt+PrtSc键的时候,只需要执行代码清单10中两个keyPress()和一个keyRelease()方法即可。
3.当这两个按键执行结束之后,屏幕上面的活动窗口已经保存到剪切板中。
如果需要将其保存本地图片,只需要从剪切板读取并通过JPEGImageEncoder类或者ImageIO类将其写入本地即可。
清单11.使用JPEGImageEncoder将Image对象保存到本地
/**
*
*@Description:
这个方法用来将Image对象保存到本地,主要是通过JPEGImageEncoder类来实现图像的
*保存
*@paramimage:
要保存的Image对象
*@paramfilename:
保存图片的文件名称
*/
publicstaticvoidwriteImageToFile(Imageimage,StringfileName){
try{
//获取Image对象的宽度和高度,这里的参数为null表示不需要通知任何观察者
intwidth=image.getWidth(null);
intheight=image.getHeight(null);
BufferedImagebi=newBufferedImage(width,height,
BufferedImage.TYPE_INT_RGB);
//通过BufferedImage绘制图像并保存在其对象中
bi.getGraphics().drawImage(image,0,0,null);
//构建图像名称及保存路径
Stringname=Const.DIRECTORY+fileName+Const.FORMAT;
Filedir=newFile(Const.DIRECTORY);
if(!
dir.exists()){
dir.mkdir();
}
FileOutputStreamout=newFileOutputStream(name);
@SuppressWarnings("restriction")
JPEGImageEncoderencoder=JPEGCodec.createJPEGEncoder(out);
encoder.encode(bi);
out.flush();
out.close();
}catch(Exceptione){
e.printStackTrace();
}
}
代码清单11是通过JPEGImageEncoder类将Image对象写到本地文件流,注意Image对象是在代码清单10中的如下语句获取到的:
Clipboardsysc=Toolkit.getDefaultToolkit().getSystemClipboard();
Transferabledata=sysc.getContents(null);
if(data!
=null){
if(data.isDataFlavorSupported(DataFlavor.imageFlavor)){
Imageimage=(Image)data.getTransferData(DataFlavor.imageFlavor);
writeImageToFile(image,fileName);
}
}
清单12.使用ImageIO将Image对象保存到本地
/**
*
*@Description:
通过使用ImageIO类来保存Image对象为本地图片
*@paramimage:
需要保存的Image对象
*@paramfilename:
文件名
*/
publicstaticvoidsaveImage(Imageimage,StringfileName)throwsException{
//获取Image对象的高度和宽度
intwidth=image.getWidth(null);
intheight=image.getHeight(null);
BufferedImagebi=newBufferedImage(width,height,
BufferedImage.TYPE_INT_RGB);
Graphicsg=bi.getGraphics();
//通过BufferedImage绘制图像并保存在其对象中
g.drawImage(image,0,0,width,height,null);
g.dispose();
Filef=newFile(fileName);
//通过ImageIO将图像写入到文件
ImageIO.write(bi,"jpg"