Python+Selenium驱动Chrome实现TPshop商城注册登录自动化测试实战
2026/9/20 13:30:17 网站建设 项目流程

简介:这是一份面向Web自动化测试入门者与Python测试开发人员的实战型PDF资料,围绕Python+Selenium+Chrome工具链,完整演示TPshop商城从注册到登录的自动化测试流程。资料逐段拆解了元素定位、隐式/显式等待、ActionChains操作、JavaScript滚动、输入校验与错误信息捕获等核心知识点,并给出了可直接运行的示例代码。包体为单个PDF文档,大小仅97KB,内容紧凑,适合系统学习后随时查阅。目前已有2431人学习下载,获得较多学习者关注。通过这套实战练习,读者可快速理解Selenium自动化的标准操作步骤,掌握编写、调试和验证测试脚本的常见思路,为商城项目后续实战打下扎实基础。

1. 从零跑通Selenium注册登录脚本,先别急着写代码

接触过Web自动化测试的同学,对Python加Selenium加Chrome这套组合应该都不陌生。但说实话,很多刚入门的朋友拿着教程里的一段脚本,看完了觉得懂了,一放到自己电脑上跑,各种报错直接把人劝退。我在学习TPshop商城项目自动化测试时,也经历了这么一段从一脸懵到逐渐理顺的过程。

这里说的TPshop,是一个开源的单商户B2C商城系统,前后台功能完整,非常适合拿来做自动化测试练手。为什么选它而不选那些更复杂的电商系统?因为测试入门阶段最忌讳的就是把精力花在环境的坑和业务理解的复杂上。TPshop的注册和登录逻辑足够典型,又不会太绕,用来练习定位、等待、断言这些基本功,恰恰是性价比最高的选择。

这篇博文我打算讲清楚一件事:如何用Python加Selenium驱动Chrome,把TPshop商城的注册和登录功能做成一套可反复执行的自动化脚本。我不会只丢一段代码让你自己研究,而是会把每一步设计背后的原因、容易踩的坑、以及排查思路都摊开来聊。无论你是刚学会Python基础语法,还是已经写过一点Selenium但总感觉不够系统,这篇内容都能给你一个可复现的完整参考。

2. 环境准备中最容易被忽略的版本匹配问题

2.1 Python、Selenium、Chrome三者之间的关系

先把这套工具链的分工理顺。Python负责写测试逻辑,Selenium相当于一个翻译官,把Python指令翻译成浏览器能听懂的操作,而Chrome是最终执行操作的那个“人”。所以整个链路里,任意一层出了问题,脚本都没法正常工作。

在实际配置环境时,最常见的坑恰恰出现在这里。很多初学者会把Selenium库安装好,然后直接写脚本,结果运行时报错找不到ChromeDriver,或者报SessionNotCreatedException,一看错误信息是Chrome版本和驱动版本不匹配。这时候有人会去下载最新的驱动,但仍然不行,因为Chrome浏览器本身是自动更新的,驱动版本必须和浏览器版本严格对齐。

以我当时的环境为例,Chrome版本是116,对应的ChromeDriver也必须是116系列的版本。Selenium有个很实用的设定,它支持的driver版本号和Chrome主版本号前几位保持一致就没问题,不需要精确到小版本一模一样。但如果你用的Chrome是115,而驱动下载的是116,大概率会报错,而且错误信息往往不够友好,容易让人误以为是代码写错了。

2.2 安装步骤与验证方法

第一步,安装Python。这个没什么好说的,官网下载安装包,安装时记得勾选Add Python to PATH。这个勾选框我每次都要提醒一次,因为漏了它,后面在命令行里输入python会提示找不到命令,很多新人卡在这一步卡了半天。

第二步,安装Selenium库。在命令行执行pip install selenium即可。如果下载速度慢,可以加-i https://pypi.tuna.tsinghua.edu.cn/simple换清华源。

第三步,下载ChromeDriver。打开Chrome浏览器,在地址栏输入chrome://version,查看版本号。然后去ChromeDriver的下载页面找到对应版本,下载后解压得到一个chromedriver.exe文件。这里有两种用法,一是把这个exe直接放到Python安装目录的scripts文件夹里,二是放到项目目录下,在代码中指定路径。我个人的习惯是放到项目目录下显式指定,这样项目换到别的电脑时,只要整个文件夹拷走就能跑,不太依赖系统环境。

验证环境是否准备好,可以用一段极简脚本:

from selenium import webdriver driver = webdriver.Chrome() driver.get("https://www.baidu.com") print(driver.title) driver.quit()

如果能正常启动浏览器并打印出百度标题,说明这套链路已经通了。如果这段脚本都跑不通,后面的内容先不用看了,回去把环境理顺再说。环境通了,整个自动化测试就等于成功了三分之一。

3. TPshop注册功能的定位策略与业务逻辑拆解

3.1 先理清页面元素再动手写脚本

TPshop安装好之后,前台首页地址一般是http://127.0.0.1/tpshop/或者带端口号的地址,具体看本地环境配置。打开首页,右上角就能看到“注册”入口。做自动化测试和手工点鼠标最大的区别在于,你得先告诉脚本“去哪里”以及“点什么”,而这个“告诉”的过程,依赖的就是元素定位。

我看到很多新手拿到一个页面,第一反应是去抄页面上的XPath,什么//*[@id="app"]/div[1]/div[2]/div[2]/div[2],这种定位方式,说实话能用,但极其脆弱,只要前端HTML有一丁点变动,脚本直接崩溃。正确的做法是优先使用ID、Name、ClassName这类相对稳定的定位方式,实在不行再用XPath或者CSS选择器,而且XPath也尽量用包含文本或者属性判断的方式,减少层级依赖。

TPshop的注册页面,邮箱输入框、手机号输入框、密码输入框、确认密码输入框都带有比较明确的属性。以手机号输入框为例,它的HTML结构里通常会有name="mobile"或类似的属性,用driver.find_element(By.NAME, "mobile")就比那一长串XPath稳当得多。核心思路是:定位方式越简单、越靠近元素的稳定属性,脚本的健壮性就越强。

3.2 业务逻辑:TPshop注册还有一个容易被忽略的点

TPshop注册分为账号注册和手机号注册两种方式,我强烈建议新手从手机号注册入手。为什么?因为账号注册流程太简单了,输入用户名和密码点提交就完事,对自动化测试而言几乎没有技术含量。而手机号注册涉及一个动态验证码的获取逻辑——它真正的验证码不是由用户输入的,而是由后台发到手机上的,测试环境中一般会在页面上直接显示。

这就引出一个非常关键的测试设计点:在处理这类验证码时,不能人为地把等待时间写死。比如有的同学习惯time.sleep(3),觉得等三秒验证码就出来了,其实这是不科学的——网络状况不同、服务器响应速度不同,实际等待时间有波动。更合理的做法是用Selenium提供的WebDriverWait显式等待,轮询页面元素直到出现为止。这不仅让脚本更加稳定,也符合真实自动化框架的设计理念。

等待的逻辑想通了,再来看页面操作的顺序:点击注册入口,切换到注册页面,选择手机号注册,输入手机号,触发发送验证码,等待验证码输入框出现并填入,填写密码和确认密码,点击同意协议,最后提交。这里面每一项操作都对应一个Selenium的动作,每一步动作之间都需要一个明确的预期结果,这就是自动化测试脚本设计的核心思维——不仅仅是写代码,而是把业务逻辑翻译成代码。

3.3 注册脚本的核心代码参考

下面这段代码是我当时跑通时使用的核心逻辑,为了篇幅不会把全部代码贴出来,但关键的几个步骤都有体现:

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 driver = webdriver.Chrome() driver.get("http://127.0.0.1/tpshop/") driver.maximize_window() # 点击免费注册 WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.LINK_TEXT, "免费注册")) ).click() # 切换到手机号注册页签 WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, ".tab li:last-child a")) ).click() # 输入手机号 mobile = "13800138000" driver.find_element(By.NAME, "mobile").send_keys(mobile) # 点击获取验证码 driver.find_element(By.ID, "sendCode").click() # 页面上会显示测试环境的验证码,等待输入框可见后填入 code_input = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.NAME, "verify_code")) ) test_code = driver.find_element(By.CSS_SELECTOR, ".code_tip").text code_input.send_keys(test_code) # 密码和确认密码 driver.find_element(By.NAME, "password").send_keys("test123456") driver.find_element(By.NAME, "password2").send_keys("test123456") # 勾选用户协议,提交 driver.find_element(By.CSS_SELECTOR, ".checkbox").click() driver.find_element(By.CSS_SELECTOR, ".btn-reg").click()

这段代码有几个值得注意的设计细节。第一,所有关键操作都用显式等待包了一层,而不是裸奔的find_element加sleep,这就保证了元素还没加载好之前脚本会耐心等待,而不是直接抛异常。第二,截取测试验证码的方式,是通过读取页面上的某个提示元素来完成的,这依赖TPshop在测试环境把验证码直接输出到了页面上。第三,每次跑完注册脚本,要换一个新的手机号,因为TPshop默认一个手机号只能注册一个账号,第二次用同一个号跑会提示已被注册,脚本就会失败。

注册成功之后,页面上通常会出现用户中心入口,或者弹出注册成功的提示,你可以用这个提示来断言注册是否成功。

4. 登录脚本的断言设计与会话保持验证

4.1 为什么登录比注册更考验脚本的兼容性

TPshop的登录逻辑比注册流程要多考虑一层:页面上登录入口和注册入口距离很近,但登录表单的控件结构有所不同,而且登录成功后页面会跳转,如果只验证“点击登录按钮没有报错”,这不算一个合格的自动化测试用例。一个合格的登录用例,至少应该验证三件事:登录动作确实执行了、页面发生了预期的跳转、页面上出现了只有登录用户才能看到的标志性元素。

这三个验证点用Selenium实现起来不难,但需要你有断言的意识。我见过很多初学者的脚本,从头到尾都是在操作元素,最后页面上报了个登录成功弹窗,脚本就结束了,没有做任何校验。这其实只能叫“脚本”,不能叫“测试”,因为你连结果对不对都没验证。

4.2 完整操作流程及代码写法

TPshop的登录页面通过首页右侧的登录入口进入,也可以直接访问登录页URL。登录表单包含用户名输入框和密码输入框,用户名这里支持手机号登录,也就意味着注册用的手机号和密码直接可以用来登录。脚本逻辑如下:

# 打开首页,点击登录 driver.get("http://127.0.0.1/tpshop/") WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.LINK_TEXT, "登录")) ).click() # 输入用户名和密码 username = "13800138000" password = "test123456" name_input = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, "username")) ) name_input.send_keys(username) driver.find_element(By.ID, "password").send_keys(password) # 如果有图形验证码,这里是测试环境时可以直接跳过或自动获取 # 点击登录 driver.find_element(By.CSS_SELECTOR, ".btn-login").click() # 验证登录结果:等待用户中心入口出现 user_center = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.CSS_SELECTOR, ".user-info")) ) assert user_center.is_displayed(), "登录失败,未找到用户信息区域"

等你真正跑起来,马上会遇到一个TPshop特有的问题——登录页面可能有图形验证码。图形验证码是自动化测试最头疼的事情之一,因为它的设计初衷就是防止机器操作。如果做的验证码比较复杂,比如扭曲变形的文字、需要拖动滑块的拼图,那就不太适合放进初学阶段的自动化脚本里了。对于TPshop默认的图形验证码,如果只是简单的四位字符,可以找开发配置一个万能验证码,或者在测试环境关闭验证码校验。做自动化测试时千万不要把重心放在破解验证码上,除非你专门研究这一块,否则纯粹是浪费时间。

登录成功后的断言,我习惯用页面跳转后出现的用户中心区域来判断。Selenium的is_displayed()方法可以判断元素是否可见,再配合assert语句,如果元素没出现,脚本就会报AssertionError,这就能明确表示登录失败了。用这种断言方式,脚本跑完以后你一眼就能看出登录是否成功,不用自己去翻浏览器界面。

4.3 一个参数化设计优化:数据驱动

注册和登录跑通之后,可以顺手做一个简单的数据驱动改造。不要继续在代码里硬编码用户名和密码,而是把它们提取到一个外部文件里,比如CSV或者JSON,每次运行时从外部读取。这样做的好处在后期的回归测试里非常明显——你可以准备一组有效账号、一组无效账号,循环执行登录脚本,验证系统对不同账号的校验是否正确。

简化的实现思路是:

import csv def load_test_data(path): cases = [] with open(path, encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: cases.append(row) return cases for case in load_test_data("login_data.csv"): username = case["username"] password = case["password"] expected = case["expected"] # 执行登录,最后用expected来判断断言内容

这个改造本身不难,但它能让脚本从“一次性玩具”变成“可回归的工具”,这是自动化测试和手动点按钮最大的差异所在。几乎每一个正式的自动化测试框架,核心都是数据与脚本分离。

5. 实战中必须记录的四个老大难问题

5.1 ChromeDriver版本不匹配,错误信息看不明白

这个问题我在环境准备部分提过,但在实战中遇到的概率实在太高,值得单独拿出来再说一次。报错通常是这样的:SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 114。这句话其实已经把答案说得很清楚了,但新手往往看不懂英文,或者不知道去哪里查Chrome版本。

解决办法就是去chrome://version页面查一下浏览器版本号,然后找到对应版本的ChromeDriver替换掉。这里有个小技巧:ChromeDriver的下载页面列出的版本里可能找不到完全一致的小版本号,但只要你选择主版本号一致的版本,一般都能正常工作。

我见过一个比较极端的案例,同事的Chrome版本是116.0.5845.188,他下载了116.0.5845.96的驱动,心里不踏实,问我差这么多会不会有问题,实际跑下来完全正常。所以记住:主版本号对齐,就基本没问题。

5.2 元素明明存在,点击却报超时

这种情况通常不是元素不存在,而是元素被遮挡了。TPshop的页面里,很多按钮会被弹窗或者浮层盖住,比如登录时弹出的营销活动弹窗、注册时的用户协议遮罩层。Selenium点击一个被遮挡的元素时会提示element not interactable或者超时。

排查思路分三步:一,先判断元素是否在DOM中存在,用find_elements看返回的列表长度;二,看元素是否可见,用is_displayed;三,如果都正常但点不了,考虑是不是有浮层盖住了。解决方式有两种,一是等浮层消失后再点击,二是用JavaScript强制执行点击。对于测试环境,我一般优先用第一种,因为更贴近真实用户的操作习惯——真用户看到弹窗第一反应是点关闭,测试脚本也应该模拟这个流程。

5.3 验证码导致用例无法稳定执行

系统加了验证码之后,自动化的稳定性会瞬间下降。刚接触测试的同学往往想着怎么去识别验证码,比如用OCR、接第三方平台,但这些方案成本高、不稳定,而且每次跑测试可能都要花钱。在项目早期做冒烟测试和功能回归时,最好的方案是找开发配合,在测试环境下屏蔽掉验证码校验,或者提供一个万能的测试验证码。

如果实在没法修改系统,只能在脚本层想办法,那至少要让这个用例可配置:可以加一个环境判断,如果当前是测试环境就跳过验证码校验逻辑,如果跑在生产环境预发环境则提示需要人工介入。这样用例既能在日常回归中跑通,又不会在不该跑的环境里乱跑。

5.4 断言位置不对,脚本“假成功”

脚本跑完没有报错,并不代表测试通过了。我遇到过不止一次这样的情况:脚本从头到尾非常流畅地执行完了,控制台也没有报任何异常,最后打开浏览器一看,根本没有登录成功,只是登录按钮的点击动作触发了一个前端校验提示,而脚本没有校验这个结果。

原因很直接,就是断言的位置放错了,或者压根没有断言。处理这个问题有没有什么方法论?有,而且是三条铁律。第一,每次操作之后,必须有一个校验,否则这个操作就没有意义;第二,校验的必须是业务结果,而不是页面有没有加载出来;第三,如果预期是成功但实际是失败,断言必须让脚本显式地失败,而不是默默无闻地跑过去。登录成功最重要的标志不是停留在登录页而是跳转到用户中心或首页并出现账号信息,要拿这类强标志性元素来断言,而不是看页面标题变了没有。

6. 项目结构如何组织,才能让它从练习变成资产

前面写的基本都是脚本层面的事情,但如果你只是把代码堆在一个py文件里,跑通一次就算完了,那这个项目对你的成长价值非常有限。真正值得花时间做的,是把这套练习按标准的自动化测试项目结构组织起来,哪怕项目的规模并不大。

我当时做的目录规划如下:

tpshop_auto_test/ ├── base/ │ ├── __init__.py │ ├── base_page.py # 封装WebDriver的公共操作 │ └── base_test.py # 封装用例的公共逻辑 ├── pages/ │ ├── __init__.py │ ├── register_page.py # 注册页面的元素与操作 │ └── login_page.py # 登录页面的元素与操作 ├── testcases/ │ ├── __init__.py │ ├── test_register.py │ └── test_login.py ├── data/ │ └── login_data.csv ├── utils/ │ └── driver_factory.py ├── reports/ └── requirements.txt

这种结构还能发挥一个作用——为将来引入pytest等主流测试框架铺垫。如果你从一开始就把脚本写成函数堆叠,想迁移到pytest框架,等于要全部推翻重写。而如果你一开始就把注册和登录分别写成独立的class和方法,将来加一段pytest断言就能直接跑出漂亮的测试报告。

说到底,注册和登录这两个功能只是起点。TPshop这个项目最好的地方在于,它给你提供了一个可以无限扩展的练习场:购物车、订单流程、后台商品管理、优惠券模块,所有这些功能都值得从手工功能测试的眼光转向自动化测试脚本。你每写完一个模块的脚本,Selenium的操作熟练度、定位策略的直觉、断言点的敏感度,都会上一个台阶。

在你开始动手之前,我最后提一个建议:不管你的Python基础多扎实,一定要老老实实地把环境从零开始搭一遍,然后把注册和登录脚本至少手敲三遍,不要复制粘贴。手敲三遍之后,你自然就理解了哪些地方容易报错,哪些坑是必然要踩的,这种体感和看代码是完全不一样的。自动化测试从来不是把代码跑通就够了,真正有价值的是每一次报错之后你能独立定位问题的过程。把这些过程记录下来,比任何测试报告都有意义。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询