多测师是一家拥有先进的教学理念,强大的师资团队,业内好评甚多的接口自动化测试培训机构!

17727591462

联系电话

您现在所在位置:接口自动化测试培训 > 新闻资讯

Robotium原理之获取WebElement元素-自动化测试

更新时间:2022-04-27 09:21:28 作者:多测师 浏览:57

  robotium框架支持WebView,在robotium中有getWebElements()、getWebElements(By by)等方法来获取android中的WebView的元素,并提供了 clickOnWebElement方法来完成点击事件.android中的原生控件是比较好攻取的,那么对于WebView这个框架是怎么获取的呢。

Robotium原理之获取WebElement元素-自动化测试

  第一步:利用JS获取页面中的所有元素

  在PC上,获取网页的元素可以通过注入javascript元素来完成,以Chrome浏览器为例,打开工具——JavaScript控制台(快捷方式:Ctrl+Shift+J),输入 javascript:prompt(document.URL)即会弹出含当前页面的URL的提示框,因此通过编写适当的JS脚本是可以在这个弹出框中显示所有页面元素的。RobotiumWeb.js就是此功能实现用的JS脚本。以solo中getWebElements()为例:

  public ArrayList getWebElements(boolean onlySufficientlyVisible){

  boolean javaScriptWasExecuted = executeJavaScriptFunction("allWebElements();");

  return getWebElements(javaScriptWasExecuted, onlySufficientlyVisible);

  }

  private boolean executeJavaScriptFunction(final String function){

  final WebView webView = viewFetcher.getFreshestView(viewFetcher.getCurrentViews(WebView.class, true));

  if(webView == null){

  return false;

  }

  //做一些JS注入执行前的准备工作,例如将WebView设为可允许执行JS等,并将RobotiumWeb.js中的脚本以String形式返回

  final String javaScript = prepareForStartOfJavascriptExecution();

  activityUtils.getCurrentActivity(false).runOnUiThread(new Runnable() {

  public void run() {

  if(webView != null){

  webView.loadUrl("javascript:" + javaScript + function);

  }

  }

  });

  return true;

  }

  可以看出这个方法执行的是allWebElements();函数,即类似执行RobotiumWeb.js文件中如下JS代码片段:

  可以把如下片段放到JavaScript控制台中看效果

  javascript:

  function allWebElements() {

  for (var key in document.all){

  try{

  promptElement(document.all[key]); //调用promptElement(element)函数

  }catch(ignored){}

  }

  finished(); //执行完后,调用finished()函数

  }

  function promptElement(element) {

  var id = element.id;

  var text = element.innerText;

  if(text.trim().length == 0){

  text = element.value;

  }

  var name = element.getAttribute('name');

  var className = element.className;

  var tagName = element.tagName;

  var attributes = "";

  var htmlAttributes = element.attributes;

  for (var i = 0, htmlAttribute; htmlAttribute = htmlAttributes[i]; i++){

  attributes += htmlAttribute.name + "::" + htmlAttribute.value;

  if (i + 1 < htmlAttributes.length) {

  attributes += "#$";

  }

  }

  var rect = element.getBoundingClientRect();

  if(rect.width > 0 && rect.height > 0 && rect.left >= 0 && rect.top >= 0){

  prompt(id + ';,' + text + ';,' + name + ";," + className + ";," + tagName + ";," + rect.left + ';,' + rect.top + ';,' + rect.width + ';,' + rect.height + ';,' + attributes); //弹出包含id、text、name等字段的提示框

  }

  }

  function finished(){

  prompt('robotium-finished'); //弹出包含robotium-finished字符串的提示框,用于标识脚本注入执行结束

  }

  从脚本中可以看出JS获得页面元素后还进行了一定的格式化处理,在每个元素之间加了;,符号,这也是为了在后面代码中更加方便地解析。脚本的最后调用了finished()函数,即弹出包含robotium-finished的提示框。这一步完成了页面元素的获取,那么提示框中包含的内容在Android中怎么获取呢?

  第二步:在Android中获取WebView中prompt提示框中的信息

  在Android的Webkit包中有个WebChromeClient类,这个类中的onJsPrompt方法就是用于处理WebView中的提示框的,当WebView中有JS提示框时,会回调该方法,String message参数将包含提示框中的信息,因此robotium写了个继承自WebChromeClient类的RobotiumWebClient类。覆写了onJsPrompt

  onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)

  @Override

  public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult r) {

  if(message != null && (message.contains(";,") || message.contains("robotium-finished"))){

  //如果提示框中包含robotium-finished字符串,即表示那段JS注入脚本执行完毕了

  if(message.equals("robotium-finished")){

  webElementCreator.setFinished(true);

  }

  else{

  webElementCreator.createWebElementAndAddInList(message, view);//有人提示框中的内容,那么就可以对提示框中的内容进行处理了

  }

  r.confirm();

  return true;

  }

  else {

  if(originalWebChromeClient != null) {

  return originalWebChromeClient.onJsPrompt(view, url, message, defaultValue, r);

  }

  return true;

  }

  }

  另外,原本的WebView默认是不允许执行JS的,因此需要先执行enableJavascriptAndSetRobotiumWebClient方法。将JavaScriptEnabled设置为true,将将WebChromeClient设置为robotiumWebClient

  public void enableJavascriptAndSetRobotiumWebClient(List webViews, WebChromeClient originalWebChromeClient){

  this.originalWebChromeClient = originalWebChromeClient;

  for(final WebView webView : webViews){

  if(webView != null){

  inst.runOnMainSync(new Runnable() {

  public void run() {

  webView.getSettings().setJavaScriptEnabled(true);

  webView.setWebChromeClient(robotiumWebClient);

  }

  });

  }

  }

  }

  第三步:将提示框中的消息存入WebElement Java bean中

  获取到了prompt提示框中的消息后,接下来就是对这些已经过处理含特殊格式的消息进行解析处理了,依次得到WebElement的id、text、name等字段。

  private WebElement createWebElementAndSetLocation(String information, WebView webView){

  String[] data = information.split(";,"); //将消息按;,符号分割,其中;,符号是在前面执行JS时加入的

  String[] elements = null;

  int x = 0;

  int y = 0;

  int width = 0;

  int height = 0;

  Hashtable attributes = new Hashtable();

  try{

  x = Math.round(Float.valueOf(data[5]));

  y = Math.round(Float.valueOf(data[6]));

  width = Math.round(Float.valueOf(data[7]));

  height = Math.round(Float.valueOf(data[8]));

  elements = data[9].split("\\#\\$");

  }catch(Exception ignored){}

  if(elements != null) {

  for (int index = 0; index < elements.length; index++){

  String[] element = elements[index].split("::");

  if (element.length > 1) {

  attributes.put(element[0], element[1]);

  } else {

  attributes.put(element[0], element[0]);

  }

  }

  }

  WebElement webElement = null;

  try{

  webElement = new WebElement(data[0], data[1], data[2], data[3], data[4], attributes);//将id、text、name等字段存入

  setLocation(webElement, webView, x, y, width, height);

  }catch(Exception ignored) {}

  return webElement;

  }

  /**

  * Sets the location of a {@code WebElement}

  *

  * @param webElement the {@code TextView} object to set location

  * @param webView the {@code WebView} the text is shown in

  * @param x the x location to set

  * @param y the y location to set

  * @param width the width to set

  * @param height the height to set

  */

  private void setLocation(WebElement webElement, WebView webView, int x, int y, int width, int height ){

  float scale = webView.getScale();

  int[] locationOfWebViewXY = new int[2];

  webView.getLocationOnScreen(locationOfWebViewXY);

  int locationX = (int) (locationOfWebViewXY[0] + (x + (Math.floor(width / 2))) * scale);

  int locationY = (int) (locationOfWebViewXY[1] + (y + (Math.floor(height / 2))) * scale);

  webElement.setLocationX(locationX);

  webElement.setLocationY(locationY);

  }

  至此,WebElement对象中包含了id、text、name等字段,还包含了x、y坐标,知道了坐标后就可以像其它Android中的原生View一样根据坐标发送点击事件。

  以上内容为大家介绍了自动化测试中的Robotium原理之获取WebElement元素,本文由多测师亲自撰写,希望对大家有所帮助。了解更多自动化测试相关知识:https://www.aichudan.com/xwzx/

联系电话

17727591462

返回顶部