继上文所将讲的python+requests+Unittest框架,本文将继续分享python代码的进一步封装思想,来提高代码的整体运行效率及整洁性,本文以接口测试框架为例进行讲解。


 接口测试框架目录:

python 任务编排框架 python代码总体框架_python 任务编排框架

  • api:存放我们自己封装的API接口
  • script:存放python代码,借助unittest框架,调用自己封装的API
  • data:存放数据文件,如用于参数化的数据
  • report:存放生成的测试报告
  • lib:存放第三方库
  • app.py:存放全局数据、公共变量
  • utils.py:存放工具函数、方法
  • run_suite.py:存放批量执行用例,生成测试报告的代码

封装登录接口思路:

  1. 先按普通方式实现HTTP请求
  2. 将请求 封装成自己定义个API接口(存入api中)
  3. 调用自己封装的API,实现接口测试(结合Unittest框架,写入到script)

整体思想:

  • 将固定不变的数据,直接写入到封装的类属性和方法中
  • 将动态变化的数据,通过参数或返回值传递

分析:

  • session:是需要创建而产生的---动态变化的
  • get()方法:不变
  • 获取验证码的url:不变
  • 获取验证码的resp:做返回值进行传出--动态变化的(传出)
  • post()方法:不变
  • 登录的url:不变
  • 登录的headers:不变
  • 登录的data:做参数---动态变化的(传入)
  • 登录的resp:做返回值进行传出--动态变化的(传出)

封装代码:

1.在api目录下创建login_api.py文件

# 在api目录下创建login_api.py
# 创建类
class Login_Api:
    # 定义属性
    def __init__(self):
        self.url_verify = 'xxxx'
        self.url_login = 'xxxxx'
        self.headers = 'xxxx'

    # 定义方法-获取验证码
    def get_verify(self, my_session):
        return my_session.get(url=self.url_verify)

    # 定义方法-登录
    def login(self, my_session, req_data):
        return my_session.post(url=self.url_login, headers=self.headers, data=req_data)

2.在script目录中创建测试类文件,从unittest.Testcase类继承并添加setUpClass及tearDownClass和普通方法

# 在script中创建test_login.py
import unittest

import requests

from api.login_api import Login_Api
# 导包

class LgxLogin(unittest.TestCase):
    my_session = None

    @classmethod
    def setUpClass(cls) -> None:
        cls.login_api = Login_Api()
        # 调用自己封装的类
        cls.my_session = requests.Session()

    @classmethod
    def tearDownClass(cls) -> None:
        cls.my_session.close()

    def test01_login_ok(self):
        # 登录成功
        # 调用自己封装的方法获取验证码
        resp_verify = self.login_api.get_verify(self.my_session)
        # 调用自己封装的方法实现登录
        req_data = 'xxxxx'
        resp_login = self.login_api.login(self.my_session, req_data)
        # 打印响应结果
        print(resp_login)
        # 增加断言-响应状态码
        self.assertEqual(200, resp_login.status_code)
        # 增加断言-响应体msg的值为登录成功
        self.assertIn('登录成功', resp_login.json().get('msg'))

    def test02_username_not_exits(self):
        # 用户名不存在
        # 调用自己封装的方法获取验证码
        resp_verify = self.login_api.get_verify(self.my_session)
        # 调用自己封装的方法实现登录
        req_data = 'AAAAAA'
        resp_login = self.login_api.login(self.my_session, req_data)
        # 打印响应结果
        print(resp_login)
        # 增加断言-响应状态码
        self.assertEqual(200, resp_login.status_code)
        # 增加断言-用户名不存在
        self.assertIn('用户名不存在', resp_login.json().get('msg'))

    def test03_pwd_error(self):
        # 密码错误
        # 调用自己封装的方法获取验证码
        resp_verify = self.login_api.get_verify(self.my_session)
        # 调用自己封装的方法实现登录
        req_data = 'BBBBB'
        resp_login = self.login_api.login(self.my_session, req_data)
        # 打印响应结果
        print(resp_login)
        # 增加断言-响应状态码
        self.assertEqual(200, resp_login.status_code)
        # 增加断言-响应体msg的值为密码错误
        self.assertIn('密码错误', resp_login.json().get('msg'))

进一步优化:

  • 将http协议和域名,写入到app.py文件中,当做一个全局变量来存储
  • 将headers存储到app.py文件中,当做一个全局变量来存储
  • 使用到全局变量时导包引用即可

以上就是本文的全部内容了,合理利用封装思想,可以时数据动态管理,应对域名、协议等共用的信息变化时可以通过直接公共方法里的属性值进行全局修改,如有疑问欢迎评论区留言讨论。