目录
一、Pytest 单元测试框架
二、Yaml 数据格式
三、PyMySQL 实现与数据库的交互
四、Requests 向服务器发送请求,接收响应
五、Allure 生成测试报告
六、Logging 生成程序运行日志
接口自动化框架:pytest + yaml + pymysql + requests + allure + logging
一、Pytest
1.概念
pytest是python的一种第三方的单元测试框架,同自带的 unittest测试框架类似, 相比于 unittest框架使用起来更简洁, 更高效。
2.Pytest测试用例规则
若不使用配置文件(见使用第2点),就需要采用默认的测试用例的规则,如下:
- 模块名:以
test_
开头或_test
结尾 - 测试类名:以
Test
开头,尽量采用驼峰式命名,并且不能包含__init__.py
文件 - 测试方法名:以
test_
开头
3.使用
(1)setup和teardown
运行于测试方法的始末,运行一次测试函数会执行一次setup和teardown。
- setup(设置)
- 在执行测试用例之前,进行必要的初始化工作,如创建测试环境、设置测试数据等。通常,每个测试用例执行前都会执行一次setup操作。
- teardown(拆卸)
- 在执行测试用例之后,进行清理工作,如关闭数据库连接、删除临时文件等。通常,每个测试用例执行后都会执行一次teardown操作。
(2)配置文件
pytest.ini文件是pytest单元测试框架的核心配置文件,一般放在项目的根目录。这个文件用来改变pytest的默认行为,如:默认的测试用例命名方式。不管是主函数的模式运行。还是命令行模式运行,都会读取这个配置文件来执行脚本。
[pytest]
# 01 把命令行参数自动添加到这里
addopts = -vs
# 02 指定执行的用例的目录
testpaths = ./test
# 03 修改默认的测试文件名规则
python_files =test_*.py
# 04 修改默认的类命名规则
python_classes =Test*
# 05 测试函数/方法的命名规则
python_functions = test_*
(3)数据参数化
@pytest.mark.parametrize(参数名,数据源)是pytest中用于参数化测试的一种方式。
数据源可以是任何可迭代对象,比如列表、元组、集合等。示例:
import pytest
@pytest.mark.parametrize('input1, input2, expected', [
(1, 2, 3),
(3, 4, 7),
(5, 6, 11)
])
def test_add(input1, input2, expected):
result = input1 + input2
assert result == expected //断言,判断实际结果与预期结果是否一致
(4)测试报告插件
在命令行或者在配置文件pytest.ini【addopts】 中,增加 --html=report/report.html。
运行代码后, 在项目目录下会产生一个 report文件夹(包), 里面有个 report.html 的文件, 就是测试报告。
(5)夹具
1.定义
在pytest中,可以使用@pytest.fixture装饰器定义夹具函数。夹具函数可以包含初始化和清理代码,例如创建临时文件、建立数据库连接等。
2.运用场景
部分脚本在每个用例执行前都要操作,如:打开浏览器、购物车的登录,数据库的连接;
部分脚本在每个用例执行后都要操作,如:关闭浏览器。
3.使用
下面是一个简单的示例,演示如何使用 pytest 夹具:
import pytest
@pytest.fixture(autouse = True) #autouse = True:自动执行
def my_fixture( ):
print("前置方法") #登录操作、数据库连接...
yield
print("后置方法") #关闭浏览器...
【说明】:
1.pytest执行测试时,先执行夹具函数的开始部分,直到遇到 yield关键字;然后执行测试函数,执行完毕后,继续执行yield关键字之后的代码;
2.夹具可以指定作用域,包括函数级别(function)、模块级别(module)、类级别(class)、会话级别(session)。
那么,pytest夹具和setup()、teardown()的区别是什么?
答:setup()、teardown()的作用域是编写该方法的目录下的每一个测试方法,而pytest夹具可以自定义作用域,更灵活。
示例:
# test_module.py
class TestClass1:
@classmethod
def setup_class(cls):
print("Setup class for TestClass1")
def setup(self):
print("Setup for TestClass1")
def test_method1(self):
print("Test method 1 in TestClass1")
def test_method11(self):
print("Test method 11 in TestClass1")
def teardown(self):
print("Teardown for TestClass1")
@classmethod
def teardown_class(cls):
print("Teardown class for TestClass1")
class TestClass2:
@classmethod
def setup_class(cls):
print("Setup class for TestClass2")
def setup(self):
print("Setup for TestClass2")
def test_method2(self):
print("Test method 2 in TestClass2")
def test_method22(self):
print("Test method 22 in TestClass2")
def teardown(self):
print("Teardown for TestClass2")
@classmethod
def teardown_class(cls):
print("Teardown class for TestClass2")
setup_class
和 teardown_class
方法是在每个测试类开始执行前后分别调用的,它们是作用于同一测试类中的前后置操作,它会在整个测试类开始执行前执行一次,类内所有测试方法执行后执行一次。
setup
和 teardown
方法则是在每个测试方法开始执行前后分别调用的,它们是作用于同一测试类中的每个测试方法的前后置操作。
# test_module.py
import pytest
@pytest.fixture(scope="module") #模块级别
#它会在整个测试模块开始执行前执行一次,并在所有测试方法执行完成后执行一次。
def module_setup_teardown():
print("Module setup")
yield
print("Module teardown")
@pytest.fixture
def function_setup_teardown(): #默认:函数级别
#它会在每个测试方法开始执行前执行一次,并在每个测试方法执行完成后执行一次。
print("Function setup")
yield
print("Function teardown")
def test_method3(module_setup_teardown, function_setup_teardown):
print("Test method 3")
4.执行测试用例顺序
pytest中的测试用例执行时默认从上到下,可使用mark标记改变默认的执行顺序。示例:
import pytest
@pytest.mark.run(order=2)
def test_second():
assert True
@pytest.mark.run(order=1)
def test_first():
assert True
@pytest.mark.run(order=3)
def test_third():
assert True
这里,test_first 将首先执行,然后是test_second,最后是test_third。
二、Yaml
1.概念
Yaml是一种轻量级的、易读的数据序列化格式。
2.编写规则
- 大小写敏感
- 使用缩进来表示层级关系(缩进不可以使用tab,只能用空格)
- # 表示注释
- 键值对使用冒号结构表示 key: value,冒号右面加空格
# 示例 YAML 文件
case_login: case_001: # 测试用户正常登陆场景 username: "admin" password: "123456" code: "6" exp: "操作成功" case_002: # 测试用户不存在的场景 username: "admin1" password: "123456" code: "6" exp: "登录用户:admin1 不存在"
三、PyMySQL
1.概念
PyMySQL 是一个用于 Python 的纯 Python 实现的 MySQL 客户端库,用于python程序连接 MySQL 数据库,执行SQL查询等操作。
2.流程
Python程序连接 MySQL 数据库有一个完整的流程。现在,我们来想象一个场景:把要执行的sql语句当作一堆货物,要从河这边运到河对岸。那么,我们需要做什么?
- 1.创建一个桥-----即一个连接connection
- 2.创建一个驴-----即一个游标cursor
- 3.运送货物--------即执行sql语句
- 4.还驴自由--------关闭游标cursor
- 5.过河拆桥--------关闭连接connection
3.示例
下面演示一下完整的连接 MySQL 数据库的流程及代码:
import pymysql
# 连接到 MySQL 数据库
conn = pymysql.connect(
host='localhost',
port=3306,
user='username',
password='password',
database='dbname',
charset='utf-8'
)
# 创建游标对象
cursor = conn.cursor()
# 执行 SQL 查询
cursor.execute("SELECT * FROM users")
# 获取查询结果
result = cursor.fetchall()
for row in result:
print(row)
# 关闭游标和连接
cursor.close()
conn.close()
四、Requests
1.概念
requests库是使用 python 编写的, 可以调用该库的函数直接向服务器发送请求, 并接收响应。
2.使用
requests库提供了简单易用的API,使得发送 HTTP 请求变得非常简单。通过几行代码就可以完成各种类型的 HTTP 请求,如 GET、POST、PUT、DELETE 等。
下面是一个简单的示例,演示了如何使用requests库发送http的get请求,并处理响应:
import requests
# 发送 HTTP GET 请求
response = requests.get('https://api.github.com/user', auth=('user', 'passwd'))
# 检查响应状态码
if response.status_code == 200:
# 打印响应内容
print(response.json())
else:
print('HTTP GET 请求失败:', response.status_code)
五、Allure
1.概念
Allure 是一个用于生成详细、美观的测试报告的开源测试框架。它支持多种测试框架(如JUnit、TestNG、Pytest等)和多种编程语言(如Java、Python等),可以轻松地集成到现有的测试流程中。
2.生成测试报告
生成测试报告的脚本如下:
if __name__ == '__main__':
pytest.main(["./test_login", "-sv", "--alluredir", "./report/temp_jsonreport"])
os.system("allure generate ./report/temp_jsonreport -o ./report/html --clean")
参数解释:
-
"./test_login": 指定运行pytest测试的模块或路径。
-
"-sv"
:这是pytest的命令行选项之一,含义如下:-s
:显示测试过程中的标准输出信息(stdout)。-v
:增加冗长的输出,会显示每个测试用例的名称。
-
"--alluredir", "./report/temp_jsonreport"
:这是pytest-allure插件的命令行选项,含义如下:--alluredir
:指定生成Allure报告需要的JSON数据输出目录。"./report/temp_jsonreport"
:指定生成的JSON数据存放的目录
allure generate ./report/temp_jsonreport -o ./report/html --clean
:使用Allure命令行工具生成HTML格式的报告。generate
:生成报告的命令。./report/temp_jsonreport
:指定JSON数据的目录。-o ./report/html
:指定生成的HTML报告输出的目录,这里是./report/html
。--clean
:在生成报告前先清空输出目录。
综上所述,这段代码的作用是运行pytest测试模块
test_login.py
,同时将运行结果输出为JSON格式的数据到./report/temp_jsonreport
目录,然后使用Allure生成工具将JSON数据转换为HTML格式的报告,并输出到./report/html
目录。
六、Logging
1.概念
Logging是Python的标准库之一,用于记录程序运行时的日志信息,便于调试和追踪问题。
2.使用
下面演示了一个配置生成日志文件的方法:
import logging.handlers
def set_log_config():
# 1.创建日志器/设置日志级别
logger = logging.getLogger()
logger.setLevel(level=logging.INFO)
# 2.创建处理器:输出到控制台/文件(按时间切割)
ls = logging.StreamHandler()
lf = logging.handlers.TimedRotatingFileHandler(filename="abc.log", when="s", backupCount=3)
# backupCount,按“s”(即秒)切割后,保留的日志个数,在此处超过3个就会自动删除
# 3.创建格式器
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)]-%(message)s'
formatter = logging.Formatter(fmt=fmt)
# 4.将格式器添加到处理器
ls.setFormatter(formatter)
lf.setFormatter(formatter)
# 5.将处理器添加到日志器
logger.addHandler(ls)
logger.addHandler(lf)
若为相对路径,日志文件会创建在当前工作目录下。而如果使用了绝对路径,日志文件会创建在指定的路径下。