UI 自动化测试selenium(四)

除了对正常的页面进行操作,我们还经常会遇到各种弹窗,或者跳转到新页面

弹窗处理

操作alert常⽤的⽅法:
switch_to.alert():获取当前页⾯上的警告框。
text:返回alert/confirm/prompt 中的⽂字信息。
accept():接受现有警告框。
dismiss():解散现有警告框。
send_keys(keysToSend):发送⽂本⾄警告框。keysToSend:将⽂本发送⾄警告框

alert(通知框
也就是只有一个确认按钮

# --- alert ---
driver.find_element(By.ID, 'b1').click()

# 打印 弹出框 提示信息(只是打印)
print(driver.switch_to.alert.text) 

# 点击 OK 按钮
driver.switch_to.alert.accept()

confirm(确认取消框
有一个确认和取消按钮

# --- confirm ---
driver.find_element(By.ID, 'b2').click()

# 打印 弹出框 提示信息
print(driver.switch_to.alert.text)

# 点击 OK 按钮 
driver.switch_to.alert.accept()

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

# 点击 取消 按钮
driver.switch_to.alert.dismiss()

prompt(输入信息框)

也就是得输入信息

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://cdn2.byhy.net/files/selenium/test4.html')


# --- prompt ---
driver.find_element(By.ID, 'b3').click()

# 获取 alert 对象
alert = driver.switch_to.alert

# 打印 弹出框 提示信息
print(alert.text)

# 输入信息,并且点击 OK 按钮 提交
alert.send_keys('web自动化 - selenium')
alert.accept()

# 点击 Cancel 按钮 取消
driver.find_element(By.ID, 'b3').click()
alert = driver.switch_to.alert
alert.dismiss()

那如果有多个输入框呢?

思路:

alert = driver.switch_to.alert相当与实例化一个窗口对象

那其实直接根据之前的选择方式就可以,不过开头变成alert.find_element(CSS_SELECT,"元素"),就是相当于在另外一个页面进行元素定位

多窗口处理流程(页面跳转)

思路:

先取得当前页面的句柄:

window=driver.current_window_handle
# 当前页面的句柄
# 可以快速切换回当前页面:
driver.switch_to.window(window)

注意这个句柄是个变量

再获得所有的窗口句柄:

解释一下为什么是获取所有句柄,那不是直接获取我们需要点开的页面的句柄?

因为没办法,只有这两个参数。

windows_all=driver.window_handles
# 获取所有页面的句柄

方法1:

#对所有句柄进行遍历
for hendle in driver.window_handles:
	#切换页面
    driver.switch_to.window(handle)
	#如果页面的标题名称与我们需要的页面相同,那就退出循环
    if '必应' in wd.title:
        break

方法2:

#打印所有的跳转页面的句柄
print(driver.window_handles)
#点击后跳转
driver.find_element(By.ID, '3b').click()
#打印所有的跳转页面的句柄
print(driver.window_handles)
#你会发现最后多了一个新句柄,那个句柄就是我们需要的
window_new=driver.window_handles
driver.switch_to.window(window_new[-1])

Frame框架

其实也就是内嵌的html框架

frame标签包含frameset、frame、iframe三种、

frameset和普通的标签一样,不会影响正常的定位,可以使用index、id、name 、webelement任意种方式定位frame。

frame存在两种:

一种是嵌套的,一种是未嵌套的。

<frame id=frame></frame>
#根据元素id或者index切换切换
driver.switch_to.frame("frame")
#切换到默认frame
driver.switch_to.default_content() 
#切换到父级frame
driver.switch_to.parent_frame()

嵌套:

driver.switch_to.frame("父节点")
driver.switch_to.frame("子节点")

文件上传

其实也就是图片或者文件的路径
使用send_key("路径")

避开繁琐登录,比如手机二维码验证、手机验证码验证

这里有一个面试题:

如果登录的时候遇到需要登录验证、人机验证,测试化的时候应该怎么解决?

登录验证比如验证码本身就是用来对抗自动化的,我们的想法应该是去绕过他,而不是去解决它。

答案:

一般是设置万能验证码、或者使用不带验证码的测试版,或者绕过验证码常见的登录场景

绕过验证码登录场景的方法:

Chrome的debug模式(Windos):

按照以下步骤进行:

  1. 确保关闭所有现存的 Chrome 进程
    打开“命令提示符”或“PowerShell”并输入以下命令来结束所有 Chrome 进程:

    taskkill /F /IM chrome.exe /T

    /F 标志是用来强制终止进程的,/IM 表示通过映像名称来指定要终止的进程,/T 终止指定的进程和由它启动的任何子进程。

  2. 在调试模式下启动 Chrome 浏览器
    打开“命令提示符”或“PowerShell”并输入以下命令来以调试模式启动 Chrome:
    我的chrome.exe路径为:C:\Program Files\Google\Chrome\Application\chrome.exe,需要改成你自己的。

    & "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:\chrome_debug"
    //注意&符号!
    //其实可以将C:\Program Files\Google\Chrome\Application这个路径加入到环境变量,代码可以省略为:
    & "chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:\chrome_debug"
    //注意&符号!
    //配置完成后一定要记得重启命令行!!!
  1. 这里的命令做了两件事:

    • 使用 --remote-debugging-port=9222 来指定远程调试端口为 9222。

    • 使用 --user-data-dir 来创建一个临时用户数据目录,这个目录将存储调试模式下的所有用户信息。

    如果C:\chrome_debug 目录不存在,Chrome 将在运行时创建该目录。你可以使用任何你希望存放用户数据的目录路径。

  2. 通过 Selenium 连接到远程调试的 Chrome 实例
    打开你的自动化脚本并使用以下 Python 代码,让 Selenium 连接到该 Chrome 实例:

    from selenium import webdriver
    
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_experimental_option("debuggerAddress", "localhost:9222")
    
    driver = webdriver.Chrome(executable_path='path_to_your_chromedriver.exe', options=chrome_options)
    
    # 现在你可以通过 driver 对象来控制已开启的 Chrome 浏览器 instance 了
    

    确保替换 path_to_your_chromedriver.exe 为你的 chromedriver 的实际路径。
    如果设置了环境变量,可省略

Chrome的debug模式(Mac):

以下是 Mac 上如何启动 Chrome 以便进行远程调试的步骤:

  1. 关闭所有现存的 Chrome 进程
    你可以使用 pkill 命令。打开终端(Terminal.app),然后输入:

    pkill -a -i "Google Chrome"

    这里 -a 选项会将应用程序的所有进程标记为可终止的,而 -i 会忽略进程名称的大小写。

  2. 在调试模式下启动 Chrome
    在终端中,使用以下命令:

    /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir="/tmp/chrome_debug"

    这个命令会启动 Chrome 并打开远程调试端口 9222,同时创建一个临时用户数据目录 /tmp/chrome_debug

  3. 通过 Selenium 连接到远程调试的 Chrome 实例
    打开你的自动化脚本并使用以下 Python 代码,让 Selenium 连接到该 Chrome 实例:

    from selenium import webdriver
    
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_experimental_option("debuggerAddress", "localhost:9222")
    
    driver = webdriver.Chrome(executable_path='path_to_your_chromedriver.exe', options=chrome_options)
    
    # 现在你可以通过 driver 对象来控制已开启的 Chrome 浏览器 instance 了
    

    确保替换 path_to_your_chromedriver.exe 为你的 chromedriver 的实际路径。
    如果设置了环境变量,可省略

COOKIE登录实现跳过登录

获取cookies

cookies = self.driver.get_cookies()

输入cookies

for cookie in cookies:
            self.driver.add_cookie(cookie)
import time
import yaml
from selenium import webdriver

class TestCookie:
    def teardown(self):
        # 关闭浏览器驱动
        self.driver.quit()

    def setup(self):
        # 实例化浏览器驱动
        self.driver = webdriver.Edge()
        # 隐式等待
        self.driver.implicitly_wait(10)
        # 跳转页面

    def test_login(self):
        self.driver.get("https://account.aliyun.com/")
        # 在sleep的过程中,登录
        time.sleep(10)
        # driver.get_cookies()可以获取cookies
        cookies = self.driver.get_cookies()
        print(cookies)
        # 将cookies存入文件
        with open("cookie.yaml","w") as f:
            yaml.safe_dump(cookies,f)

    def test_add_cookie(self):
        # 这里一定要再登录一次!!!!
        self.driver.get("https://account.aliyun.com/")
        #获取文件中的 cookies
        cookies = yaml.safe_load(open("cookie.yaml"))
        print(cookies)
        for cookie in cookies:
            self.driver.add_cookie(cookie)
        time.sleep(3)
        # 再次访问以验证 cookie 是否添加成功
        self.driver.get("https://account.aliyun.com/")