Python+Selenium前端页面测试自动化

(selenium学习日志一)

【找元素】

学习selenium,个人的感觉是主要任务在【找元素】。而对于查找页面元素,有以下几个方法:

  1. find_element(self, by=By.ID, value=None)                   #需要 importfrom selenium.webdriver.common.by import By
  2. find_element_by_css_selector(self, css_selector)  #通过CSS样式,如“#kw”
  3. find_element_by_class_name(self, name)                #通过node的classname,如

  4. find_element_by_tag_name(self, name)                    #相当于node name ,如

  • find_element_by_name(self, name)                            #通过node的name属性
  • find_element_by_partial_link_text(self, link_text)      #部分链接文字,如登录 sign
  • find_element_by_link_text(self, link_text)                    #全部链接文字,如sign
  • find_element_by_xpath(self, xpath)                              #xpath路径
  • find_element_by_id(self, id_)
  • (以上方法的具体解析,网上很多,建议查看 虫师 作品 http://www.cnblogs.com/fnng/p/3183777.html)

    如果有id,自然用find_element_by_id,如果没有,建议使用find_element_by_xpath,这个可以应付页面上的所有元素。而很多时候,常常会出现 No Such Element的报错。

    针对这个问题,我归纳有以下几点:

    1、元素处在不同的frame、iframe;

    2、元素处在不同的window窗口;

    3、页面未加载成功,元素不存在;

    4、(也算第三点的一部分)由于网络线路等等原因,导致与服务器中断(又或者,你的这个请求得到的结果不正确,只是服务器只以为正确了),部分元素没来得及加载。

            请注意,这里我强调的是浏览器“放弃”请求。


    我的解决方案如下:

    1、可以使用switch_to_frame一层层迭代,再查找元素;

    2、可以使用switch_to_window;

    3、网上的建议有两点:第一,使用WebDriverWait智能等待,如WebDriverWait(self.driver,7000).until(EC.alert_is_present(),"Time out,alert not appear");

                                              第二,设置页面加载等待时间,如self.driver.implicitly_wait(10)

         以上两点,我建议第一点,但在我实际操作中,依然没有很智能,还是会报No Such Element的错误。因此,我建议自己写一个函数等待,用起来顺心,如下:

        

    def WaitAndFindElement(self,by,value=0,timedeta=5,timeout=300):
            element = None
            endtime = timeout
            
            while endtime > 0:
                try:
                    element = self._driver.find_element(by, value)
                except:
                    pass
                if element:
                    break
                else:
                    time.sleep(timedeta)
                    endtime = endtime - timedeta
            
            return element
         

          同时,页面加载时间是不固定的,会因为你的网络而有所变化,所以强烈建议以上方法,智能等待。

          另外,有网上有不少人问:WebDriver如何判断一个页面是否加载成功?

           对这个问题,我想没有现成的函数实现。有人回答,len(driver.page_source) > 200,或者查找某个元素是否存在用来判断页面是否加载成功.....

          个人感觉,问这个问题的思路错了。因为,WebDriver页面测试应着眼于元素上,而不应该死死盯在页面上。所以,我们应该想的是元素是否加载成功

    4、 当你使用第三点中的方法,智能等待元素出现的时候,如果没有发现【返回结果不正确】或者【已和服务器断开】,好吧,你就傻傻地等待。我曾遇到

          这种情况,此时只需要重新请求即可,即driver.refresh()。如果你有想法,可以改写第三点的方法,请不要死循环或者多次请求,服务器会骂娘的。

    【弹窗处理】

    html dom 弹出有以下几种:

    1、window.open(新页面.html)   弹出一个新的页面,不常用;

    2、window.showModalDialog   弹出子窗口,有父子关系;

    3、alert 、 confirm、prompt,弹出子窗口,有父子关系;

    4、通过javascript控制div弹出,属于原来的页面,不存在父子关系,现在最流行的弹窗方式

    第一到第三点,组合使用switch_to_window、switch_to_frame、driver.switch_to_alert().accept()都能解决问题,也没什么好说的。我想强调的是这几点的区分,

    很多时候,我们一看到弹出,就立刻使用driver.switch_to_alert().accept()处理。最烦的是,程序报错了也没醒悟,一直忙着去问度娘。亲,度娘也没想到你会这样子啊。

    请看,左边的是confirm弹窗,右边是div弹出,很明显嘛。如果再无法区分,可以查看html,因为第四点不存在父子关系,所以【确定】按钮可以从html中找到。

    Python+Selenium前端页面测试自动化_第1张图片Python+Selenium前端页面测试自动化_第2张图片

    【隐藏元素处理】

    在这里插个题外话,html隐藏元素有两种:

    1、display:none     相当于元素从页面中被移走,它下面所在的元素跟上填充,即消失

    2、visibility=false   元素被隐藏,但位置还在

    (以下方法有针对第一种实践过,第二种在理论上方法适用)

    先模拟第一点:(A为隐藏元素Element)当鼠标移动元素B上时,元素A出现;等鼠标离开,元素A隐藏

    解决方法:

    方案一:使用ActionChains(driver).move_to_element(B) 。也许,此时你会讶异,A元素没出现。其实,A元素出现,只是在你看到她之前,她又匆匆离去

                    原因在于move_to_element在执行时,鼠标在B上,执行后,鼠标已离开B。为了达到鼠标悬停的效率,可以使用如下方法:

                    ActionChains(driver).move_to_element(B).click_and_hold()

                    可没想到的是,元素B竟然是个链接,当点击后,driver发生了页面跳转,鼠标去到一个新的页面,你只有悲伤地看着她离你越来越远了。

                    如果你不放弃,可以考虑【循环】,即是,你尝试千万次的接触,纵使千万次都擦肩而过,只为A的一次回眸。

                    但这种方法成功的概率很低,且耗时多,不管你有多痴情。代码如下:  

        def ClickA():
            try:
                favs_close = fs.find_element_by_xpath('../preceding-sibling::a[@class="S_close"]') #元素B的xpath
            except:
                return False
            return True
        
        def MoveToAndClickA():
            while True:
                driver.move_to_element(B)
                result = ClickA()
                if result:
                    break

    方法二:(极力推荐) 使用javascript直接操作隐藏元素A,selenium使用execute_script()执行脚本。这是个完美的解决方案,且普遍适用,因为js可以操作所有的DOM

                      节点。js脚本中,你可以使用

                       var elementA= document.getElementByClassName(A)    (或者使用getElementsByTagName等等)

                       do something at A


    以上为个人经验所谈,如有错误,望各位指出


    你可能感兴趣的:(webdriver,python,selenium)