1. 程式人生 > 其它 >Selenium的ActionChains Api介面詳解

Selenium的ActionChains Api介面詳解

ActionChains

有時候我們在通過Selenium做UI自動化的時候,明明能夠在DOM樹內看到這個元素,但是我在通過driver click、sendkey的時候,就是點選不到或無法輸入字串。實際上這是由於WEB中某些元素需要通過一系列連貫的操作才能處於可以點選的狀態,driver提供的click方法是每次都只執行一個命令操作,而我們需要連貫的操作。或者經常遇到那種,需要滑鼠懸浮後,要操作的元素才會出現的某種場景,那麼我們就要模擬滑鼠懸浮到某一個位置,做一系列的連貫操作,這裡就要應用Selenium提供的ActionChains模組

具體使用方法參考官方文件:https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

或某大佬翻譯的中文文件:https://python-selenium-zh.readthedocs.io/zh_CN/latest/7.2%20%E8%A1%8C%E4%B8%BA%E9%93%BE/

引入方式

#引入方式一
from selenium.webdriver.common.action_chains import ActionChains
#引入方式二
from selenium.webdriver import ActionChains

實際上ActionChains這個模組的實現的核心思想就是,當你呼叫ActionChains的方法時,不會立即執行,而是會將所有的操作按順序存放在一個List裡,當你呼叫perform()方法時,佇列中的時間會依次執行。(注:推薦一個尺子工具,MeasulerIt)

ActionChains方法列表

click(on_element=None) ——單擊滑鼠左鍵

click_and_hold(on_element=None) ——點選滑鼠左鍵,不鬆開

context_click(on_element=None) ——點選滑鼠右鍵

double_click(on_element=None) ——雙擊滑鼠左鍵

drag_and_drop(source, target) ——拖拽到某個元素然後鬆開

drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某個座標然後鬆開

key_down(value, element=None

) ——按下某個鍵盤上的鍵

key_up(value, element=None) ——鬆開某個鍵

move_by_offset(xoffset, yoffset) ——滑鼠從當前位置移動到某個座標

move_to_element(to_element) ——滑鼠移動到某個元素

move_to_element_with_offset(to_element, xoffset, yoffset) ——移動到距某個元素(左上角座標)多少距離的位置

perform() ——執行鏈中的所有動作

release(on_element=None) ——在某個元素位置鬆開滑鼠左鍵

send_keys(*keys_to_send) ——傳送某個鍵到當前焦點的元素

send_keys_to_element(element, *keys_to_send) ——傳送某個鍵到指定元素

drag_and_drop(滑鼠拖動)

# 將source元素拖放至target元素處,引數為兩個elementObj
ActionChains(driver).drag_and_drop(source=source,target=target)

# 將一個source元素 拖動到針對source坐上角坐在的x y處 可存在負寬度的情況和負高度的情況
ActionChains(driver).drag_and_drop_by_offset(source, x, y)

# 這種也是拖拽的一種方式,都是以源元素的左上角為基準,移動座標
ActionChains(driver).click_and_hold(dom).move_by_offset(169,188).release().perform()

move_to_element

# 滑鼠移動到某一個元素上,結束elementObj
ActionChains(driver).move_to_element(e)

# 滑鼠移動到制定的座標上,引數接受x,y
ActionChains(driver).move_by_offset(e['x'],e['y'])

例:
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(
'http://www.baidu.com')
time.sleep(
2)
# driver.execute_script('document.body.scrollTop=0')
driver.execute_script('document.documentElement.scrollTop')
time.sleep(
1)
a
= driver.find_element_by_id('a').location
dis
= driver.find_element_by_id('dis1')
ActionChains(driver).move_by_offset(a[
'x'],a['y']).double_click(dis).perform()

click

# 單擊事件,可接受elementObj
ActionChains(driver).click()

# 雙擊事件,可接受elementObj
ActionChains(driver).double_click()

# 點選滑鼠右鍵
ActionChains(driver).context_click()

# 點選某個元素不鬆開,接收elementObj
ActionChains(driver).click_and_hold()

# # 某個元素上鬆開滑鼠左鍵,接收elementObj
ActionChains(driver).release()

舉例說明:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@author:chenshifeng
@file:test_actionchains.py
@time:2020/09/27
"""
import pytest
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.action_chains import ActionChains

class TestDefaultSuite():
def setup_method(self, ):
self.driver
= webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(
5)

</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> teardown_method(self):
    self.driver.quit()

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 滑鼠點選測試</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> @pytest.mark.skip</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_case_click(self):
    self.driver.get(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://sahitest.com/demo/clicks.htm</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
    click_btn </span>= self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//input[@value="click me"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 單擊按鈕</span>
    doubleclick_btn = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//input[@value="dbl click me"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 雙擊按鈕</span>
    rightclick_btn = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//input[@value="right click me"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 右鍵單擊按鈕</span>

    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> action=ActionChains(self.driver)</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> action.click(click_btn)  # 單擊</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> action.double_click(doubleclick_btn)  # 雙擊</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> action.context_click(rightclick_btn)  # 右鍵</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> action.perform()</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> sleep(5)</span>

    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 或者直接以長鏈的方式執行,按照順序依次執行</span>

ActionChains(self.driver).click(click_btn).double_click(doubleclick_btn).context_click(rightclick_btn).perform()

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 滑鼠移動測試</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_case_move(self):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> self.driver.get('https://www.baidu.com/')</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> set_ele=self.driver.find_element_by_id('s-usersetting-top')  # 百度的設定元素</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> ActionChains(self.driver).move_to_element(set_ele).perform()</span>
    <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> sleep(5)</span>
    self.driver.get(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">http://sahitest.com/demo/mouseover.htm</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    write </span>=<span style="color: rgba(0, 0, 0, 1)"> self.driver.find_element_by_xpath(
        </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//input[@value="Write on hover"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 滑鼠移動到此元素,在下面的input框中會顯示“Mouse moved”</span>
    blank = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//input[@value="Blank on hover"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 滑鼠移動到此元素,會清空下面input框中的內容</span>
    result = self.driver.find_element_by_name(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">t1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    action </span>=<span style="color: rgba(0, 0, 0, 1)"> ActionChains(self.driver)
    action.move_to_element(write).perform()  </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 移動到write,顯示“Mouse moved”</span>
    <span style="color: rgba(0, 0, 255, 1)">print</span>(result.get_attribute(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">value</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> action.move_to_element(blank).perform()</span>
    action.move_by_offset(10, 50).perform()  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 移動到距離當前位置(10,50)的點,與上句效果相同,移動到blank上,清空</span>
    <span style="color: rgba(0, 0, 255, 1)">print</span>(result.get_attribute(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">value</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
    action.move_to_element_with_offset(blank, </span>10, -40).perform()  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 移動到距離blank元素(10,-40)的點,可移動到write上</span>
    <span style="color: rgba(0, 0, 255, 1)">print</span>(result.get_attribute(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">value</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
    sleep(</span>2<span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 滑鼠拖拽</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_case_drapdrop(self):
    self.driver.get(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">http://sahitest.com/demo/dragDropMooTools.htm</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    dragger </span>= self.driver.find_element_by_id(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">dragger</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 被拖拽元素</span>
    item1 = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//div[text()="Item 1"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 目標元素1</span>
    item2 = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//div[text()="Item 2"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 目標2</span>
    item3 = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//div[text()="Item 3"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 目標3</span>
    item4 = self.driver.find_element_by_xpath(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//div[text()="Item 4"]</span><span style="color: rgba(128, 0, 0, 1)">'</span>)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 目標4</span>
action = ActionChains(self.driver) action.drag_and_drop(dragger, item1).perform() # 1.移動dragger到目標1 sleep(2) action.click_and_hold(dragger).release(item2).perform() # 2.效果與上句相同,也能起到移動效果 sleep(2) action.click_and_hold(dragger).move_to_element(item3).release().perform() # 3.效果與上兩句相同,也能起到移動的效果 sleep(2) # action.drag_and_drop_by_offset(dragger, 400, 150).perform() # 4.移動到指定座標 action.click_and_hold(dragger).move_by_offset(400, 150).release().perform() # 5.與上一句相同,移動到指定座標 sleep(2)

if name == 'main':
pytest.main()

執行結果

Testing started at 12:59 上午 ...
/usr/local/bin/python3.9 "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path /Users/chenshifeng/MyCode/PythonCode/SFDSZL/test_selenium/test_actionchains.py
Launching pytest with arguments /Users/chenshifeng/MyCode/PythonCode/SFDSZL/test_selenium/test_actionchains.py in /Users/chenshifeng/MyCode/PythonCode/SFDSZL/test_selenium

============================= test session starts ==============================
platform darwin
-- Python 3.9.0, pytest-6.1.1, py-1.9.0, pluggy-0.13.1 -- /usr/local/bin/python3.9
cachedir: .pytest_cache
rootdir:
/Users/chenshifeng/MyCode/PythonCode/SFDSZL/test_selenium
plugins: allure
-pytest-2.8.18
collecting ... collected
3 items

test_actionchains.py::TestDefaultSuite::test_case_click
test_actionchains.py::TestDefaultSuite::test_case_move
test_actionchains.py::TestDefaultSuite::test_case_drapdrop

============================== 3 passed in 37.93s ==============================

Process finished with exit code 0
PASSED [ 33%]PASSED [ 66%]Mouse moved

Mouse moved
PASSED [100%]

key_down與key_up

有時我們需要模擬鍵盤操作時,那麼就需要用到ActionChains中的key操作了,提供了兩個方法,key_down與key_up,模擬按下鍵盤的某個鍵子,與鬆開某個鍵子,接收的引數是按鍵的Keys與elementObj。可以與send_keys連用(例:全選、複製、剪下、貼上)

# key_down 模擬鍵盤摁下某個按鍵 key_up 鬆開某個按鍵,與sendkey連用完成一些操作,每次down必須up一次否則將出現異常
ActionChains(driver).key_down(Keys.CONTROL,dom).send_keys('a').send_keys('c').key_up(Keys.CONTROL)\
    .key_down(Keys.CONTROL,dom1).send_keys('v').key_up(Keys.CONTROL).perform()

Keys 實際是Selenium提供的一個鍵盤事件模組,在模擬鍵盤事件時需要匯入Keys模組

引入路徑

from selenium.webdriver.common.keys import Keys
繼續舉例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@author:chenshifeng
@file:test_actionchains.py
@time:2020/09/27
"""
import pytest
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

class TestDefaultSuite():
def setup_method(self, ):
self.driver
= webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(
5)

</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> teardown_method(self):
    self.driver.quit()

</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_key(self):
    self.driver.get(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">https://www.baidu.com/</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    dom </span>= self.driver.find_element_by_id(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">kw</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

    ActionChains(self.driver).key_down(Keys.SHIFT, dom).send_keys(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span>).send_keys(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">c</span><span style="color: rgba(128, 0, 0, 1)">'</span>).key_up(Keys.SHIFT).pause(2).perform()</pre>

end

轉載至https://www.cnblogs.com/feng0815/p/8344120.html