1. 项目概述与价值定位

最近在技术社区和招聘要求里,“UI自动化测试”这个词出现的频率越来越高。很多刚接触测试或者想从功能测试转型的同学,常常觉得这个概念听起来高大上,实际操作起来却不知从何下手。其实,UI自动化的核心,就是用代码模拟人的操作,让程序去点点按钮、填填表单。今天,我就以一个最经典、最刚需的场景——“用户登录”为例,带你手把手用Python和Selenium写一个完整的登录UI自动化脚本。这个脚本麻雀虽小,五脏俱全,涵盖了环境搭建、元素定位、数据驱动、异常处理等核心知识点。无论你是想提升测试效率,还是为学习自动化打下第一块基石,这个从零到一的实践过程都值得你花时间跟着走一遍。你会发现,所谓的“自动化”,并没有想象中那么遥不可及。

2. 环境准备与核心工具解析

2.1 Python与Selenium的安装与配置

工欲善其事,必先利其器。我们的自动化脚本运行在Python环境中,并通过Selenium库来控制浏览器。因此,第一步就是搭建好这个基础环境。

首先,确保你的电脑上安装了Python。建议使用Python 3.7及以上版本,因为社区支持和库的兼容性更好。你可以打开命令行(Windows上是CMD或PowerShell,Mac/Linux上是Terminal),输入 python --version python3 --version 来检查。如果没有安装,去Python官网下载安装包,记得勾选“Add Python to PATH”这个选项,这是为了能在命令行中直接使用python命令。

接下来安装Selenium。Selenium是一个强大的浏览器自动化工具,它提供了一套WebDriver API,允许我们用代码像真实用户一样操作浏览器。安装非常简单,只需要一条pip命令:

pip install selenium

如果你在国内,觉得下载速度慢,可以使用清华的镜像源来加速:

pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple

注意:有些同学可能会遇到同时安装了Python2和Python3的情况,导致命令混淆。这时,明确使用 pip3 install selenium 来为Python3安装库是更稳妥的做法。

2.2 浏览器驱动的选择与下载

Selenium本身不能直接控制浏览器,它需要一个“桥梁”,这就是浏览器驱动(WebDriver)。不同的浏览器需要不同的驱动。Chrome浏览器因其强大的开发者工具和广泛的用户基础,成为了自动化测试的首选,所以我们以ChromeDriver为例。

驱动下载的核心原则:驱动版本必须与你的Chrome浏览器版本匹配! 这是新手最容易踩坑的地方。版本不匹配会导致脚本无法启动浏览器,并报错。

查看你的Chrome浏览器版本:打开Chrome,点击右上角三个点 -> 帮助 -> 关于Google Chrome。记下版本号(例如,版本 115.0.5790.170)。

然后,去ChromeDriver的官方下载站点或国内镜像站,下载对应版本的驱动。官方地址有时访问不稳定,国内一些高校的镜像站是很好的替代选择。下载后,你会得到一个可执行文件(Windows是 chromedriver.exe ,Mac/Linux是 chromedriver )。

驱动的存放位置有三种常见方案,各有利弊:

  1. 放入系统PATH路径 :这是最“干净”的做法。将 chromedriver.exe 文件放在系统环境变量PATH包含的任意目录下,例如Windows的 C:\Windows\ 或专门创建的脚本工具目录。这样,你在代码中初始化时,只需写 webdriver.Chrome() ,Selenium会自动在PATH中查找驱动。
  2. 放入项目目录 :将驱动文件直接放在你的Python脚本所在的文件夹里。在代码中需要指定驱动路径: webdriver.Chrome(executable_path='./chromedriver') 。这种方式项目自包含,便于管理,但每个项目都要放一份。
  3. 指定绝对路径 :在代码中明确写出驱动的完整磁盘路径。例如: webdriver.Chrome(executable_path=r'C:\Users\YourName\Tools\chromedriver.exe') 。这种方式最直接,但代码移植性差,换台电脑就得改路径。

对于初学者,我推荐第二种方式,简单直观,不容易因系统环境问题出错。等熟悉后,可以过渡到第一种,更符合生产环境的部署习惯。

2.3 集成开发环境(IDE)的选择

写Python脚本,一个好用的编辑器或IDE能极大提升效率。对于自动化测试脚本开发,我首推 Visual Studio Code (VSCode)

VSCode轻量、免费、插件生态丰富。你需要安装两个核心插件:

  • Python :由Microsoft官方提供,提供代码高亮、智能提示(IntelliSense)、代码调试、环境管理等功能。
  • Pylance :作为Python插件的语言服务器,能提供更强大、更快的代码补全和类型检查。

安装好VSCode和插件后,打开你的项目文件夹,VSCode通常能自动识别Python环境。如果遇到多个Python环境,你可以通过点击编辑器底部状态栏的Python版本号进行切换。配置好这些,你的代码编写体验会非常流畅,比如输入 webdriver. 之后,它会自动弹出 Chrome Firefox 等可选类和方法,大大减少拼写错误和记忆负担。

3. 登录脚本核心逻辑与代码实现

3.1 脚本骨架与浏览器启动

让我们开始编写第一个脚本。创建一个新的Python文件,比如命名为 login_automation.py 。一个好的脚本应该结构清晰,我们从一个最简单的骨架开始:

# 导入必要的库
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

# 1. 创建浏览器驱动实例
driver = webdriver.Chrome()  # 如果驱动不在PATH,需指定executable_path参数

# 2. 打开目标登录页面
driver.get("https://www.example.com/login")  # 请替换为实际的登录页面URL
driver.maximize_window()  # 最大化窗口,确保元素可见

# 3. 后续的定位与操作代码将写在这里...

# 4. 等待一会儿以便观察,然后关闭浏览器
time.sleep(5)
driver.quit()

这段代码做了四件事:导入库、启动Chrome浏览器、访问一个登录页面、等待5秒后关闭。 driver.quit() 会关闭浏览器并结束WebDriver进程,而 driver.close() 只会关闭当前标签页。在自动化脚本中,通常用 quit() 来做清理。

实操心得一:关于等待的哲学 这里我用了 time.sleep(5) ,这是一种“强制等待”。它简单粗暴,但效率低下,并且不稳定(如果页面5秒没加载完呢?)。在实际项目中,我们几乎不会这样用。这里只是为了演示效果。真正的自动化脚本必须使用更智能的“显式等待”或“隐式等待”,我们稍后会详细讲。

3.2 元素定位:自动化测试的基石

自动化操作的前提是找到页面上的元素(输入框、按钮、链接等)。Selenium提供了8种主要的定位方式,常用的是前6种:

  1. ID driver.find_element(By.ID, “username”) 。ID通常是唯一的,定位速度最快,首选。
  2. Name driver.find_element(By.NAME, “password”) 。Name属性也常用于表单元素。
  3. Class Name driver.find_element(By.CLASS_NAME, “btn-submit”) 。注意,一个元素可能有多个class,这里要匹配完整的class字符串。
  4. Tag Name driver.find_element(By.TAG_NAME, “input”) 。通常用于定位一组同类元素,如所有输入框。
  5. Link Text driver.find_element(By.LINK_TEXT, “忘记密码?”) 。专门用于定位超链接( <a> 标签),且要完全匹配链接文本。
  6. Partial Link Text driver.find_element(By.PARTIAL_LINK_TEXT, “忘记”) 。链接文本的部分匹配。
  7. CSS Selector driver.find_element(By.CSS_SELECTOR, “#loginForm input[type=‘text’]”) 。功能强大,语法灵活,是进阶必备。
  8. XPath driver.find_element(By.XPATH, “//form[@id=‘loginForm’]//input[1]”) 。最强大的定位方式,可以遍历XML/HTML文档,但写起来复杂,执行速度相对慢。

如何查看元素属性? 打开Chrome浏览器,进入目标登录页面,按F12打开开发者工具。点击左上角的箭头图标(或按Ctrl+Shift+C),然后去页面上点击你想操作的元素,比如用户名输入框。在开发者工具的“Elements”面板中,该元素的代码会被高亮。你可以查看它的 id name class 等属性。

假设我们的登录页面有一个典型结构:

<input type="text" id="user" name="username" placeholder="请输入用户名">
<input type="password" id="pass" name="password" placeholder="请输入密码">
<button type="submit" class="btn-login">登录</button>

那么,我们的定位代码可以这样写:

# 定位用户名输入框
username_input = driver.find_element(By.ID, “user”)  # 方式1:通过ID
# 或者 username_input = driver.find_element(By.NAME, “username”) # 方式2:通过Name

# 定位密码输入框
password_input = driver.find_element(By.ID, “pass”)

# 定位登录按钮
login_button = driver.find_element(By.CLASS_NAME, “btn-login”)
# 或者如果按钮有唯一文本,也可以用:driver.find_element(By.XPATH, “//button[text()=‘登录’]”)

3.3 模拟用户操作:输入与点击

定位到元素后,我们就可以模拟用户行为了。最常用的两个操作是 send_keys() (输入文本)和 click() (点击)。

# 在用户名输入框中输入文本
username_input.send_keys(“your_username”)

# 在密码输入框中输入文本
password_input.send_keys(“your_password”)

# 点击登录按钮
login_button.click()

有时候,输入框可能有默认文字(placeholder), send_keys() 会直接追加在后面。更严谨的做法是先清空输入框:

username_input.clear()  # 清空输入框
username_input.send_keys(“new_username”)

实操心得二:关于点击的替代方案 不是所有“按钮”都是 <button> 标签,也可能是 <input type=“submit”> <div> 伪装成的按钮。如果 click() 不生效,可以尝试:

  • 模拟键盘回车:在密码输入后,执行 password_input.send_keys(Keys.ENTER)
  • 执行JavaScript点击: driver.execute_script(“arguments[0].click();”, login_button) 。这种方式能绕过一些前端框架的事件绑定问题,作为备选方案。

3.4 引入智能等待:让脚本更稳定

回到之前提到的等待问题。 time.sleep() 是糟糕的实践。我们应该使用Selenium提供的 显式等待(Explicit Wait)

显式等待会针对某个条件进行等待,在设定的最大时间范围内,只要条件满足就立即继续执行,否则超时则抛出异常。这比死等固定时间高效和可靠得多。

我们需要导入相关模块:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

然后,在关键操作前后加入等待。例如,等待登录按钮可点击后再点击:

# 创建一个等待对象,最多等10秒,每0.5秒检查一次条件
wait = WebDriverWait(driver, 10)

# 等待登录按钮出现且可点击
login_button = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, “btn-login”)))
login_button.click()

# 等待登录成功后的某个元素出现,比如用户头像或“退出”链接
# 这可以作为登录成功的断言
success_element = wait.until(EC.presence_of_element_located((By.ID, “userAvatar”)))

expected_conditions 模块提供了很多预置条件,如 presence_of_element_located (元素存在DOM中), visibility_of_element_located (元素可见), element_to_be_clickable (元素可点击)等。根据场景选用合适的条件,是编写稳定自动化脚本的关键。

4. 构建健壮的登录自动化脚本

4.1 完整脚本示例与逐行解析

现在,我们将所有部分组合起来,形成一个完整、相对健壮的登录脚本。这个脚本包含了异常处理的基本框架。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

def test_login():
    """
    一个简单的登录UI自动化测试函数
    """
    driver = None  # 初始化driver变量,以便在finally块中访问
    try:
        # 初始化浏览器驱动,指定驱动路径(根据你的实际情况修改)
        driver = webdriver.Chrome(executable_path=‘./chromedriver’) 
        driver.maximize_window()
        wait = WebDriverWait(driver, 10)  # 创建显式等待对象

        # 步骤1: 导航到登录页面
        login_url = “https://www.example.com/login”  # 替换为你的登录页
        print(f“正在访问登录页面: {login_url}”)
        driver.get(login_url)

        # 步骤2: 等待页面关键元素加载完成(例如登录表单)
        # 这里假设页面有一个id为‘loginForm’的表单,等待它出现
        wait.until(EC.presence_of_element_located((By.ID, “loginForm”)))
        print(“登录页面加载完成。”)

        # 步骤3: 定位并操作元素
        # 定位用户名输入框并输入
        username_box = wait.until(EC.visibility_of_element_located((By.ID, “user”)))
        username_box.clear()
        username_box.send_keys(“test_user”)  # 替换为你的测试用户名
        print(“已输入用户名。”)

        # 定位密码输入框并输入
        password_box = driver.find_element(By.ID, “pass”)
        password_box.clear()
        password_box.send_keys(“test_password”)  # 替换为你的测试密码
        print(“已输入密码。”)

        # 定位登录按钮并点击
        login_btn = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, “btn-login”)))
        login_btn.click()
        print(“已点击登录按钮。”)

        # 步骤4: 验证登录是否成功
        # 等待登录后才会出现的元素,如图标或欢迎语
        # 这里假设登录成功后,页面会出现一个ID为‘welcome’的元素
        time.sleep(2)  # 给页面跳转一点缓冲时间,实际应用中最好用等待条件替代
        success_indicator = wait.until(
            EC.visibility_of_element_located((By.ID, “welcome”))
        )
        
        # 简单的断言:如果成功元素存在且可见,则认为登录成功
        if success_indicator.is_displayed():
            print(“*** 登录成功! ***”)
            # 可以在这里加入更复杂的验证,比如检查欢迎文本内容
            # assert “欢迎” in success_indicator.text
        else:
            print(“!!! 登录失败,未找到成功标识。 !!!”)

        # 步骤5: 登录后操作(示例:等待3秒后截图)
        time.sleep(3)
        driver.save_screenshot(“login_success.png”)
        print(“已保存登录成功后的截图。”)

    except Exception as e:
        # 捕获任何异常,并截图保存,便于排查问题
        print(f“脚本执行过程中发生错误: {e}”)
        if driver:
            driver.save_screenshot(“error_snapshot.png”)
            print(“已保存错误时的页面截图。”)
    finally:
        # 无论成功与否,最后都关闭浏览器
        if driver:
            driver.quit()
            print(“浏览器已关闭。”)

# 执行测试函数
if __name__ == “__main__”:
    test_login()

逐行解析与设计逻辑:

  1. 函数封装 :将主要逻辑放在 test_login() 函数中,使结构清晰,便于管理和复用。
  2. 异常处理(try-except-finally) :这是生产级脚本的必备结构。
    • try 块中是主流程。
    • except 块捕获所有异常,并打印错误信息。 关键一步是保存出错时的页面截图 ,这对于远程调试或分析不可复现的Bug至关重要。
    • finally 块确保无论是否出错,浏览器驱动都会被正确关闭,避免残留进程占用资源。
  3. 智能等待贯穿始终 :在打开页面后、操作关键元素前,都使用了 WebDriverWait 配合 expected_conditions 进行等待,极大提高了脚本的稳定性和容错能力。
  4. 操作与日志结合 :每个关键步骤后都使用 print() 输出日志,方便运行时观察脚本执行到了哪一步。
  5. 验证点(断言) :登录后,通过等待和检查一个特定的成功元素(如欢迎语)来验证登录功能是否正常。这是自动化测试的“测试”部分,而不仅仅是“操作”部分。
  6. 截图功能 :使用 driver.save_screenshot() 保存成功后的页面状态,作为执行证据。

4.2 从脚本到测试用例:参数化与数据驱动

上面的脚本将测试数据(用户名、密码)硬编码在代码里。这只能测试一组数据。真正的测试需要覆盖多种情况:正确账号、错误密码、空用户名、错误格式等。这就需要 数据驱动

一个简单的方法是将测试数据放到一个列表或字典中,然后循环执行:

test_data = [
    {“username”: “correct_user”, “password”: “correct_pwd”, “expected”: “success”},
    {“username”: “wrong_user”, “password”: “correct_pwd”, “expected”: “fail”},
    {“username”: “correct_user”, “password”: “”, “expected”: “fail”},
    {“username”: “”, “password”: “correct_pwd”, “expected”: “fail”},
]

def login_with_data(username, password):
    # … 这里是之前的登录操作逻辑,但使用传入的username和password参数 …
    username_box.send_keys(username)
    password_box.send_keys(password)
    # … 后续操作 …

    # 根据expected判断验证逻辑
    # if expected == “success”: 检查成功元素
    # else: 检查错误提示元素

if __name__ == “__main__”:
    for data in test_data:
        print(f“正在测试用例: 用户名={data[‘username’]}, 密码={data[‘password’]}”)
        # 注意:每次循环需要重启浏览器,或者做好登出清理,避免状态污染
        test_login_with_data(data[‘username’], data[‘password’], data[‘expected’])

更进阶的做法是将测试数据存储在外部文件中,如JSON、YAML或Excel/CSV,然后由脚本读取。 pytest 这样的测试框架也提供了强大的参数化功能( @pytest.mark.parametrize ),非常适合管理多组测试数据。

4.3 页面对象模型(POM)设计模式初探

当测试场景变多,脚本会越来越臃肿,元素定位语句散落在各个函数里,难以维护。这时就需要引入 页面对象模型(Page Object Model, POM) 。POM是一种设计模式,将每个页面抽象成一个类,页面的元素定位和基本操作封装成类的方法。测试脚本只调用这些方法,不关心具体如何定位和操作。

例如,为登录页面创建一个类:

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)
        # 元素定位器(Locators)
        self.username_input = (By.ID, “user”)
        self.password_input = (By.ID, “pass”)
        self.login_button = (By.CLASS_NAME, “btn-login”)
        self.welcome_text = (By.ID, “welcome”)

    def enter_username(self, username):
        element = self.wait.until(EC.visibility_of_element_located(self.username_input))
        element.clear()
        element.send_keys(username)

    def enter_password(self, password):
        element = self.driver.find_element(*self.password_input) # 注意这里的解包*
        element.clear()
        element.send_keys(password)

    def click_login(self):
        element = self.wait.until(EC.element_to_be_clickable(self.login_button))
        element.click()

    def get_welcome_message(self):
        element = self.wait.until(EC.visibility_of_element_located(self.welcome_text))
        return element.text

然后在测试脚本中,使用就非常清晰了:

def test_login_with_pom():
    driver = webdriver.Chrome()
    driver.get(“https://www.example.com/login”)
    
    login_page = LoginPage(driver)  # 初始化登录页面对象
    login_page.enter_username(“test_user”)
    login_page.enter_password(“test_pwd”)
    login_page.click_login()
    
    welcome_msg = login_page.get_welcome_message()
    assert “欢迎” in welcome_msg
    
    driver.quit()

POM极大地提高了代码的可读性、可维护性和复用性。当登录页面的输入框ID发生变化时,你只需要修改 LoginPage 类中的一处定位器即可,所有测试用例都不需要改动。

5. 常见问题排查与实战技巧

5.1 高频错误与解决方案速查表

在编写和运行Selenium脚本时,你几乎一定会遇到下面这些问题。这里我整理了一个速查表,附上原因分析和解决方案。

问题现象 可能原因 解决方案与排查步骤
WebDriverException: Message: ‘chromedriver’ executable needs to be in PATH 1. 未下载ChromeDriver。
2. ChromeDriver未放在PATH路径。
3. ChromeDriver版本与Chrome浏览器不匹配。
1. 检查是否已下载对应版本的ChromeDriver。
2. 将ChromeDriver所在目录添加到系统环境变量PATH,或在代码中指定 executable_path
3. 核对浏览器和驱动版本号,必须匹配。
NoSuchElementException: Unable to locate element 1. 元素定位表达式写错了。
2. 页面尚未加载完成,元素还不存在。
3. 元素在iframe或shadow DOM内。
4. 元素是动态生成的,ID/Class等属性每次刷新会变。
1. 用浏览器开发者工具复查定位表达式。
2. 在操作元素前增加显式等待( WebDriverWait )。
3. 使用 driver.switch_to.frame() 切换到iframe,或使用特殊方法处理shadow DOM。
4. 尝试使用更稳定的定位方式,如XPath通过相对路径或文本定位,CSS Selector通过属性组合定位。
ElementNotInteractableException: element not interactable 1. 元素不可见(被遮挡、样式为 display:none visibility:hidden )。
2. 元素未被渲染到可操作状态(如禁用状态)。
3. 另一个元素覆盖在了目标元素上。
1. 使用 EC.visibility_of_element_located 等待元素可见。
2. 检查元素是否有 disabled 属性,等待其变为可用( EC.element_to_be_clickable )。
3. 滚动元素到可视区域: driver.execute_script(“arguments[0].scrollIntoView();”, element)
4. 检查是否有弹窗、蒙层遮挡。
脚本在本地运行成功,但在服务器/CI环境失败 1. 服务器是无图形界面的(Headless)环境。
2. 浏览器或驱动版本不一致。
3. 屏幕分辨率不同导致元素位置变化。
1. 配置无头浏览器选项: options = webdriver.ChromeOptions(); options.add_argument(‘--headless’)
2. 在服务器环境也使用固定版本的浏览器和驱动,或使用Docker容器统一环境。
3. 设置固定的窗口大小: driver.set_window_size(1920, 1080) 。避免使用基于坐标的操作。
InvalidSelectorException 提供的CSS Selector或XPath语法错误。 将你的定位表达式粘贴到浏览器开发者工具的Console中,用 document.querySelector() (CSS) 或 $x() (XPath) 测试是否能找到元素。
页面跳转后找不到元素 操作(如点击登录)导致页面刷新或跳转,但脚本立即去寻找新页面的元素,此时新页面可能还未加载。 在引发页面跳转的操作(如 click() )之后,增加一个针对新页面某个关键元素的显式等待。

5.2 高级定位技巧与调试手段

当常规定位方式失效时,你需要一些“武器库”里的高级技巧。

1. 使用相对XPath或CSS Selector避免依赖易变属性: 不要过度依赖自动生成的、冗长且易变的XPath(如 //*[@id=“j_id0:j_id1:j_id2:inputText1”] )。尝试使用更有语义的定位:

  • 通过文本内容 //button[contains(text(), ‘登录’)]
  • 通过属性组合 input[name=‘username’][type=‘text’] (CSS)
  • 通过父子/兄弟关系 //form[@id=‘loginForm’]//input[@type=‘password’]

2. 处理动态ID/Class: 如果元素的ID是类似 ‘user-12345’ 这样带随机后缀的,可以使用 starts-with contains ends-with 函数(XPath)或属性选择器(CSS)。

  • XPath: //input[starts-with(@id, ‘user-’)]
  • CSS: input[id^=‘user-’] (以‘user-’开头)

3. 处理iframe: 如果元素在 <iframe> 标签内,你必须先切换到对应的iframe框架,才能定位其中的元素。

# 通过ID或Name切换
driver.switch_to.frame(“iframe_id_or_name”)
# 定位并操作iframe内的元素...
# 操作完成后,切回主页面
driver.switch_to.default_content()

4. 强大的调试工具: driver.page_source 和截图 当页面元素异常,在开发者工具里能看到但在脚本中找不到时,可以将当前页面的HTML结构保存下来分析。

with open(“page_dump.html”, “w”, encoding=“utf-8”) as f:
    f.write(driver.page_source)
print(“当前页面源码已保存。”)

结合出错时的截图 ( driver.save_screenshot(‘debug.png’) ),你可以清晰地看到脚本“眼中”的页面是什么样子,这对于排查动态加载、渲染差异问题非常有效。

5.3 提升脚本稳定性的工程化思考

一个能跑起来的脚本和一个能在团队中、在CI/CD流水线上稳定运行的脚本,中间隔着工程化的距离。

1. 配置管理: 不要将URL、账号密码、等待超时时间等硬编码在脚本中。应该使用配置文件(如 config.ini config.yaml )或环境变量来管理。例如:

import os
from dotenv import load_dotenv  # 可以使用python-dotenv库

load_dotenv()  # 从 .env 文件加载环境变量

LOGIN_URL = os.getenv(“LOGIN_URL”, “https://default.example.com/login”)
TEST_USER = os.getenv(“TEST_USER”)
TEST_PASS = os.getenv(“TEST_PASS”)
IMPLICIT_WAIT = int(os.getenv(“IMPLICIT_WAIT”, “10”))

2. 日志记录: print() 只是初级阶段。应该使用Python内置的 logging 模块,可以方便地控制日志级别(DEBUG, INFO, WARNING, ERROR)、输出到文件、并格式化日志信息。

import logging
logging.basicConfig(level=logging.INFO,
                    format=‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’)
logger = logging.getLogger(__name__)
logger.info(“正在访问登录页面…”)

3. 集成测试框架: 将你的脚本函数改造成 pytest unittest 的测试用例。这样可以利用框架提供的测试发现、夹具(Fixture,如 setup / teardown )、参数化、断言和丰富的报告插件。

# 使用pytest示例
import pytest

class TestLogin:
    @pytest.fixture(scope=“function”)
    def driver(self):
        d = webdriver.Chrome()
        yield d
        d.quit()

    def test_valid_login(self, driver):
        driver.get(LOGIN_URL)
        # … 调用POM页面对象进行登录操作 …
        assert “欢迎” in login_page.get_welcome_message()

4. 持续集成(CI): 将你的自动化测试脚本提交到Git仓库,并配置CI工具(如Jenkins, GitLab CI, GitHub Actions)。每次代码提交或定时任务,CI会自动拉取代码、安装依赖、执行测试并生成报告。这才是UI自动化测试价值最大化的地方——持续守护产品质量。

从一行代码开始,到一个稳定的、可维护的、可集成的自动化测试用例,这个过程本身就是一次微型的软件工程实践。它锻炼的不仅仅是Selenium API的调用,更是你的编程思维、设计模式和工程化能力。希望这个从零开始的登录UI自动化脚本,能成为你打开自动化测试大门的第一把钥匙。

更多推荐