嘿,朋友。既然你点开了这篇文章,我猜你要么刚入行测试,正对着满屏的报错日志发懵;要么就是准备转行,想找个扎实、能落地的入门路径。别慌,测试这行当,看着门槛低,其实水很深,但也最讲究“手感”和“逻辑”。今天我不跟你整那些虚头巴脑的理论定义,咱们直接上手,像搭积木一样,把你从环境配好、到写脚本、再到扛住压力、最后搞定兼容性,一步步领进门。
第一步:别急着写代码,先把“战场”清理干净
很多新手一上来就打开Python,想着我要写Selenium,我要写Requests。停!在动鼠标之前,你得先确保你的开发环境是“干净”且“专业”的。这就像赛车手上车前要先检查胎压一样,基础不牢,地动山摇。
1.1 语言选择:为什么我们首选 Python + JavaScript?
你可能听说过 Java 做测试,确实,大厂老牌系统多用 Java。但作为新手,Python 是绝对的首选。为什么?
- 语法像说话:
requests.get(url)这行代码,你读一遍就知道它在干嘛。 - 生态无敌:Selenium、Pytest、Locust、Allure,这些顶级工具对 Python 的支持是最丝滑的。
- 转行友好:学会 Python 测试,你还能顺手摸一点自动化运维和数据分析,职业天花板更高。
对于 Web 前端兼容性测试,你不得不了解 JavaScript,因为浏览器里跑的就是它。你不需要成为前端专家,但你得会看控制台(Console)的报错,那里面藏着真相。
1.2 环境配置实操:用虚拟环境保护你的系统
千万别在全局 Python 里乱装包,否则今天装 requests 2.25,明天装 requests 2.28,项目直接崩给你看。我们需要 虚拟环境。
假设你用的是 Windows 或 Mac,打开终端(CMD 或 Terminal),跟着我敲:
# 1. 创建一个叫 'web_test' 的项目文件夹并进入
mkdir web_test_project
cd web_test_project
# 2. 创建虚拟环境 (名字叫 venv)
python -m venv venv
# 3. 激活虚拟环境
# Windows:
venv\Scripts\activate
# Mac/Linux:
source venv/bin/activate
# 注意:看到命令行前面出现了 (venv),说明激活成功了
接下来,安装你的“武器库”:
# 接口测试必备
pip install requests pytest pytest-html
# 浏览器自动化必备
pip install selenium webdriver-manager
# 性能压测必备 (轻量级)
pip install locust
# 报告美化 (让你的测试报告看起来像那么回事)
pip install allure-pytest
专家提示:webdriver-manager 这个包是神器。以前你还要手动下载 ChromeDriver,还得对版本,烦死人。有了它,Selenium 启动时会自动下载匹配你浏览器版本的驱动,一劳永逸。
第二步:接口测试——抓住数据的命门
Web 应用就像一座冰山,前端界面只是露出来的一角,水面下庞大的逻辑和数据处理都发生在 API 接口里。如果接口错了,前端页面做得再漂亮也是空中楼阁。
2.1 什么是接口?通俗点说
你点一下“登录”,浏览器并不是直接把你的人肉翻进数据库。它做的是:
- 浏览器把用户名密码打包成一张纸条(JSON 格式)。
- 纸条塞进信封(HTTP 请求),发给服务器。
- 服务器检查纸条,回传一个结果(成功或失败)。
- 浏览器收到结果,决定是跳转首页还是弹出“密码错误”。
我们要测的,就是这个“纸条”和“回传结果”。
2.2 用 Python Requests 写第一个登录接口测试
我们要用 pytest 框架,因为它结构清晰,方便后续扩展。新建一个文件 test_login.py。
import requests
import pytest
# 假设我们的测试地址是 http://192.168.1.100:8080 (这是你们本地的开发环境)
BASE_URL = "http://localhost:8080/api"
class TestLogin:
"""登录模块测试类"""
def test_login_success(self):
"""场景1:账号密码正确,应该登录成功并返回 Token"""
payload = {
"username": "admin",
"password": "123456"
}
# 发送 POST 请求
response = requests.post(f"{BASE_URL}/login", json=payload)
# 断言:状态码应该是 200
assert response.status_code == 200
# 断言:返回的 JSON 里应该有 'token' 字段,且不为空
json_data = response.json()
assert "token" in json_data
assert len(json_data["token"]) > 10 # 简单的长度校验,防止返回空字符串
def test_login_wrong_password(self):
"""场景2:密码错误,应该返回特定错误码"""
payload = {
"username": "admin",
"password": "wrong_password"
}
response = requests.post(f"{BASE_URL}/login", json=payload)
# 有些系统密码错返回 401,有些返回 200 但 msg 不同,这里假设返回 400
assert response.status_code == 400
json_data = response.json()
assert json_data["code"] == 1001 # 假设 1001 代表密码错误
def test_login_missing_field(self):
"""场景3:不传密码,接口应该报错,而不是崩掉"""
payload = {
"username": "admin"
# 故意没传 password
}
response = requests.post(f"{BASE_URL}/login", json=payload)
# 即使参数缺失,接口也不应返回 500 (服务器内部错误)
assert response.status_code != 500
运行测试:
pytest test_login.py -v
看到 PASSED 和 FAILED 的字样了吗?这就是测试的生命。
2.3 接口测试的常见报错与排查
新手最容易遇到的坑,我列几个典型的:
ConnectionError: Could not connect to the server- 原因:服务器没启动,或者 IP/端口写错了。
- 解决:先 Ping 一下那个 IP,或者用浏览器手动访问一下
http://localhost:8080看看通不通。
JSONDecodeError: Expecting value- 原因:接口返回的不是 JSON,可能是 HTML 报错页面(比如 502 Bad Gateway),或者返回了空。
- 解决:打印
response.text看看实际返回了什么。很多时候是服务器炸了,返回了一段 HTML 代码,而不是 JSON。
断言失败:
AssertionError- 原因:业务逻辑变了。比如以前登录返回
token,现在改成access_token。 - 解决:检查最新的接口文档,修改断言逻辑,而不是怀疑代码。
- 原因:业务逻辑变了。比如以前登录返回
第三步:UI 自动化——让浏览器替你干活
接口通了,页面不一定能用。用户点击按钮没反应?弹窗没弹出来?这时候需要 Selenium 来模拟真人的浏览器操作。
3.1 为什么要用自动化?
手动点100次登录很枯燥,但让脚本点100次,只需1分钟。而且自动化能发现一些人工难以察觉的问题,比如偶发的页面加载超时、内存泄漏导致的卡顿。
3.2 搭建 Selenium 环境并写出第一个脚本
新建 test_ui_login.py:
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
from webdriver_manager.chrome import ChromeDriverManager
import time
def test_login_ui_flow():
# 1. 初始化浏览器驱动,自动管理驱动版本
options = webdriver.ChromeOptions()
# 可选:无头模式,不打开浏览器窗口,适合后台运行
# options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
try:
# 2. 打开登录页
driver.get("http://localhost:8080/login")
# 3. 等待页面加载完毕,特别是等待用户名输入框出现
# 最多等10秒,每0.5秒刷新一次判断
username_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username"))
)
# 4. 输入账号密码
username_input.send_keys("admin")
password_input = driver.find_element(By.ID, "password")
password_input.send_keys("123456")
# 5. 点击登录按钮
login_btn = driver.find_element(By.ID, "login-btn")
login_btn.click()
# 6. 等待跳转,验证是否成功
# 假设登录成功后 URL 会变成 /dashboard
WebDriverWait(driver, 10).until(
EC.url_contains("/dashboard")
)
# 7. 截图留念,证明测试通过
driver.save_screenshot("success_login.png")
print("测试通过:登录成功并已截图保存")
except Exception as e:
print(f"测试失败: {e}")
driver.save_screenshot("error_login.png") # 失败了也截图,方便排查
raise
finally:
# 8. 关闭浏览器
driver.quit()
if __name__ == "__main__":
test_login_ui_flow()
关键点解析:
- WebDriverWait:这是自动化的灵魂。很多页面是异步加载的,如果你直接
find_element,可能元素还没渲染出来,脚本就报错了。等待显式条件满足再操作,是稳定性的保证。 - By.ID / By.XPATH:定位元素的方式。优先用 ID,稳定且快;如果没 ID,再用 XPATH 根据层级关系找。
- Finally 块:不管中间出不出错,最后都要
quit()关闭浏览器,否则你会开满一屏幕的浏览器窗口,电脑卡死。
3.3 UI 自动化的常见报错
NoSuchElementException- 原因:元素找不到。可能是 ID 变了,可能是页面没加载完,也可能是元素在 iframe 里。
- 解决:
- 按 F12 打开开发者工具,F1 看看元素是否存在。
- 如果是 iframe 里的元素,先
driver.switch_to.frame("frame_id")切进去再找。 - 增加等待时间,或者改用显式等待。
ElementNotInteractableException- 原因:元素存在,但被遮挡了,或者还在滚动区域外面。
- 解决:尝试用 JavaScript 强制滚动到元素位置
driver.execute_script("arguments[0].scrollIntoView();", element),或者用 JS 点击driver.execute_script("arguments[0].click();", element)。
TimeoutException- 原因:等得太久了,元素还没出来。
- 解决:检查网络是否慢,或者检查 XPath 写得对不对。有时候是测试环境服务器响应慢,可以适当增加等待时间,但不要用
time.sleep()硬等,那是偷懒的做法,不稳定。
第四步:接口压力测试——看看你的系统能扛多少人
系统单测没问题,一上并发就崩,这叫“虚胖”。压力测试就是为了找出系统的瓶颈。
这里推荐 Locust,一个基于 Python 的高性能分布式负载测试工具。它的好处是你可以用 Python 代码来编写用户行为,非常灵活。
4.1 安装与配置
pip install locust
4.2 编写压测脚本
新建 locustfile.py:
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
"""模拟一个真实用户的行为"""
# 用户等待时间:每次请求间隔 1-3 秒随机等待,模拟真人节奏
wait_time = between(1, 3)
# 基础 URL,方便调用
host = "http://localhost:8080"
@task(3) # 权重为3,表示这个任务发生的概率是下面的3倍
def login(self):
with self.client.post("/api/login", json={"username": "admin", "password": "123456"}, catch_response=True) as response:
if response.status_code == 200:
response.success()
# 把 token 存下来,后续请求用
self.token = response.json().get("token")
else:
response.failure(f"Login failed with status {response.status_code}")
@task(1) # 权重为1
def view_dashboard(self):
# 假设查看首页需要带 token
if hasattr(self, 'token'):
headers = {"Authorization": f"Bearer {self.token}"}
with self.client.get("/api/dashboard", headers=headers, catch_response=True) as response:
if response.status_code == 200:
response.success()
else:
response.failure(f"Dashboard failed")
else:
# 没登录就去访问 dashboard,预期会失败,但也记录一下
with self.client.get("/api/dashboard", catch_response=True) as response:
if response.status_code == 401:
response.success() # 401 是预期内的,不算失败
else:
response.failure(f"Unexpected status {response.status_code}")
if __name__ == "__main__":
import os
os.system("locust -f locustfile.py --headless -u 100 -r 10 --run-time 1m")
命令解释:
-u 100:模拟 100 个并发用户。-r 10:每秒启动 10 个用户( Ramp-up 阶段)。--run-time 1m:跑 1 分钟。--headless:无界面运行,直接在终端看结果。
4.3 如何看懂压测结果?
运行后,你会得到几个关键指标:
- RPS (Requests Per Second):每秒处理请求数。越高越好,但要结合 CPU 使用情况看。
- Avg (Average Response Time):平均响应时间。如果超过 1秒,用户体验就开始差了。
- Median:中位数响应时间。比平均值更靠谱,因为它不受极端慢请求的影响。
- 95th percentile:95% 的请求都在这个时间内完成。这是衡量用户体验的关键指标。
- Failures:失败率。如果失败率超过 1%,系统就有问题。
常见瓶颈排查:
- RPS 上不去,CPU 100%:代码逻辑有死循环,或者数据库查询没加索引。
- RPS 上不去,IO Wait 高:磁盘读写太慢,或者是网络带宽打满了。
- 响应时间随着用户增加线性增长:系统没有缓存,每次请求都要查数据库,典型的数据库瓶颈。
第五步:浏览器兼容性——世界不止 Chrome 一个
你的系统在 Chrome 上完美运行,但在 Safari 或 IE 上乱成一团?这是很多项目的噩梦。作为测试,你必须考虑兼容性。
5.1 兼容性测试策略
确定目标浏览器矩阵:
- 不要试图测试所有浏览器。问产品经理:“我们的用户主要用什么?”
- 通常包括:Chrome (最新2个版本), Firefox (最新), Safari (最新), Edge (最新)。如果国内项目,还要考虑 360浏览器、QQ浏览器等国产双核浏览器。
使用云服务:
- 你不可能买无数台 Mac 和 Windows 电脑。
- 推荐使用 BrowserStack 或 Sauce Labs。它们提供云端真实的浏览器环境,你可以在本地控制远程的浏览器。
- 对于预算有限的小团队,可以用 LambdaTest,它有免费额度。
5.2 手动兼容性排查技巧
如果你不能访问付费云服务,可以自己动手:
CSS 兼容性问题:
- 很多新 CSS 属性(如
grid,flex的高级用法)在老版本浏览器支持不好。 - 工具:使用 Can I Use 网站查询某个属性在各浏览器的支持率。
- 解决:使用 PostCSS 或 Babel 自动添加浏览器前缀(如
-webkit-,-moz-)。
- 很多新 CSS 属性(如
JavaScript 兼容性问题:
- 老浏览器不支持
async/await或Promise。 - 工具:Babel 转译。确保你的构建工具(Webpack/Vite)配置了正确的 targets。
- 排查:打开 Safari 的开发者工具,看 Console 里的红色报错。Safari 的报错信息有时候很模糊,但能告诉你哪一行错了。
- 老浏览器不支持
真机测试:
- 手机端的兼容性至关重要。iOS 和 Android 的 WebView 内核不同。
- 如果没有真机,至少用 Chrome DevTools 的 Device Mode 模拟 iPhone 和 Android 的屏幕尺寸和
