自动化工具 加快 WEB 自动化定位工具

撞树桐 · 2017年07月12日 · 4900 次阅读
本帖已被设为精华帖!

想法

自动化中,有很大一部分时间,是用来增加和维护元素定位的工作。比如,增加一个信的页面,需要抓取页面元素的定位信息,写一个元素定位的 POJO 类。如果要元素界面变了,还需要找出那些元素定位更改失效了,需要重新编写 POJO。这是一件很麻烦的事情。

基于上述问题,我想加快和优化 WEB 自动化的进程,有一个简单的想法,分享给大家。利用火狐的插件,记录元素的定位信息,将信息发送给服务端,自动生成 POJO 类。

需要实现的功能

  • 火狐插件记录元素定位
  • 火狐插件检查元素定位有效性
  • 火狐插件发送元素定位信息到服务端
  • 火狐插件加载服务端的定位信息
  • 服务端解析元素定位信息,生成 POJO 类

实践

火狐插件

插件不可能自己开发,依托了已有的插件功能,自己可以新增功能。这里用到了 firefox 中的 firebug 和 firepath 两个插件,使用这两个插件进行改造

安装好两个插件后,大概这样,可以使用 firepath 进行元素的定位。

改造一 : 增加 firepath 下的按钮

我需要增加如下按钮,来实现上述功能

  1. 添加:添加元素的定位信息
  2. 查看:查看已有的元素定位
  3. 清除:删除所有定位信息
  4. 载入:从服务端下载已有的元素定位

改造儿:添加定位元素

当我用 firepath 抓取元素信息时,会在 firepath 的路径中显示以定位元素的 xpath,获取以下定位信息。

点击增加后,会弹出填写定位信息。描述会生成 POJO 的注释信息,变量名会变为 POJO 的属性。

改造三:查看定位元素

如下:

展现已有的定位信息(但不能更改),并在最后一个输入框显示该定位是否有效,如果无效则显示 “无效的”(一会儿展示),可以删除当前元素定位。

改造四:发送定位信息

在上述查看中,可以将元素信息发送给服务端,服务端根据信息解析成 POJO 源码,复制到项目中即可。

我这里抓取了一些元素定位信息,并发送个服务端,服务端会生成 Baidu.java 的类源文件。如下

POJO 源文件 Baidu.java

package me.utils.selenium_utils.page;

    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;

    public class Baidu{
        /**
        * 百度logo
        **/
        @FindBy(xpath=".//*[@id='lg']/img")
        public  WebElement bd_logo;
        /**
        * 搜索框
        **/
        @FindBy(xpath=".//*[@id='kw']")
        public  WebElement kw;
        /**
        * hao123
        **/
        @FindBy(xpath=".//*[@id='u1']/a[2]")
        public  WebElement bd_hao123;
        /**
        * 地图链接
        **/
        @FindBy(xpath=".//*[@id='u1']/a[3]")
        public  WebElement bd_ditu_link;
        /**
        * 视频链接
        **/
        @FindBy(xpath=".//*[@id='u1']/a[4]")
        public  WebElement bd_shipin_link;
        /**
        * 新闻链接
        **/
        @FindBy(xpath=".//*[@id='u1']/a[1]")
        public  WebElement bd_news_link;
        /**
        * 搜索按钮
        **/
        @FindBy(xpath=".//*[@id='su']")
        public  WebElement su;
    }

这时我们可以下载源码,将其复制到项目中应用。注意:这里不要手动修改定位 Java 类源文件。如果我们需要写一些方法时,继承该定位类即可。
如下:我们写一个 BaiduPage 类

public class BaiduPage extends Baidu {

    public void search(String content){
        kw.sendKeys(content);
        su.click();
    }
}

在测试中使用,如下


...
@Test
    void test() throws InterruptedException{
        driver = (WebDriver) context.getBean("freshWebDriver");
        driver.get("http://www.baidu.com");

        BaiduPage page = PageFactory.initElements(driver, BaiduPage.class);
        page.search("testerhome");
        Thread.sleep(5000);
        driver.close();
    }
...

为什么不能手动修改类?
好处一在于一会我们要自动修改定位信息。好处二在于,下回自动生成时,也不会使你定义的 search(String content) 被覆盖掉。

改造五:载入定位信息

定位是需要经常修改的,这意味这,我们经常要手动找到已经失效的元素定位信息,这是一件令人沮丧的事情。

载入的目的就是为了解决这个问题。点击载入后,会输入完整的类名,如 me.utils.selenium_utils.page.Baidu。这是插件会从服务端下载定位信息。这里我们假设,刚才定位搜索框的信息是.//*[@id='kw1'],这时该定位在百度页面上无效的。我们载入看看

点击查看

看到这里显示.//*[@id='kw1']是无效的,因为在百度首页 dom 中根本不存在该定位元素。这时我们就可以删除后重新添加该元素。发送后会自动覆盖上次的定位信息,生成新的 POJO 类。

服务端

服务端的功能简单,就是收发元素定位信息,将信息生成 Java 源码,提供下载。这里没什么好说的,展示一下 Json 数据

部分

{
    "name": "Baidu",
    "url": "https://www.baidu.com/",
    "elements": [
        {
            "name": "bd_logo",
            "type": "xpath",
            "value": ".//*[@id='lg']/img",
            "description": "百度logo",
            "valid": true
        }
    ]
}

总结

至此,我们可以准确的将定位信息,自动生成 Java 源码,且可维护。不必复制来复制去了。这里提供给大家这个想法和实践,小弟这些愚见,如有不妥之处,望指正,欢迎拍砖!最后来个完整的图。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 28 条回复 时间 点赞

楼主,是否开源这个工具呀,感觉确实挺方便的

给力,不错

—— 来自 TesterHome 官方 安卓客户端

略屌,赞一个

BaiduPage 这个类在调用 Baidu 这个类的时候为什么不直接调用, 而要用继承

End 回复

代码写的很一般,达不到开源的水平。。。暂时先自用改改。

fdeferf 回复

如果你直接在定位类中写方法,你下回再生成新的定位信息,不是会把以前的方法覆盖掉么。。。用继承是为了避免这个问题。定位类 Baidu.java 只有自动生成的元素定位信息,BaiduPage 是为了定义方法。

思寒_seveniruby 将本帖设为了精华贴 07月13日 19:53

厉害,求指导如何改造插件,是用火狐开发者工具嘛,第一步就遇到困难😂

gdx 回复

😂 我以前也没接触过,上周三刚看的。。。等我整理一下,写下来再告诉你😅

撞树桐 回复

十分感谢☺

思路挺赞的,不错的.
如果对于一个页面多个相似的控件而又没有相应的 id/name 加以区分,只能通过 index 的方式处理定位或者通过 xpath 轴的方式处理的,能否正常工作?比如百度搜索之后结果的百度快照?

Young 回复

那只能用 xpath 的函数匹配了,比如百度快照可以写成.//a[contains(text(),'百度快照')],对应的 Java 类型是 List,至于是否可以正常工作,暂时还没有测试。至于你说的 xpath 轴的方式,那就看 selenium 支持的好不好了吧。。跟这个工具应该没什么关系😀

除了定位失败的元素会无效之外,定位成功的元素也可能无效。

就像你的例子上,如果地图搜索和视频搜索如果两个按钮位置交换了。这个工具能发现无效?如果中间增加了一个 a,“xxx 搜索” 呢?

在 xpath 定位里这种事情很常见的吧。特别是工具生成的 xpath,什么 a【1】、 a【2】之类的,页面更新后 a1 仍然存在,但却不是以前的 a1 了。

ting 回复

如果是两个按钮交换了位置,并不会显示失效,只要 dom 中有这个 xpath 路径,就不会显示失效。
检查语句如下:
var result = xPathExpression.evaluate(this.getContextNode() || this.FirePathPanel.location.document, XPathResult.ANY_UNORDERED_NODE_TYPE, null);
value.valid = result.singleNodeValue == null ? false : true;

撞树桐 回复

是啊,还是得手写。

ting 回复

😅 😅 没太明白你的意思,手写什么。。。

ting 回复

你说这些问题可能是自动化测试的一个痛点吧,这个工具只是方便生成 POJO 的 Java 对象,并不能解决自动化测试本身的这个痛点。

想知道怎么扩展 Firepath 插件,网上也没搜到相关资料,能给一些思路吗

这个和阿里的 AUI 是不是类似?另外阿里的 yanis 开源的 UI recorder 可以看一下

mark 回复

可以先看一下官方的教程
https://developer.mozilla.org/zh-CN/docs/Add-ons/Overlay_Extensions/XUL_School
,先看前两章就行,了解结构和概念的东西。xul 其实跟 html 类似,最终主要就是用 JS 写代码。看 Firepath 的源码,看看主要部件是如何关联工作的,不明白的地方用 console.log 调试。

simple 回复

真没用过你说的这两个工具,一会儿我看一下,其实做这个小工具我也是临时起兴,做着玩的。。。😈

simple 回复

刚看了一眼 UI recorder,这完全不是一个等级的东西,感觉像记事本和 IDE 的差距😂

不错方案~~~~~

End 回复

有兴趣可以看看我之前写的一个:https://github.com/fudax/selenium_recorder

槽神 回复

我一会儿就学习学习😁

撞树桐 回复

三年前的东西了,刚测试了一下,发现跟不上脚步了,baidu 首页都搞不定了

槽神 回复

😂 你骗我。。。我刚下完,3 年前就写出这工具不错了。话说工具这种东西,一旦不维护,就没法用了。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册