【Unittest】Unittest接口测试框架开发-以登录模块为例

文章目录

    • 框架结构
    • 框架目录结构
    • 封装被测试系统接口
    • 定义接口测试用例
    • 集成测试报告
    • 测试数据参数化
      • (一)分析与数据构造
      • (二)基于JSON实现参数化
      • (三)基于数据库实现参数化

框架结构

框架结构包括:被测系统、API、数据库、TestCase、测试数据、测试报告。

(1)将测试用例TestCase与被测试系统API进行分离,便于后期维护。
(2)测试用例TestCase是通过unittest进行管理,并提供了丰富的断言(等于、包含等)。
(3)通过参数化思想测试数据与测试脚本的分离。
(4)调用数据库进行结果验证或将数据库作为参数化的数据源。
(5)借助第三方工具快速的生成HTML报告。

框架目录结构

  • data – 管理测试数据的文件夹
  • report – 管理测试结果报告的文件夹
  • api – 封装被测试系统的接口
  • scripts – 测试用例脚本
  • tools – 第三方工具包管理
  • app.py – 配置信息文件
  • run_suite.py – 测试用例执行入口
  • utils.py – 自定义工具类

【Unittest】Unittest接口测试框架开发-以登录模块为例_第1张图片

封装被测试系统接口

在api包下新建login.py

# 封装被测试系统接口


# 定义接口类
class LoginAPI:

    # 初始化
    def __init__(self):
        self.url_login = "http://xxxlogin"

    # 登录接口
    def login(self, session, username, password):
        login_data = {
            "username": username,
            "password": password
        }
        return session.post(url=self.url_login, data=login_data)

定义接口测试用例

在script包下新建test01_login.py

# 导包
import requests
import unittest
from api.login import LoginAPI

# 定义测试类
class TestLoginAPI(unittest.TestCase):
    # 前置处理
    def setUp(self):
        self.login_api = LoginAPI()
        self.session = requests.Session()

    # 后置处理
    def tearDown(self):
        if self.session:
            self.session.close()

    # 定义测试方法
    
    # 登录成功
    def test01_login_success(self):
        # 调用登录接口
        response = self.login_api.login(self.session, "15588888888", "123456")
        print(response.json())
        self.assertEqual(200, response.status_code)
        self.assertEqual(1, "登录成功", response.json().get("msg"))

    # 账号不正确
    def test02_user_isnot_exist(self):
        # 调用登录接口
        response = self.login_api.login(self.session, "13388888888", "123456")
        print(response.json())
        self.assertEqual(200, response.status_code)
        self.assertEqual(-1, response.json().get("status"))
        self.assertIn("账号不存在", response.json().get("msg"))
        
    # 密码错误
    def test03_password_exist(self):
        # 调用登录接口
        response = self.login_api.login(self.session, "13488888888", "error")
        print(response.json())
        self.assertEqual(200, response.status_code)
        self.assertEqual(-2, response.json().get("status"))
        self.assertIn("密码错误", response.json().get("msg"))

集成测试报告

将HTMLTestRunner.py放到tools包下
编辑run_suite.py

# 导包
import time
import unittest
from scripts.test01_login import TestLoginAPI
from tools.HTMLTestRunner import HTMLTestRunner

# 封装测试套件
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestLoginAPI))
# 指定报告路径
report = "./report/report-{}.html".format(time.strftime("%Y%m%d-%H%M%S"))
# 打开文件流
with open(report, "wb") as f:
  # 创建HTMLTestRunner执行器
  runner = HTMLTestRunner(f, title="接口测试报告")
  # 执行测试套件
  runner.run(suite)

测试数据参数化

(一)分析与数据构造

1、分析需要参数化的参数有哪些:
(1)输入数据:用户名、密码
(2)预期结果:content_type、状态码、业务码、业务消息
2、选择数据承载形式:
(1)json
(2)db
3、修改测试用例的代码:
(1)构建参数化数据(build_data方法)
(2)在测试用例前引用参数化(@parameterized装饰器)
(3)在具体的测试用例中,按照获得的数据进行参数替换

(二)基于JSON实现参数化

在data包下新建login.json

[
  {
    "desc": "case01 登录成功",
    "username": "15588888888",
    "password": "123456",
    "Content_Type": "image",
    "status-code": "200",
    "status": 1,
    "msg": "登录成功"
  },
  {
    "desc": "case02 账号不存在",
    "username": "13388888888",
    "password": "123456",
    "Content_Type": "image",
    "status-code": "200",
    "status": -1,
    "msg": "账号不存在"
  },
    {
    "desc": "case03 密码错误",
    "username": "15588888888",
    "password": "eroor",
    "Content_Type": "image",
    "status-code": "200",
    "status": -2,
    "msg": "密码错误"
  }
]

修改script包下test01_login.py的代码

# 导包
import json
import requests
import unittest
from api.login import LoginAPI
from parameterized import parameterized
# 构造测试数据
def build_data():
    json_file = "../data/login.json"
    test_data = []
    with open(json_file, encoding="utf-8") as f:
        json_data = json.load(f)
        for case_data in json_data:
            username = case_data.get("username")
            password = case_data.get("password")
            status_code = case_data.get("status_code")
            content_type = case_data.get("content_type")
            status = case_data.get("status")
            msg = case_data.get("msg")
            test_data.append((username, password, status_code,content_type, status, msg))
            print("test_data = {}".format((username, password, status_code, content_type, status, msg)))
            return test_data

# 定义测试类
class TestLoginAPI(unittest.TestCase):
    # 前置处理
    def setUp(self):
        self.login_api = LoginAPI()
        self.session = requests.Session()

    # 后置处理
    def tearDown(self):
        if self.session:
            self.session.close()
    # 定义测试方法
    @parameterized.expand(build_data)
    def test01_login(self, username, password, status_code,content_type, status, msg):
        # 调用登录接口
        response = self.login_api.login(self.session, username, password)
        print(response.json())
        self.assertEqual(status_code, response.status_code)
        self.assertEqual(status, response.json().get("status"))
        self.assertIn(msg, response.json().get("msg"))

(三)基于数据库实现参数化

修改script包下test01_login.py的代码

# 导包
import requests
import unittest
from api.login import LoginAPI
from tools.dbutil import DBUtil
from parameterized import parameterized
# 构造测试数据
def build_data():
    sql = "select * from t_login"
    db_data = DBUtil.exe_sql(sql)
    print(db_data)
    test_data = []
    for case_data in db_data:
        username = case_data[2]
        password = case_data[3]
        status_code = case_data[4]
        content_type = case_data[5]
        status = case_data[6]
        msg = case_data[7]
        test_data.append((username, password, status_code,content_type, status, msg))
        print("test_data = {}".format((username, password, status_code, content_type, status, msg)))
        return test_data

# 定义测试类
class TestLoginAPI(unittest.TestCase):
    # 前置处理
    def setUp(self):
        self.login_api = LoginAPI()
        self.session = requests.Session()

    # 后置处理
    def tearDown(self):
        if self.session:
            self.session.close()

    # 定义测试方法
    @parameterized.expand(build_data)
    def test01_login(self, username, password, status_code, content_type, status, msg):
        # 调用登录接口
        response = self.login_api.login(self.session, username, password)
        print(response.json())
        self.assertEqual(status_code, response.status_code)
        self.assertEqual(status, response.json().get("status"))
        self.assertIn(msg, response.json().get("msg"))

你可能感兴趣的:(python,开发语言,unittest,自动化测试)