Selenium WebDriver中一些鼠标和键盘事件的使用

发表于:2015-6-26 13:31

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:罗小双    来源:51Testing软件测试网采编

  清单 9. 修饰键方法 KeyDown(theKey)、keyUp(theKey)
  Actions action = new Actions(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();
  在 WebDriver API 中,KeyDown(Keys theKey)、KeyUp(Keys theKey) 方法的参数只能是修饰键: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 枚举出来的所有按键,Enum Keys。 但是并没有列出键盘上的所有按键,比如字母键 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 图像对象并保存到本地。
  * @param filename : 要保存的图像的名称
  */
  public static void sendComposeKeys(String fileName) throws Exception {
  // 构建 Robot 对象,用来操作键盘
  Robot robot = new Robot();
  // 模拟按下键盘动作,这里通过使用 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);
  // 获取系统剪切板实例
  Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard();
  // 通过 getContents() 方法就可以将剪切板内容获取并存入 Transferable 对象中
  Transferable data = sysc.getContents(null);
  if (data != null) {
  /***
  判断从剪切板获取的对象内容是否为 Java Image 类, 如果是将直接转化为 Image 对象。
  到此为止,我们就从发出组合键到抓取活动窗口,再读取剪切板并存入 Image 对象的过程
  就完成了,接下来要做的就是需要将 Image 对象保存到本地。
  */
  if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) {
  Image image = (Image) data
  .getTransferData(DataFlavor.imageFlavor);
  writeImageToFile(image, fileName);
  }
  }
  }
  Robot 类对键盘的处理是通过 keyPress(int keycode)、keyRelease(int keycode) 方法来实现的,其中他们需要的参数是键盘按键对应的虚拟键码,虚拟键码的值可以通过 KeyEvent 类来获取。在 Java API 中对于虚拟键码的解释如下: 虚拟键码用于报告按下了键盘上的哪个键,而不是一次或多次键击组合生成的字符(如 "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 类来实现图像的
  * 保存
  * @param image : 要保存的 Image 对象
  * @param filename : 保存图片的文件名称
  */
  public static void writeImageToFile(Image image, String fileName) {
  try {
  // 获取 Image 对象的宽度和高度, 这里的参数为 null 表示不需要通知任何观察者
  int width = image.getWidth(null);
  int height = image.getHeight(null);
  BufferedImage bi = new BufferedImage(width, height,
  BufferedImage.TYPE_INT_RGB);
  // 通过 BufferedImage 绘制图像并保存在其对象中
  bi.getGraphics().drawImage(image, 0, 0, null);
  // 构建图像名称及保存路径
  String name = Const.DIRECTORY + fileName + Const.FORMAT;
  File dir = new File(Const.DIRECTORY);
  if (!dir.exists()) {
  dir.mkdir();
  }
  FileOutputStream out = new FileOutputStream(name);
  @SuppressWarnings("restriction")
  JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
  encoder.encode(bi);
  out.flush();
  out.close();
  } catch (Exception e) {
  e.printStackTrace();
  }
  }
  代码清单 11 是通过 JPEGImageEncoder 类将 Image 对象写到本地文件流,注意 Image 对象是在代码清单 10 中的如下语句获取到的:
  Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard();
  Transferable data = sysc.getContents(null);
  if (data != null) {
  if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) {
  Image image = (Image) data
  .getTransferData(DataFlavor.imageFlavor);
  writeImageToFile(image, fileName);
  }
  }
  清单 12. 使用 ImageIO 将 Image 对象保存到本地
  /**
  *
  * @Description: 通过使用 ImageIO 类来保存 Image 对象为本地图片
  * @param image : 需要保存的 Image 对象
  * @param filename : 文件名
  */
  public static void saveImage(Image image, String fileName) throws Exception {
  // 获取 Image 对象的高度和宽度
  int width = image.getWidth(null);
  int height = image.getHeight(null);
  BufferedImage bi = new BufferedImage(width, height,
  BufferedImage.TYPE_INT_RGB);
  Graphics g = bi.getGraphics();
  //通过 BufferedImage 绘制图像并保存在其对象中
  g.drawImage(image, 0, 0, width, height, null);
  g.dispose();
  File f = new File(fileName);
  // 通过 ImageIO 将图像写入到文件
  ImageIO.write(bi, "jpg", f);
  }
  使用 sendKeys(keysToSend) 批量上传文件
  在 Selenium2.0 之前,要上传文件是比较麻烦的一件事件,因为点击 Upload File 控件会弹出 Windows 窗口以提供用户选择文件,但是 Window 窗口已经是浏览器之外的组件,所以 Selenium 本身没办法控制, 而必须使用 Java Robot 类来模拟键盘去操作剪切板实现上传功能,而且及其不稳定。 在 Selenium 2.0 之后,WebDriver 解决了这个问题。前面已经谈到过,直接使用 WebElement 类的 sendKeys(keysToSend) 方法就可以实现文件上传了。但是如果想批量上传文件,使用 element.sendKeys(“C:\\test\\upload\\test1.txt”, “C:\\test\\upload\\test2.txt”...) 方法也是不行的,它能通过执行,但是实际上没有上传成功。这时可以通过循环的方式来实现文件的批量上传,代码清单 13 是我在百度云上面批量上传文件的测试。
  清单 13. 批量上传文件
  /**
  *
  * @Description: 在百度云上测试文件批量上传功能,主要是通过循环的方式去做单一
  * 的上传动作 , 登陆过程已经去掉
  */
  @Test
  public void test_mutilUploadFile() throws Exception {
  System.out.println("upload start");
  // 获取上传控件元素
  WebElement uploadButton = driver.findElement(By.name("html5uploader"));
  // 构建上传文件路径,将需要上传的文件添加到 CharSequence 数组
  CharSequence[] files = new CharSequence[5];
  files[0] = "C:\\test\\test1.txt";
  files[1] = "C:\\test\\test2.txt";
  files[2] = "C:\\test\\test3.txt";
  files[3] = "C:\\test\\test4.txt";
  files[4] = "C:\\test\\test5.txt";
  // 循环列出每支需要上传的文件路径,做单一上传动作
  for(CharSequence file: files){
  uploadButton.sendKeys(file);
  }
  Thread.sleep(2000);
  System.out.println("upload end");
  }
  当执行结束后,效果如图 1。
  图 1. 批量上传文件
  结束语
  在 Selenium WebDriver 中,有了 Actions 类和 Keys 枚举对键盘和鼠标的操作已经做的非常到位,再结合 Java 本身 Robot、KeyEvent 等类的使用,基本上可以满足工作中遇到的对鼠标键盘操作的应用了。
  其次要注意的地方是 WebDriver 对浏览器的支持问题,Selenium WebDriver 支持的浏览器非常广泛,从 IE、Firefox、Chrome 到 Safari 等浏览器, WebDriver 都有相对应的实现:InterntExplorerDriver、FirefoxDriver、ChromeDriver、SafariDriver、AndroidDriver、 IPhoneDriver、HtmlUnitDriver 等。根据个人的经验,Firefox 以及 Chrome 浏览器对 WebDriver 的支持最好了,Firefox 搭上 Firebug 以及 Firepath, 在写脚本的过程中非常方便,而 ChromeDriver 是 Google 公司自己支持与维护的项目。HtmlUnitDriver 速度最快,一个纯 Java 实现的浏览器。IE 比较慢,而且对于 Xpath 等支持不是很好。更多关于 Selenium WebDriver 的知识,大家可以从下面的链接去访问 Selenium 官方文档。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号