这次我们来看一个面向初学者的Python自动化测试教程。这个教程的核心目标很明确:让零基础的小白也能从环境搭建开始,一步步掌握自动化测试的核心工具,并最终完成一个完整的项目实战。它不空谈理论,而是聚焦于“能不能用”和“怎么用”,重点覆盖了Selenium、接口测试、Appium等主流工具链,并提供了可运行的实战项目代码。
对于想入门自动化测试的开发者来说,最关心的往往是环境配置是否复杂、工具是否稳定、学完能否立刻上手做项目。本文将围绕这些核心问题展开,带你完成从Python环境安装、测试工具配置、到编写第一个自动化脚本,再到集成化项目实战的全过程。我们会重点关注每一步的操作细节、可能遇到的坑以及解决方案,确保你跟着做就能跑通。
1. 核心能力速览
本教程内容并非一个单一的软件,而是一套完整的学习路径和工具集。下表概括了其核心覆盖范围:
| 能力项 | 说明 |
|---|---|
| 目标读者 | 自动化测试零基础初学者、希望系统提升的测试工程师、需要快速上手测试脚本的开发人员。 |
| 技术栈 | Python 3.x, Selenium, Pytest, Requests, Appium, Allure 等。 |
| 环境门槛 | 普通Windows/Mac电脑即可,无需高性能GPU。主要依赖Python环境和浏览器驱动。 |
| 核心功能 | 1. Web UI自动化 (Selenium) 2. 接口自动化测试 (Requests + Pytest) 3. 移动端App自动化 (Appium) 4. 测试报告生成 (Allure) 5. 企业级项目实战框架搭建。 |
| 学习产出 | 获得一套可运行的、结构清晰的自动化测试项目代码,理解从用例设计、脚本编写到报告生成的全流程。 |
| 是否支持“批量任务” | 是。通过Pytest可以方便地组织和管理大量测试用例,并支持批量执行。 |
| 是否提供“接口/API” | 是。教程中包含对被测系统接口的测试,并会教你如何封装自己的测试API。 |
2. 适用场景与使用边界
这套教程主要解决以下几个实际问题:
- 入门迷茫:针对不知道自动化测试从何学起的新手,提供一条清晰的、手把手的学习路径。
- 环境劝退:详细解决Python环境配置、驱动安装、环境变量设置等初期最容易卡住的“拦路虎”。
- 工具串联:不仅讲解单个工具(如Selenium)的用法,更演示如何将Pytest、Requests、Allure等工具组合起来,形成一个高效的测试工作流。
- 缺乏实战:通过模拟真实项目(如电商网站、API服务)的测试场景,让学习者拥有“项目经验”,而不仅仅是孤立的知识点。
使用边界与注意事项:
- 合法合规:所有自动化测试操作应仅针对你有权测试的系统(如公司项目、开源项目或专为学习搭建的测试环境)。严禁对未授权的线上生产系统进行自动化测试,这可能被视为攻击行为。
- 学习目的:教程中的技术和代码主要用于学习自动化测试原理与实践。将其应用于实际业务时,需充分考虑测试稳定性、维护成本及与CI/CD流程的集成。
- 环境差异:由于操作系统版本、浏览器版本、驱动版本的差异,某些步骤可能需要微调。教程会提供通用的排查思路。
3. 环境准备与前置条件
在开始编写第一行自动化代码之前,一个干净、正确的开发环境是成功的一半。请按顺序完成以下准备。
3.1 基础软件安装
Python 安装:这是所有工作的基础。建议安装 Python 3.8 或 3.9 版本,这两个版本生态兼容性最好。
- 操作:访问 Python 官网下载安装包。安装时务必勾选“Add Python to PATH”选项,这是避免后续无数“命令找不到”错误的关键。
- 验证:安装完成后,打开命令行(CMD或Terminal),输入
python --version或python -V。正确显示版本号即表示安装成功。
代码编辑器/IDE:推荐使用Visual Studio Code (VSCode)。它轻量、免费,且通过插件能完美支持Python开发和测试。
- 操作:官网下载安装VSCode。
- 必备插件:安装后,在扩展商店搜索并安装
Python和Pylance插件。
3.2 包管理工具配置
Python通过pip管理第三方库。为了获得更快的下载速度和稳定的环境,建议配置国内镜像源。
- 临时使用:在安装命令后加
-i参数。pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple - 永久配置(推荐):
- Windows:在用户目录(如
C:\Users\你的用户名\)下创建pip文件夹,并在其中创建pip.ini文件,内容如下:[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn - Mac/Linux:在用户目录下创建
~/.pip/pip.conf文件,内容同上。
- Windows:在用户目录(如
4. 安装部署核心测试工具
环境就绪后,开始安装本教程涉及的核心测试库和工具。
4.1 安装Web自动化工具链
打开命令行,依次执行以下命令:
# 安装Selenium,用于控制浏览器 pip install selenium # 安装WebDriver管理器,自动下载和管理浏览器驱动,解决驱动版本匹配难题 pip install webdriver-manager # 安装Pytest,测试框架核心,用于组织、运行用例和断言 pip install pytest # 安装Pytest的增强插件,用于控制用例执行顺序、多线程等 pip install pytest-xdist pytest-ordering # 安装Allure-Pytest适配器,用于生成漂亮的测试报告 pip install allure-pytest注意:webdriver-manager是一个神器,它能自动检测你电脑上的浏览器版本,并下载匹配的ChromeDriver或GeckoDriver,极大简化了环境配置。
4.2 安装接口测试工具链
# 安装Requests库,用于发送HTTP请求(GET, POST, PUT, DELETE等) pip install requests # 安装用于数据验证和格式化的库 pip install jsonschema # 用于验证JSON响应结构 pip install pyyaml # 用于读取YAML格式的测试数据4.3 安装移动端测试工具链(可选)
如果你需要学习App自动化,还需配置Appium环境。这是一个相对复杂的过程,简要步骤如下:
- 安装Node.js:Appium Server基于Node.js。从Node.js官网下载安装。
- 安装Appium:通过npm安装。
npm install -g appium - 安装Appium客户端库:
pip install Appium-Python-Client - 安装Android SDK或Xcode(用于iOS):并配置好环境变量(如
ANDROID_HOME)。 - 安装UI自动化驱动:对于Android,通常需要
uiautomator2驱动。
由于移动端环境配置篇幅较长,本教程后续实战部分将先以Web和接口自动化为主。建议初学者先掌握前者,再专门攻克Appium环境。
5. 功能测试与效果验证:从第一个脚本到完整流程
现在,我们来实际验证每个核心工具是否工作正常。
5.1 验证一:Selenium Web自动化(Hello World)
创建一个名为first_selenium_test.py的文件。
from selenium import webdriver from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service import time # 使用webdriver-manager自动设置ChromeDriver路径 service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) try: # 1. 打开百度 driver.get("https://www.baidu.com") print("当前页面标题:", driver.title) time.sleep(2) # 等待页面加载,实际项目应使用WebDriverWait # 2. 定位搜索框,输入关键词 search_box = driver.find_element(By.ID, "kw") search_box.send_keys("Selenium自动化测试") print("已输入搜索关键词") # 3. 定位搜索按钮,并点击 search_button = driver.find_element(By.ID, "su") search_button.click() print("已点击搜索按钮") time.sleep(3) # 4. 验证搜索结果页面标题是否包含关键词 assert "Selenium自动化测试" in driver.title print("断言成功:页面标题包含‘Selenium自动化测试’") finally: # 5. 关闭浏览器 driver.quit() print("浏览器已关闭,测试完成!")运行与验证:
- 在文件所在目录打开命令行。
- 执行
python first_selenium_test.py。 - 预期结果:会自动打开Chrome浏览器,访问百度,输入文字并搜索,最后控制台打印出成功信息,浏览器关闭。
- 成功标准:脚本能自动执行所有操作,且不报错。如果遇到“Chrome版本不匹配”错误,
webdriver-manager会自动处理。
5.2 验证二:Pytest测试框架与断言
Pytest让测试更结构化。创建test_sample.py文件。
import requests # 被测函数 def add(a, b): return a + b # Pytest测试用例 def test_add_integers(): assert add(1, 2) == 3 def test_add_strings(): assert add("Hello, ", "World!") == "Hello, World!" def test_api_status(): # 测试一个公开的API接口 response = requests.get("https://httpbin.org/status/200") assert response.status_code == 200运行与验证:
- 在命令行执行
pytest test_sample.py -v(-v显示详细信息)。 - 预期结果:Pytest会收集并运行三个以
test_开头的函数,并输出类似3 passed的结果。 - 成功标准:所有测试用例通过。这验证了Pytest的基本运行和断言机制。
5.3 验证三:Requests接口测试
创建test_api_with_requests.py文件。
import requests import pytest BASE_URL = "https://jsonplaceholder.typicode.com" # 一个免费的测试API网站 def test_get_posts(): """测试获取帖子列表""" response = requests.get(f"{BASE_URL}/posts") assert response.status_code == 200 data = response.json() assert isinstance(data, list) # 返回的应该是列表 assert len(data) > 0 # 列表不应为空 # 验证第一条数据有预期的字段 first_post = data[0] assert 'userId' in first_post assert 'id' in first_post assert 'title' in first_post assert 'body' in first_post print("GET /posts 接口测试通过") def test_create_post(): """测试创建新帖子""" new_post = { "title": "foo", "body": "bar", "userId": 1, } headers = {'Content-type': 'application/json; charset=UTF-8'} response = requests.post(f"{BASE_URL}/posts", json=new_post, headers=headers) assert response.status_code == 201 # 创建成功应返回201 created_post = response.json() assert created_post['title'] == new_post['title'] assert created_post['body'] == new_post['body'] assert created_post['userId'] == new_post['userId'] assert 'id' in created_post # 服务器应返回一个唯一的id print(f"POST /posts 接口测试通过,创建的文章ID为: {created_post['id']}") if __name__ == "__main__": # 也可以直接运行这个脚本 test_get_posts() test_create_post()运行与验证:
- 执行
pytest test_api_with_requests.py -v或python test_api_with_requests.py。 - 预期结果:脚本会发送真实的HTTP请求到测试服务器,并验证响应状态码和数据结构。
- 成功标准:两个测试函数均通过,控制台打印成功信息。这证明了Requests库能正常工作,并且你已掌握基本的接口测试验证点。
6. 项目实战:搭建一个简易的自动化测试框架
掌握了点状技能后,我们将它们串联起来,搭建一个结构清晰、易于维护的测试项目。这是从“会用工具”到“能做项目”的关键一步。
6.1 项目目录结构
创建一个名为auto_test_project的文件夹,并组织如下结构:
auto_test_project/ ├── config/ # 配置文件 │ └── config.yaml # 存放测试环境URL、数据库配置等 ├── test_cases/ # 测试用例目录 │ ├── web_ui/ # Web UI测试用例 │ │ └── test_baidu_search.py │ ├── api/ # 接口测试用例 │ │ └── test_jsonplaceholder_api.py │ └── conftest.py # Pytest共享夹具(fixture) ├── common/ # 公共模块 │ ├── __init__.py │ ├── webdriver_manager.py # 浏览器驱动封装 │ └── request_client.py # 请求客户端封装 ├── test_data/ # 测试数据文件 │ └── user_data.json ├── logs/ # 日志目录(自动生成) ├── reports/ # 测试报告目录(自动生成) ├── requirements.txt # 项目依赖列表 └── pytest.ini # Pytest配置文件6.2 核心模块封装示例
1. 封装浏览器驱动 (common/webdriver_manager.py)
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.options import Options def get_chrome_driver(headless=False): """获取Chrome浏览器驱动实例 Args: headless (bool): 是否无头模式运行(不显示浏览器界面) Returns: WebDriver实例 """ chrome_options = Options() if headless: chrome_options.add_argument("--headless") # 无头模式,适合CI环境 chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--window-size=1920,1080") # 使用webdriver-manager自动管理驱动 service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service, options=chrome_options) driver.implicitly_wait(10) # 设置隐式等待10秒 return driver2. 封装请求客户端 (common/request_client.py)
import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class RequestClient: def __init__(self, base_url): self.base_url = base_url self.session = requests.Session() # 配置重试策略,增强稳定性 retries = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504]) self.session.mount('http://', HTTPAdapter(max_retries=retries)) self.session.mount('https://', HTTPAdapter(max_retries=retries)) def get(self, endpoint, params=None, **kwargs): url = f"{self.base_url}{endpoint}" response = self.session.get(url, params=params, **kwargs) logger.info(f"GET {url} - Status: {response.status_code}") return response def post(self, endpoint, data=None, json=None, **kwargs): url = f"{self.base_url}{endpoint}" response = self.session.post(url, data=data, json=json, **kwargs) logger.info(f"POST {url} - Status: {response.status_code}") return response # 可以继续封装put, delete等方法3. 编写一个完整的Web UI测试用例 (test_cases/web_ui/test_baidu_search.py)
import pytest from common.webdriver_manager import get_chrome_driver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class TestBaiduSearch: """百度搜索测试类""" @pytest.fixture(scope="class") def driver(self): """测试类级别的fixture,所有用例共享一个浏览器实例""" d = get_chrome_driver(headless=False) # 调试时可设为False看界面 yield d d.quit() # 测试类结束后关闭浏览器 def test_search_selenium(self, driver): """测试搜索Selenium""" driver.get("https://www.baidu.com") # 使用显式等待,更健壮 search_box = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "kw")) ) search_box.send_keys("Selenium") driver.find_element(By.ID, "su").click() # 等待结果出现 WebDriverWait(driver, 10).until( EC.title_contains("Selenium") ) assert "Selenium" in driver.title def test_search_pytest(self, driver): """测试搜索Pytest""" driver.get("https://www.baidu.com") search_box = driver.find_element(By.ID, "kw") search_box.clear() search_box.send_keys("Pytest") driver.find_element(By.ID, "su").click() WebDriverWait(driver, 10).until( EC.title_contains("Pytest") ) assert "Pytest" in driver.title6.3 运行项目并生成报告
- 安装项目依赖:在项目根目录创建
requirements.txt,内容包含之前安装的所有库。然后运行pip install -r requirements.txt。 - 配置Pytest:创建
pytest.ini文件。[pytest] testpaths = test_cases python_files = test_*.py python_classes = Test* python_functions = test_* addopts = -v --tb=short --strict-markers log_cli = true log_cli_level = INFO - 执行测试并生成Allure报告:
执行后,Allure会生成一个包含图表、用例详情、失败截图(需额外配置)的漂亮HTML报告,这是向团队展示测试结果的有效方式。# 运行所有测试用例 pytest # 运行指定模块 pytest test_cases/web_ui/ # 运行并生成Allure结果数据 pytest --alluredir=./reports/allure-results # 生成并打开Allure HTML报告 (需要先安装Allure命令行工具) allure serve ./reports/allure-results
7. 接口API与批量任务实践
7.1 设计可复用的API测试用例
利用Pytest的参数化功能,可以轻松实现批量测试。创建test_cases/api/test_parametrize_api.py:
import pytest import requests BASE_URL = "https://jsonplaceholder.typicode.com" # 参数化测试数据:每个元组代表一组测试输入和预期结果 @pytest.mark.parametrize("post_id, expected_title", [ (1, "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"), (2, "qui est esse"), (3, "ea molestias quasi exercitationem repellat qui ipsa sit aut"), ]) def test_get_post_by_id(post_id, expected_title): """参数化测试:验证不同ID的帖子标题是否正确""" response = requests.get(f"{BASE_URL}/posts/{post_id}") assert response.status_code == 200 post_data = response.json() assert post_data['id'] == post_id assert post_data['title'] == expected_title print(f"帖子ID {post_id} 测试通过,标题为: {post_data['title']}") # 从文件读取测试数据(更工程化的做法) import json with open('./test_data/post_ids.json', 'r') as f: # 假设有这个文件 test_data = json.load(f) @pytest.mark.parametrize("data", test_data) def test_get_post_from_file(data): """从JSON文件读取数据驱动测试""" response = requests.get(f"{BASE_URL}/posts/{data['id']}") assert response.status_code == 200 post_data = response.json() assert post_data['title'] == data['expected_title']运行pytest test_cases/api/test_parametrize_api.py -v,你会看到Pytest自动运行了多组测试数据,实现了真正的“批量任务”。
7.2 搭建一个简单的测试任务队列(概念)
对于更复杂的批量任务(如每晚定时跑全量用例),可以结合schedule库或CI/CD工具(如Jenkins、GitLab CI)。
一个简单的本地定时执行脚本示例run_daily_tests.py:
import schedule import time import subprocess import logging from datetime import datetime logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') def job(): """定时执行的任务:运行测试并生成报告""" logging.info("开始执行每日自动化测试任务...") timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") result_dir = f"./reports/daily_run_{timestamp}" # 使用subprocess调用pytest命令 cmd = f"pytest --alluredir={result_dir}" try: subprocess.run(cmd, shell=True, check=True) logging.info(f"测试任务完成,报告已生成至: {result_dir}") except subprocess.CalledProcessError as e: logging.error(f"测试执行失败,返回码: {e.returncode}") # 每天上午9点执行 schedule.every().day.at("09:00").do(job) logging.info("定时任务调度器已启动,等待执行...") while True: schedule.run_pending() time.sleep(60) # 每分钟检查一次8. 常见问题与排查方法
自动化测试过程中,90%的问题集中在环境配置和元素定位上。下表列出了常见问题及解决方案:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
ModuleNotFoundError: No module named 'selenium' | Python环境未安装Selenium库,或不在当前使用的Python环境中。 | 命令行执行pip list,查看是否有selenium。检查VSCode或终端使用的Python解释器路径。 | 1. 确认在正确的环境中执行pip install selenium。2. 在VSCode中按 Ctrl+Shift+P,选择Python: Select Interpreter,切换到已安装库的环境。 |
WebDriverException: Message: 'chromedriver' executable needs to be in PATH | 未找到ChromeDriver,或版本与Chrome浏览器不匹配。 | 检查Chrome浏览器版本。手动下载的ChromeDriver是否在PATH中。 | 推荐方案:安装webdriver-manager库,并使用本文示例代码,让它自动管理驱动。 |
| Selenium脚本运行时浏览器闪退 | 浏览器驱动与浏览器版本严重不兼容;或脚本执行完毕自动退出。 | 查看脚本最后是否调用了driver.quit()或driver.close()。 | 1. 确保使用webdriver-manager。2. 在脚本调试时,可以在最后加 time.sleep(10)临时阻止关闭,观察页面。 |
找不到页面元素 (NoSuchElementException) | 1. 页面尚未加载完成。 2. 元素定位符(如ID、XPath)写错了。 3. 元素在iframe或shadow DOM内。 | 1. 添加显式等待 (WebDriverWait)。2. 使用浏览器开发者工具检查元素属性。 3. 检查是否存在iframe。 | 1.必用显式等待替代time.sleep。2. 使用相对稳定的定位方式,如ID、CSS Selector。 3. 切换到正确的iframe: driver.switch_to.frame(frame_element)。 |
| Pytest找不到测试用例 | 测试文件/函数命名不符合Pytest默认规则,或不在当前搜索路径。 | 执行pytest --collect-only查看Pytest发现了哪些用例。 | 1. 确保测试文件以test_开头,函数以test_开头。2. 在 pytest.ini中配置testpaths。3. 在命令行指定具体文件路径: pytest path/to/test_file.py。 |
| 接口测试返回403/404等错误 | 1. 请求URL错误。 2. 需要请求头(如Token、Content-Type)。 3. 请求方法不对。 | 1. 打印出完整的请求URL和参数。 2. 使用Postman等工具先调试通接口。 3. 查看接口文档。 | 1. 仔细核对URL和参数。 2. 在Requests请求中添加必要的headers。 3. 使用Session对象保持会话(如登录态)。 |
| Allure报告生成后是空的 | 运行测试时没有指定--alluredir,或目录路径错误。 | 检查运行命令和--alluredir指定的目录下是否有.json结果文件。 | 1. 确保运行命令正确:pytest --alluredir=./results。2. 生成报告: allure generate ./results -o ./report --clean。 |
9. 最佳实践与使用建议
遵循以下建议,可以让你的自动化测试代码更健壮、更易维护:
- 环境隔离:使用
venv或conda为每个项目创建独立的Python虚拟环境,避免包版本冲突。 - 配置与代码分离:将URL、账号密码、数据库连接等配置信息放在
config.yaml或.env文件中,不要硬编码在脚本里。 - 使用Page Object模式(PO):对于UI自动化,将页面元素定位和操作封装成单独的类。这极大提高了代码复用性和可维护性。
- 善用Fixture:Pytest的Fixture是管理测试前置和后置条件(如启动浏览器、登录、清理数据)的强大工具,多用
@pytest.fixture。 - 添加日志和截图:在关键步骤和用例失败时,记录日志并对浏览器页面截图。这对于调试CI/CD环境下的失败用例至关重要。
- 断言要具体:断言失败信息应清晰明了。使用Pytest内置的断言即可,它提供了很好的失败信息。
- 考虑测试稳定性:网络波动、页面加载慢都会导致测试失败。合理使用显式等待、重试机制,并对非核心功能的检查点做宽松断言。
- 版本控制:将你的测试框架代码用Git管理起来,方便团队协作和回溯。
10. 总结与下一步
通过本文的梳理,你应该已经完成了一个Python自动化测试从零开始的核心闭环:环境搭建 -> 工具安装 -> 单个功能验证 -> 项目框架搭建 -> 批量任务与报告生成 -> 问题排查。
最值得立刻尝试的,是按照第5节的验证步骤,确保你的Selenium和Pytest环境能跑通第一个脚本。这是信心的起点。最容易踩的坑是环境配置,尤其是驱动问题,请务必使用webdriver-manager来规避。
接下来,你可以沿着这个框架深入:
- 深入Web UI:学习更复杂的元素定位(XPath, CSS Selector)、处理弹窗、下拉框、文件上传。
- 深入接口测试:设计数据驱动测试、集成数据库验证、测试加密接口、性能测试入门。
- 集成CI/CD:将你的测试项目接入Jenkins、GitLab CI或GitHub Actions,实现代码提交后自动测试。
- 探索移动端:当Web和接口测试熟练后,再按照第4.3节的指引,攻克Appium移动端自动化。
自动化测试是一个“动手”远比“动眼”重要的领域。建议你立即创建一个项目文件夹,把文中的代码敲一遍,在解决问题的过程中,你会掌握得更加牢固。这套教程提供的路径和代码,可以作为你长期学习和参考的基石。