五、自动执行测试
json文件是一个特殊格式的文本文件
- json是一种语法, 用来表达一些数据的
- json文件的内容就是用json表达的一些数据
- json的语法格式类似于python字典, 由大括号包裹, 有键,每个键对应一个值
{
"name":"tom",
"age":30
}
json读json文件
import json
open读的方式打开json文件
dict1 = json.load(打开文件对象) # 把json文件的内容读取到python的字典dict1中
close关闭已经打开的json文件
# 读取a.json文件, 显示键"age"对应的值
import json
file = open("a.json", "r", encoding="utf-8")
dict1 = json.load(file) # 把json文件的内容, 转化成一个python的字典
file.close()
print(dict1["age"])
a.json
{
"name":"tom",
"age":30
}
写json文件
import json
open用写的方式打开文件
json.dump(字典, open打开的文件对象, ensure_ascii=False) ensure_ascii=False中文不转义
关闭文件
import json
file = open("a.json", "w", encoding="utf-8")
dict1 = {"name":"刘备", "height":1.75}
json.dump(dict1, file, ensure_ascii=False) # ensure_ascii=False 中文不转义
file.close()
pytest
pytest自动执行测试用例
- 测试用例所在的模块(py)命名一定要采用标识符的命名规则
- 一个测试用例就是一个方法
- 方法名习惯test开头
- 方法所在的类习惯Test开头, 并采用大驼峰命名法
import pytest
if __name__ == "__main__":
pytest.main(["-s", "测试用例所在的py文件名", "其他的测试用例所在的文件.py"])
# "-s"作用是, 如果没有-s测试用例中的print将不会输出任何内容
# m1.py
# 被测试的函数
def my_sum(a, b):
return a + b
# m2.py 存放测试用例
# 测试m1.py中的my_sum函数是否正确
from m1 import my_sum
'''
测试用例
测试数据, 一个实参为4, 一个实参为2, 预期结果为6
'''
# 一个测试用例就是一个方法, 所以一定先要定义一个类
class TestFunc: # 存放测试用例的类, 业内习惯Test开头, 并且采用大驼峰命名法
# 类当中的方法就是测试用例
def test_01(self): # 这个方法就是测试用例, 名字习惯以小写test开头
result = my_sum(4, 2)
if result == 6:
print("测试通过")
else:
print("测试失败")
def test_02(self):
result = my_sum(1, 2)
if result == 3:
print("测试通过")
else:
print("测试失败")
# m3.py 存放测试用例
class TestM:
def test_01(self):
print("我是TestM中的测试用例test_01")
- pytest中执行测试用例的代码
import pytest
if __name__ == "__main__":
pytest.main(["-s", "m2.py", "m3.py"]) #"-s"的意思是执行测试用例的时候, 显示print的输出, "m2.py"测试用例所在的文件名
断言
- 用代码判断测试用例执行是否通过
assert 条件 # 条件成立, 代表断言通过, 否则代表断言不通过
# m2.py 存放测试用例
# 测试m1.py中的my_sum函数是否正确
from m1 import my_sum
'''
测试用例
测试数据, 一个实参为4, 一个实参为2, 预期结果为6
'''
# 一个测试用例就是一个方法, 所以一定先要定义一个类
class TestFunc: # 存放测试用例的类, 业内习惯Test开头, 并且采用大驼峰命名法
# 类当中的方法就是测试用例
def test_01(self): # 这个方法就是测试用例, 名字习惯以小写test开头
result = my_sum(4, 2)
assert result == 6 # result是实际运行结果, 6是预期结果, 实际结果与预期结果相同, 断言通过
def test_02(self):
result = my_sum(1, 2)
assert result == 3
if __name__ == "__main__":
TestFunc().test_01() # 把TestFunc这个类实例化后,直接调用test_01方法
'''
t = TestFunc()
t.test_01()
'''
# m3.py 存放测试用例
class TestM:
def test_01(self):
assert True # 这个测试用例永远不会失败
setup和teardown
- 测试用例所在的类可以定义两个方法, 一个是setup, 一个是teardown
- 如果一个类中有多个测试用例, 每个测试用例执行前会自动调用setup方法, 每个测试用例执行完成后会自动调用teardown方法
# m2.py 存放测试用例
# 测试m1.py中的my_sum函数是否正确
from m1 import my_sum
'''
测试用例
测试数据, 一个实参为4, 一个实参为2, 预期结果为6
'''
# 一个测试用例就是一个方法, 所以一定先要定义一个类
class TestFunc: # 存放测试用例的类, 业内习惯Test开头, 并且采用大驼峰命名法
# 类当中的方法就是测试用例
def test_01(self): # 这个方法就是测试用例, 名字习惯以小写test开头
result = my_sum(4, 2)
assert result == 6 # result是实际运行结果, 6是预期结果, 实际结果与预期结果相同, 断言通过
def test_02(self):
result = my_sum(1, 2)
assert result == 3
def setup(self):
print("setup方法给调用了")
def teardown(self):
print("teardown方法给调动了")
if __name__ == "__main__":
TestFunc().test_01() # 把TestFunc这个类实例化后,直接调用test_01方法
'''
t = TestFunc()
t.test_01()
'''
setup_class和teardown_class
- 一个类中不管有多少测试用例, 所有测试用例执行前, 自动调用一次setup_class, 所以测试用例执行完成后自动调用一次teardown_class
# m2.py 存放测试用例
# 测试m1.py中的my_sum函数是否正确
from m1 import my_sum
'''
测试用例
测试数据, 一个实参为4, 一个实参为2, 预期结果为6
'''
# 一个测试用例就是一个方法, 所以一定先要定义一个类
class TestFunc: # 存放测试用例的类, 业内习惯Test开头, 并且采用大驼峰命名法
# 类当中的方法就是测试用例
def test_01(self): # 这个方法就是测试用例, 名字习惯以小写test开头
result = my_sum(4, 2)
assert result == 6 # result是实际运行结果, 6是预期结果, 实际结果与预期结果相同, 断言通过
def test_02(self):
result = my_sum(1, 2)
assert result == 3
def setup(self):
print("setup方法给调用了")
def teardown(self):
print("teardown方法给调动了")
def setup_class(self):
print("setup_class方法给调用了")
def teardown_class(self):
print("teardown_class方法给调动了")
if __name__ == "__main__":
TestFunc().test_01() # 把TestFunc这个类实例化后,直接调用test_01方法
'''
t = TestFunc()
t.test_01()
'''
参数化
- 多个测试用例, 代码完全相同, 只有测试数据与预期结果不同, 使用参数化后可以去掉冗余代码
import pytest
# 在要使用参数化的方法前
@pytest.mark.parametrize("形参的说明", [(形参对应的实参), (形参对应的实参), (....)])
def 测试用例(self, 和形参的说明里一样的具体形参):
pass
[里有几个元组, 被参数化的方法就会自动执行几次]
# m4.py 存放测试用例
# 测试m1.py中的my_sum函数是否正确
import pytest
from m1 import my_sum
'''
测试用例1
测试数据, 一个实参为4, 一个实参为2, 预期结果为6
测试用例2
测试数据, 一个实参为1, 一个实参为2, 预期结果为3
测试用例3
测试数据, 一个实参为10, 一个实参为1, 预期结果为11
'''
class TestFunc:
@pytest.mark.parametrize("a, b, expect", [(4, 2, 6), (1, 2, 3), (10, 1, 11)])
def test_01(self, a, b, expect): # a和b代表调动my_sum提供的实参, expect代表预期结果
result = my_sum(a, b)
assert result == expect
生成html版本测试报告
import pytest
if __name__ == "__main__":
pytest.main(["-s", "--html=a.html", "m4.py"]) #"-s"的意思是执行测试用例的时候, 显示print的输出, "m2.py"测试用例所在的文件名
pytest.ini配置文件
- pytest.ini配置文件一定要在项目目录里, 不能在任何一个包里
[pytest]
addopts = -s --html=a.html
testpaths = ./
python_files = m*.py
python_classes = Test*
python_functions = test*
- 第一行必须为[pytest]
- 第二行, -s代表执行测试用例的时候, 可以显示print的输出结果, --html=a.html 生成测试报告的文件名
- 第三行: 在哪个包里查找测试用例所在的py文件
- 第四行: 测试用例所在的py文件名, 支持通配符 m*.py查找所有以m开头, .py结尾的文件
- 第五行: 测试用例所在的类名必须以Test开头
- 第六行: 测试用例的方法名必须以test开头
import pytest
if __name__ == "__main__":
pytest.main() # 启用pytest.ini配置文件, 来执行测试用例