pytest+selenium做自动化测试(登录注册)有感

安装装环境的小插曲:安装了135版本的谷歌浏览器和对应135版本的驱动,运行demo程序时报错(打开谷歌,在百度网站进行搜索),原因就是selenium不使用我下载的135版本的谷歌浏览器,而是在C:\Users\wenyong\.cache\selenium\chrome\win64\140.0.7339.80下载一个140版本的谷歌浏览器,然后造成浏览器和驱动版本不一致!难怪第一次运行半天没动静,下东西去了。

        关键是我代码里指定用我自己下载的浏览器它也还是报错(浏览器和驱动不兼容),禁用Selenium的自动管理貌似也没起到作用。包括降低selenuim版本。后来我卸载了自己下载的浏览器,就用它下载的吧,然后换了个和他匹配的驱动,成功运行了。(但是今天学习完毕后回过头反思,兼容性测试就是要测高版本和低版本的兼容性问题,你怎么办?考虑过没有?)

1.完整的多版本浏览器测试解决方案

1.使用配置文件管理不同浏览器版本

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.edge.options import Options as EdgeOptions
import pytest
import os

# 浏览器配置字典 - 可以轻松切换不同版本
BROWSER_CONFIGS = {
    "chrome_140": {
        "browser_type": "chrome",
        "browser_path": r"C:\Program Files\Google\Chrome\Application\chrome.exe",
        "driver_path": r"C:\WebDriver\chrome_140\chromedriver.exe"
    },
    "chrome_120": {
        "browser_type": "chrome", 
        "browser_path": r"D:\Browsers\Chrome_120\chrome.exe",
        "driver_path": r"C:\WebDriver\chrome_120\chromedriver.exe"
    },
    "chrome_100": {
        "browser_type": "chrome",
        "browser_path": r"D:\Browsers\Chrome_100\chrome.exe",
        "driver_path": r"C:\WebDriver\chrome_100\chromedriver.exe"
    },
    "firefox_115": {
        "browser_type": "firefox",
        "browser_path": r"D:\Browsers\Firefox_115\firefox.exe",
        "driver_path": r"C:\WebDriver\geckodriver.exe"
    },
    "edge_110": {
        "browser_type": "edge",
        "browser_path": r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
        "driver_path": r"C:\WebDriver\msedgedriver.exe"
    }
}

@pytest.fixture(scope="function", params=["chrome_140", "chrome_120", "chrome_100"])
def browser(request):
    """多版本Chrome浏览器测试"""
    config_name = request.param
    config = BROWSER_CONFIGS[config_name]
    
    print(f"使用浏览器版本: {config_name}")
    
    if config["browser_type"] == "chrome":
        chrome_options = Options()
        chrome_options.binary_location = config["browser_path"]
        chrome_options.add_argument('--disable-blink-features=AutomationControlled')
        
        service = Service(executable_path=config["driver_path"])
        driver = webdriver.Chrome(service=service, options=chrome_options)
        
    elif config["browser_type"] == "firefox":
        firefox_options = FirefoxOptions()
        firefox_options.binary_location = config["browser_path"]
        driver = webdriver.Firefox(executable_path=config["driver_path"], options=firefox_options)
        
    elif config["browser_type"] == "edge":
        edge_options = EdgeOptions()
        edge_options.binary_location = config["browser_path"]
        edge_options.use_chromium = True
        driver = webdriver.Edge(executable_path=config["driver_path"], options=edge_options)
    
    driver.implicitly_wait(10)
    yield driver, config_name  # 返回驱动和配置名称
    driver.quit()

def test_compatibility(browser):
    """兼容性测试"""
    driver, browser_version = browser
    driver.get("https://hmshop-test.itheima.net/Home/user/login.html")
    
    # 记录测试的浏览器版本
    print(f"在 {browser_version} 上进行测试")
    
    # 执行测试逻辑
    # ...
    
    assert "登录" in driver.title
    print(f"{browser_version} 测试通过")

2.通过命令行参数选择浏览器版本

import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

def pytest_addoption(parser):
    """添加命令行选项"""
    parser.addoption("--browser-version", action="store", default="chrome_140", 
                    help="选择浏览器版本: chrome_140, chrome_120, chrome_100, firefox_115, edge_110")

@pytest.fixture(scope="function")
def browser(request):
    """根据命令行参数选择浏览器版本"""
    browser_version = request.config.getoption("--browser-version")
    
    # 浏览器配置
    configs = {
        "chrome_140": {
            "path": r"C:\Program Files\Google\Chrome\Application\chrome.exe",
            "driver": r"C:\WebDriver\chrome_140\chromedriver.exe"
        },
        "chrome_120": {
            "path": r"D:\Browsers\Chrome_120\chrome.exe",
            "driver": r"C:\WebDriver\chrome_120\chromedriver.exe"
        },
        # 添加更多版本...
    }
    
    config = configs.get(browser_version, configs["chrome_140"])
    
    chrome_options = Options()
    chrome_options.binary_location = config["path"]
    
    # 完全禁用Selenium的自动管理
    service = Service(
        executable_path=config["driver"],
        service_args=['--disable-build-check']
    )
    
    driver = webdriver.Chrome(service=service, options=chrome_options)
    yield driver
    driver.quit()

# 运行方式: pytest --browser-version=chrome_120

3.使用环境变量控制

import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

# 设置环境变量彻底禁用自动下载
os.environ['SE_DISABLE_AUTO_DOWNLOAD'] = 'true'
os.environ['SE_DONT_DOWNLOAD_CHROMEDRIVER'] = 'true'
os.environ['WD_BROWSER_PATH'] = ''  # 清空自动检测

def get_browser(version="140"):
    """手动创建指定版本的浏览器实例"""
    version_configs = {
        "140": {
            "browser": r"C:\Program Files\Google\Chrome\Application\chrome.exe",
            "driver": r"C:\WebDriver\chrome_140\chromedriver.exe"
        },
        "120": {
            "browser": r"D:\Browsers\Chrome_120\chrome.exe", 
            "driver": r"C:\WebDriver\chrome_120\chromedriver.exe"
        },
        "100": {
            "browser": r"D:\Browsers\Chrome_100\chrome.exe",
            "driver": r"C:\WebDriver\chrome_100\chromedriver.exe"
        }
    }
    
    config = version_configs[version]
    
    chrome_options = Options()
    chrome_options.binary_location = config["browser"]
    
    service = Service(executable_path=config["driver"])
    
    return webdriver.Chrome(service=service, options=chrome_options)

@pytest.fixture(scope="function", params=["140", "120", "100"])
def multi_version_browser(request):
    """多版本浏览器测试"""
    driver = get_browser(request.param)
    yield driver
    driver.quit()

2.元素定位的作用

        版本问题不报错了,但是还是没有成功的让Python控制浏览器完成搜索任务(打开谷歌,在百度网站进行搜索)!这个代码网上有现成的代码,我把这个代码以及运行报错都发给了deepseek,当然很可能是我把有问题的源码(百度网页元素更改导致之前的代码不能用了)给到大模型,由于聊天记忆的原因,一直没有给我纠正这个错误!通过元素定位,发现原来的代码 "kw"、“su”不能进行元素定位了!其实大模型分析的时候就给说了有可能是网站跟新导致元素定位不准,我看这代码是前几个月的不可能网站就做了跟新,也没必要做这个跟新,就一直没有去元素定位往这方面想!在他给我的另外的几个可能的情况里扰!

"""
import webbrowser

search_query = "北京烤鸭"
baidu_url = f"https://www.baidu.com/s?wd={search_query}"
webbrowser.open(baidu_url)
"""

# 导包 webdriver
from selenium import webdriver
import time

# 实例化浏览器对象 谷歌 tab键
driver = webdriver.Chrome()

# 打开百度
driver.get("https://www.baidu.com")

from selenium.webdriver.common.by import By
# 输入北京烤鸭
driver.find_element(By.ID, "kw").send_keys("北京烤鸭")

# 点击搜索按钮
driver.find_element(By.ID, "su").click()

time.sleep(3)
# 关闭浏览器
driver.quit()

元素定位后很快实现了这个自动化操作,元素定位有几种方式,其中用id或者css_selector最常用。 发现搜索框和搜索按钮的css_selector变化了分别是:#chat-textarea   #chat-submit-button

3.整合pytest

小白的疑惑,使用ython做web自动化测试时,有了selenium库,为什么还要用到pytest?

有个恰当的比喻:

  • Selenium = 演员(执行具体的浏览器操作)

  • pytest = 导演+制片人(组织、管理、报告测试)

功能维度Seleniumpytest
主要职责浏览器自动化操作测试框架管理
功能点击、输入、导航等测试组织、断言、测试报告
定位元素定位和交互测试用例管理和执行
报告无内置报告功能丰富的报告生成
数据驱动需要自己实现内置数据驱动支持
没有pytest只能写脚本,有 pytest就能做结构化测试。

记住一些规则,pytest 就能自动发现并运行您的测试了!这是 pytest 的"约定优于配置"理念的体现。Java里的sprongboot也提到过这个理念!

项目规则示例
测试文件test_*.py 或 *_test.pytest_login.pylogin_test.py
测试函数以 test_ 开头test_valid_login()
测试类以 Test 开头TestLogin
类方法以 test_ 开头test_login_success()

我把登录和注册两个测试用例写在main方法里,结果运行就报错了!

Fixture (夹具)是 pytest 测试框架的核心机制,它通过依赖注入(spring里核心就是控制反转和依赖注入!)模式实现测试资源的声明式管理。其主要作用体现在三个维度:

  1. 资源生命周期治理 - 封装测试对象的创建、分配与销毁过程,确保资源使用的规范性和安全性

  2. 测试环境一致性保障 - 通过预设环境状态,消除测试间的相互干扰,保证测试用例的独立性与可重复性

  3. 测试代码重构优化 - 分离测试逻辑与基础设施代码,降低耦合度,提升测试套件的可维护性与可扩展性

说人话就是准备工作写在fixture修饰的方法里,看下面的代码就一目了然了

Scope 是 pytest 夹具中控制资源生命周期范围的核心参数,它定义了夹具实例在测试会话中的创建频率和共享范围。我当时的范围是module(同一模块内所有测试共享夹具实例),运行两个测试用例(登录和注册)会报错,哪怕我按照deepseek的建议在登录用例结束后不要调用 browser.quit(),给我的理由是测试函数中手动调用 browser.quit() 破坏了fixture的生命周期管理,第二个测试用例尝试使用已被关闭的浏览器实例!  但是我注释调这句话还是报错,注册用例依然不能正常运行,界面都打不开!把作用域改成function就没问题,哪怕登录用例加上browser.quit()也可以正确运行!

# 导入所需的库
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
import pytest
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time

from selenium.webdriver.support.wait import WebDriverWait


# 定义 fixture 用于初始化和关闭浏览器
@pytest.fixture(scope="function")
def browser():
    # 创建 ChromeOptions 对象
    chrome_options = Options()

    # 指定 Chrome 浏览器路径(使用你之前成功的路径)
    chrome_binary_path = r"C:\Users\wenyong\.cache\selenium\chrome\win64\140.0.7339.80\chrome.exe"
    chrome_options.binary_location = chrome_binary_path

    # 添加其他选项
    chrome_options.add_argument('--disable-blink-features=AutomationControlled')
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    # 1. 打开浏览器并访问登录页面
    driver = webdriver.Chrome(options=chrome_options)  # 初始化 Chrome 浏览器
    driver.implicitly_wait(10)  # 设置隐式等待时间为 10 秒
    yield driver  # 返回浏览器对象
    driver.quit()  # 测试结束后关闭浏览器


def test_login(browser):
    # 打开登录页面
    browser.get("https://hmshop-test.itheima.net/Home/user/login.html")  # 打开登录页面

    # 输入用户名
    username_input = browser.find_element(By.CSS_SELECTOR, "#username")  # 定位用户名输入框
    username_input.clear()  # 清空用户名输入框
    username_input.send_keys("13600001111")  # 输入用户名 13600001111

    # 输入密码
    password_input = browser.find_element(By.CSS_SELECTOR, "#password")  # 定位密码输入框
    password_input.clear()  # 清空密码输入框
    password_input.send_keys("123456")  # 输入密码 123456

    # 输入图片验证码
    verify_code_input = browser.find_element(By.CSS_SELECTOR, "#verify_code")  # 定位验证码输入框
    verify_code_input.clear()  # 清空验证码输入框
    verify_code_input.send_keys("8888")  # 输入验证码 8888

    # 点击登录按钮
    login_button = browser.find_element(By.CSS_SELECTOR, "#loginform > div > div.login_bnt > a")  # 定位登录按钮
    login_button.click()  # 点击登录按钮
    time.sleep(3)
    # 关闭浏览器
    #browser.quit()

#注册的测试用例
def test_register(browser):
    # 1. 访问注册页面
    browser.get("https://hmshop-test.itheima.net/Home/User/reg.html")
    wait = WebDriverWait(browser, 20)

    current_url = browser.current_url
    print(f"当前URL: {current_url}")
    print(f"页面标题: {browser.title}")

    # 2. 输入用户名
    username_input = browser.find_element(By.CSS_SELECTOR, "#username")
    username_input.clear()
    username_input.send_keys("19896257372")

    # 3. 输入密码
    password_input = browser.find_element(By.CSS_SELECTOR, "#password")
    password_input.clear()
    password_input.send_keys("1989625")

    #4.输入验证码
    verify_code_input = browser.find_element(By.CSS_SELECTOR, "#reg_form2 > div > div > div > div:nth-child(2) > div.liner > input")

    # 5. 输入确认密码
    confirm_password_input = browser.find_element(By.CSS_SELECTOR, "#password2")
    confirm_password_input.clear()
    confirm_password_input.send_keys("123456")

    #点击同意协议并注册
    agree_button = browser.find_element(By.CSS_SELECTOR, "#reg_form2 > div > div > div > div.line.liney.clearfix > div > a")
    agree_button.click()




执行也不是run某个文件 ,而是在终端用pytest!

        生成测试结果:pytest -–alluredir=report,将结果转为报告:allure serve report 需要两个环境:一是java运行环境(allure核心解析测试结果数据、生成报告的逻辑是java开发的),二是要node.js环境(npm包下载allure命令行工具,npm需要node环境,生成后的静态文件(HTML/CSS/JS写的Allure 报告的前端界面)本身不依赖 Node,直接用浏览器打开即可查看。)

4.自动化测试的应用场景:

回归测试:包括缺陷修复后手动做的回归测试,还有Git push后通过cicd流水线自动触发的自动化测试套件。

冒烟测试:仅验证软件最核心、最基本的功能(如登录、主要流程操作、关键按钮响应等),不涉及复杂场景或细节功能。电商平台的冒烟测试可能包括 “打开首页→搜索商品→加入购物车→提交订单” 这一核心流程,可能不涉及测试优惠券使用、退款等细节。执行时间短(通常几分钟到一小时内),目的是快速反馈软件是否 “可测”,尽早发现严重问题!

数据驱动的参数化的测试也适合做自动化,比如登录,要考虑很多边界值,一个个手动执行不如把这些边界值参数都做成参数让程序一个个跑。

压力测试:高并发、大流量场景难以手动模拟!压力测试常需要持续数小时甚至数天(如验证系统的稳定性、内存泄漏问题),手动测试无法长时间保持高效、一致的操作,而自动化脚本可以 24 小时不间断执行。压力测试需收集响应时间、错误率、服务器 CPU / 内存占用等大量指标,自动化工具可实时记录并生成可视化报告(如 TPS 曲线、响应时间分布),手动记录不仅效率低,还易出错。   下一篇博客,我就要写python自动化测试做接口自动化、app自动化,web自动化看看还有什么可以补充!

<think>好的,用户想了解如何使用pytestselenium框架进行UI自动化测试。首先,我需要整理一个清晰的步骤指南,涵盖环境安装、基本用法、测试案例和框架集成。根据提供的引用内容,特别是引用[2]和[3],用户可能需要详细的步骤和示例代码。首先,环境配置部分需要说明安装pytestselenium和浏览器驱动。用户可能不熟悉驱动配置,需要强调webdriver的路径设置或使用管理工具。接下来,pytest的基本使用,比如测试发现规则和断言方法,引用[2]提到练习pytest基本使用是实验的一部分,所以这部分需要简明扼要。 然后是selenium的基本操作,比如打开网页、元素定位和表单操作。引用[2]中的案例涉及搜索和登录功能,因此需要提供类似的示例,例如搜索python.org和登录github。这部分需要代码示例,并解释每一步的作用。 接下来是整合pytestselenium,这里可以提到使用fixture来管理浏览器实例,这样每个测试用例不需要重复初始化。引用[3]提到了结合Allure生成报告,但用户的问题可能暂时不需要高级功能,但可以简要提及作为扩展。此外,需要注意常见的潜在问题,比如元素定位方式的变化、等待机制的处理,以及如何处理弹窗或验证码。引用[3]中的框架可能包含这些优化点,可以建议用户参考。 最后,生成相关问题需要考虑用户可能的后续需求,比如性能优化、框架扩展或实际应用场景。确保问题覆盖用户可能遇到的下一步挑战,比如如何处理动态元素或提升测试稳定性。需要检查是否符合系统级指令,所有数学公式是否正确使用$...$,独立公式是否单独成段。但当前问题不涉及数学公式,所以可能不需要这部分。确保回答使用中文,结构清晰,分步骤说明,并添加引用标识。引用[2]详细描述了实验步骤,所以相关部分需要标注引用。同时,代码块要正确使用Python语法,并注意缩进。</think>### 如何使用 pytestselenium 框架进行 UI 自动化测试? #### 一、环境安装与配置 1. **安装依赖包** ```bash pip install pytest selenium webdriver-manager ``` - `pytest`:测试框架,支持用例发现、参数化、断言等功能 - `selenium`:浏览器自动化工具 - `webdriver-manager`:自动管理浏览器驱动(如ChromeDriver)[^2] 2. **配置浏览器驱动** ```python from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager driver = webdriver.Chrome(ChromeDriverManager().install()) ``` - 无需手动下载驱动,`webdriver-manager`会自动匹配当前浏览器版本[^3] --- #### 二、pytest 基本使用 1. **测试用例编写规则** - 文件名需以 `test_` 开头(如 `test_login.py`) - 函数名需以 `test_` 开头(如 `test_search()`) - 使用 `assert` 断言验证结果[^2] 2. **示例:简单断言测试** ```python def test_addition(): assert 1 + 1 == 2 ``` --- #### 三、selenium 基本操作 1. **浏览器操作** ```python driver.get("https://www.python.org") # 打开网页 driver.maximize_window() # 最大化窗口 driver.refresh() # 刷新页面 driver.quit() # 关闭浏览器 ``` 2. **元素定位与交互** ```python # 通过ID定位搜索框并输入内容 search_input = driver.find_element("id", "id-search-field") search_input.send_keys("pytest") # 通过XPath定位搜索按钮并点击 search_button = driver.find_element("xpath", "//button[@type='submit']") search_button.click() ``` --- #### 四、整合 pytestselenium 1. **使用 fixture 管理浏览器** ```python import pytest from selenium import webdriver @pytest.fixture(scope="module") def browser(): driver = webdriver.Chrome() yield driver driver.quit() ``` 2. **完整测试案例:Python官网搜索功能** ```python def test_python_search(browser): browser.get("https://www.python.org") search_input = browser.find_element("id", "id-search-field") search_input.send_keys("pytest") search_button = browser.find_element("xpath", "//button[@type='submit']") search_button.click() assert "Results" in browser.page_source ``` 3. **登录功能测试示例(Github)** ```python def test_github_login(browser): browser.get("https://github.com/login") username = browser.find_element("id", "login_field") password = browser.find_element("id", "password") username.send_keys("your_username") password.send_keys("your_password") login_button = browser.find_element("name", "commit") login_button.click() assert "Dashboard" in browser.title ``` --- #### 五、优化与扩展 1. **参数化测试** 使用 `@pytest.mark.parametrize` 实现多组数据测试: ```python @pytest.mark.parametrize("keyword", ["pytest", "selenium", "unittest"]) def test_search_keywords(browser, keyword): browser.get("https://www.python.org") search_input = browser.find_element("id", "id-search-field") search_input.send_keys(keyword) search_button.click() assert keyword in browser.page_source ``` 2. **集成 Allure 报告** - 安装 Allure:`pip install allure-pytest` - 生成报告:`pytest --alluredir=./results` - 查看报告:`allure serve ./results`[^3] --- #### 常见问题与解决 1. **元素定位失败** - 使用显式等待:`WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "element_id")))` - 检查动态加载内容或iframe嵌套 2. **验证码处理** - 测试环境禁用验证码 - 使用第三方服务(如Twilio)自动识别(仅限简单验证码) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值