一、数据类型
1.1 整数(int)
Python 的整数没有大小上限,随便写多大都能存、能计算,不会溢出。
python
# Python直接算1后面1000个0,Java必须用BigInteger写一堆代码
big_num = 10 ** 1000
print(big_num)
1.2 浮点数(float)
Python 的 float 等价 Java 的 double(64 位双精度),浮点数有精度损失,建议使用 decimal 模块进行精确计算。
python
from decimal import Decimal
# 测试decimal模块
a = Decimal('1.23')
b = Decimal('4.56')
print(a + b) # 输出: 5.79
1.3 字符串(str)
字符串可以进行拼接和重复操作。
python
# 字符串拼接
s1 = 'hello'
s2 = 'world'
print(s1 + s2) # 输出: helloworld
# 字符串重复
s = 'hello'
print(s * 3) # 输出: hellohellohello
1.4 布尔值(bool)
bool 继承自 int,True = 1,False = 0,可以直接参与运算。
python
print(True + 1) # 输出: 2
print(False * 5) # 输出: 0
1.5 None 值
None 表示空值,等价于 Java 的 null。
python
# None 表示空值
a = None
print(a) # 输出: None
1.6 列表(list)
列表是 Python 中最常用的数据结构,相当于 Java 的 ArrayList。
python
# 列表
a = [1, 2, 3]
print(a) # 输出: [1, 2, 3]
# 列表支持混合类型
mixed_list = [1, "hello", 3.14, True]
print(mixed_list) # 输出: [1, 'hello', 3.14, True]
# 列表常用操作
a.append(4) # 添加元素到末尾
a.insert(0, 0) # 在指定位置插入
a.pop() # 删除最后一个元素
a.remove(2) # 删除指定值的元素
二、数据结构进阶
2.1 元组(tuple)
元组是不可变的序列,一旦创建就不能修改。
python
# 元组
t = (1, 2, 3)
print(t) # 输出: (1, 2, 3)
# 尝试修改会报错
# t[0] = 99 # TypeError: 'tuple' object does not support item assignment
# 元组解包
a, b, c = t
print(a, b, c) # 输出: 1 2 3
2.2 字典(dict)
字典是键值对集合,相当于 Java 的 HashMap。
python
# 字典
d = {"name": "Alice", "age": 25}
print(d) # 输出: {'name': 'Alice', 'age': 25}
# 添加键值对
d["email"] = "alice@example.com"
# 访问值
print(d["name"]) # 输出: Alice
print(d.get("age")) # 输出: 25
# 删除键值对
del d["age"]
2.3 集合(set)
集合是无序不重复元素的集合,相当于 Java 的 HashSet。
python
# 集合
s = {1, 2, 3, 3, 2} # 自动去重
print(s) # 输出: {1, 2, 3}
# 添加元素
s.add(4)
# 集合运算
s1 = {1, 2, 3}
s2 = {3, 4, 5}
print(s1 | s2) # 并集: {1, 2, 3, 4, 5}
print(s1 & s2) # 交集: {3}
print(s1 - s2) # 差集: {1, 2}
三、控制流程
3.1 条件判断
python
x = 10
if x > 10:
print("大于10")
elif x == 10:
print("等于10")
else:
print("小于10")
3.2 循环
python
# for 循环 - 迭代
for i in range(5): # 0-4
print(i)
# 遍历列表
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# while 循环
count = 0
while count < 5:
print(count)
count += 1
3.3 异常处理
python
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"除零错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
else:
print("没有异常发生")
finally:
print("无论如何都会执行")
四、函数与模块
4.1 函数定义
python
def add(a, b=0): # 默认参数
"""加法函数"""
return a + b
result = add(10, 20) # 30
result = add(10) # 10(使用默认值)
4.2 模块导入
python
import math
from utils import logger
from utils.logger import get_logger as gl
五、面向对象编程
5.1 类定义
python
class Person:
# 类属性(所有实例共享)
species = "Homo sapiens"
# 构造方法
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
# 实例方法
def greet(self):
print(f"Hello, {self.name}")
# 类方法
@classmethod
def get_species(cls):
return cls.species
# 静态方法
@staticmethod
def is_adult(age):
return age >= 18
5.2 继承
python
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age) # 调用父类构造
self.grade = grade
def study(self):
print(f"{self.name} is studying in grade {self.grade}")
5.3 多态
python
class Dog:
def speak(self):
return "Woof!"
class Cat:
def speak(self):
return "Meow!"
def animal_sound(animal):
print(animal.speak())
dog = Dog()
cat = Cat()
animal_sound(dog) # Woof!
animal_sound(cat) # Meow!
5.4 封装
python
class BankAccount:
def __init__(self, balance):
self.__balance = balance # 私有属性(约定用双下划线)
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
六、Python 进阶特性
6.1 列表推导式
python
# 生成 0-9 的平方列表
squares = [x**2 for x in range(10)]
# 带条件的列表推导
even_squares = [x**2 for x in range(10) if x % 2 == 0]
# 字典推导式
squares_dict = {x: x**2 for x in range(5)}
6.2 生成器
python
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
for num in fibonacci(10):
print(num)
6.3 装饰器
python
def logger(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
result = func(*args, **kwargs)
print(f"Done")
return result
return wrapper
@logger
def add(a, b):
return a + b
6.4 上下文管理器
python
with open("file.txt", "r") as f:
content = f.read()
# 文件自动关闭
七、文件操作
7.1 读写文件
python
# 写入文件
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, World!")
# 读取文件
with open("output.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
7.2 JSON 操作
python
import json
# 写入 JSON
data = {"name": "Alice", "age": 25}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f)
# 读取 JSON
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
print(data)
八、Python 常见"坑"与注意事项
8.1 可变默认参数陷阱
python
# ❌ 错误示例
def add_item(item, lst=[]):
lst.append(item)
return lst
add_item(1) # [1]
add_item(2) # [1, 2] ❌ 不是预期的 [2]
# ✅ 正确示例
def add_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
8.2 浅拷贝与深拷贝
python
import copy
# 浅拷贝
a = [1, 2, [3, 4]]
b = a.copy()
b[2][0] = 99
print(a) # [1, 2, [99, 4]] ❌ 内部列表被修改
# 深拷贝
c = copy.deepcopy(a)
c[2][0] = 88
print(a) # [1, 2, [99, 4]] ✅ 原列表不受影响
8.3 布尔值陷阱
python
# ❌ 错误示例
if x = None: # 语法错误,不能在条件中赋值(应该用 == 或 is)
pass
# ✅ 正确示例
if x is None: # 使用 is 判断 None(推荐)
pass
# ✅ 也可以使用 ==
if x == None: # 也能工作,但不推荐
pass
注意: Python 中判断 None 推荐使用 is 而不是 ==,因为 is 比较的是对象身份,而 == 比较的是值。
8.4 字符串不可变
python
s = "hello"
# s[0] = 'H' # ❌ TypeError: 'str' object does not support item assignment
s = s.upper() # ✅ 返回新字符串
九、Python 实用技巧(自动化测试必备)
9.1 f-string 格式化字符串(Python 3.6+)
f-string 是最推荐的字符串格式化方式,简洁高效。
python
name = "Alice"
age = 25
# 基本用法
print(f"姓名: {name}, 年龄: {age}") # 输出: 姓名: Alice, 年龄: 25
# 表达式计算
print(f"明年年龄: {age + 1}") # 输出: 明年年龄: 26
# 调用方法
print(f"姓名大写: {name.upper()}") # 输出: 姓名大写: ALICE
# 字典访问
data = {"status": 200, "message": "OK"}
print(f"状态码: {data['status']}, 消息: {data['message']}")
# 格式化数字
pi = 3.1415926
print(f"π 保留两位小数: {pi:.2f}") # 输出: π 保留两位小数: 3.14
9.2 类型注解(Type Hints)
类型注解帮助 IDE 提供更好的代码提示,提高代码可读性。
python
from typing import List, Dict, Optional, Union
# 基本类型注解
def greet(name: str) -> str:
return f"Hello, {name}"
# 列表类型
def process_items(items: List[str]) -> int:
return len(items)
# 字典类型
def get_user_info(user_id: int) -> Dict[str, str]:
return {"id": str(user_id), "name": "Alice"}
# 可选类型(可能为 None)
def find_user(user_id: int) -> Optional[str]:
if user_id == 1:
return "Alice"
return None
# 联合类型
def parse_value(value: Union[str, int]) -> str:
return str(value)
9.3 pathlib 模块(现代文件操作)
pathlib 是 Python 3.4+ 引入的面向对象路径操作库,比 os.path 更优雅。
python
from pathlib import Path
# 创建路径对象
project_root = Path(__file__).parent.parent
config_file = project_root / "config" / "config.yaml"
# 检查文件是否存在
if config_file.exists():
print(f"配置文件存在: {config_file}")
# 读取文件内容
content = config_file.read_text(encoding="utf-8")
# 写入文件内容
output_file = project_root / "output" / "result.txt"
output_file.parent.mkdir(parents=True, exist_ok=True) # 创建目录
output_file.write_text("Hello, World!", encoding="utf-8")
# 遍历目录
log_dir = project_root / "logs"
for log_file in log_dir.glob("*.log"):
print(f"日志文件: {log_file.name}")
9.4 *args 和 **kwargs
用于接收可变数量的参数,在装饰器和通用函数中非常有用。
python
# *args 接收任意数量的位置参数
def sum_all(*args):
return sum(args)
print(sum_all(1, 2, 3)) # 输出: 6
print(sum_all(1, 2, 3, 4, 5)) # 输出: 15
# **kwargs 接收任意数量的关键字参数
def print_config(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_config(host="localhost", port=8080, debug=True)
# 输出:
# host: localhost
# port: 8080
# debug: True
# 组合使用
def flexible_function(required, *args, **kwargs):
print(f"必需参数: {required}")
print(f"位置参数: {args}")
print(f"关键字参数: {kwargs}")
flexible_function("req", 1, 2, name="Alice", age=25)
十、Python 与 Java 的核心差异
10.1 类型系统
| 特性 | Python | Java |
|---|---|---|
| 类型检查 | 动态类型 | 静态类型 |
| 变量声明 | a = 1 |
int a = 1; |
| 类型转换 | 自动 | 需要显式转换 |
| 泛型 | 无需泛型 | 必须使用泛型 |
10.2 语法差异
| 特性 | Python | Java |
|---|---|---|
| 代码块 | 缩进 | 花括号 {} |
| 分号 | 不需要 | 必须 |
| 注释 | # 单行,''' ''' 多行 |
// 单行,/* */ 多行 |
| 字符串 | 单引号/双引号均可 | 只能双引号 |
| 布尔值 | True/False(首字母大写) |
true/false(小写) |
| 空值 | None |
null |
10.3 内存管理
| 特性 | Python | Java |
|---|---|---|
| 垃圾回收 | 引用计数 + 自动回收 | JVM 垃圾回收器 |
| 内存泄漏 | 循环引用可能导致 | 较少见 |
十一、Python 生态与工具
11.1 包管理
bash
# 安装包
pip install requests
# 卸载包
pip uninstall requests
# 查看已安装包
pip list
# 导出依赖
pip freeze > requirements.txt
# 安装依赖
pip install -r requirements.txt
11.2 虚拟环境
bash
# 创建虚拟环境
python -m venv venv
# 激活虚拟环境(Windows)
venv\Scripts\activate
# 激活虚拟环境(Linux/Mac)
source venv/bin/activate
# 退出虚拟环境
deactivate
十二、自动化测试专项
12.1 pytest 测试框架详解
12.1.1 pytest 简介
pytest 是 Python 中最流行的测试框架,相比 Java 的 JUnit 更简洁、更强大。
核心特点:
- 简单易用,学习曲线平缓
- 自动发现测试文件和测试用例
- 支持参数化测试
- 强大的 fixture 机制(替代 JUnit 的 setUp/tearDown)
- 丰富的插件生态(测试报告、覆盖率等)
安装:
bash
pip install pytest pytest-html
12.1.2 测试用例编写
基本规则
- 测试文件以
test_开头或_test.py结尾 - 测试类以
Test开头(首字母大写) - 测试方法以
test_开头 - 使用
assert进行断言
示例:简单测试用例
python
# test_example.py
def test_addition():
"""测试加法运算"""
assert 1 + 2 == 3
def test_string_equal():
"""测试字符串相等"""
assert "hello" == "hello"
class TestMath:
"""数学运算测试类"""
def test_multiply(self):
"""测试乘法"""
assert 2 * 3 == 6
def test_divide(self):
"""测试除法"""
assert 10 / 2 == 5
12.1.3 pytest Fixture(夹具)
Fixture 是 pytest 中最强大的功能之一,用于管理测试依赖和共享资源。
基本用法
python
import pytest
# 定义 fixture
@pytest.fixture
def setup_data():
"""准备测试数据"""
print("\nSetup: 准备数据")
data = {"name": "test", "value": 100}
yield data # 提供测试数据给测试用例
print("\nTeardown: 清理数据") # 测试完成后执行
# 使用 fixture
def test_use_fixture(setup_data):
assert setup_data["name"] == "test"
assert setup_data["value"] == 100
Fixture 作用域
| 作用域 | 说明 | 生命周期 |
|---|---|---|
function |
默认,每个测试函数 | 每个测试函数执行一次 |
class |
每个测试类 | 每个测试类执行一次 |
module |
每个模块 | 每个模块执行一次 |
session |
整个测试会话 | 整个测试会话执行一次 |
python
@pytest.fixture(scope="session")
def session_fixture():
"""整个测试会话只执行一次"""
print("Session setup")
yield
print("Session teardown")
conftest.py 文件
conftest.py 是 pytest 的特殊配置文件,用于存放共享的 fixture。pytest 会自动发现并加载它。
python
# tests/conftest.py
import pytest
import yaml
import os
@pytest.fixture(scope="session")
def config():
"""读取配置文件"""
config_path = os.path.join(os.path.dirname(__file__), "..", "config", "config.yaml")
with open(config_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
@pytest.fixture(scope="function")
def logger():
"""获取日志记录器"""
from utils.logger import get_logger
return get_logger("test")
12.1.4 参数化测试
使用 @pytest.mark.parametrize 实现参数化测试,减少重复代码。
基本参数化
python
import pytest
@pytest.mark.parametrize("a, b, expected", [
(1, 2, 3), # 用例1:正常加法
(0, 0, 0), # 用例2:边界情况
(-1, 1, 0), # 用例3:负数相加
(1.5, 2.5, 4.0), # 用例4:小数相加
])
def test_add_parametric(a, b, expected):
"""参数化测试加法运算"""
assert a + b == expected
带 ID 的参数化
python
@pytest.mark.parametrize(
"a, b, expected",
[
(10, 20, 30),
(0, 0, 0),
(-5, -10, -15),
],
ids=["正常加法", "零操作数", "负数相加"] # 自定义用例名称
)
def test_add_with_ids(a, b, expected):
assert a + b == expected
从 JSON 文件读取参数化数据
python
import pytest
import json
# 从 JSON 文件加载测试数据
with open("test_data/parametric_test_data.json", "r", encoding="utf-8") as f:
test_data = json.load(f)["parametric_test"]["test_cases"]
@pytest.mark.parametrize(
"case_data",
test_data,
ids=[case["case_id"] for case in test_data]
)
def test_from_json(case_data):
"""从 JSON 文件读取测试数据"""
result = case_data["a"] + case_data["b"]
assert result == case_data["expected_result"]
12.1.5 断言
pytest 支持 Python 原生 assert,并能自动生成详细的错误信息。
常用断言方式
python
def test_assertions():
# 基本断言
assert 1 + 1 == 2
# 断言包含
assert "hello" in "hello world"
# 断言不相等
assert 1 != 2
# 断言为真/假
assert True
assert not False
# 断言异常
with pytest.raises(ZeroDivisionError):
1 / 0
# 断言异常并检查消息
with pytest.raises(ValueError, match="invalid literal"):
int("abc")
12.1.6 测试标记
使用标记对测试用例进行分类,支持分场景执行。
定义标记
在 pytest.ini 或 pyproject.toml 中配置:
ini
[pytest]
markers =
smoke: 冒烟测试用例
regression: 回归测试用例
api: 接口测试用例
ui: UI测试用例
使用标记
python
import pytest
@pytest.mark.smoke
def test_critical_function():
"""冒烟测试:关键功能"""
pass
@pytest.mark.api
@pytest.mark.regression
def test_api_function():
"""接口回归测试"""
pass
按标记运行测试
bash
# 运行冒烟测试
python -m pytest -m smoke
# 运行接口测试
python -m pytest -m api
# 排除某个标记
python -m pytest -m "not ui"
# 组合标记
python -m pytest -m "api and regression"
12.1.7 测试报告
生成 HTML 报告
bash
# 生成 HTML 报告
python -m pytest --html=reports/report.html
# 生成详细报告(包含失败详情)
python -m pytest --html=reports/report.html --self-contained-html
常用命令行参数
bash
# 显示详细输出
python -m pytest -v
# 只运行失败的测试
python -m pytest --lf
# 显示测试耗时
python -m pytest --durations=10
# 运行指定文件
python -m pytest tests/test_example.py
# 运行指定测试类
python -m pytest tests/test_example.py::TestMath
# 运行指定测试方法
python -m pytest tests/test_example.py::TestMath::test_multiply
# 停止于第一个失败
python -m pytest -x
# 显示打印输出
python -m pytest -s
12.1.8 与 Java JUnit 的对比
| 特性 | pytest | JUnit |
|---|---|---|
| 测试发现 | 自动发现 test_ 开头 |
需要注解 @Test |
| 前置/后置 | fixture | @Before/@After |
| 参数化 | @pytest.mark.parametrize |
@ParameterizedTest |
| 断言 | 原生 assert |
assertEquals() 等 |
| 测试报告 | 插件 pytest-html |
插件 surefire-report |
| 标记 | @pytest.mark |
@Tag |
12.2 requests 库(接口测试)
requests 是 Python 最流行的 HTTP 库,用于接口测试。
12.2.1 基本用法
python
import requests
# GET 请求
response = requests.get("https://api.example.com/users", timeout=10)
print(response.status_code) # 状态码
print(response.json()) # JSON 响应
print(response.text) # 文本响应
# POST 请求(JSON)
data = {"name": "Alice", "age": 25}
response = requests.post(
"https://api.example.com/users",
json=data, # 自动序列化为 JSON
timeout=10
)
# POST 请求(表单)
form_data = {"username": "admin", "password": "123456"}
response = requests.post(
"https://api.example.com/login",
data=form_data, # 表单数据
timeout=10
)
# 带请求头
headers = {
"Authorization": "Bearer token123",
"Content-Type": "application/json"
}
response = requests.get(
"https://api.example.com/protected",
headers=headers,
timeout=10
)
# 带查询参数
params = {"page": 1, "limit": 10}
response = requests.get(
"https://api.example.com/users",
params=params, # 自动拼接到 URL
timeout=10
)
12.2.2 异常处理
python
import requests
from requests.exceptions import RequestException, Timeout, ConnectionError
try:
response = requests.get("https://api.example.com/users", timeout=10)
response.raise_for_status() # 如果状态码不是 2xx,抛出异常
data = response.json()
print(data)
except Timeout:
print("请求超时")
except ConnectionError:
print("连接失败")
except RequestException as e:
print(f"请求异常: {e}")
12.2.3 Session 对象
Session 可以保持会话状态(如 Cookie),适合需要登录的场景。
python
import requests
# 创建会话
session = requests.Session()
# 登录
login_data = {"username": "admin", "password": "123456"}
session.post("https://api.example.com/login", json=login_data)
# 后续请求会自动携带 Cookie
response = session.get("https://api.example.com/profile")
print(response.json())
# 设置通用请求头
session.headers.update({"Authorization": "Bearer token123"})
# 关闭会话
session.close()
12.2.4 实战示例
python
import pytest
import requests
@pytest.fixture(scope="module")
def api_client():
"""API 测试客户端"""
session = requests.Session()
session.headers.update({"Content-Type": "application/json"})
yield session
session.close()
class TestUserAPI:
"""用户接口测试类"""
@pytest.mark.api
def test_get_user(self, api_client):
"""测试获取用户信息"""
response = api_client.get("https://api.example.com/users/1", timeout=10)
assert response.status_code == 200
data = response.json()
assert "id" in data
assert "name" in data
@pytest.mark.api
@pytest.mark.parametrize("user_id", [1, 2, 3])
def test_get_user_parametric(self, api_client, user_id):
"""参数化测试获取不同用户"""
response = api_client.get(f"https://api.example.com/users/{user_id}", timeout=10)
assert response.status_code == 200
12.3 Selenium(UI 自动化测试)
Selenium 是 Web UI 自动化测试的标准工具。
12.3.1 基本用法
python
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
from selenium.webdriver.chrome.service import Service
# 创建浏览器驱动
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
# 打开网页
driver.get("https://www.baidu.com")
# 元素定位
search_box = driver.find_element(By.ID, "kw")
search_button = driver.find_element(By.ID, "su")
# 输入文本
search_box.send_keys("自动化测试")
# 点击按钮
search_button.click()
# 显式等待(推荐)
wait = WebDriverWait(driver, 10)
result = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".result"))
)
# 获取文本
print(result.text)
# 关闭浏览器
driver.quit()
12.3.2 元素定位方式
python
# ID 定位
element = driver.find_element(By.ID, "element_id")
# CSS Selector 定位(推荐)
element = driver.find_element(By.CSS_SELECTOR, ".class_name")
element = driver.find_element(By.CSS_SELECTOR, "#id_name")
element = driver.find_element(By.CSS_SELECTOR, "div > p")
# XPath 定位
element = driver.find_element(By.XPATH, "//div[@class='test']")
# 名称定位
element = driver.find_element(By.NAME, "username")
# 标签名定位
elements = driver.find_elements(By.TAG_NAME, "input")
# 链接文本定位
element = driver.find_element(By.LINK_TEXT, "点击这里")
12.3.3 Page Object 模式
Page Object 是 UI 自动化的最佳实践,将页面元素和操作封装成类。
python
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BaiduHomePage:
"""百度首页页面对象"""
def __init__(self, driver):
self.driver = driver
self.search_box = (By.ID, "kw")
self.search_button = (By.ID, "su")
def open(self):
"""打开百度首页"""
self.driver.get("https://www.baidu.com")
return self
def search(self, keyword):
"""搜索关键词"""
search_input = WebDriverWait(self.driver, 10).until(
EC.visibility_of_element_located(self.search_box)
)
search_input.clear()
search_input.send_keys(keyword)
search_btn = self.driver.find_element(*self.search_button)
search_btn.click()
return BaiduSearchResultPage(self.driver)
class BaiduSearchResultPage:
"""百度搜索结果页面对象"""
def __init__(self, driver):
self.driver = driver
self.result_container = (By.CSS_SELECTOR, ".result")
def get_result_count(self):
"""获取结果数量"""
results = self.driver.find_elements(*self.result_container)
return len(results)
def is_keyword_in_results(self, keyword):
"""检查关键词是否在结果中"""
page_source = self.driver.page_source
return keyword in page_source
# 使用示例
def test_baidu_search(driver):
home_page = BaiduHomePage(driver)
result_page = home_page.open().search("自动化测试")
assert result_page.get_result_count() > 0
assert result_page.is_keyword_in_results("自动化测试")
12.3.4 pytest + Selenium 集成
python
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
@pytest.fixture(scope="function")
def driver():
"""浏览器驱动 fixture"""
service = Service(ChromeDriverManager().install())
options = webdriver.ChromeOptions()
# options.add_argument('--headless') # 无头模式
driver = webdriver.Chrome(service=service, options=options)
driver.implicitly_wait(10) # 隐式等待
yield driver
driver.quit() # 测试结束后关闭浏览器
def test_baidu_homepage(driver):
"""测试百度首页"""
driver.get("https://www.baidu.com")
assert "百度" in driver.title
12.4 YAML 配置文件读取
YAML 是常用的配置文件格式,比 JSON 更易读。
python
import yaml
# 读取 YAML 文件
with open("config/config.yaml", "r", encoding="utf-8") as f:
config = yaml.safe_load(f)
# 访问配置项
base_url = config["base_url"]
timeout = config["timeout"]
browser_type = config["browser"]["type"]
print(f"基础URL: {base_url}")
print(f"超时时间: {timeout}")
print(f"浏览器: {browser_type}")
config.yaml 示例:
yaml
environment: development
base_url: http://localhost:8080
timeout: 30
browser:
type: chrome
headless: true
implicit_wait: 10
api:
username: test_user
password: test_password
十三、项目实战指南
13.1 项目结构
auto-test-framework/
├── config/ # 配置文件
│ └── config.yaml # 主配置文件
├── test_data/ # 测试数据
│ ├── api/ # 接口测试数据
│ └── ui/ # UI测试数据
├── tests/ # 测试用例
│ ├── api/ # 接口测试
│ ├── ui/ # UI测试
│ ├── conftest.py # 共享fixture
│ └── demo/ # 示例测试
├── utils/ # 工具函数
│ ├── logger.py # 日志工具
│ └── helpers.py # 辅助函数
├── pages/ # 页面对象(UI测试)
├── reports/ # 测试报告
├── logs/ # 日志文件
├── pytest.ini # pytest配置
├── pyproject.toml # 项目配置
└── requirements.txt # 依赖清单
13.2 开发流程
- 编写测试数据 :在
test_data/目录下创建 JSON/YAML 文件 - 编写测试用例 :在
tests/目录下创建测试文件 - 运行测试 :
python -m pytest -v - 查看报告 :打开
reports/report.html - 调试优化:根据测试结果修复问题
13.3 最佳实践
- 测试数据分离:不要在代码中硬编码测试数据
- 使用 fixture:复用初始化代码
- 参数化测试:一套逻辑覆盖多种场景
- 异常处理:精准捕获预期异常
- 日志记录:关键步骤记录日志
- 断言明确:添加清晰的错误消息
- 代码复用:提取公共方法到 utils
13.4 常见问题排查
问题1:测试用例未被发现
- 检查文件名是否以
test_开头 - 检查类名是否以
Test开头 - 检查方法名是否以
test_开头
问题2:fixture 未生效
- 检查
conftest.py是否在正确的目录 - 检查 fixture 名称是否与参数名一致
- 检查 scope 是否合适
问题3:导入错误
- 检查项目根目录是否有
__init__.py - 检查 PYTHONPATH 是否包含项目根目录
- 使用绝对导入而非相对导入
问题4:中文乱码
- 文件读写时指定
encoding="utf-8" - JSON 文件保存时使用
ensure_ascii=False
十四、Python 知识体系总结
14.1 Python 知识点概览
Python 的知识体系其实非常庞大,远不止文档中这些内容。以下是完整的 Python 知识体系:
基础语法
- 变量与数据类型
- 运算符与表达式
- 控制流程(if/for/while)
- 函数定义与调用
- 异常处理
数据结构
- 列表(list)
- 元组(tuple)
- 字典(dict)
- 集合(set)
- 字符串(str)
- 字节(bytes)
面向对象
- 类与对象
- 继承与多态
- 封装
- 魔术方法
- 元类(metaclass)
进阶特性
- 装饰器
- 生成器
- 迭代器
- 上下文管理器
- 列表推导式
- Lambda 表达式
- 类型注解(typing)
并发编程
- 多线程(threading)
- 多进程(multiprocessing)
- 协程(asyncio)
- 并发安全(锁、信号量)
网络编程
- Socket 编程
- HTTP 请求(requests)
- Web 框架(Flask/Django)
- WebSocket
数据处理
- 文件操作(os/pathlib)
- JSON/YAML 处理
- CSV/Excel 处理
- 数据库操作(SQLAlchemy)
测试框架
- pytest
- unittest
- mock
- coverage
工具与生态
- 包管理(pip)
- 虚拟环境(venv)
- 代码格式化(black)
- 类型注解(typing)
专项领域
- 数据科学(NumPy/Pandas)
- 机器学习(scikit-learn)
- Web 开发(Django/Flask)
- 自动化测试(Selenium/requests)
- 数据可视化(Matplotlib)
14.2 学习建议
- 循序渐进:从基础语法开始,逐步深入
- 实践为主:多写代码,多做项目
- 查阅文档:遇到问题查阅官方文档
- 参与社区:加入 Python 社区,交流学习
- 阅读源码:学习优秀开源项目的代码风格
最后更新: 2026-05-25