接口测试(七)—— 参数化、数据库操作类封、接口自动化框架

news2024/9/30 3:22:21

目录

一、接口自动化测试框架

1、目录结构

二、封装iHRM登录

1、普通方式实现

2、登录接口对象层

3、登录接口测试用例层

4、封装断言方法

三、参数化

1、回顾UnitTest参数化 

1.1 原始案例

1.2 参数化实现

1.3 从json文件读取

2、登录接口参数化

2.1 组织数据文件

2.2 读取数据文件

2.3 使用 parameterized 实现参数化

四、员工管理接口

1、普通方法实现

2、接口对象层

3、接口测试用例层

4、数据库工具类封装

5、解决反复修改手机号

6、完整参数化步骤:添加员工接口参数化

7、获取请求头

8、提取项目目录

9、生成测试报告


一、接口自动化测试框架

1、目录结构

7 部分(5个目录、2个文件):

  • api/: 存储接口对象层(自己封装的 接口)
  • scripts/: 存储测试脚本层 (unittest框架实现的 测试类、测试方法)
  • data/: 存储 .json 数据文件
  • report/: 存储 生成的 html 测试报告
  • common/: 存储 通用的 工具方法
  • config.py: 存储项目的配置信息(全局变量)
  • run_suite.py: 组装测试用例、生成测试报告的 代码

二、封装iHRM登录

==登录接口==

1、普通方式实现

import unittest
import requests

class TestIhrmLogin(unittest.TestCase):

    # 测试方法1,登录成功
    def test01_login_success(self):
        # 组织url
        url = "http://ihrm-test.itheima.net/api/sys/login"
        header = {"Content-Type": "application/json"}
        json_data = {"mobile": "13800000002", "password": "123456"}
        resp = requests.post(url=url, headers=header, json=json_data)
        print("登录成功:", resp.json())

        # 断言
        self.assertEqual(200, resp.status_code)
        self.assertEqual(True, resp.json().get("success"))
        self.assertEqual(10000, resp.json().get("code"))
        self.assertIn("操作成功", resp.json().get("message"))

    # 测试方法2,密码错误
    def test02_pwd_err(self):
        # 组织url
        url = "http://ihrm-test.itheima.net/api/sys/login"
        header = {"Content-Type": "application/json"}
        json_data = {"mobile": "13800000002", "password": "123456789"}
        resp = requests.post(url=url, headers=header, json=json_data)
        print("密码错误:", resp.json())

        # 断言
        self.assertEqual(200, resp.status_code)
        self.assertEqual(False, resp.json().get("success"))
        self.assertEqual(20001, resp.json().get("code"))
        self.assertIn("用户名或密码错误", resp.json().get("message"))

2、登录接口对象层

1. 在 api/ 下,创建 ihrm_login_api.py 文件。
2. 在 文件内,封装 IhrmLoginApi 类,添加 login 类方法。
3. 安照 普通方式实现,分析。实现 login 类方法。

分析:

import requests

class IhrmLoginApi(object):

    # 登录方法
    @classmethod
    def login(cls, json_data):
        url = "http://ihrm-test.itheima.net/api/sys/login"
        header = {"Content-Type": "application/json"}
        resp = requests.post(url=url, headers=header, json=json_data)
        return resp

if __name__ == '__main__':
    data = {"mobile": "13800000002", "password": "123456"}
    resp = IhrmLoginApi.login(data)
    print(resp.json())

3、登录接口测试用例层

1. 在 scripts/ 下,创建 test_ihrm_login.py 文件
2. 在 文件内,创建 测试类 TestIhrmLogin 从 unittest.TestCase 继承
3. 添加 测试方法, 并实现

import unittest
from api.ihrm_login_api import IhrmLoginApi

class TestIhrmLogin(unittest.TestCase):

    # 登录成功
    def test01_login_success(self):
        # 组织请求数据
        json_data = {"mobile": "13800000002", "password": "123456"}
        # 调用自己封装的接口
        resp = IhrmLoginApi.login(json_data)
        print("登录成功:", resp.json())

        # 断言
        self.assertEqual(200, resp.status_code)
        self.assertEqual(True, resp.json().get("success"))
        self.assertEqual(10000, resp.json().get("code"))
        self.assertIn("操作成功", resp.json().get("message"))

    # 手机号为空
    def test02_mobile_none(self):
        # 组织请求数据
        json_data = {"mobile": None, "password": "123456"}
        # 调用自己封装的接口
        resp = IhrmLoginApi.login(json_data)
        print("手机号为空:", resp.json())

        # 断言
        self.assertEqual(200, resp.status_code)
        self.assertEqual(False, resp.json().get("success"))
        self.assertEqual(20001, resp.json().get("code"))
        self.assertIn("用户名或密码错误", resp.json().get("message"))

    # 密码错误
    def test03_pwd_err(self):
        # 组织请求数据
        json_data = {"mobile": "13800000002", "password": "123456890"}
        # 调用自己封装的接口
        resp = IhrmLoginApi.login(json_data)
        print("密码错误:", resp.json())

        # 断言
        self.assertEqual(200, resp.status_code)
        self.assertEqual(False, resp.json().get("success"))
        self.assertEqual(20001, resp.json().get("code"))
        self.assertIn("用户名或密码错误", resp.json().get("message"))

4、封装断言方法

1. 在 common/ 下,新建文件 assert_util.py 文件,
2. 在文件内,添加 函数 assert_util()
3. 在 函数内,实现通用的断言函数。
4. 在 测试方法中,使用 直接封装的 通用断言函数, 实现断言
 

# 定义 通用断言方法
def assert_util(self, resp, status_code, success, code, message):
    self.assertEqual(status_code, resp.status_code)
    self.assertEqual(success, resp.json().get("success"))
    self.assertEqual(code, resp.json().get("code"))
    self.assertIn(message, resp.json().get("message"))

使用断言方法

assert_util(self, resp, 200, True, 10000, "操作成功")
assert_util(self, resp, 200, False, 20001, "用户名或密码错误")
assert_util(self, resp, 200, False, 20001, "用户名或密码错误")

三、参数化

参数化的核心:数据驱动(用数据驱动测试用例执行)

  • 数据驱动:针对一个接口,只写一个测试方法。用一份测试数据文件,管理各个测试用例的测试数据。

参考文章:软件测试 —— Python(七)之UnitTest框架与测试报告 

1、回顾UnitTest参数化 

1.1 原始案例

import unittest

# 待 测试方法
def add(x, y):
    return x + y

class TestAdd(unittest.TestCase):
    def test01_add(self):
        res = add(10, 20)
        self.assertEqual(30, res)

    def test02_add(self):
        res = add(100, 200)
        self.assertEqual(300, res)

    def test03_add(self):
        res = add(1000, 20)
        self.assertEqual(1020, res)

1.2 参数化实现

实现步骤:
1. 导包 from parameterized import parameterized
2. 在通用测试方法上一行,添加 @parameterized.expand()
3. 给 expand() 传入 [(),(),()] 格式数据。( 调用 read_json_data() )
4. 修改 通用测试方法形参,按 数据中的 key 设计 参数。
5. 在 通用测试方法 内,使用形参

import unittest
from parameterized import parameterized

# 待 测试方法
def add(x, y):
    return x + y

data = [
{"x": 10, "y": 20, "except": 30},
{"x": 100, "y": 200, "except": 300},
{"x": 1000, "y": 20, "except": 1020},
{"x": 4, "y": 18, "except": 23}
]

# [{},{},{}] ---> [(),(),()]
def read_json_data():
    list_data = []
    for item in data:
        tmp = tuple(item.values())
        list_data.append(tmp)
    return list_data

class TestAdd(unittest.TestCase):
    # 通用测试方法(实现参数化)
    @parameterized.expand(read_json_data())
    def test_add(self, x, y, except_data):
        res = add(x, y)
        self.assertEqual(except_data, res)

1.3 从json文件读取

创建 json 文件,写入 [{},{},{}] 格式数据    

[
{"x": 10, "y": 20, "except": 30},
{"x": 100, "y": 200, "except": 300},
{"x": 1000, "y": 20, "except": 1020},
{"x": 4, "y": 18, "except": 22}
]

 修改 读取数据的 read_json_data 函数,添加 打开json文件,读数据的代码

# [{},{},{}] ---> [(),(),()]
def read_json_data():
    list_data = []
    # 从 .json 文件中,读取 [{},{},{}] 数据
    with open("./params_data.json", "r", encoding="utf-8") as f:
        data = json.load(f)
        for item in data:
            tmp = tuple(item.values())
            list_data.append(tmp)
    return list_data

2、登录接口参数化

2.1 组织数据文件

[
{
"desc": "登录成功",
"req_data": {
"mobile": "13800000002",
"password": "123456"
},
"stauts_code": 200,
"success": true,
"code": 10000,
"message": "操作成功"
},
{
"desc": "手机号为空",
"req_data": {
"mobile": null,
"password": "123456"
},
"stauts_code": 200,
"success": false,
"code": 20001,
"message": "用户名或密码错误"
},
{
"desc": "密码错误",
"req_data": {
"mobile": "13800000002",
"password": "123456789"
},
"stauts_code": 200,
"success": false,
"code": 20001,
"message": "用户名或密码错误"
},
{
"desc": "多参",
"req_data": {
"mobile": "13800000002",
"password": "123456",
"abc": "123"
},
"stauts_code": 200,
"success": true,
"code": 10000,
"message": "操作成功"
},
{
"desc": "少参",
"req_data": {
"password": "123456"
},
"stauts_code": 200,
"success": false,
"code": 20001,
"message": "用户名或密码错误"
},
{
"desc": "无参",
"req_data": null,
"stauts_code": 200,
"success": false,
"code": 99999,
"message": "抱歉,系统繁忙,请稍后重试!"
},
{
"desc": "错误参数",
"req_data": {
"abc": "13800000002",
"password": "123456"
},
"stauts_code": 200,
"success": false,
"code": 20001,
"message": "用户名或密码错误"
}
]

2.2 读取数据文件

1. 在 common/ 下 创建 read_json_util.py 文件
2. 在 文件内,定义函数,从 json文件中读取数据,转换成 元组列表,返回

import json

# 定义函数,读取 data/xxx.json 文件
def read_json_data():
    with open("../data/ihrm_login.json", "r", encoding="utf-8") as f:
        json_data = json.load(f)
        list_data = []
        for item in json_data:
            tmp = tuple(item.values())
            list_data.append(tmp)
    # 这个 返回,坚决不能在 for 内
    return list_data

if __name__ == '__main__':
    ret = read_json_data()
    print(ret)
# 测试结果
[('登录成功', {'mobile': '13800000002', 'password': '123456'}, 200, True, 10000, '操作成功'), ('手
机号为空', {'mobile': None, 'password': '123456'}, 200, False, 20001, '用户名或密码错误'), ('密码错
误', {'mobile': '13800000002', 'password': '123456789'}, 200, False, 20001, '用户名或密码错误'),
('多参', {'mobile': '13800000002', 'password': '123456', 'abc': '123'}, 200, True, 10000, '操作成
功'), ('少参', {'password': '123456'}, 200, False, 20001, '用户名或密码错误'), ('无参', None, 200,
False, 99999, '抱歉,系统繁忙,请稍后重试!'), ('错误参数', {'abc': '13800000002', 'password':
'123456'}, 200, False, 20001, '用户名或密码错误')]

2.3 使用 parameterized 实现参数化

步骤:
1. 导包 from parameterized import parameterized
2. 在 通用测试方法上一行,添加 @parameterized.expand()
3. 给 expand() 传入 元组列表数据( 调用 自己封装的 读取 json 文件的 函数 read_json_data() )
4. 修改 通用测试方法形参,与 json 数据文件中的 key 一致。
5. 在 通用测试方法内,使用形参

import unittest
from api.ihrm_login_api import IhrmLoginApi
from common.assert_util import assert_util
from common.read_json_util import read_json_data
from parameterized import parameterized

"""
1. 导包 from parameterized import parameterized
2. 在 通用测试方法上一行,添加 @parameterized.expand()
3. 给 expand() 传入 元组列表数据( 调用 自己封装的 读取 json 文件的 函数 read_json_data() )
4. 修改 通用测试方法形参,与 json 数据文件中的 key 一致。
5. 在 通用测试方法内,使用形参
"""
class TestIhrmLogin(unittest.TestCase):
    # 通用测试方法(实现参数化)
    @parameterized.expand(read_json_data())
    def test_login(self, desc, req_data, stauts_code, success, code, message):
        # 调用自己封装的接口
        resp = IhrmLoginApi.login(req_data)
        print(desc, ":", resp.json())
        # 断言
        assert_util(self, resp, stauts_code, success, code, message)

四、员工管理接口

1、普通方法实现

import requests

# 添加员工
url = "http://ihrm-test.itheima.net/api/sys/user"
header = {"Content-Type": "application/json", "Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
json_data = {
    "username": "业务猪001",
    "mobile": "13978734783",
    "workNumber": "9527"
} 
resp = requests.post(url=url, headers=header, json=json_data)
print("添加员工:", resp.json())

# 查询员工
url_query = "http://ihrm-test.itheima.net/api/sys/user/1469566449784717312"
header_query = {"Content-Type": "application/json","Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
resp_query = requests.get(url=url_query, headers=header_query)
print("查询员工:", resp_query.json())

# 修改员工
url_modify = "http://ihrm-test.itheima.net/api/sys/user/1469566449784717312"
header_modify = {"Content-Type": "application/json","Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
modify_data = {"username": "齐天大圣"}
resp_modify = requests.put(url=url_modify, headers=header_modify, json=modify_data)
print("修改员工:", resp_modify.json())

# 删除员工
url_del = "http://ihrm-test.itheima.net/api/sys/user/1469566449784717312"
header_del = {"Content-Type": "application/json","Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
resp_del = requests.delete(url=url_del, headers=header_del)
print("删除员工:", resp_del.json())

2、接口对象层

"""
员工管理模块的 接口对象层
"""
import requests

class IhrmEmpCURD(object):
    # 添加员工
    @classmethod
    def add_emp(cls, header, json_data):
        url = "http://ihrm-test.itheima.net/api/sys/user"
        resp = requests.post(url=url, headers=header, json=json_data)
        return resp

    # 查询员工
    @classmethod
    def query_emp(cls, emp_id, header):
        url = "http://ihrm-test.itheima.net/api/sys/user/" + emp_id
        resp = requests.get(url=url, headers=header)
        return resp

    # 修改员工
    @classmethod
    def modify_emp(cls, emp_id, header, modify_data):
        url = "http://ihrm-test.itheima.net/api/sys/user/" + emp_id
        resp = requests.put(url=url, headers=header, json=modify_data)
        return resp

    # 删除员工
    @classmethod
    def delete_emp(cls, emp_id, header):
        url = "http://ihrm-test.itheima.net/api/sys/user/" + emp_id
        resp = requests.delete(url=url, headers=header)
        return resp

if __name__ == '__main__':
    header = {"Content-Type": "application/json",
    "Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
    data_add = {
        "username": "业务猪001",
        "mobile": "13978734786",
        "workNumber": "9527"
    } 
    resp = IhrmEmpCURD.add_emp(header, data_add)
    print("添加:", resp.json())
    emp_id = "1469572901224054784"
    resp = IhrmEmpCURD.query_emp(emp_id, header)
    print("查询:", resp.json())
    data = {"username": "齐天大圣"}
    resp = IhrmEmpCURD.modify_emp(emp_id, header, data)
    print("修改:", resp.json())
    resp = IhrmEmpCURD.delete_emp(emp_id, header)
    print("删除:", resp.json())

3、接口测试用例层

import unittest
from api.ihrm_emp_curd import IhrmEmpCURD
from common.assert_util import assert_util

class TestEmpAdd(unittest.TestCase):
    # 必选参数
    def test01_add_emp(self):
        # 准备数据
        header = {"Content-Type": "application/json",
                "Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
        json_data = {
            "username": "业务猪001",
            "mobile": "13978734787",
            "workNumber": "9527"
        } 

        #调用自己封装的 接口
        resp = IhrmEmpCURD.add_emp(header, json_data)
        print("添加-必选:", resp.json())

        # 断言
        assert_util(self, resp, 200, True, 10000, "操作成功")

    # 组合参数
    def test02_add_emp(self):
        # 准备数据
        header = {"Content-Type": "application/json",
                "Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
        json_data = {
            "username": "业务猪001",
            "mobile": "13978743801",
            "workNumber": "9527",
            "formOfEmployment": "2"
        } 

        #调用自己封装的 接口
        resp = IhrmEmpCURD.add_emp(header, json_data)
        print("添加-组合:", resp.json())

        # 断言
        assert_util(self, resp, 200, True, 10000, "操作成功")

    # 全部参数
    def test03_add_emp(self):
        # 准备数据
        header = {"Content-Type": "application/json",
                "Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
        json_data = {"username": "大猪乔治",
            "mobile": "13899078431",
            "timeOfEntry": "2021-12-01", "formOfEmployment": 1,
            "workNumber": "777888", "departmentName": "测试",
            "departmentId": "1452603344685203456",
            "correctionTime": "2021-12-30T16:00:00.000Z"}

        # 调用自己封装的 接口
        resp = IhrmEmpCURD.add_emp(header, json_data)
        print("添加-全部:", resp.json())

        # 断言
        assert_util(self, resp, 200, True, 10000, "操作成功")

4、数据库工具类封装

1. 在 common/ 下,创建 db_util.py 文件
2. 在 文件内, 实现 数据库 工具类及常用的数据库操作方法(查、增删改)

import pymysql

# 封装数据库工具类
class DBUtil(object):
    # 添加类属性
    conn = None

    @classmethod
    def __get_conn(cls):
        # 判断 conn 是否为空,如果是,再创建
        if cls.conn is None:
            cls.conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
                                        password="iHRM_student_2021", database="test_db",
charset="utf8")
        # 返回 非空连接
        return cls.conn

    @classmethod
    def __close_conn(cls):
        # 判断,conn 不为空,需要关闭。
        if cls.conn is not None:
            cls.conn.close()
            cls.conn = None

    # 常用方法:查询一条
    @classmethod
    def select_one(cls, sql):
        cursor = None
        res = None
        try:
            # 获取连接
            cls.conn = cls.__get_conn()
            # 获取游标
            cursor = cls.conn.cursor()
            # 执行 查询语句
            cursor.execute(sql)
            # 提取一条结果
            res = cursor.fetchone()
        except Exception as err:
            print("查询sql错误:", str(err))
        finally:
            # 关闭游标
            cursor.close()
            # 关闭连接
            cls.__close_conn()
            # 将查询sql执行的 结果,返回
            return res

    # 常用方法:增删改
    @classmethod
    def uid_db(cls, sql):
        cursor = None
        try:
            # 获取连接
            cls.conn = cls.__get_conn()
            # 获取游标
            cursor = cls.conn.cursor()
            # 执行 uid 语句
            cursor.execute(sql)
            print("影响的行数:", cls.conn.affected_rows())
            # 提交事务
            cls.conn.commit()
        except Exception as err:
            # 回滚事务
            cls.conn.rollback()
            print("增删改 SQL 执行失败:", str(err))
        finally:
            # 关闭游标
            cursor.close()
            # 关闭连接
            cls.__close_conn()

if __name__ == '__main__':
    res = DBUtil.select_one("select * from t_book;")
    print("查询结果为:", res)
    DBUtil.uid_db("update t_book set is_delete = 1 where id = 1111;")

5、解决反复修改手机号

解决思路:
1. 在 添加员工 接口测试 前(setUp),指定一个要使用的手机号,做 删除 delete sql 实现!
2. 测试 添加员工 接口, 使用 这个手机号。
3. 在 添加员工 接口测试 后(tearDown),再次 删除 这个手机号。delete sql 实现!
4. 将 手机号 定义成 全局手机号, 存放在 config.py 文件中。 TEL = “13900231473”

class TestEmpAdd(unittest.TestCase):

    def setUp(self) -> None:
        # 删除手机号
        delete_sql = f"delete from bs_user where mobile = '{TEL}'"
        DBUtil.uid_db(delete_sql)

    def tearDown(self) -> None:
        # 删除手机号
        delete_sql = f"delete from bs_user where mobile = '{TEL}'"
        DBUtil.uid_db(delete_sql)

    # 必选参数
    def test01_add_emp(self):
        # 准备数据
        header = {"Content-Type": "application/json","Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
        json_data = {
            "username": "业务猪001",
            "mobile": TEL,
            "workNumber": "9527"
        } 
        #调用自己封装的 接口
        resp = IhrmEmpCURD.add_emp(header, json_data)
        print("添加-必选:", resp.json())
        # 断言
        assert_util(self, resp, 200, True, 10000, "操作成功")

    # 组合参数
    def test02_add_emp(self):
        # 准备数据
        header = {"Content-Type": "application/json","Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
        json_data = {
            "username": "业务猪001",
            "mobile": TEL,
            "workNumber": "9527",
            "formOfEmployment": "2"
        } 
        #调用自己封装的 接口
        resp = IhrmEmpCURD.add_emp(header, json_data)
        print("添加-组合:", resp.json())
        # 断言
        assert_util(self, resp, 200, True, 10000, "操作成功")

    # 全部参数
    def test03_add_emp(self):
        # 准备数据
        header = {"Content-Type": "application/json","Authorization": "Bearer b040daed-39c1-4302-8777-f950770c8a26"}
        json_data = {
            "username": "大猪乔治",
            "mobile": TEL,
            "timeOfEntry": "2021-12-01", "formOfEmployment": 1,
            "workNumber": "777888", "departmentName": "测试",
            "departmentId": "1452603344685203456",
            "correctionTime": "2021-12-30T16:00:00.000Z"}
        # 调用自己封装的 接口
        resp = IhrmEmpCURD.add_emp(header, json_data)
        print("添加-全部:", resp.json())
        # 断言
        assert_util(self, resp, 200, True, 10000, "操作成功")

6、完整参数化步骤:添加员工接口参数化

完整参数化步骤:
1. 组织测试数据到 json 文件中。 格式 [{},{},{}]
2. 读取 json 数据文件中的 [{},{},{}] 数据,转换成 [(),(),()] 数据
3. 在 测试脚本中,借助 parameterized 实现参数化
        1. 导包 from parameterized import parameterized
        2. 在 通用测试方法上一行,添加 @parameterized.expand()
        3. 给 expand() 传入 元组列表数据( 调用 自己封装的 读取 json 文件的 函数 read_json_data() )
        4. 修改 通用测试方法形参,与 json 数据文件中的 key 一致。
        5. 在 通用测试方法内,使用形参


json 数据文件:

[
{
"desc": "必选参数",
"json_data": {
"username": "业务猪001",
"mobile": "13900043762",
"workNumber": "9527"
},
"stauts_code": 200,
"success": true,
"code": 10000,
"message": "操作成功"
},
{
"desc": "组合参数",
"json_data": {
"username": "业务猪001",
"mobile": "13900043762",
"workNumber": "9527",
"formOfEmployment": "2"
},
"stauts_code": 200,
"success": true,
"code": 10000,
"message": "操作成功"
},
{
"desc": "全部参数",
"json_data": {
"username": "大猪乔治",
"mobile": "13900043762",
"timeOfEntry": "2021-12-01",
"formOfEmployment": 1,
"workNumber": "777888",
"departmentName": "测试",
"departmentId": "1452603344685203456",
"correctionTime": "2021-12-30T16:00:00.000Z"
},
"stauts_code": 200,
"success": true,
"code": 10000,
"message": "操作成功"
}
]

7、获取请求头

1. 在 common/ 下 创建 get_header.py 文件
2. 在 文件内 创建 get_header() 函数,实现 登录成功,获取令牌,拼接成 请求头,返回。
3. 在 scripts/ 的测试脚本文件中,添加 setUpClass 方法,调用 get_header() 函数。 将返回值 保存到 类属性上
4. 在 使用 请求头的位置,直接从类属性获取

# 在 common/ 下 创建 get_header.py 文件 实现 get_header 函数
import requests

def get_header():
    url = "http://ihrm-test.itheima.net/api/sys/login"
    data = {"mobile": "13800000002", "password": "123456"}
    resp = requests.post(url=url, json=data)
    print(resp.json())
    # 从 响应体中,获取 data的值
    token = resp.json().get("data")
    header = {"Content-Type": "application/json","Authorization": "Bearer " + token}
    return header



# 在 scripts/ 的测试脚本文件中,添加 setUpClass 方法,调用 get_header 函数。 
# 将返回值 保存到 类属性上
from common.get_header import get_header
class TestEmpAdd(unittest.TestCase):
    # 类属性
    header = None
    @classmethod
    def setUpClass(cls) -> None:
        cls.header = get_header()



# 在 使用 请求头的位置,直接从类属性获取
resp = IhrmEmpCURD.add_emp(self.header, json_data)

8、提取项目目录

相关知识:

  • __file__ : 获取 当前文件的 绝对路径。
  • BASE_DIR = os.path.dirname(__file__) : 获取 到 当前文件的 上一级目录。
    • 此行代码,写在 config.py 中, 可以直接获取 项目目录

 项目中使用:

​​​​​​​1. 在 config.py 文件中,添加 获取项目路径 全局变量 BASE_DIR = os.path.dirname(__file__)
2. 修改 common/ 下 read_json_util.py 文件中,读取 json 文件 函数read_json_data(),添加 参数 path_filename
3. 在 使用 read_json_data()函数 时, 拼接 json 文件路径, 传入到 函数中。

 

9、生成测试报告

参考文章:软件测试 —— Python(七)之UnitTest框架与测试报告

步骤:
1. 创建测试套件实例。 suite
2. 添加 测试类
3. 创建 HTMLTestReport 类实例。 runner
4. runner 调用 run(), 传入 suite


实现:

import unittest
from config import BASE_DIR
from scripts.test_emp_add_params import TestEmpAddParams
from scripts.test_ihrm_login_params import TestIhrmLoginParams
from htmltestreport import HTMLTestReport

# 1. 创建测试套件实例。 suite
suite = unittest.TestSuite()

# 2. 添加 测试类, 组装测试用例
suite.addTest(unittest.makeSuite(TestIhrmLoginParams))
suite.addTest(unittest.makeSuite(TestEmpAddParams))

# 3. 创建 HTMLTestReport 类实例。 runner
# runner = HTMLTestReport(BASE_DIR + "/report/ihrm.html") # 绝对路径
runner = HTMLTestReport("./report/ihrm.html", description="描述", title="标题") # 相对路径

# 4. runner 调用 run(), 传入 suite
runner.run(suite)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/96355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java8流操作之不常用但是很好用的隐藏api

前言 1、一些普通的方式就不再多说了,这里主要说一些不常用的,但是作用很大的api方式 2、如果想要细致了解可以参考 JAVA8的流操作,十分推荐 一、flatMap 1、这个api主要是用来推平流的,和map不一致,map是对象到对…

Python基础(十六):函数的初步认识

文章目录 函数的初步认识 一、函数的作用 二、函数的使用步骤 1、定义函数 2、调用函数 3、快速体验 三、函数的参数作用 四、函数的返回值作用 1、应用 五、函数的说明文档 1、语法 2、快速体验 3、函数嵌套调用 七、函数应用 1、打印图形 2、函数计算 八、总…

还在为多张Excel汇总统计发愁?Python 秒处理真香!

为什么越来越多的非程序员白领都开始学习 Python ?他们可能并不是想要学习 Python 去爬取一些网站从而获得酷酷的成就感,而是工作中遇到好多数据分析处理的问题,用 Python 就可以简单高效地解决。本文就通过一个实际的例子来给大家展示一下 P…

新手传奇gm架设要学会的几个修改技巧

每个传奇gm对于架设一个服务器都有自己独立的看法和想法,一些人之所以会想着要架设一个传奇私服主要原因是自己在其他人的服力玩得不是那么舒心。所以想要按照自己的想法和思路打造一个适合自己的专属服务器进行游戏,其实这两者之间是有必然联系的&#…

毕业三年活得像个废物,转行网络安全,写给像我一样迷茫的人...

首先说说我吧,普通二本非科班商贸专业毕业,三年了,做过电商,做过新媒体,做过业务员,从躺平到摆烂,一开始还挺享受这样的生活的,毕竟每月4千工资,抛出吃住,剩个…

重学webpack系列(八) -- webpack的运行机制与工作原理

前面几个章节我们分别去探索了webpack的loader机制、plugin机制、devServer、sourceMap、HMR,但是你是否知道这些配置项是怎么去跟webpack本身执行机制挂钩的呢?这一章我们就来探索一下webpack的运行机制与工作原理吧。 webpack核心工作过程 我们打开w…

第十四章 文件操作

1.文件的基本操作 文件,对我们并不陌生,文件是数据源(保存数据的地方)的一种,比如大家经常使用的Word文档,TXT文件,excel文件…都是文件。文件最主要的作用就是保存数据,它既可以保…

用户虚拟地址空间管理-mm_struct

一、进程虚拟地址空间管理概览 二、mm_struct结构体的主要成员 atomic_t mm_users;共享同一个用户虚拟地址空间的进程的数量,也就是线程组包含的进程的数量atomic_t mm_count;内存描述符的引用计数struct vm_area_struct *mmap;虚拟内存区域链表struct rb_root mm_…

【java】课程设计--抽卡模拟器

文章目录工期安排自己实现菜单逻辑抽卡算法0.书写要求1.用户需求2.设计思想3.各个功能和算法描述4.系统调试中问题5.总结新知识怎么打开任务管理器改进(进一步的设想)交给她们实现1.注册登录2.读文件-显示查找内容暂时成功案例工期安排 1 自定义增加和删…

数据权限就该这么设计

在项目实际开发中我们不光要控制一个用户能访问哪些资源,还需要控制用户只能访问资源中的某部分数据。 控制一个用户能访问哪些资源我们有很成熟的权限管理模型即RBAC,但是控制用户只能访问某部分资源(即我们常说的数据权限)使用…

[附源码]Python计算机毕业设计红旗家具城管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

✿✿✿JavaScript --- 事件

目录 1.事件相关概念 2. js中注册监听(事件绑定)的方式 (1)在定义标签时,添加事件名称属性。属性值是js代码(js代码会被自动封装到一个function函数的方法体中) (2)通过js获取元素对象,再添加事件。 补…

ADI Blackfin DSP处理器-BF533的开发详解54:CVBS输出-DSP和CH7024的应用详解(含源码)

硬件准备 ADSP-EDU-BF533:BF533开发板 AD-HP530ICE:ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 CVBS OUT 视频输出 硬件实现原理 CVBS_OUT 子卡板连接在 ADSP-EDU-BF53x 开发板的扩展端口 PORT3 和 PORT4 上,板卡插入时&#xff0…

window10 下Tomcat安装步骤

目录先安装JDK根据JDK选择tomcat版本下载安装设置系统变量运行测试先安装JDK 略过 根据JDK选择tomcat版本 打开CMD窗口,运行java -version查看本机JDK版本 C:\Users\admin>java -version java version "11.0.17" 2022-10-18 LTS Java(TM) SE Runtime E…

python函数讲解进阶

关于python函数的基本知识可以点击“python函数讲解” 目录 一.函数多返回值 思考 二.函数参数种类 1.位置参数 2.关键字参数 3.缺省参数 4.不定长参数 位置传递 关键字传递 总结 三.匿名函数 函数作为参数传递 lambda匿名函数 一.函数多返回值 思考 运行之后&…

Python抓取电商平台数据 / 采集商品评论 / 可视化展示 词云图...

前言 大家早好、午好、晚好吖 ❤ ~ 我给大家准备了一些资料,包括: 2022最新Python视频教程、Python电子书10个G (涵盖基础、爬虫、数据分析、web开发、机器学习、人工智能、面试题)、Python学习路线图等等 直接在文末名片自取即可&#x…

[附源码]Node.js计算机毕业设计公交电子站牌管理系统软件Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

多模态在医疗中的应用

多模态是把要检索的模态融合起来,做整体的检索,查询和检索的必须至少有一个模态是相同的,也就是要查询和检索的模态都已经在融合模态里了。 跨模态是检索结果和查询的模态是不同,如图像检索文本,视频和音频。跨模态检索…

2022-12-17 TCP/IP 协议栈_2

TCP/IP 协议栈_2前言一、TCP/IP协议栈四层协议系统二、封装和分用总结前言 既然要学习计算机网络编程, 就不得不提计网祖师爷 W Richard Stevens, 天妒英才, 先生于1999年就早早陨落. 不知多少人凭着先生所著 “TCP/IP详解” 以及 “UNIX网络编程” 吃的盆满钵满. 而至今可说还…

深入浅出 - Rust 所有权与内存管理机制

一、从变量说起 fn main() {// 基本数据类型let a 5;let b a;// 指针let ptr_a &a;let ptr_b &b;println!("a value {}", a);println!("b value {}", b);println!("ptr_a value {:p}", ptr_a);println!("ptr_b value {:p}…