Python+Selenium电商登录与搜索自动化测试实战指南
1. 项目概述:为什么电商登录与搜索测试值得自动化?
做电商平台测试的同行应该都深有体会,登录和搜索这两个功能点,几乎是每次版本迭代、每次回归测试的必测项。手动操作一遍,输入账号密码、验证码(如果有)、点击搜索框、输入关键词、查看结果列表……流程看似简单,但重复十次、百次,不仅枯燥,还极易因疲劳导致漏测。更关键的是,这两个功能直接关系到用户能否进入平台并找到想要的商品,是用户体验的“咽喉要道”,一旦出问题,转化率立马跳水。
所以,用 Python + unittest + Selenium 把这部分工作自动化,是一个投入产出比极高的选择。Python 语法简洁,生态丰富;unittest 是 Python 自带的单元测试框架,结构清晰,能很好地组织测试用例和生成报告;Selenium 则是 Web UI 自动化的“老炮儿”,浏览器兼容性好,能模拟真实用户操作。这个组合拳,能让我们把精力从重复劳动中解放出来,去关注更复杂的业务逻辑和探索性测试。
这个项目,就是带你从零开始,搭建一个针对电商平台登录和搜索功能的自动化测试脚本。我会把每一步的“为什么”都讲清楚,并附上我踩过坑后总结的实战技巧。无论你是刚接触自动化测试的新手,还是想优化现有脚本的老手,都能从中找到可以直接“抄作业”的干货。
2. 环境搭建与核心工具选型解析
工欲善其事,必先利其器。环境配置是第一步,也是劝退很多新手的“拦路虎”。这里我会给出最稳定、最通用的方案,并解释为什么这么选。
2.1 Python 环境:版本与包管理器的抉择
首先,Python 版本我强烈推荐使用 Python 3.8 到 3.11 之间的稳定版本。Python 3.12+ 有时会遇到一些第三方库的兼容性问题,而 3.7 及以下已逐步停止主流支持。安装时,务必勾选“Add Python to PATH”,这是后续一切顺利的基础。
安装完成后,打开命令行(CMD 或 Terminal),输入 python --version 确认版本。接下来是包管理器, pip 是标配,但为了环境隔离,我强烈建议使用 venv 创建虚拟环境。这能保证你的项目依赖独立,不会污染系统环境,也便于在不同项目间切换。
# 在你的项目目录下
python -m venv venv
# 激活虚拟环境
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
激活后,命令行前缀会显示 (venv) ,表示你已进入虚拟环境。
注意 :很多教程会推荐 Anaconda,但对于纯 Web 自动化测试项目,venv 更轻量,且与 PyCharm、VSCode 等 IDE 的集成更无缝。除非你后续需要大量科学计算库,否则 venv 足矣。
2.2 浏览器与驱动:版本同步是生命线
Selenium 本身只是一个“指挥棒”,它需要通过浏览器驱动(如 ChromeDriver)来实际操控浏览器。这里最大的坑就是 版本匹配 。
- 浏览器选择 :首选 Google Chrome ,因为它的市场占有率最高,开发者工具强大,且 ChromeDriver 更新最及时。确保你的 Chrome 已更新到最新稳定版。
- 驱动下载 :打开 Chrome,在地址栏输入
chrome://settings/help查看版本号。然后去 ChromeDriver 官网 下载 完全相同版本号 的驱动。如果官网没有完全匹配的版本,就选最接近的次要版本。 - 驱动放置 :下载的
chromedriver.exe(Windows)文件,有两个推荐放置位置:- 方法一(推荐) :放在你的项目根目录下。在代码中指定相对路径即可,便于项目管理。
- 方法二 :放在 Python 安装目录的
Scripts文件夹下(Windows)或/usr/local/bin下(macOS/Linux)。这样可以在系统任何位置直接调用,但要注意多个项目可能产生冲突。
验证驱动是否可用:在命令行(确保在虚拟环境内)输入 chromedriver --version ,如果能输出版本信息,则配置成功。
2.3 核心库安装:不止于 Selenium
在激活的虚拟环境中,使用 pip 安装以下库:
pip install selenium
pip install webdriver-manager # 强烈推荐的辅助工具
-
selenium:核心库,不必多说。 -
webdriver-manager:这是一个神器。它可以自动检测你本地 Chrome 浏览器的版本,并自动下载、匹配对应的 ChromeDriver,彻底解决手动管理驱动版本的烦恼。对于新手和团队协作来说,能省去大量沟通和维护成本。
此外,为了更好的测试报告,我们还可以安装:
pip install html-testrunner # 用于生成更美观的HTML报告
环境至此就绪。我个人的体会是,花半小时把环境稳扎稳打地配好,远比在后续脚本运行时莫名其妙报错,再回头折腾一小时要高效得多。
3. 项目结构设计与测试框架搭建
好的项目结构是代码可维护性的基石。我们不能把所有代码都堆在一个 .py 文件里。下面是我经过多个项目沉淀下来的一个清晰结构:
ecommerce_auto_test/
│
├── drivers/ # 存放浏览器驱动(如果不用webdriver-manager)
│ └── chromedriver.exe
│
├── reports/ # 存放自动生成的测试报告
│ └── (报告文件)
│
├── test_cases/ # 测试用例目录
│ ├── __init__.py
│ ├── test_login.py # 登录测试用例
│ └── test_search.py # 搜索测试用例
│
├── page_objects/ # 页面对象模型目录
│ ├── __init__.py
│ ├── base_page.py # 页面基类
│ ├── login_page.py # 登录页面类
│ └── search_page.py # 搜索页面类
│
├── utilities/ # 工具类目录
│ ├── __init__.py
│ └── config_reader.py # 配置文件读取
│
├── configs/ # 配置文件目录
│ └── config.ini # 存放URL、账号、密码等
│
├── main.py # 测试执行入口
└── requirements.txt # 项目依赖列表
3.1 页面对象模型(Page Object Model, POM)详解
POM 是 UI 自动化测试的核心设计模式。它的核心思想是 将页面元素定位和元素操作封装成单独的类 。这样做的巨大优势在于:
- 高复用性 :元素定位逻辑只写一次,所有测试用例都可调用。
- 易维护性 :当页面UI发生变化(例如搜索框的id改了),你只需要在对应的
Page类里修改一次定位器,所有用到这个搜索框的测试用例都自动生效,无需逐个修改。 - 高可读性 :测试用例读起来就像业务逻辑(
login_page.login(username, password)),而不是一堆find_element_by_id的技术代码。
我们来创建最基础的 base_page.py ,它包含所有页面类的通用方法:
# page_objects/base_page.py
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
class BasePage:
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10) # 设置显式等待10秒
def find_element(self, *locator):
"""查找单个元素,加入显式等待"""
try:
return self.wait.until(EC.presence_of_element_located(locator))
except TimeoutException:
print(f"元素未找到: {locator}")
raise
def click(self, *locator):
"""点击元素"""
element = self.find_element(*locator)
element.click()
def input_text(self, text, *locator):
"""向元素输入文本"""
element = self.find_element(*locator)
element.clear()
element.send_keys(text)
def get_text(self, *locator):
"""获取元素文本"""
element = self.find_element(*locator)
return element.text
这个基类封装了最常用的操作,并引入了 WebDriverWait 显式等待 。这是 Selenium 自动化中 至关重要 的技巧。因为网络加载或JS渲染需要时间,如果代码执行太快而元素还没出现,就会抛出 NoSuchElementException 。显式等待会定期(默认0.5秒)检查条件是否成立,最多等待指定时间(这里10秒),这比固定的 time.sleep() 更智能、更高效。
3.2 配置文件管理
把测试数据(如URL、账号密码)硬编码在脚本里是坏习惯。我们将它们抽离到 config.ini 中:
# configs/config.ini
[DEFAULT]
base_url = https://www.example-mall.com # 替换为目标电商平台地址
[LOGIN]
username = your_test_account@email.com
password = your_test_password
invalid_username = wrong@email.com
invalid_password = wrongpass
[SEARCH]
valid_keyword = 手机
invalid_keyword = @#$%^&*
empty_keyword =
然后创建一个工具类来读取它:
# utilities/config_reader.py
import os
import configparser
def get_config(section, key):
config = configparser.ConfigParser()
# 获取项目根目录路径,拼接config.ini的路径
current_dir = os.path.dirname(os.path.dirname(__file__))
config_path = os.path.join(current_dir, 'configs', 'config.ini')
config.read(config_path)
return config.get(section, key)
这样,当测试环境变更(例如从测试环境切换到预发布环境),或者账号密码需要更新时,你只需要修改这个配置文件,而无需触动任何测试代码。
4. 登录功能自动化测试实战
登录功能看似简单,但测试点不少:正常登录、用户名错误、密码错误、空输入等。我们采用 POM 模式来实现。
4.1 登录页面对象封装
首先,分析目标电商平台的登录页面。通常包含:用户名输入框、密码输入框、登录按钮、可能的错误信息提示框。我们需要用浏览器的开发者工具(F12)来获取这些元素的定位方式(如ID、Class Name、XPath等)。
实操心得 :优先使用
id定位,因为它是唯一的,速度最快。其次是name、class name。xpath和css selector功能强大但可能随页面结构调整而变化,尽量使用相对路径和属性组合,避免使用绝对路径。
假设我们分析的定位信息如下:
- 用户名输入框:
id="username" - 密码输入框:
id="password" - 登录按钮:
xpath="//button[@type='submit']" - 错误信息区域:
class="error-message"
创建 login_page.py :
# page_objects/login_page.py
from .base_page import BasePage
from utilities.config_reader import get_config
class LoginPage(BasePage):
# 页面元素定位器
USERNAME_INPUT = ("id", "username")
PASSWORD_INPUT = ("id", "password")
LOGIN_BUTTON = ("xpath", "//button[@type='submit']")
ERROR_MSG = ("class name", "error-message")
SUCCESS_INDICATOR = ("xpath", "//a[contains(text(),'我的账户')]") # 登录成功后的页面元素
def __init__(self, driver):
super().__init__(driver)
self.base_url = get_config("DEFAULT", "base_url")
self.login_url = self.base_url + "/login" # 假设登录页面路径为 /login
def open(self):
"""打开登录页面"""
self.driver.get(self.login_url)
def login(self, username, password):
"""执行登录操作"""
self.input_text(username, *self.USERNAME_INPUT)
self.input_text(password, *self.PASSWORD_INPUT)
self.click(*self.LOGIN_BUTTON)
def get_error_message(self):
"""获取错误提示文本"""
try:
return self.get_text(*self.ERROR_MSG)
except:
return "No error message found" # 如果找不到错误元素,返回特定字符串
def is_login_success(self):
"""判断是否登录成功"""
try:
# 显式等待成功元素出现
self.find_element(*self.SUCCESS_INDICATOR)
return True
except:
return False
4.2 登录测试用例编写
接下来,使用 unittest 框架编写测试用例。unittest 的核心组件包括:
setUp:每个测试方法执行前运行,用于初始化(如打开浏览器,打开页面)。tearDown:每个测试方法执行后运行,用于清理(如关闭浏览器)。setUpClass/tearDownClass:整个测试类开始前/结束后运行一次。- 测试方法:必须以
test_开头。
创建 test_login.py :
# test_cases/test_login.py
import unittest
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from page_objects.login_page import LoginPage
from utilities.config_reader import get_config
class TestLogin(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""整个测试类只执行一次:启动浏览器"""
# 使用webdriver-manager自动管理驱动
cls.driver = webdriver.Chrome(ChromeDriverManager().install())
cls.driver.maximize_window() # 最大化窗口,确保元素可见
cls.login_page = LoginPage(cls.driver)
def setUp(self):
"""每个测试方法执行前:刷新到登录页面"""
self.login_page.open()
def test_01_login_success(self):
"""测试用例1:使用正确账号密码登录"""
username = get_config("LOGIN", "username")
password = get_config("LOGIN", "password")
self.login_page.login(username, password)
# 断言:登录成功后,应该能找到“我的账户”等成功标识
self.assertTrue(self.login_page.is_login_success(),
"登录成功断言失败!")
def test_02_login_with_wrong_password(self):
"""测试用例2:使用正确用户名和错误密码登录"""
username = get_config("LOGIN", "username")
password = get_config("LOGIN", "invalid_password")
self.login_page.login(username, password)
# 断言:应该出现错误提示信息
error_msg = self.login_page.get_error_message()
self.assertIn("密码错误", error_msg or "") # 根据实际错误提示调整
def test_03_login_with_empty_credentials(self):
"""测试用例3:用户名和密码都为空登录"""
self.login_page.login("", "")
# 断言:应该出现“请输入”之类的提示
error_msg = self.login_page.get_error_message()
self.assertTrue(error_msg and len(error_msg) > 0,
"空输入未出现错误提示!")
@classmethod
def tearDownClass(cls):
"""整个测试类结束后:关闭浏览器"""
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
注意事项 :
- 测试独立性 :每个测试方法(
test_*)都应该是独立的,不依赖于其他测试方法的状态。这就是为什么我们在setUp中每次都打开登录页面,而不是依赖上一条测试的最终页面。- 断言的艺术 :断言是测试的灵魂。除了
assertTrue/assertFalse,还有assertEqual、assertIn等。断言信息要清晰,能直接看出失败原因。- 使用
webdriver-manager:在setUpClass中,我们使用ChromeDriverManager().install()来自动获取匹配的驱动,这是最佳实践。
5. 搜索功能自动化测试实战
搜索功能的核心是输入关键词,验证结果列表是否正确显示。这里会涉及到更多的页面交互和结果验证。
5.1 搜索页面对象封装
假设搜索框在首页顶部,搜索后跳转到结果页。
- 首页搜索框:
id="q" - 首页搜索按钮:
xpath="//button[contains(@class,'search-btn')]" - 结果页商品列表项:
css selector=".product-item"(每个商品项的CSS类) - 结果页“无结果”提示:
class="no-result"
创建 search_page.py :
# page_objects/search_page.py
from .base_page import BasePage
from selenium.webdriver.common.keys import Keys
class SearchPage(BasePage):
# 首页元素
SEARCH_INPUT = ("id", "q")
SEARCH_BUTTON = ("xpath", "//button[contains(@class,'search-btn')]")
# 结果页元素
PRODUCT_ITEMS = ("css selector", ".product-item")
NO_RESULT_MSG = ("class name", "no-result")
FIRST_PRODUCT_TITLE = ("css selector", ".product-item:first-child .title") # 第一个商品标题
def __init__(self, driver):
super().__init__(driver)
from utilities.config_reader import get_config
self.base_url = get_config("DEFAULT", "base_url")
def open_homepage(self):
"""打开首页"""
self.driver.get(self.base_url)
def search_from_homepage(self, keyword):
"""在首页执行搜索"""
self.open_homepage()
self.input_text(keyword, *self.SEARCH_INPUT)
# 两种触发搜索的方式:点击按钮或按回车键,这里展示回车键,更接近用户习惯
self.find_element(*self.SEARCH_INPUT).send_keys(Keys.ENTER)
# 或者使用点击按钮:self.click(*self.SEARCH_BUTTON)
def get_search_result_count(self):
"""获取搜索结果数量"""
try:
elements = self.driver.find_elements(*self.PRODUCT_ITEMS)
return len(elements)
except:
return 0
def is_no_result_displayed(self):
"""检查是否显示‘无结果’提示"""
try:
element = self.find_element(*self.NO_RESULT_MSG)
return element.is_displayed()
except:
return False
def get_first_product_title(self):
"""获取第一个商品的标题文本"""
try:
return self.get_text(*self.FIRST_PRODUCT_TITLE)
except:
return "No product found"
5.2 搜索测试用例编写
搜索的测试点包括:有效关键词搜索、无效关键词搜索、空搜索、搜索结果相关性验证等。
创建 test_search.py :
# test_cases/test_search.py
import unittest
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from page_objects.search_page import SearchPage
from utilities.config_reader import get_config
class TestSearch(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome(ChromeDriverManager().install())
cls.driver.maximize_window()
cls.search_page = SearchPage(cls.driver)
def setUp(self):
"""每个测试前确保回到首页,保证测试独立性"""
self.search_page.open_homepage()
def test_01_search_with_valid_keyword(self):
"""测试用例1:使用有效关键词搜索"""
keyword = get_config("SEARCH", "valid_keyword") # 例如“手机”
self.search_page.search_from_homepage(keyword)
# 断言1:搜索结果数量应大于0
result_count = self.search_page.get_search_result_count()
self.assertGreater(result_count, 0, f"搜索关键词‘{keyword}’未找到任何结果!")
# 断言2:第一个商品标题应包含关键词(简单相关性验证)
first_title = self.search_page.get_first_product_title().lower()
self.assertIn(keyword.lower(), first_title,
f"第一个商品标题‘{first_title}’不包含关键词‘{keyword}’")
def test_02_search_with_invalid_keyword(self):
"""测试用例2:使用无效特殊字符搜索"""
keyword = get_config("SEARCH", "invalid_keyword") # 例如“@#$%”
self.search_page.search_from_homepage(keyword)
# 断言:应显示‘无结果’提示,或结果数量为0
no_result_displayed = self.search_page.is_no_result_displayed()
result_count = self.search_page.get_search_result_count()
self.assertTrue(no_result_displayed or result_count == 0,
"无效关键词搜索未得到预期无结果状态!")
def test_03_search_with_empty_keyword(self):
"""测试用例3:搜索框为空直接搜索"""
# 有些平台空搜索会跳转到特定页面或提示,这里假设会停留在首页或提示
self.search_page.search_from_homepage("") # 输入空字符串
# 这里断言比较灵活,可以是当前URL仍是首页,或者有提示信息
current_url = self.driver.current_url
# 假设空搜索不会改变URL(即还在首页)
self.assertEqual(current_url, self.search_page.base_url + "/",
"空搜索后页面发生了不应有的跳转!")
def test_04_search_keyword_trimming(self):
"""测试用例4:验证搜索关键词首尾空格是否被自动修剪"""
# 这是一个边界测试,很多搜索框会trim输入
keyword_with_spaces = " 手机 "
expected_keyword = "手机"
self.search_page.search_from_homepage(keyword_with_spaces)
# 验证方式:检查搜索后,搜索输入框内的值是否被修剪(如果页面保留的话)
# 或者通过结果相关性间接验证。这里我们假设搜索是trim的,并检查结果
result_count = self.search_page.get_search_result_count()
self.assertGreater(result_count, 0, "带空格的搜索未返回结果!")
# 更严谨的做法是获取搜索结果页的搜索框回显值,这里省略
@classmethod
def tearDownClass(cls):
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
6. 测试执行、报告生成与高级技巧
6.1 统一测试执行入口
我们创建 main.py 作为项目的主入口,用于批量执行所有测试用例并生成报告。
# main.py
import unittest
import os
import sys
import HtmlTestRunner
# 将项目根目录添加到Python路径,确保导入无误
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
def run_all_tests():
"""发现并运行所有测试用例"""
# 指定测试用例所在的目录
test_dir = os.path.join(project_root, 'test_cases')
# 使用TestLoader发现所有以‘test_’开头的.py文件中的测试用例
suite = unittest.TestLoader().discover(test_dir, pattern='test_*.py')
# 定义报告输出目录
report_dir = os.path.join(project_root, 'reports')
if not os.path.exists(report_dir):
os.makedirs(report_dir)
# 使用HTMLTestRunner生成更美观的报告
report_file = os.path.join(report_dir, 'automation_test_report.html')
with open(report_file, 'wb') as f:
runner = HtmlTestRunner.HTMLTestRunner(
stream=f,
report_title='电商平台自动化测试报告',
descriptions='登录与搜索功能测试执行结果',
verbosity=2
)
result = runner.run(suite)
print(f"测试报告已生成: {report_file}")
# 返回测试结果(例如用于CI/CD集成)
return result.wasSuccessful()
if __name__ == '__main__':
success = run_all_tests()
sys.exit(0 if success else 1) # 如果测试失败,返回非0退出码
运行 python main.py ,脚本会自动执行 test_cases 目录下所有测试,并在 reports 文件夹生成一个详细的 HTML 报告,里面包含了每个测试用例的执行状态、耗时和可能的失败信息,非常直观。
6.2 常见问题排查与实战技巧
在实际操作中,你肯定会遇到各种问题。这里我总结了一个速查表:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
NoSuchElementException |
1. 元素定位符写错。 2. 页面未加载完成,代码执行太快。 3. 元素在iframe或shadow DOM内。 4. 元素被动态生成,DOM结构变化。 |
1. 用浏览器开发者工具复查定位符。 2. 使用显式等待 WebDriverWait 。 3. 先 driver.switch_to.frame() 切换iframe。 4. 使用更稳定的相对XPath或CSS,或等待父元素出现。 |
ElementNotInteractableException |
1. 元素被遮挡(如弹窗)。 2. 元素不可见( display:none )。 3. 元素未处于可交互状态(如disabled)。 |
1. 关闭遮挡物。 2. 等待元素可见 ( EC.visibility_of_element_located )。 3. 检查元素状态,或通过JS强制操作。 |
| 脚本在本地运行成功,在服务器/CI失败 | 1. 浏览器驱动版本不匹配。 2. 服务器无图形界面(Headless模式)。 3. 网络环境或分辨率不同。 |
1. 使用 webdriver-manager 。 2. 配置Headless Chrome选项。 3. 在CI中设置固定窗口大小,增加等待时间。 |
| 测试报告乱码或无法生成 | 1. 文件编码问题。 2. 报告目录无写入权限。 |
1. 确保Python脚本和模板文件使用UTF-8编码。 2. 检查并修改 reports 目录权限。 |
| 登录时遇到验证码 | 这是自动化测试的难点。 | 1. 联系开发,在测试环境关闭验证码 ,这是最可行的方案。 2. 使用OCR库识别简单验证码(成功率低)。 3. 使用第三方打码平台API(有成本)。 |
高级技巧分享:
- 智能等待策略 :不要混用
time.sleep()。坚持使用显式等待 (WebDriverWait),并针对不同场景使用不同的条件,如presence_of_element_located(元素存在)、visibility_of_element_located(元素可见)、element_to_be_clickable(元素可点击)。 - 页面加载状态判断 :对于单页面应用(SPA),页面“加载完成”不等于“元素就绪”。可以通过等待某个特定元素(如加载动画消失)或检查
document.readyState来判断。def wait_for_page_loaded(self, timeout=30): """等待页面JS加载完成""" script = "return document.readyState" def page_loaded(driver): return driver.execute_script(script) == "complete" WebDriverWait(self.driver, timeout).until(page_loaded) - 失败截图 :在
tearDown或测试失败时自动截图,能极大方便问题定位。可以重写unittest的tearDown方法。def tearDown(self): if hasattr(self, '_outcome') and self._outcome.errors: # 测试失败 screenshot_name = f"failure_{self._testMethodName}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png" self.driver.save_screenshot(os.path.join('reports', screenshot_name)) print(f"测试失败,截图已保存: {screenshot_name}") - 数据驱动测试 :如果有多组登录数据要测试,可以使用
unittest的@parameterized.expand装饰器(需安装parameterized库)或读取外部CSV/Excel文件,避免写多个重复的测试方法。
7. 持续集成与后续优化方向
当你的自动化脚本稳定运行后,可以考虑将其集成到持续集成(CI)流水线中,比如 Jenkins、GitLab CI 或 GitHub Actions。这样可以在每次代码提交后自动运行测试,及时反馈构建质量。核心步骤就是在 CI 配置中安装 Python 环境、依赖,然后执行 python main.py 命令。
后续的优化方向可以包括:
- 引入日志系统 :使用 Python 的
logging模块记录详细的执行过程,方便追溯。 - 测试数据外部化 :将测试用例数据(如多种搜索词组合)放到 JSON 或 YAML 文件中管理。
- 并发执行 :使用
pytest-xdist或unittest的multiprocessing模块并行运行测试用例,缩短执行时间。 - 容器化 :使用 Docker 将测试环境(包括浏览器、驱动、Python版本)固化,确保在任何机器上运行结果一致。
这个项目麻雀虽小,五脏俱全,涵盖了从环境搭建、框架设计、用例编写到报告生成和问题排查的完整流程。最关键的是理解 POM 设计模式、显式等待机制以及如何编写健壮、可维护的测试用例。在实际工作中,你可以以此为基础,不断扩展,覆盖购物车、下单、支付等更复杂的电商业务流程。
更多推荐
所有评论(0)