Robotium学习笔记五
来源:互联网 发布:买网站域名去那里 编辑:程序博客网 时间:2024/05/10 02:50
在前面四篇笔记中基本完成了对Solo类大部分方法的记录,在这篇笔记中将对webView的操作做一个记录
还是老套路,先从获取所有的WebElement控件开始,Robotium主要是使用了一套JavaScript脚本,将脚本注入的网页中并执行响应的函数来获取Elements的,下面来看看代码
public WebElement getWebElement(By by, int index){int match = index + 1;WebElement webElement = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), true);if(webElement == null) {if(match > 1){Assert.fail(match + " WebElements with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' are not found!");}else {Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");}}return webElement;}这个方法主要是调用waitForElement(),继续往下看searcher.searchForWebElement()
这里也没有其他什么特别,一个计时器,然后调用searcher.searchForWebElement(by, minimumNumberOfMatches); 继续往下看,在这里这到了我想要的东西 getWebElement()
打开看到如下:
public ArrayList<WebElement> getWebElements(final By by, boolean onlySufficientlyVisbile){boolean javaScriptWasExecuted = executeJavaScript(by, false);if(config.useJavaScriptToClickWebElements){if(!javaScriptWasExecuted){return new ArrayList<WebElement>();}return webElementCreator.getWebElementsFromWebViews();}return getWebElements(javaScriptWasExecuted, onlySufficientlyVisbile);}这里这首先调用了executeJavaScript(by, false);
public boolean executeJavaScript(final By by, boolean shouldClick){if(by instanceof By.Id){return executeJavaScriptFunction("id(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}else if(by instanceof By.Xpath){return executeJavaScriptFunction("xpath(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}else if(by instanceof By.CssSelector){return executeJavaScriptFunction("cssSelector(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}else if(by instanceof By.Name){return executeJavaScriptFunction("name(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}else if(by instanceof By.ClassName){return executeJavaScriptFunction("className(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}else if(by instanceof By.Text){return executeJavaScriptFunction("textContent(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}else if(by instanceof By.TagName){return executeJavaScriptFunction("tagName(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");}return false;}可以看出根据By类传入不同类型的参数执行不同的js方法
private boolean executeJavaScriptFunction(final String function){final WebView webView = viewFetcher.getFreshestView(viewFetcher.getCurrentViews(WebView.class, true));if(webView == null){return false;}final String javaScript = prepareForStartOfJavascriptExecution();activityUtils.getCurrentActivity(false).runOnUiThread(new Runnable() {public void run() {if(webView != null){webView.loadUrl("javascript:" + javaScript + function);}}});return true;}
这个方法首先拿到一个webView对象,prepareForStartOfJavaScriptExecution()是将RobotiumWeb.js文件加载成字符串,并将RobotiumWebClient.class这个类的实例加载(这个类继承自google的WebChromeClient类,主要用来处理prompt)
最后LoadUrl 将js字符串和函数拼接成了一个大的js脚本 形成类似这样的脚本: 调用 allWebElement()函数
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字符串的提示框,用于标识脚本注入执行结束 }
生成一个prompt 含有 id,text,name等信息,在这里刚才注册的WebChromeClient就起到作用了,他可以处理这个 prompt(当网页弹出prompt时 会自动调用onjsPrompt方法)
public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult r) {if(message != null && (message.contains(";,") || message.contains("robotium-finished"))){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;}}它使用 webElementCreator.createWebElementAndAddInList(message, view);将prompt中的信息解析存贮到 webElements中.
public void createWebElementAndAddInList(String webData, WebView webView){WebElement webElement = createWebElementAndSetLocation(webData, webView);if((webElement!=null)) webElements.add(webElement);}
private WebElement createWebElementAndSetLocation(String information, WebView webView){String[] data = information.split(";,");String[] elements = null;int x = 0;int y = 0;int width = 0;int height = 0;Hashtable<String, String> attributes = new Hashtable<String, String>();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]);}}}createWebElementAndSetLocation这个方法是将 prompt中具体的参数封装成一个 Element对象包括 id,name 坐标等等这个坐标应该是 Element相对于WebView的坐标
回到WebUtils的getWebElements方法,在最后调用getWebElements(javaScriptWasExecuted, onlySufficientlyVisbile)
private ArrayList<WebElement> getWebElements(boolean javaScriptWasExecuted, boolean onlySufficientlyVisbile){ArrayList<WebElement> webElements = new ArrayList<WebElement>();if(javaScriptWasExecuted){for(WebElement webElement : webElementCreator.getWebElementsFromWebViews()){if(!onlySufficientlyVisbile){webElements.add(webElement);}else if(isWebElementSufficientlyShown(webElement)){webElements.add(webElement);}}}return webElements;}
getWebElements是筛选出当前可见的的Element并返回集合,就找到了需要的Element
下面来看看点击Element的操作,点击element其实和点击view的原理差不多,使用上面已经得到了element,中坐标属性就可以了
public void clickOnWebElement(By by, int match, boolean scroll, boolean useJavaScriptToClick){WebElement webElement = null;if(useJavaScriptToClick){webElement = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), false);if(webElement == null){Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");}webUtils.executeJavaScript(by, true);return;}WebElement webElementToClick = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), scroll);if(webElementToClick == null){if(match > 1) {Assert.fail(match + " WebElements with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' are not found!");}else {Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");}}clickOnScreen(webElementToClick.getLocationX(), webElementToClick.getLocationY(), null);}
关键的方法和view的click是一样的,其实最开始我在这里有一点不明白,就是获取element的坐标值,不知道是相对于webview还是相对于屏幕的,但是看到这里基本上可以判断这个坐标值是相对于屏幕的了.
Robotium的学习目前告一段落了,其实还有很多地方不是完全明白,可能也有很多说错的地方,希望大家直接指出来,欢迎拍砖
0 0
- Robotium学习笔记五
- Robotium学习笔记
- robotium学习笔记
- Robotium学习笔记一
- Robotium学习笔记二
- Robotium学习笔记三
- Robotium学习笔记一
- Robotium学习笔记二
- Robotium学习笔记三
- Robotium学习笔记三
- Robotium学习笔记二
- Robotium学习笔记一
- Robotium学习笔记
- Robotium学习笔记二
- Robotium学习笔记三
- Robotium学习笔记四
- robotium学习笔记
- robotium学习笔记(二)----问题
- centos yum源配置
- string对象和C风格代码的混用
- EHcache缓存框架详解
- 安装Ubuntu图需要安装的相关工具
- 相机标定(1)---初识相机标定 标定的含义,意义
- Robotium学习笔记五
- USACODual Palindromes回文
- 字符串分割
- python配置文件操作
- 相机标定(2)---摄像机标定原理
- 深入了解DSP与ARM的区别与联系
- 两分钟彻底让你明白Android Activity生命周期(图文)!
- MM模块-关于批次特性的查看和获取
- 单目相机标定