【接口自动化测试】

文章目录

  • 接口自动化测试
    • 接口与接口测试
    • 接口自动化测试
      • mysql数据库接口测试用例访问
        • mysql测试用例管理
        • pymysql结合pandas操作mysql
      • pytest自动化测试框架
      • pytest中的断言
      • pytest中的参数化
      • pytest中的组织管理
      • pytest的前置与后置操作
      • pytest中的fixture
      • 多fixture应用
      • fixture中conftest的统一配置
      • fixture的作用域控制与自动运行
      • 使用fixture实现参数化
      • 使用fixture实现测试控制
      • fixture集成allure生成漂亮的测试报告环境安装
  • http协议
  • requests接口请求

接口自动化测试

接口与接口测试

接口自动化测试

mysql数据库接口测试用例访问

mysql测试用例管理

将测试用例存储在数据库中的思路:测试用例的书写可以与Excel测试用例字段一致,但是字段名称要使用应为;可以将Excel作为数据源导入到Excel中:
在mysql中,右击【表】,点击【导入向导……】
【接口自动化测试】_第1张图片
在此处选择你要导入的文件类型,此处选择【Excel文件】后点击【下一步】
【接口自动化测试】_第2张图片
【导入从】中选择要导入的Excel文件,在【表】中会展示选中的Excel文件的所有sheet页,选择你要导入的sheet页,选好后点击【下一步】
【接口自动化测试】_第3张图片
【字段名行】即指定字段名所在行,【第一个数据行】即指定数据起始行,确认无误后点击【下一步】
【接口自动化测试】_第4张图片
【目标表】指的是数据库中的表名,可以改名字,确认无误点击【下一步】
【接口自动化测试】_第5张图片
在此页可以修改字段名、选择字段、确定主键,确认无误后点击【下一步】
【接口自动化测试】_第6张图片
选择想要的操作后点击【下一步】
【接口自动化测试】_第7张图片
点击【开始】
【接口自动化测试】_第8张图片

pymysql结合pandas操作mysql

原本使用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自动化测试框架

一、pytest是python的第三方的单元测试库,能自动识别测试模块和测试函数、支持非常丰富的断言(assert)语句
二、pytest中的使用约束:

  1. 测试文件的文件名必须以test_开头或以_test结尾
  2. 测试类必须以Test开头
  3. 测试的函数名必须以test_开头
  4. 测试类里面不能使用init()方法,即构造方法

三、pytest的安装命令:pip install pytest,如果执行该指令后,使用import pytest导包时报错,可在pycharm中手动导包:
【接口自动化测试】_第9张图片
【接口自动化测试】_第10张图片
【接口自动化测试】_第11张图片
四、写点测试代码:

import pytest

def test_demo():
    assert 1 == 1

五、运行代码:

  1. 方法一:在代码所在文件夹开启终端,执行:pytest .\test_pytest1.py,即pytest 文件名
    【接口自动化测试】_第12张图片
  2. 方法二:在代码文件中运行:
import pytest

def test_demo():
    assert 1 == 1

if __name__ == "__main__":
     pytest.main(['test_pytest1.py'])# 文件名

pytest中的断言

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'])

pytest中的参数化

参数化:代码不变,但是传参时,参数要进行不断的迭代,进而需要判断多个值

# 参数化
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中的组织管理

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的前置与后置操作指的是,代码中模块、函数、方法的测试类别的前置、后置操作

# 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

一、pytest中的fixture介绍

  1. fixture可以将测试的复杂需求简单化、组件化;
  2. 他为测试提供了已定义的、可靠的和一致的上下文;
  3. 他定义了构成测试准备阶段的步骤和数据;
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应用主要指:

  1. 同一个fixture有多个返回值
  2. 一个测试函数可传入多个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中conftest的统一配置

之前都是把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)

直接运行测试函数,可正常打印输出

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实现参数化

# 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)

使用fixture实现测试控制

有些测试案例不执行,应该怎么办呢?

# 跳过测试
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

fixture集成allure生成漂亮的测试报告环境安装

步骤:

  1. 下载allure
    【接口自动化测试】_第13张图片
    下载zip包并解压即可
  2. 安装java运行环境jdk8
  3. 配置jdk的环境变量
    【接口自动化测试】_第14张图片
  4. 安装python的allure的支持库:pip install allure-pytest
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")

http协议

requests接口请求

一、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)

你可能感兴趣的:(自动化测试,数据库,mysql,测试用例)