将测试用例存储在数据库中的思路:测试用例的书写可以与Excel测试用例字段一致,但是字段名称要使用应为;可以将Excel作为数据源导入到Excel中:
在mysql中,右击【表】,点击【导入向导……】
在此处选择你要导入的文件类型,此处选择【Excel文件】后点击【下一步】
【导入从】中选择要导入的Excel文件,在【表】中会展示选中的Excel文件的所有sheet页,选择你要导入的sheet页,选好后点击【下一步】
【字段名行】即指定字段名所在行,【第一个数据行】即指定数据起始行,确认无误后点击【下一步】
【目标表】指的是数据库中的表名,可以改名字,确认无误点击【下一步】
在此页可以修改字段名、选择字段、确定主键,确认无误后点击【下一步】
选择想要的操作后点击【下一步】
点击【开始】
原本使用pymysql操作mysql:
import pymysql
db_info = {
"host":"192.168.0.108",
"user":"root",
"password":"123",
"database":"mydb2",
"charset":"utf8"
}
conn = pymysql.connect(**db_info)
cursor = conn.cursor()
sql = "select * from mumu"
cursor.execute(sql)
result = cursor.fetchall()
print(result)
print(type(result))#
使用pandas操作mysql:
import pymysql
import pandas as pd
db_info = {
"host":"192.168.0.108",
"user":"root",
"password":"123",
"database":"mydb2",
"charset":"utf8"
}
conn = pymysql.connect(**db_info)
# 结合pandas执行sql
sql = "select * from mumu"
result = pd.read_sql(sql, conn)
print(result)
print(type(result))
一、pytest是python的第三方的单元测试库,能自动识别测试模块和测试函数、支持非常丰富的断言(assert)语句
二、pytest中的使用约束:
test_
开头或以_test
结尾Test
开头test_
开头init()
方法,即构造方法三、pytest的安装命令:pip install pytest
,如果执行该指令后,使用import pytest
导包时报错,可在pycharm中手动导包:
四、写点测试代码:
import pytest
def test_demo():
assert 1 == 1
五、运行代码:
import pytest
def test_demo():
assert 1 == 1
if __name__ == "__main__":
pytest.main(['test_pytest1.py'])# 文件名
import pytest
def add(a, b):
return a + b
# assert后面支持的是一个表达式,表达式执行成功则该函数断言成功,反之则失败
def test_dengyu():
assert 3 == add(1,2)
def test_budengyu():
assert 5 != add(1,3)
def test_dayu():
assert 5 > add(1,3)
def test_dayudengyu():
assert 5 >= add(1,3)
def test_xiao():
assert 1 < add(1,2)
def test_xiaoyudengyu():
assert 1 <= add(1,3)
def test_baohan():
assert 1 in [1,2,3]
def test_bubaohan():
assert 1 not in [1,2,3]
def test_iftrue():
assert bool(1) is True# pytest底层不会自动将1转成布尔类型,所以此处我们需要使用bool(1)手动转换,如果不转换的话,会断言失败,如下面test_iffalse()的执行结果
def test_iffalse():
assert 0 is False# 断言失败
if __name__ == "__main__":
pytest.main(['test_pytest2.py'])
参数化:代码不变,但是传参时,参数要进行不断的迭代,进而需要判断多个值
# 参数化
import pytest
def add(a, b):
return a + b
# 第一种实现参数化的写法:会将x=1,y=2;x=0,y=3;x=1,y=4依次赋值给test_add1方法的x,y参数
@pytest.mark.parametrize(['x','y'],[(1,2),(0,3),(1,4)])
def test_add1(x, y):
assert 3 == add(x, y)
# 第二种参数化的写法
xy = [(-1,3),(-1,4),(1,-4)]# 参数成对放在数组中
@pytest.mark.parametrize(['x','y'],xy)
def test_add2(x,y):
assert 3 == add(x, y)
# 把存储在mysql当中的测试用例参数化出来
import pymysql
db_info={
"host":"192.168.1.116",
"user":"root",
"password":"123",
"database":"mydb2",
"charset":"utf8"
}
conn = pymysql.connect(**db_info)
cursor = conn.cursor()
sql = "select * from mumu"
cursor.execute(sql)
result = cursor.fetchall()
# 将从数据库中获取的值result,赋值给id,case_id,title,interface_type,uri,method,if_login,input_data,data_type,expect这些字段,将这些字段传给test_mysql_param方法,将数据库中的数据参数化到测试方法中
@pytest.mark.parametrize(['id',
'case_id',
'title',
'interface_type',
'uri',
'method',
'if_login',
'input_data',
'data_type',
'expect'],result)
def test_mysql_param(id,case_id,title,interface_type,uri,
method,if_login,input_data,data_type,
expect):
print(title)
if __name__ == "__main__":
pytest.main(['test_pytest3.py'])
pytest中的组织管理用于控制测试用例的执行顺序,需要在终端安装:pip install pytest_ordering
# 测试用例的组织管理
import pytest
def test_01():
print(1)
# @pytest.mark.first# 永远第一个执行,比order=1还先
def test_02():
print(2)
# @pytest.mark.last# 最后一个执行,但是他的优先级比order=-1低,会先执行last,再执行order=-1
def test_03():
print(3)
@pytest.mark.run(order=1)# order的值是执行顺序,此处表示第一个执行test_04方法
def test_04():
print(4)
class TestLogin():
def test_09(self):
print(9)
@pytest.mark.run(order=2)
def test_05(self):
print(5)
@pytest.mark.run(order=-2)# 倒数第二个执行
def test_06(self):
print(6)
@pytest.mark.run(order=-1)# -1表示最后一个执行
def test_07(self):
print(7)
def test_08(self):
print(8)
if __name__ == "__main__":
pytest.main(['test_pytest4.py'])
"""
在pytest当中,测试方法执行的顺序,默认是从上到下
我们使用pytest.mark.run进行测试函数执行顺序的标记时
需要先安装pip install pytest_ordering
在优先级方面(正数) pytest.mark.first是最高优先级
(倒数) pytest.mark.last优先级要低于order=-1
如果我们在进行标记顺序时,假设我们采用了数字的形式,那么就都用数字
"""
pytest的前置与后置操作指的是,代码中模块、函数、方法的测试类别的前置、后置操作
# pytest的前置和后置操作
import pytest
def setup_module():
print("这是前置的模块级别的函数")# 模块指的是一个.py文件
def teardown_module():
print("这是后置的模块级别的函数")
def setup_function():
print("这是前置的函数级别运行的函数")
def teardown_function():
print("这是后置的函数级别运行的函数")
"""
在Python 3.6的版本中下边的两个前置和后置函数setup和teardown是可以运行的,
但是优先级没有setup_function和teardown_function的优先级高
"""
#
# def setup():
# print("前置函数级别的11111")
#
# def teardown():
# print("后置函数级别的22222")
def test_01():
print("测试1运行了")
assert 1==1
def test_02():
print("测试2运行了")
assert 1==1
class TestMyClass():
def setup_class(self):
print("这是前置的class级别的方法")
def teardown_class(self):
print("这是后置的class级别的方法")
def setup_method(self, method):
print("我是前置的类中的方法级别的")
print(method)
def teardown_method(self):
print("我是后置的类中的方法级别的")
# 类中的前置和后置方法必须要写method,不能写function
# def setup_function(self):
# print("我是类中的function")
def test_of_method1(self):
print("<<<我是类中的测试方法11111>>>")
def test_of_method2(self):
print("<<<我是类中的测试方法222>>>")
if __name__ == "__main__":
pytest.main(['test_pytest6.py'])
以上运行结果:这是前置的模块级别的函数、这是前置的函数级别运行的函数、测试1运行了、这是后置的函数级别运行的函数、这是前置的函数级别运行的函数、测试2运行了、这是后置的函数级别运行的函数、这是前置的class级别的方法、我是前置的类中的方法级别的、<<<我是类中的测试方法11111>>>、我是后置的类中的方法级别的、我是前置的类中的方法级别的、<<<我是类中的测试方法222>>>、我是后置的类中的方法级别的、这是后置的class级别的方法、这是后置的模块级别运行的函数
一、pytest中的fixture介绍
import pytest
@pytest.fixture()
def first_fixture():
print("这是我人生中第一个fixture")
return 1
# fixture之间可以互相调用和传递
@pytest.fixture()
def second_fixture(first_fixture):
print("这是我人生中的第二个fixture")
return first_fixture + 2
# fixture可以作为函数传给某个函数的形参,fixture的返回值会传递到函数里面。所以,可以用fixture做一些前置操作,然后将操作结果(fixture的返回值)传入测试方法
def test_case1(first_fixture):
print("这是我的第一个测试用例")
r = first_fixture
print(r)# fixture的返回值会传递到函数里面,所以此处打印1
def test_case2(second_fixture):
print("这是我的第二个测试用例")
print(second_fixture)# 3
if __name__ == "__main__":
pytest.main(['-vs','test_pytest12.py'])
# 如果控制台在应该输出内容但却没有输出任何信息时,可以在main方法中添加-vs
# -v:查看详细信息
# -s:查看打印信息
多fixture应用主要指:
应用场景:当有多个处理规则时,可以把不同的规则写在不同的fixture,然后将fixture(返回的处理结果)传给同一个测试函数进行判断。
import pytest
@pytest.fixture()
def first_fixture():
print("我是第一个fixture")
return 1,2,3# 多个返回值
@pytest.fixture()
def second_fixture():
return "第2个值"
# 一个测试函数可传入多个fixture
def test_case1(first_fixture, second_fixture):
print("这是第一个测试用例")
print(first_fixture)# (1,2,3) 返回的是一个元组
a, b, c = first_fixture# 用3个变量来接收
print(a)# 1
print(b)# 2
print(c)# 3
assert (1,2,3) == first_fixture# true
r = second_fixture
print(r)
之前都是把fixture写在测试文件里面,本节讲如何把fixture写在测试文件外面,创建conftest.py文件并将fixture写入,在运行代码时,会自动将conftest.py的内容加载到测试文件里,所以可以将公共fixture写入conftest.py中,conftest.py代码如下:
import pytest
@pytest.fixture()
def first_fixture():
print("我是第一个fixture")
return 1,2,3
@pytest.fixture()
def second_fixture():
return "第2个值"
测试函数代码如下:
def test_case1(first_fixture, second_fixture):
print("这是我的测试用例")
print(first_fixture)
print(second_fixture)
直接运行测试函数,可正常打印输出
# 作用域与自动执行
import pytest
# 比模块更高一级的是会话级别,程序从运行到结束就是一次会话
@pytest.fixture(scope="session", autouse=True)
def session_fixture():
print("我是会话级别的作用域")
@pytest.fixture(scope="module", autouse=True)
def module_fixture():
print("我是模块级别的作用域")
"""
当我们使用fixture时,把scope的值设置成class时
每一个测试类之前都会被运行
pytest在每个测试函数的外层会自动的把函数包装成一个测试类
"""
@pytest.fixture(scope="class", autouse=True)
def class_fixture():
print("我是类级别的作用域")
"""
在使用fixture时,scope=function时
无论时在函数中,还是在方法中,都是作用域都funtion在生效
"""
@pytest.fixture(scope="function", autouse=True)
def function_fixture():
print("我是函数级别的作用域")
"""
在我们使用的最新的Python版本中,去掉了scope=method这个作用域
在Python3.6的版本上边这种写法会生效
"""
# @pytest.fixture(scope="method", autouse=True)
# def method_fixture():
# print("我是方法级别的作用域")
def test_case1():
print("-----我是函数的测试用例11111----")
def test_case2():
print("-----我是函数的测试用例2222----")
class TestMyClass():
def test_of_method1(self):
print("《《《我是类中的测试方法1111》》》")
def test_of_method2(self):
print("《《《我是类中的测试方法2222》》》")
以上执行结果为:我是会话级别的作用域、我是模块级别的作用域、我是类级别的作用域、我是函数级别的作用域、-----我是函数的测试用例11111----、我是类级别的作用域、我是函数级别的作用域、-----我是函数的测试用例2222----、我是类级别的作用域、我是函数级别的作用域、《《《我是类中的测试方法1111》》》、我是函数级别的作用域、《《《我是类中的测试方法2222》》》
# fixture实现参数化
import pytest
test_data = [
{
"case_name":"登录成功的测试",
"username":"admin",
"password":"123"
},
{
"case_name":"登录失败的测试",
"username":"aaaaa",
"password":"11111"
},
{
"case_name":"用户名为空的登录",
"username":"",
"password":"22222"
},
]
@pytest.fixture(params=test_data)
def param_data(request):
# request是pytest内置的fixture,必须这样写才能传进来
# 它的作用主要就是用来帮助我们传递参数
return request.param
def test_login(param_data):# 传入的参数必须是可迭代的对象,会把参数一个个迭代进测试方法
username = param_data.get('username')
print(username)
password = param_data.get('password')
print(password)
case_name = param_data.get('case_name')
print(case_name)
有些测试案例不执行,应该怎么办呢?
# 跳过测试
import pytest
# 无理由跳过
@pytest.mark.skip
def test_dengyu():
assert 3 == 3
a = 1
@pytest.mark.skipif(a>0, reason="a大于了0我跳过了")
def test_dayu():
assert 5 != 4
步骤:
import pytest
import os
def add(a, b):
return a + b
def test_dengyu():
assert 3 == add(1,2)
def test_budengyu():
assert 5 != add(1,3)
def test_dayu():
assert 5 > add(1,3)
def test_dayudengyu():
assert 5 >= add(1,3)
def test_xiao():
assert 1 < add(1,2)
def test_xiaoyudengyu():
assert 1 <= add(1,3)
def test_baohan():
assert 1 in [1,2,3]
def test_bubaohan():
assert 1 not in [1,2,3]
def test_iftrue():
assert bool(1) is True
def test_iffalse():
assert 0 is False
if __name__ == "__main__":
# 生成allure的数据文件夹./result
pytest.main(['test_pytest13.py',
"--alluredir",
"./result"])
# 数据文件在./result,报告生成在./report_allure中
# --clean:如果之前存在,则删除
os.system("allure generate ./result -o ./report_allure --clean")
一、requests是一款非常火爆且常用的python三方库,能实现http协议的各种请求方法,使用简单易上手
二、安装方法:pip install requests
三、requests发送get接口请求
import requests
# response = requests.get("http://www.baidu.com")
# print(response)
# print(response.status_code)
# print(response.text)
url = "http://localhost:5000/"
# 无参数的get请求
r1 = requests.get(url)
print(r1.text)
# 带路径的get请求
r2 = requests.get(url + "hello")
print(r2.text)
# 路径上带参数的get请求
r3 = requests.get(url + "hello/我是参数")
print(r3.text)
# 路径上带参数,并且带有参数值的get请求
r4 = requests.get(url + "hello/args/我是参数11?key=我是key&value=我是value")
print(r4.text)
# 第二种带参数的方式
r5 = requests.get(url + "hello/args/我是参数222",{
"key":"我是key2",
"value":"我是value2"} )
print(r5.text)
四、requests发送post接口请求
import requests
url = "http://localhost:5000/"
r1 = requests.post(url + "mypost")
print(r1.text)
# 请求数据是表单类型的数据
r2 = requests.post(url + "mypost1",
data={
"username":"我是名字",
"sex":"我是性别"
})
print(r2.text)
# 请求是json类型的数据
r3 = requests.post(url + "mypost2",
json={
"user":"我是json的user的key",
"value":"我是value",
"sex":"男"
})
print(r3.text)
五、requests发送请求头信息
import requests
import json
url = "http://111.231.103.117:8083"
login_uri = "/loginWithJwt"
login_data = {
"userName":"imooc",
"password":"12345678"
}
login_response = requests.get(url+login_uri,login_data)
print(login_response.text)
print(type(login_response.text))#
data = json.loads(login_response.text)# json解析响应的数据,将JSON字符串解析为一个Python字典
print(type(data))#
jwt_token = data['data']# 获取到token
print(jwt_token)
# headers中的信息
headers = {
"jwt_token":jwt_token
}
cart_add_uri = "/cart/add"
# parameter指的是data类型
cart_add_response = requests.post(url + cart_add_uri,
data={
"count":5,
"productId":3
},
headers=headers)# 请求头信息传入headers
print(cart_add_response.text)