首页 > 其他分享 >元素定位、规避监控、APP自动化测试(Appium)等

元素定位、规避监控、APP自动化测试(Appium)等

时间:2024-09-06 16:24:58浏览次数:14  
标签:webdriver Appium option selenium APP driver element 规避 import

元素定位

我们通过webdriver打开一个网络页面,目的是为了操作当前页面已完成浏览器中的一些UI测试步骤,所以必然需要操作网页。而网页的内容组成是由HTML标签(element,也叫元素),所以基于selenium操作网页实际上本质就是操作元素。那么要操作元素就必须先获取元素对象。selenium中关于元素的获取也叫元素的定位,提供了8种元素定位操作可以让测试人员获取一个或多个HTML元素。

定位类型低版本代码新版本代码描述
xpath driver.find_element_by_xpath(“xpath”)<br>driver.find_elements_by_xpath(“xpath”) driver.find_element(By.XPATH, “xpath”)<br>driver.find_elements(By.XPATH, “xpath”) 基于xpath路径表达式对HTML元素进行提取操作
selector driver.find_element_by_css_selector(“css_selector”)<br>driver.find_elements_by_css_selector(“css_selector”) driver.find_element(By.CSS_SELECTOR, “css_selector”)<br>driver.find_elements(By.CSS_SELECTOR, “css_selector”) 基于css选择器对HTML元素进行提取操作
id driver.find_element_by_id(“id”) driver.find_element(By.ID,“id”) 基于HTML元素的id属性对元素进行提取操作
class driver.find_element_by_class_name(class_name")<br>driver.find_elements_by_class_name(class_name") driver.find_element(By.CLASS_NAME, “class_name”)<br>driver.find_elements(By.CLASS_NAME, “class_name”) 基于HTML元素的class属性对元素进行提取操作
tag driver.find_element_by_tag_name(“tag_name”)<br>driver.find_elements_by_tag_name(“tag_name”) driver.find_element(By.TAG_NAME, “tag_name”)<br>driver.find_elements(By.TAG_NAME, “tag_name”) 基于HTML元素的标签名对元素进行提取操作
link_text driver.find_element_by_link_text(“link_text”)<br>driver.find_elements_by_link_text(“link_text”) driver.find_element(By.LINK_TEXT,“link_text”)<br>driver.find_elements(By.LINK_TEXT,“link_text”) 基于HTML元素的超链接文本内容对元素进行提取操作
name driver.find_element_by_name(“name”)<br>driver.find_elements_by_name(“name”) driver.find_element(By.NAME, “name”)<br>driver.find_elements(By.NAME, “name”) 基于HTML元素的name属性对元素进行提取操作,常用于表单元素
partial_link_text driver.find_element_by_partial_link_text(“partial_link_text”)<br>driver.find_elements_by_partial_link_text(“partial_link_text”) driver.find_element(By.PARTIAL_LINK_TEXT, “partial_link_text”)<br>driver.find_elements(By.PARTIAL_LINK_TEXT, “partial_link_text”) 基于HTML元素的部分超链接对元素进行提取操作
基于xpath、css selector与class属性值获取元素
import time

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

service = Service(executable_path="./chromedriver.exe")
driver = webdriver.Chrome(service=service)

# 打开一个页面
driver.get("https://www.luffycity.com")

# 基于xpath路径获取元素
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/img[1]')

# # 基于css选择符获取元素
# element = driver.find_element(By.CSS_SELECTOR, '#__layout &gt; div &gt; div.mbox &gt; div &gt; img.close')

# # 基于class属性值来获取元素
# element = driver.find_elements(By.CLASS_NAME, 'close')
# # 如果使用find_elements获取多个元素,返回结果是一个列表,需要通过下标来选择操作的是哪一个?
# element = element[0]


# 等待3秒以后点击(这个等待不是必须的,而是为了方便查看而已)
time.sleep(3)
print(element.click())

# 等待10秒退出,如果当前窗口只有一个浏览器页面,则表示退出当前浏览器
time.sleep(10)
driver.close()

import time

from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 规避网站监测
option.add_experimental_option('useAutomationExtension', False)  # 去掉开发者警告
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'}) # 规避网站监测

# 打开一个页面
driver.get("https://www.baidu.com")

# 基于xpath路径获取元素
element = driver.find_element(By.ID, 'kw')
# 往输入框元素中通过键盘录入数据使用 send_keys()
element.send_keys("路飞学城")

# 找到提交按钮并点击
element = driver.find_element(By.ID, 'su')
element.click()

time.sleep(3)
# 从搜索结果找到有路飞学城的链接内容,并点击
element = driver.find_element(By.LINK_TEXT, '路飞学城')
element.click()
"""
错误提示:
NoSuchElementException: Message: no such element: Unable to locate element: {"method":"link text","selector":"路飞学城"}
异常,没有这样的一个元素:基于  {"method":"link text","selector":"路飞学城"} 查找不到元素(本地元素不可达)
原因是百度在用户搜索内容以后,采用了ajax进行异步刷新页面数据的,所以会导致selenium代码在元素时,百度服务器有可能没有返回数据结果,没有数据结果则没有该结果连接,因此报错
"""

# 等待10秒退出,如果当前窗口只有一个浏览器页面,则表示退出当前浏览器
time.sleep(10)
driver.close()

基于tag获取元素,往往用于获取iframe内嵌框架页中的元素。

import time

from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 规避网站监测
option.add_experimental_option('useAutomationExtension', False)  # 去掉开发者警告
service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'}) # 规避网站监测

# 打开一个页面
driver.get("https://mail.163.com")

iframe_list = driver.find_elements(By.TAG_NAME, 'iframe')
form_iframe = iframe_list[0]
# 切换窗口到指定iframe
driver.switch_to.frame(form_iframe)

driver.find_element(By.NAME, 'email').send_keys('moooluo2022')
time.sleep(3)
driver.find_element(By.NAME, 'email').clear()

# 等待10秒退出,如果当前窗口只有一个浏览器页面,则表示退出当前浏览器
time.sleep(10)
driver.close()

小练习:在上面的163邮箱登陆表单中,新增一段代码,实现自动输入密码操作。

import time

from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 规避网站监测
option.add_experimental_option('useAutomationExtension', False)  # 去掉开发者警告
service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'}) # 规避网站监测

# 打开一个页面
driver.get("https://mail.163.com")

iframe_list = driver.find_elements(By.TAG_NAME, 'iframe')
form_iframe = iframe_list[0]
# 切换窗口到指定iframe
driver.switch_to.frame(form_iframe)

driver.find_element(By.NAME, 'email').send_keys('moooluo2022')
# time.sleep(3)
# driver.find_element(By.NAME, 'email').clear()

driver.find_element(By.NAME, 'password').send_keys('123456')

driver.find_element(By.ID, 'dologin').click()

# 等待10秒退出,如果当前窗口只有一个浏览器页面,则表示退出当前浏览器
time.sleep(10)
driver.close()

元素操作
操作描述
click() 点击当前元素
send_keys() 给当前表单元素输入文本内容
clear() 给当前表单元素清空内容
submit() 点击提交按钮,提交表单,要使用submit提交表单则按钮必须有form表单才行,如果ajax提交的不行。
get_attribute() 获取元素的指定属性值
value_of_css_property() 获取元素的CSS样式的指定属性的属性值,不准确.
is_displayed() 查看元素是否显示可见
is_enabled() 查看表单元素是否启用
is_selected() 查看元素是否被选择,一般判断表单元素,如radio单选框或checkbox多选框
size 获取元素的尺寸大小
text 获取元素的文本内容
模拟登陆操作

代码:

import time
from getpass import getpass
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By


def get_driver():
    # 初始化一个谷歌浏览器实例对象
    service = Service("chromedriver.exe")
    driver = webdriver.Chrome(service=service)
    return driver


def task(username, password):
    # 打开一个网址
    driver.get("https://www.luffycity.com")
    time.sleep(3)  # 可以不用,这句代码的作用主要是便于观察

    # 关闭广告
    driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/img[1]').click()

    # 点击登陆
    driver.find_element(By.CLASS_NAME, 'signin').click()
    time.sleep(3)

    # 往账号输入框输入账号
    element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[2]/div[1]/div[1]/input')
    element.send_keys(username)

    # 往密码输入框输入密码
    element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[2]/div[1]/div[2]/input')
    element.send_keys(password)

    element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[2]/button')
    element.click()

    time.sleep(5)
    driver.quit()


if __name__ == '__main__':
    username = input("账号: ")
    # python的getpass会与pycharm内置的run终端形成阻塞,
    # 所以使用了getpass,则需要改成cmd或pycharm的Terminal终端来运行python脚本
    password = getpass("密码:")
    driver = get_driver()
    task(username, password)

查看操作元素的相关属性
import time
from getpass import getpass
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By


# 初始化一个谷歌浏览器实例对象
service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service)

# 打开一个网址
driver.get("http://localhost:63342/code/7.html?_ijt=gom325r5bev2q5u5q3uelkchje")

# # 查看元素的显示模式,是否是可见
# element = driver.find_element(By.NAME, 'access_token')
# display = element.is_displayed()
# print(display)
#
# # 查看元素的属性值
# print(element.get_attribute("value"))
# outline = element.value_of_css_property('border')
# print(outline)

# element = driver.find_element(By.XPATH, '/html/body/form/input[4]')
# enabled = element.is_enabled()
# print(enabled)

# # 提交表单
# element = driver.find_element(By.XPATH, '/html/body/form/input[5]')
# element.submit()


element = driver.find_element(By.XPATH, '/html/body/h1')
print(element.text)

time.sleep(5)
driver.quit()

规避监测

现在不少网站有对selenium采取了监测机制。这些监测机制会导致我们使用selenium访问网站时出现各种拦截机制,如出现验证码等。

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service)

driver.get("https://www.baidu.com")

driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()

time.sleep(3)
driver.quit()

解决方案:

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service


option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 规避网站监测
option.add_experimental_option('useAutomationExtension', False)  # 去掉开发者警告

service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'}) # 规避网站监测


driver.get("https://www.baidu.com")

driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()

time.sleep(5)
driver.quit()

鼠标事件

在上面的selenium操作中,我们获取元素可以直接调用click方法实现鼠标点击效果。但是,如果要进行更加复杂多样的鼠标操作,如鼠标右键、鼠标移动、拖动等等,则需要依赖于 ActionChains (动作链) 模块提供的鼠标操作来完成。

from selenium.webdriver.common.action_chains import ActionChains

基本使用

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.action_chains import ActionChains

# 初始化一个谷歌浏览器实例对象
option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})


# 打开一个网址
driver.get("https://www.luffycity.com")

# 关闭广告
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/img[1]')
element.click()

time.sleep(5)
# 定位元素,定位到顶部导航菜单的"题库"上面
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/header/div/div/nav/a[6]')
# move_to_element 把鼠标悬停在指定元素上面
# context_click 执行鼠标右键
# 动作链在设置动作以后,不会自动执行,所以需要在动作链的末尾,调用perform执行整个动作链
ActionChains(driver).move_to_element(element).context_click().perform()

time.sleep(5)
driver.quit()

ActionChains动作链可以保存1个或多个连贯的鼠标操作,但是最终执行鼠标操作需要调用perform()方法。常用鼠标操作:

操作描述
double_click(element) 鼠标双击
context_click(element) 鼠标右击
drag_and_drop(source, target) 鼠标拖动(将一个元素移动到另一个元素位置)
drag_and_drop_by_offset(source, xoffset, yoffset) 鼠标拖动(将一个元素移动到指定坐标位置)
move_to_element(element) 鼠标移动并悬放到指定元素的上方
move_by_offset(xoffset, yoffset) 将鼠标从当前位置移动到指定坐标处

测试页面:

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Title&lt;/title&gt;
    &lt;style&gt;
    .box{
        width: 100px;
        height: 100px;
        background: red;
    }
    .box:hover{
        background: blue;
    }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="box"&gt;&lt;/div&gt;
    &lt;script&gt;
    var box = document.querySelector(".box")
    box.ondblclick = function(){
        box.style.background = "yellow";
    }
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

测试双击与鼠标选放

import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.action_chains import ActionChains

service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service)

# 打开一个网址
driver.get("C:/Users/Administrator/Desktop/code/11-测试页面.html")

element = driver.find_element(By.CLASS_NAME, 'box')
ActionChains(driver).move_to_element(element).perform()
time.sleep(1)
ActionChains(driver).double_click().perform()
time.sleep(3)
driver.quit()

拖拽元素

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions, ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys


option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

# 设置浏览器窗口最大化
driver.maximize_window()

# 进入页面
driver.get('https://www.jq22.com/yanshi10850')

iframe = driver.find_element(By.TAG_NAME, "iframe")
driver.switch_to.frame(iframe)

element1 = driver.find_element(By.XPATH, '//*[@id="bar"]/li[1]')
element2 = driver.find_element(By.XPATH, '//*[@id="foo"]')
time.sleep(3)
ActionChains(driver).drag_and_drop(element1, element2).perform()

time.sleep(10)
driver.quit()
键盘事件

前面我们在元素操作中使用了send_keys()方法来模拟键盘输入,而针对复杂的组合键盘操作,webdriver提供了键盘上几乎所有的按键方法,使用前导入Keys类即可。

from selenium.webdriver.common.keys import Keys
方法名描述
send_keys(Keys.ENTER) 回车键Enter
send_keys(Keys.BACK_SPACE) 删除键BackSpace
send_keys(Keys.SPACE) 空格键(Space)
send_keys(Keys.TAB) 制表键(Tab)
send_keys(Keys.ESCAPE) 复位键Esc
send_keys(Keys.CONTROL,‘a’) 全选Ctrl+A
send_keys(Keys.CONTROL,‘c’) 复制Ctrl+C
send_keys(Keys.CONTROL,‘x’) 剪切Ctrl+X
send_keys(Keys.CONTROL,‘v’) 粘贴Ctrl+V
send_keys(Keys.F1) 键盘F1
…… ……
send_keys(Keys.F12) 键盘F12
   
基本使用

页面:

&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Title&lt;/title&gt;
    &lt;style&gt;

    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;textarea name="content" id="" cols="30" rows="10"&gt;hello!EveryBody!&lt;/textarea&gt;
&lt;/body&gt;
&lt;/html&gt;

代码:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys

service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service)
driver.get("C:/Users/Administrator/Desktop/code/12-测试页面.html")
time.sleep(3)
element = driver.find_element(By.TAG_NAME, "textarea")
element.send_keys(Keys.CONTROL, 'a')
element.send_keys(Keys.BACK_SPACE)

time.sleep(3)
element.send_keys("2012年9月25日,辽宁舰正式交付中国海军;2019年12月17日,山东舰入列,中国海军进入双航母时代;2022年6月17日,福建舰来了,我们有三艘航母了。")

time.sleep(5)
driver.quit()

回车键等操作

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys


option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

# 设置浏览器窗口最大化
driver.maximize_window()
# driver.minimize_window()  # 最小化
# 进入页面
driver.get('https://www.baidu.com/')
# 定位输入框
element = driver.find_element(By.ID, "kw")
# 向输入框中输入内容
element.send_keys("路飞学城")
time.sleep(2)
# 删除上一步中多输入的文字
element.send_keys(*[Keys.BACK_SPACE for i in range(2)])
element.send_keys("在线教育")

time.sleep(2)
# 使用回车代替点击按钮
element.send_keys(Keys.ENTER)
time.sleep(2)

屏幕截图

在selenium中,截取网页的图片有多种方式,一般常用的有2种方式:截取可见区域和截取指定区域。

截取可见区域

主要是通过driver.save_screenshot来完成。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service

# 初始化一个谷歌浏览器实例对象

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                       {'source': 'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

driver.get('https://www.luffycity.com')

# 关闭广告
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/img[1]')
element.click()

# 调用浏览器驱动对象的save_screenshot方法就可以实现截图
driver.save_screenshot('./luffycity.png')  # 图片必须保存为 png 格式
driver.quit()

save_screenshot使用过程中,需要注意2点:

  1. save_screenshot方法保存的图片格式必须是png格式,否则不行。
  2. save_screenshot保存图片的目录,必须是已经存在的,否则无法保存图片。
截取指定区域

通过先获取HTML文档中的元素对象,再通过元素对象调用screenshot 来进行截取。

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service


# 初始化一个谷歌浏览器实例对象
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                       {'source': 'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

driver.get('https://www.luffycity.com')

# 关闭广告
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/img[1]')
element.click()

# 点击登陆
driver.find_element(By.CLASS_NAME, 'signin').click()
time.sleep(3)

# 往账号输入框输入账号
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[2]/div[1]/div[1]/input')
element.send_keys("13928835901")

# 往密码输入框输入密码
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[2]/div[1]/div[2]/input')
element.send_keys("123")

element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[2]/button')
element.click()

time.sleep(2)
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div')
# 通过元素的 screenshot 方法直接保存图片
element.screenshot('./login_result.png')
time.sleep(3)
driver.quit()

等待机制

针对一些通过ajax局部刷新或延时显示的数据,在selenium使用过程中如果没有等待数据显示就直接执行后续代码就会有问题。

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("C:/Users/Administrator/Desktop/test/测试自动化-day04/素材/chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

driver.get("http://www.baidu.com")

driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()
# time.sleep(3)
driver.find_element(By.PARTIAL_LINK_TEXT, "路飞学城").click()
time.sleep(3)
driver.quit()

上面虽然使用了time.sleep(3)让selenium强制等待了3秒,但是这种操作不够灵活,因为数据加载有时候不需要3秒就显示出来了,而程序并没有办法知道而导致最终呆呆的等待了3秒才继续执行。当然,也有可能3秒后数据还没有出来,那么程序则依然报错。所以开发中针对上述问题,我们是不能使用time.sleep来草草了事的,而是要使用selenium提供的另外两种等待机制。

显式等待
import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions


option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

driver.get("http://www.baidu.com")

driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()
# 使用time.sleep这种机械化的强制等待,实际上是有可能出问题的。即便没有问题,也会存在着让测试代码浪费等待时间的情况。
# time.sleep(3)
# driver.find_element(By.PARTIAL_LINK_TEXT, "路飞学城").click()

# 显式等待
WebDriverWait(driver=driver, timeout=60, poll_frequency=0.5, ignored_exceptions=None).until(expected_conditions.presence_of_element_located((By.PARTIAL_LINK_TEXT, '路飞学城'))).click()

time.sleep(3)
driver.quit()

selenium提供了 WebDriverWait类实现显式等待机制,WebDriverWait类接收4个参数来指定等待机制。

  • driver,浏览器驱动对象
  • timeout,最长超时等待时间,单位(秒)
  • poll_frequency,轮询检测等待条件的时间,也就是每隔多长时间检测一次条件,默认是0.5秒
  • ignored_exceptions,timeout超时后的异常信息,默认抛出NoSuchElementException

基本使用:

WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5, ignored_exceptions=None)

WebDriverWait类提供了两个方法来完成等待条件的检测实现:

  • until(self, method, message=‘’),method为等待检测条件的判断方法,until表示直到返回True,用的较多。
  • until_not(self, method, message=‘’),method为等待检测条件的判断方法,until_not表示直到返回False。

上面代码用到的method指定为expected_conditions模块并调用其presence_of_element_located方法判断指定元素是否存在。

expected_conditions模块提供了各种判断:

  • presence_of_element_located判断某个元素是否存在于HTML文档中。
  • presence_of_elements_located 判断是否至少有1个元素存在HTML中。只要有1个元素存在,则该方法就返回True。

显式等待的另一种写法,首先实例化一个显式等待对象,这样可以在各个地方灵活的调用:

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions


option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

# 1. 先创建一个显式等待对象
wait = WebDriverWait(driver=driver, timeout=60, poll_frequency=0.5, ignored_exceptions=None)

driver.get("http://www.baidu.com")

driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()
# 使用time.sleep这种机械化的强制等待,实际上是有可能出问题的。即便没有问题,也会存在着让测试代码浪费等待时间的情况。
# time.sleep(3)
# driver.find_element(By.PARTIAL_LINK_TEXT, "路飞学城").click()

# 2. 显式等待对象调用判断等待方法
wait.until(expected_conditions.presence_of_element_located((By.PARTIAL_LINK_TEXT, '路飞学城'))).click()

time.sleep(3)
driver.quit()

隐式等待

也叫全局等待。我们可以直接通过浏览器驱动对象driver调用隐式等待,并且用法也相对简单:

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions


option=ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver=webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})
# 设置隐式等待
driver.implicitly_wait(time_to_wait=10)  # 只需要一个等待超时时间参数

driver.get("https://www.baidu.com")

driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()

driver.find_element(By.PARTIAL_LINK_TEXT, "路飞学城").click()

time.sleep(3)
driver.quit()

implicitly_wait等待时间单位为秒,如上例所示,我们指定了10秒。需要注意的是,隐式与显式等待有明显的区别,隐式等待应用于全局,每当使用driver驱动找某个元素时,隐式等待机制就会被触发(导致测试代码的运行速度变慢),如果元素存在,则继续执行,否则,它将以轮询的方式判断元素是否定位成功,直至等待超时,抛出错误NoSuchElementException。而显式等待则只是指定某(些)个元素是否存在时执行。

在等待机制的选择上,我们可以在三种等待机制中灵活选择:

  • 普通(静态页面较多)网页,强制等待和显式等待可以相互搭配,提高效率。适用于前后端不分离的UI场景测试。
  • 动态页面较多的时候,则可以全局设置隐式等待。适用于前后端分离的UI场景测试
窗口切换

在测试客户端时,往往存在有些功能流程需要点击打开并操作多个窗口页面的情况。此时就需要使用selenium在多个窗口中相互切换操作了。selenium中提供了三个方法给测试开发人员完成窗口切换操作。

方法名描述
driver.switch_to.window 切换普通窗口
driver.switch_to.frame 切换进入iframe窗口
driver.switch_to.default_content 切换退出iframe窗口
driver.window_handles 窗口数组
切换普通窗口
import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait  # 等待页面加载某些元素
from selenium.webdriver.support import expected_conditions

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                       {'source': 'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})

wait = WebDriverWait(driver, 10)

try:
    driver.get("https://www.baidu.com")

    driver.find_element(By.ID, "kw").send_keys("路飞学城")
    driver.find_element(By.ID, "su").click()
    wait.until(expected_conditions.presence_of_element_located((By.LINK_TEXT, '路飞学城'))).click()
    # 查看当前浏览器中打开的窗口列表
    print(driver.window_handles)
    time.sleep(3)
    # 根据数组下标索引切换窗口
    driver.switch_to.window(driver.window_handles[0])
    time.sleep(3)
    driver.find_element(By.LINK_TEXT, '百度百科').click()
    print(driver.window_handles)  # 此时应该有3个窗口了
    time.sleep(3)
    driver.switch_to.window(driver.window_handles[1]) # 切换到路飞窗口
finally:
    time.sleep(3)
    driver.quit()

切换iframe窗口

两个方法:

  • switch_to.frame(iframe),进入窗口
  • switch_to.default_content(),退出窗口
import time
import getpass
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service


def get_driver():
    """获取浏览器驱动对象"""
    option = ChromeOptions()
    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    option.add_experimental_option('useAutomationExtension', False)
    service = Service("chromedriver.exe")
    driver = webdriver.Chrome(service=service, options=option)
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                           {'source': 'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'})
    # 设置隐式等待
    driver.implicitly_wait(10)
    return driver

def task(url, username, password, to, theme):
    """
    发送邮件
    :param url  打开站点地址
    :param username 登陆账号
    :param password 登陆密码
    :param to 收件人邮箱账号
    :param theme 邮件的主体
    """
    driver.get(url)
    iframe = driver.find_elements(By.TAG_NAME, 'iframe')
    driver.switch_to.frame(iframe[0])
    driver.find_element(By.CLASS_NAME, 'dlemail').send_keys(username)
    driver.find_element(By.CLASS_NAME, 'dlpwd').send_keys(password)
    driver.find_element(By.ID, 'dologin').click()
    # 登陆以后刷新了页面了,所以需要重新获取driver浏览器驱动对象,否则无法进行后续操作
    driver.switch_to.window(driver.window_handles[0])
    driver.find_element(By.ID, '_mail_component_149_149').click()
    driver.find_element(By.CLASS_NAME, 'nui-editableAddr-ipt').send_keys(to)
    driver.find_elements(By.CLASS_NAME, 'nui-ipt-input')[2].send_keys(theme)

    content_iframe = driver.find_element(By.CLASS_NAME, 'APP-editor-iframe')
    driver.switch_to.frame(content_iframe)
    driver.find_element(By.TAG_NAME, "p").send_keys("这是通过selenium添加的邮件内容!!!")
    driver.switch_to.default_content()
    # 发送邮件
    driver.find_elements(By.CLASS_NAME, 'nui-btn-text')[2].click()

if __name__ == '__main__':
    url = 'https://mail.163.com'
    theme = '一份测试邮件'
    to = '[email protected]'
    content = '测试邮件内容.................................'
    # username = input('用户名: ').strip()
    username = "moooluo2022"
    # pycharm中直接运行python脚本会导致getpass进入阻塞,所以需要使用终端命令行运行python脚本
    password = getpass.getpass(prompt="密码: ")
    driver = get_driver()
    try:
        task(url, username, password, to, content)
    except Exception as e:
        print(f"发送邮件出错:{e}")
    finally:
        time.sleep(20)
        driver.quit()

执行js代码

实际上,我们之前有提到关于selenium实际上操作浏览器都是通过webdriver完成对应的功能操作的,而webdriver实际上是通过js代码来控制浏览器的。因此针对如果selenium本身如果没有提供的操作,则我们可以使用js代码来完成一些窗口操作。例如:滚动条。

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service


option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 规避网站监测
option.add_experimental_option('useAutomationExtension', False)  # 去掉开发者警告

service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'}) # 规避网站监测

driver.get("https://www.baidu.com")

# # 执行没有返回的值的js代码
# driver.execute_script('confirm("hello, luffycity!")')
#
# # 关闭alert弹窗
# time.sleep(3)
# # 让driver浏览器驱动对象,切换焦点(切换上下文)到弹窗
# alert = driver.switch_to.alert
# # 点击确定,以达到关闭弹窗的效果
# # alert.accept()
# alert.dismiss()   # 关闭弹窗,相当于点击了取消

"""让浏览器执行js代码并获取代码的返回值"""

"""例如:获取cookie"""
# result = driver.execute_script('return document.cookie')
# cookies = result.split(";")
# cookies_dict = {i[0]:i[1] for i in [item.split("=") for item in cookies]}
# print(cookies_dict.get("BIDUPSID"))
# 有了cookie以后,以后就可以跳过登陆测试其他的功能操作了。

"""例如:获取本地存储中的token"""
result = driver.execute_script("return localStorage")
print(result) #
time.sleep(5)
driver.quit()

操作滚动条

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service)

driver.get("https://www.luffycity.com")

# 关闭广告
element = driver.find_element(By.XPATH, '//*[@id="__layout"]/div/div[2]/div/img[1]')
element.click()

num = 0
while num &lt;= driver.execute_script("""return parseInt(getComputedStyle(document.querySelector('.main'))["height"])"""):
    num += 1
    driver.execute_script(f"window.scrollTo(0, {20*num})")
    time.sleep(0.01)

time.sleep(3)
driver.quit()

无头浏览器

所谓的无头浏览器(Headless),实际上就是不需要打开浏览器去操作浏览器完成对应UI效果。

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

option = ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])  # 规避网站监测
option.add_experimental_option('useAutomationExtension', False)  # 去掉开发者警告

# 开启浏览器的无头模式
option.add_argument('--headless')
option.add_argument('--disable-gpu')  # 允许在无GPU的环境下运行,可选
option.add_argument('--window-size=1920x1080')  # 建议设置

service = Service("chromedriver.exe")
driver = webdriver.Chrome(service=service, options=option)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {'source':'Object.defineProperty(navigator,"webdriver",{get:()=&gt;undefind})'}) # 规避网站监测
# 设置隐式等待
driver.implicitly_wait(time_to_wait=10)  # 只需要一个等待超时时间参数

# 打开网页
driver.get("https://www.baidu.com")
# 搜索内容
driver.find_element(By.ID, "kw").send_keys("路飞学城")
driver.find_element(By.ID, "su").click()

# 点击搜索结果
driver.find_element(By.PARTIAL_LINK_TEXT, "路飞学城").click()

# 调用浏览器驱动对象的save_screenshot方法就可以实现截图
driver.save_screenshot('./baidu_search_result.png')  # 图片必须保存为 png 格式

driver.quit()

使用无头浏览器,在运行一些经过验证的测试脚本时,可以达到节约系统资源的优点,而且少了浏览器的UI效果,UI测试脚本的运行速度会加快。

APP自动化测试

APP移动端测试是指对移动端应用进行的测试,测试应用功能是否满足特定的需求。移动端测试一般分3类:APP功能测试、APP自动化测试、APP安全测试。其中常用的APP自动化测试工具有:Robtium、macaca、Appium、UiAutomator、Monkey、MonkeyRunner、Instrumentation、Athrun等等。

工具支持语言跨平台跨应用 
Robotium Java Android 不支持  
Macaca Java、Python、node.js Android、IOS 支持 可以作为简洁版的Appium工具
Appium Java、c#、Python、PHP、Perl、Ruby、node.js Android、IOS、H5 支持  

Appium

基本介绍

Appium由Sauce labs公司(是美国的一家提供自动化的软件测试服务公司)基于node.jsexpress框架开发http server,是一个开源、跨平台的移动端自动化测试框架,可以用来测试原生及混合的移动端应用。Appium支持IOS、Android及H5等移动端应用。Appium使用WebDriver的json wire协议来驱动Apple系统的UIAutomation库(由苹果官方提供的自动化测试库)、Android系统的UIAutomator框架(由Android官方提供的自动化测试库)。

img

与selenium的关系

appium继承了selenium的webdriver,也就是selenium2.0,所以appium在调试中实际上也调用了selenium的某些功能。

appium起到了一个电脑连接移动端的桥梁,然后我们可以在电脑上调用selenium工具来调试移动端应用。

appium原理

appium本质上就是一个使用node.js编写的http server(Http服务器),它对外暴露了一系列REST API接口提供给测试开发人员进行调用。

这个http server的功能其实很简单:监听一个端口,然后接收由client发送来的command。翻译这些command,把这些command转成移动设备可以理解的形式发送给移动设备,然后移动设备执行完这些command后把执行结果返回给httpserver,http server再把执行结果返回给client。

在这里client其实就是发起command的设备,一般来说就是我们编写代码执行的机器,执行appium测试代码的机器。狭义点理解,可以把client理解成是代码,当然这些代码可以是java/ruby/python/js的,只要它实现了webdriver标准协议就可以。

这样的设计思想带来了一些好处:

  • 可以带来多语言的支持;
  • 可以把server放在任意机器上,哪怕是云服务器都可以;(是的,appium和webdriver天生适合云测试)

img

安装步骤

安装java环境

目前,java环境普遍来说使用的都是java8,所以我们直接下载安装1.8版本的sdk即可(jdk是Java语言的软件开发工具包,是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库)。

下载地址:https://www.oracle.com/java/technologies/downloads/

鼠标右键安装(注意,不要把它安装到有中文的路径下,所以最好默认路径即可),一路点击确定下一步即可完成安装。

注意:javasdk环境是依赖于JAVA_HOME的,依次打开控制面板系统与安全系统高级系统设置环境变量系统变量新建。变量名中输入JAVA_HOME,变量值中填写刚才获取到的路径C:\tool\Java\jdk1.8.0_201(注意,此处根据自己的实际路径填写,别瞎复制)。

 

保存了JAVA_HOME环境变量,点击下方的Path环境变量,里面把java sdk安装目录下bin目录加入到环境变量中。

 

cmd终端输入java -version,出现如下内容表示安装完成。

 

安装Android SDK

[Android SDK](https://baike.baidu.com/item/Android SDK)(software development kit,译作:软件开发工具包),是用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。Android SDK 指的是Android专属的软件开发工具包。

下载地址:https://www.androiddevtools.cn/#sdk-tools

 

把下载下来的sdk压缩包解压到一个没有中文路径的目录下。例如:我的是 C:/tool/

 

解压完成以后,进入sdk目录下,点击 SDK Manager.exe(sdk开发工具管理器,提供了类似pip的功能)。

按下面图中所示,勾选安卓开发最基本的7个模块到本地。

 

 

 

安装完成以后,Android SDK Tools会在安装成功以后,从上面隐藏掉,不用在意。

接下来,需要把以下三个路径加入到环境变量中,让系统能识别 android sdk(注意根据自己实际的解压路径填写,不要瞎复制)。

C:\tool\android-sdk-windows\tools
C:\tool\android-sdk-windows\platform-tools
C:\tool\android-sdk-windows\build-tools\29.0.3

 

cmd终端下输入命令adb,出现如下效果则安装正确。

 

  • adb.exe( Android Debug Bridge,安卓调试桥),调试app用的命令行工具,借助这个工具,我们可以直接在PC端就可以通过USB或者wifi就可以管理设备或模拟器的状态。保存在android-sdk-windows\platform-tools
  • aapt.exe(Android Asset Packaging Tool),安卓开发使用的一个自动资源打包工具,可以用来检测apk的包名和activity名称。保存在android-sdk-windows\build-tools\&lt;安卓sdk版本&gt;
安装模拟器

appium既支持使用真机测试,也支持模拟器测试。不过我们测试过程中实际上也并非一定要使用真机,因为我们测试的并非是移动端的操作系统而是app本身,所以很多时候测试开发过程中使用模拟器会更加方便,最关键的是模拟器可以轻松切换不同版本。这里推荐使用夜神模拟器(它不仅有windows版本,也有ios版本,而像其他的雷神模拟器,则仅支持windows版本,没有ios版本)。

下载地址:https://www.yeshen.com/

提示:如果windows下同时安装了安卓模拟器和docker-desktop的同学,如果无法顺利启动模拟器,可能需要执行以下命令,切换模拟器与docker-desktop的虚拟化服务。

# 使用模拟器
bcdedit /set hypervisorlaunchtype off
# 使用docker-desktop
bcdedit /set hypervisorlaunchtype auto

模拟器默认在安装以后会在bin目录下提供一个adb.exe安卓调试桥接工具(夜神模拟器叫nox_adb.exe),但是这个工具的版本有可能与我们安装的android sdk的abd.exe版本不一样,这样会导致无法使用appium调试模拟器中的移动端应用,所以需要把android sdk的abd.exe复制并改名替换掉模拟器bin目录下的adb.exe。真机测试则没有这个问题。

找到android sdk安装目录下platform-tools目录下的adb.exe。

 

找到夜神安装目录的bin目录下的nox_adb.exe,并备份,然后替换成上面的。

同时打开模拟器中的配置,修改为手机版面,并开启开发者模式,并勾选开启USB调试功能。

 

 

 

 

点击7下召唤神龙~。。。。说错了,重来,点击7点是打开当前设备的开发者选项。

 

返回上一步,就可以看到多了一个开发者选项了,接下来,开启USB调试选项。

 

 

安装appium

因为版本更新的原因,实际上appium是存在着2个分支版本的,分别是appium Server 与 appium Desktop。其中,appium Server的安装比较复杂需要先安装node.js,所以目前来说官方已经不再更新与维护appium Server分支了,而是推荐测试开发者安装 appium Desktop版本。所以此处,我们直接通过以下链接到github下根据自己当前使用的操作系统安装appium Desktop即可。

下载地址:https://github.com/appium/appium-desktop/releases

 

下载到本地以后双击exe文件,一路默认安装即可。

完成上面操作以后,打开终端输入adb devices ,看到如下效果,则表示安装环境全部完成。

 

> adb devices的结果是当前连接到PC端的所有的移动端设备列表。左侧参数是设备ID,右侧参数是设备的连接状态。 > > 如果使用模拟器则显示效果如下: > 127.0.0.1:5555 device # 表示雷电模拟器 > 127.0.0.1:62001 device # 表示夜神模拟器 > > 如果使用真机则显示效果如下: > UJN0221722001562 device

注意:鸿蒙手机实际上虽然不是安卓系统,但是鸿蒙手机为了兼容安卓,实际上也提供了adb调试,但是很遗憾的是,我们不能直接使用USB调试,只能改用wifi调试才可以测试鸿蒙系统下的app。

adb命令

以下是开发中比较常用的adb命令:

命令描述
adb devices 查询连接到系统的所有移动端设备状态,常见状态:<br>device:连接正常<br/>offline:已断开<br/>unauthorized:未授权(手机端弹出的调试框没有允许)
adb -s 设备ID 指定设备使用adb,设置ID通过上面adb devices可以获取
adb -s 设备ID shell [命令] 使用Android Linux内核的命令
adb -s 设备ID install -r 包名+路径 安装apk包,-r表示覆盖安装,可以使用aapt d badging apk文件路径查看app包名。
adb -s 设备ID uninstall 包名 卸载apk
adb -s 设备ID push 电脑路径 手机路径 电脑文件上传至手机
adb -s 设备ID pull 手机路径 电脑路径 手机文件下载至电脑
adb -s 设备ID shell pm list packages 列出手机中装的所有APP的包名
adb -s 设备ID shell pm clear apk包名 清除应用数据及缓存
**`adb -s 设备ID shell dumpsys window windows grep mFocusedApp`**

安装:

# 通过自动打包工具aapt,查看下载回来的apk的包名,并把源apk文件名改成包名。
aapt d badging C:\Users\Administrator\Desktop\test\jd.apk

# 通过adb指定设备,进行安装
adb -s 127.0.0.1:62001 install C:\Users\Administrator\Desktop\test\com.jingdong.app.mall.apk

# 卸载apk包
adb -s 127.0.0.1:62001 uninstall com.jingdong.app.mall
安装appium-inspector

Appium Inspector是appium Server UI内置的一个元素定位工具,在早期版本中是内置的,新版本已经分离了,所以可以通过以下链接进行安装。

下载地址:https://github.com/appium/appium-inspector/releases

 

安装Appium-Python-Client

Python想要操作appium,就要有专门的的连接工具模块-appium-python-client。直接安装即可。

pip install appium-python-client

OK。经过上面的步骤以后,appium的安装步骤就全部完成了。

基本使用

  1. 打开appium,点击startServer。

 

  1. 打开模拟器或真机,选择要启动的应用,通过cmd终端查找当前应用的包名(appPackage)与激活入口地址(appActivity)。

     

    例如我们在模拟器中选择并打开“设置“。

     adb devices
     adb -s 127.0.0.1:62001 shell dumpsys window windows | grep mFocusedApp
     # adb shell dumpsys window windows | grep mFocusedApp
    

    效果:

     

  2. 通过python操作移动端打开“设置”应用。

    import time
    from appium.webdriver.webdriver import WebDriver
    
    # Appium 服务器初始化参数
    desired_capabilities = {
      "platformName": "Android",  # 系统类型 IOS/Android
      "platformVersion": "7",     # 操作系统版本
      "deviceName": "127.0.0.1:62001",  # 设备类型,设备ID,IOS必须填写
      # adb shell dumpsys window windows | grep mFocusedApp
      "appPackage": "com.jingdong.app.mall",  # 要打开的APP包名
      "appActivity": ".MainFrameActivity"             # APP激活的首屏名称
    }
    
    driver = WebDriver("http://127.0.0.1:4723/wd/hub", desired_capabilities)
    
    time.sleep(5)
    
    driver.quit()
    
    

jsonwp协议

在前面的Appium基本介绍时,我们提到过Appium Server实际上就是一个HTTP服务器,它对外暴露了一系列的restful API接口给开发者进行远程调用。

img

所以我们上面编写的python代码打开设置应用这个过程,本质上就是通过jsonwp(json wire protocol, WebDriver 开发者编写的一种通信协议)协议来实现对远程APP的操作的。

请求方法uri地址描述
POST /session 新建会话
DELETE /session/会话ID 删除会话
GET /status 获取appium服务器状态信息

更多restful API接口操作:https://w3c.github.io/webdriver/#x6-5-endpoints

postman操作

// 新建会话
// POST http://127.0.0.1:4723/wd/hub/session
{
    "desiredCapabilities": {
        "platformName": "Android",
        "platformVersion": "7",
        "deviceName": "127.0.0.1:62001",
        "appPackage": "com.android.settings",
        "appActivity": ".Settings"
    }
}

// 删除会话【会话ID在上面的请求操作的响应字典中可以找到】
// DELETE http://127.0.0.1:4723/wd/hub/session/d9cd07ad-1170-49fd-99cc-a4fb4f4e4435

capability

初始化参数(Capability)是JSON数据类型编码的键和值,当一个新的自动化会话被请求时,Appium客户端发送此参数到服务端。此参数传递到Appium drivers用于设置各种重要事项测试工作。每种客户端语言都有特定的Appium客户端构建参数,但最终他们以JSON数据发送到Appium Server的。

初始化参数(Capability)可以编写在WebDriver测试代码中或者存放在Appium Server GUI中(Inspector会话)。

启动参数文档:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

中文翻译文档:https://github.com/appium/appium/blob/master/docs/cn/writing-running-appium/caps.md

通用参数
描述
automationName 自动化测试的引擎 Appium (默认)或者 Selendroid
platformName 使用的手机操作系统 iOSAndroid, 或者 FirefoxOS
platformVersion 手机操作系统的版本 例如 7.14.4
deviceName 使用的手机或模拟器设备名称 iPhone SimulatoriPad SimulatoriPhone Retina 4-inchAndroid EmulatorGalaxy S4, 等等… 在 iOS 上,使用 Instruments 的 instruments -s devices 命令可返回一个有效的设备的列表,例如:iPhone X等。在 Andorid 上虽然这个参数目前已被忽略,但仍然需要添加上该参数。
app 本地绝对路径_或_远程 http URL 所指向的一个安装包(.ipa,.apk,或 .zip 文件)。Appium 将其安装到合适的设备上。请注意,如果您指定了 appPackage 和 appActivity 参数(见下文),Android 则不需要此参数了。该参数也与 browserName 不兼容。 /abs/path/to/my.apk 或 http://myapp.com/app.ipa
browserName 做自动化时使用的浏览器名字。如果是一个应用则只需填写个空的字符串 ‘Safari’ 对应 iOS,‘Chrome’, ‘Chromium’, 或 ‘Browser’ 则对应 Android
newCommandTimeout 用于客户端在退出或者结束 session 之前,Appium 等待客户端发送一条新命令所花费的时间(秒为单位) 例如 60
language (Sim/Emu-only) 为模拟器设置语言 例如 fr
locale (Sim/Emu-only) 为模拟器设置所在区域 例如 fr_CA
udid 连接真机的唯一设备号 例如 1ae203187fc012g
orientation (Sim/Emu-only) 模拟器当前的方向 竖屏 或 横屏
autoWebview 直接转换到 Webview 上下文(context)。默认值为 false truefalse
noReset 在当前 session 下不会重置应用的状态。默认值为 false truefalse
fullReset (iOS)删除所有的模拟器文件夹。(Android) 要清除 app 里的数据,请将应用卸载才能达到重置应用的效果。在 Android, 在 session 完成之后也会将应用卸载掉。默认值为 false truefalse
Android 独有
描述
appActivity Activity 的名字是指从你的包中所要启动的 Android acticity。他通常需要再前面添加. (例如 使用 .MainActivity 代替 MainActivity MainActivity.Settings
appPackage 运行的 Android 应用的包名 com.example.android.myAppcom.android.settings
appWaitActivity 用于等待启动的 Android Activity 名称 SplashActivity
appWaitPackage 用于等待启动的 Android 应用的包 com.example.android.myAppcom.android.settings
appWaitDuration 用于等待 appWaitActivity 启动的超时时间(以毫秒为单位)(默认值为 20000) 30000
device

标签:webdriver,Appium,option,selenium,APP,driver,element,规避,import
From: https://www.cnblogs.com/Haier123/p/18400498

相关文章

  • 短剧APP系统搭建,短剧市场的发展机遇
    短剧作为近几年内发展快速的行业,一直深受大众的欢迎,各种让观众上头的短剧层出不穷,深深吸引着大众。短剧的巨大发展前景也吸引了大量资本涌入市场,目前,短剧入局者也都获得了不菲的经济收益!随着短剧行业的快速发展,短剧APP平台也进入到了蓬勃发展期,为大众带来一个便利、丰富的短剧观看......
  • estimate、appraise、assess和evaluate的区别
    estimate:预估。estimate的结果一定是一个具体的数字。比如:Governmentsourcesestimatealong-term50percentincreaseinrailfares.(政府消息人士估计,火车票会上涨50%)。宾语中带有数值结果是estimate的重要特征:其它几个词的宾语都是被评估的事物,强调的是评估行为本身,通常不......
  • 【Java】【SpringBoot】读取配置文件(appliation.yml)的值
    这里叙述4中读取配置文件(application.yml)方法  application.yml配置如下:#测试数据(用于读取数据文件值)student:name:lisiage:13name:zhangsan使用@value注解@SpringBootTestpublicclassApplicationTest{@Value("${student.name}")privateStr......
  • 媒体网站广告APP首页怎么投放?新闻首页视频焦点图文字链意义详解
    【本篇由言同数字媒体广告发稿原创】在信息爆炸的数字时代,媒体网站和新闻APP成为了重要的信息传播平台。广告作为这些平台的重要组成部分,通过多种形式帮助品牌达到目标受众。本文将介绍媒体网站和新闻APP的广告形式、行业领域新闻媒体的广告实例,以及广告合作的方法。广告形式1.首......
  • 基于SpringBoot+Vue+uniapp的同城蔬菜配送管理系统(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 基于SpringBoot+Vue+uniapp的教学辅助微信小程序(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 基于SpringBoot+Vue+uniapp的课程教学网站(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 基于SpringBoot+Vue+uniapp的电商平台的用户画像(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 仿 SOUL 社交友附近人婚恋约仿陌陌 APP 源码系统
    前言专门为单身男女打造的恋爱交友社区,就是一个由千千万万单身男女组建的大家庭。他们来自全国各地,或许有着不同的人生经历,却有着共同的对恋爱交友的渴望。他们可以通过文字、语音、视频聊天的方式,和镜头前的彼此诉说自己工作中发生的趣事,也可以分享自己在生活中遇到的惊喜。......
  • DAY87 APP 攻防-安卓逆向篇&Smail 语法&反编译签名重打包&Activity 周期&Hook 模块
    1、APK逆向-数据修改-结构&格式2、APK逆向-逻辑修改-Smail语法3、APK逆向-视图修改-Activity&Xml#章节点:1、APP资产-内在提取&外在抓包2、APP逆向-反编译&删验证&重打包3、APP安全-存储&服务&组件&注册等演示案例:ØAPK逆向-数据修改-结构&格式ØA......