Windows下Webdriver (Python版本)实践小结

阿凡达2018-07-06 12:46
Webdriver,一个进行web应用测试自动化的工具。简单说就是一个UI自动化测试工具。相信许多做测试的小伙伴对这个工具都有一些了解。关于这个工具的介绍,相信Google,百度上都很详尽,我这里就不再赘述了。
想起来用webdriver主要是日常工作基本都是跟web界面打交道,并且有一个稳定的web产品,UI基本稳定下来,这个时候做web界面自动化最合适不过了。如果能完成这个web产品的UI自动化,那么我们产品功能有更新的时候,跑一遍自动化,可以为我们省下很多回归测试的时间。以下是一些我利用webdriver实现UI自动化过程中遇到的一些问题以及解决方法:


1. 登录(切换iframe)
我们的产品用的是urs登录组件,而登录组件是包裹在iframe里面的。没法直接定位登录输入框来send_keys,这种情况下只能先切换到iframe里面,才能使用平时的定位方式(id,class,xpath等等)。切换代码如下:
    logginIframe =self.driver.find_elements_by_tag_name("iframe") 
    self.driver.switch_to.frame(logginIframe[0])
首先通过tag_name找到所有的iframe,此时可以通过查看页面结构,或者调试的方式来获知登录组件所在的iframe,这样就可以正常定位登录框输入登录用户名密码了。
然而如果用phantomjs(无头浏览器,或者说是无UI界面的浏览器,请自行Google),问题来了,通过tag_name找到的iframe元素为空,怎么办?怎么办?查switch_to.frame这个方法的定义,豁然开朗,switch_to.frame这个方法可以接受一个整数索引,一个整数就代表dom结构中的一个iframe,从0开始尝试,刚到1,就顺利切换到登录组件所在iframe了。
 def frame(self, frame_reference):
        """
        Switches focus to the specified frame, by index, name, or webelement.

        :Args:
         - frame_reference: The name of the window to switch to, an integer representing the index,
                            or a webelement that is an (i)frame to switch to.
        :Usage:
            driver.switch_to.frame('frame_name')
            driver.switch_to.frame(1)
            driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0])
        """ 
这告诉我们,用一个方法的时候最好去看看这个方法的具体用法,参数的类型可以有哪些选择。


2. 上传文件
(1) 如果是简单的一个input类型的按钮,可以直接通过定位输入框,然后send_keys要上传的文件的路径即可。
(2) 如果不是简单的input,而是打开文件窗口的,怎么办呢?Python可以考虑用SendKeys这个模块,pip install SendKeys 安装该模块。跑自动化的时候确定鼠标焦点在webdriver所打开的浏览器上,那么就可以通过这个库来输入要上传的文件地址,实例代码如下:
for i in imglist:
        SendKeys('"'+ i + '" ')
        time.sleep(1)
        SendKeys('{ENTER}')
上述代码实现输入多个要上传的图片地址,然后模拟点击键盘ENTER键。然而问题又来了,如果输入焦点不在输入框的话,就没法正确输入,这对本机跑测试的时候干其它事情有很大影响,并且还不支持中文的文件名称输入。
于是寻找其他解决方案,然后发现了Autoit这个windows操作窗口的工具。这个工具的原理很容易理解,就是获取上传文件这个窗口,然后往输入框中输入要上传的文件路径,

最后点击打开按钮。
这个流程用代码描述清楚之后,代码保存成.au3文件,示例代码如下:
    ControlFocus("打开","","Edit1") ;识别文件上传弹窗
    WinWait("[CLASS:#32770]","",10) ;10s等待窗口显示
     
    ControlSetText("打开","","Edit1","C:\Users\Public\Music\Sample Music\橙翼 - 陶然四季.mp3")          ;设置需要上传的文件路径到文件名输入框中
    Sleep(2000)
    ControlClick("打开","","Button1") ;点击打开按钮
之后用Aut2exe_x64.exe这个Autoit提供的软件来生成可执行文件.exe。

之后就可以在需要上传文件的步骤处用python提供的os.system(“XX.exe”)函数来执行这个exe文件了,该exe程序会帮你填入要上传的文件的路径,并且支持多个文件上传,示例代码如下:
 driver.find_element_by_xpath('//*[@id="pic-box"]/div/div/div').click()time.sleep(1)
 os.system("uploadThreePics.exe")
 time.sleep(1)
 publishBt.click()
然而这个方法只适用用windows系统,对于其他系统,建议还是使用SendKeys。

3. 切换窗口
Webdriver是通过引用句柄来识别浏览器窗口的,句柄可以看成是浏览器窗口的唯一标识id。Web界面有些链接是新窗口打开的,如果要切换到新窗口那么就可以先保存下当前窗口的句柄,然后获取窗口句柄列表,循环迭代窗口句柄列表,跟当前窗口句柄比较,如果不是当前句柄,那么就切换到新的窗口句柄中。
需要注意的是,如果要关闭一个窗口,那么这个窗口必须是当前窗口,以下代码可以实现关闭非当前窗口:
    cur_handle = driver.current_window_handle
        for i in driver.window_handles:
            if i != cur_handle:
                driver.switch_to_window(i)
                driver.close()
        driver.switch_to_window(cur_handle) 

4. 隐藏元素的定位
隐藏元素,主要是指一些需要hover(指鼠标移动到按钮上)某个按钮,才出现的菜单按钮,可能还有一些需要某些操作流程才出现的元素,希望能通过修改css属性display:block来显示。
对于需要hover才能出现的元素,可以通过webdriver提供的库ActionChains来实现,先移动到需要hover的元素,然后就可以定位元素了,代码如下:   
ActionChains(driver).move_to_element(element.get_xpath('//*[@id="settingNav"]/a')).perform()
有些时候,这样做还是没法定位到元素,怎么办?别怕,还有另外一招,包管用!webdriver提供了一个函数driver.execute_script(script),这个函数可以直接执行js代码,比如hover才出现的元素,很大可能是原来就有这个元素,只不过css属性display:nome ,既然是这样,那么就可以通过js来修改元素的css属性来让元素出现,以便的定位,代码如下: 
js = 'document.getElementById("setting-box").style.display = "block"'
driver.execute_script(js)
其实执行脚本这个函数还有很多用处,比如我想滚动一下浏览器页面到下面,或者滚动到顶部,那么我可以这样写:
js = 'window.scrollTo(0,0)'
driver.execute_script(js)
 
js = 'window.scrollTo(0,document.body.scrollHeight)'
driver.execute_script(js)
还可以模拟按钮的点击事件,总之利用js能干的事情,这个函数基本都能实现。没有做不到,只有想不到,欢迎大家挖掘更多的玩法,与我们一起分享。

以上是我实践过程中的浅薄之见,理解可能存在有疑惑的地方,欢迎大家指点。

本文来自网易实践者社区,经作者李敏授权发布。