web实现ping操作_Web 自动化测试: 如实现可滚动元素的滚动操作

ee2b8eb3d8dcf9b881ca2c768b1fd16a.png

使用 selenium 进行 Web 自动化测试对我来说是个常规操作。用了很多次后,我经常会抱怨 selenium 封装的操作实在是太少了,比 cypress 差远了。

比如说 selenium 没有对页面的滚动提供丰富 API , 有的只有一个孤零零的 location_once_scrolled_into_view 方法,把一个元素滚动到可视范围之内。 这远远不能满足日常的需求啊!要知道,现在大多数的网页都需要不停的滚动鼠标加载新内容。

如果是单个窗口的滚动还好,但是遇到一些变态的 ERP 系统就为难了。 每一个页面都像是战国时代的诸侯国,被割裂成一块块相互独立的模块,每个模块都需要滚动操作, 全局的窗口滚动根本就不好使,就像周王无法再调令其他诸侯国一样。

我们来看一个例子。打开禅道的演示页面:https://demo.zentao.net/my/, 除了窗口本身需要滚动以获取底部的更多内容以外, “最新动态” 和 “我的待办” 都有自己独立的滚动条。selenium 如何控制这样的诸侯国呢?

5526a537d4d28168bbdf67901c15c078.png

这样的模块实现的技术有几种。有的会把一个区域的内容放在一个 iframe 当中,有的是包裹在一个 div 标签当中。不管是哪一种方式,实际上,我们都可以把他们当成是单个元素进行处理,如何来操作这些可以被滚动的元素呢?

上面说过,官方的 Selenium API 当中只有一个 el.location_once_scrolled_into_view 方法把某个元素滚动到可视范围内。这个方法并不够灵活,如果想要更加灵活的操作,比如滑动到底部、滑动一半等,就需要借助 JavaScript 。 基本上,如果 selenium 没有实现的操作,都可以借助 JS 操作。

对于一个网页的 DOM 对象来说呢,有全局的 window.scrollTo 方法,可以对整个窗口实现滚动操作。如果想把网页滚动到最底部,可以在任意网页按 F12 进入开发者工具,选择 console 输入 JS 代码:

 window.scrollTo(0, document.body.scrollHeight);

22b8e26785b540f10c03233e406320fd.png

同样的, 在 DOM 对象当中,也实现了对单个元素的滚动操作。 直接设置元素的 scrollTop 属性,表示讲可滚动元素的高度设置到多高。以禅道为例,如果要把 "最新动态" 这个元素向下滚动 800px,可以编写对应的 JS 代码:

 // 定位元素
 el = document.querySelector("div[data-name=最新动态]>div.panel-body");
 // 向下滚动 800 像素
 el.scrollTop = 800;

如果想滚动到一半,也可以通过元素的 scrollHeight 属性控制:

 el.scrollTop = el.scrollHeight * 0.5;

如果元素可以左右滚动,则可以设置元素的 scrollLeft 属性:

 el.scrollLeft = el.scrollWidth * 0.5;

通过设置 scrollTop 和 scrollLeft 属性有时候比较麻烦,可以适用 scrollTo 方法简化操作, 表示滚动到一半的宽度,一半的高度;

 el.scrollTo(el.scrollWidth * 0.5, el.scrollHeight * 0.5);
 

也可以适用 scrollBy 表示从现在的位置往右边和下边滑动多少像素点:

 el.scrollBy(el.scrollWidth * 0.1, el.scrollHeight * 0.1);

3d1769fe40c52d9c685671c99dda11e6.png

如果希望通过 Selenium 实现滚动操作,可以调用 selenium 当中的 execute_script 方法去执行对应的 js 语句。要实现上面的效果,可以访问页面之后,执行 JS 语句:

 from selenium import webdriver
 
 driver = webdriver.Chrome()
 driver.get("https://demo.zentao.net/my/")
 js_code = """
 el = document.querySelector("div[data-name=最新动态]>div.panel-body");
 el.scrollTo(0, el.scrollHeight);
 """
 driver.execute_script(js_code);

对 selenium 比较熟悉的同学可以封装一个上层 API, 当需要执行滚动操作时,直接调用方法就可以了:

 class SeleniumUpAPI:
     """Selenium的上层封装"""
     def __init__(self, driver:Remote):
         self.driver = driver
 
     def element_scroll_to(self, el:WebElement, x_percent=0, y_percent=0):
         """滚动元素到百分比位置.
         x: 宽度的比率,0.5
         y: 高度的比率,0.5
         """
         jscode = """arguments[0].scrollTo(
             arguments[1] * arguments[0].scrollWidth,
             arguments[2] * arguments[0].scrollHeight
             );
         """
         self.driver.execute_script(jscode, el, x_percent, y_percent)

最后贴上完整的代码:

 import time
 from selenium.webdriver import Remote, Chrome
 from selenium.webdriver.remote.webelement import WebElement
 
 class SeleniumUpAPI:
     """Selenium的上层封装"""
     def __init__(self, driver:Remote):
         self.driver = driver
 
     def element_scroll_to(self, el:WebElement, x_percent=0, y_percent=0):
         """滚动元素到百分比位置.
         x: 宽度的比率,0.5
         y: 高度的比率,0.5
         """
         jscode = """arguments[0].scrollTo(
             arguments[1] * arguments[0].scrollWidth,
             arguments[2] * arguments[0].scrollHeight
             );
         """
         self.driver.execute_script(jscode, el, x_percent, y_percent)
 
     def element_scroll_by(self, el:WebElement, x_percent=0, y_percent=0):
         """每次滚动多少个像素点,以元素百分比操作
         x: 宽度的比率,0.1
         y: 高度的比率,0.1
         """
         jscode = """arguments[0].scrollBy(
             arguments[1] * arguments[0].scrollWidth,
             arguments[2] * arguments[0].scrollHeight
             );
         """
         self.driver.execute_script(jscode, el, x_percent, y_percent)
 
 
 
 class Element:
     def scroll(self, x_percent=0, y_percent=0):
         """滚动.
         x: 宽度的比率,0.5
         y: 高度的比率,0.5
         """
         jscode = """arguments[0].scroll({
             top:arguments[1] * arguments[0].scrollHeight,
             left:arguments[1] * arguments[0].scrollWidth
             });
         """
         self.driver.execute_script(self, el, y_percent, x_percent)
 
 if __name__ == "__main__":
     driver = Chrome()
     driver.get("https://example.cypress.io/commands/actions")
     d = SeleniumUpAPI(driver)
     el = d.driver.find_element("id", "scroll-vertical")
     el.location_once_scrolled_into_view
     time.sleep(2)
     d.scroll_element(el, 0.5, 0.5)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值