• python+pytest接口自动化之token关联登录


    前言

    今天呢我们就来聊聊接口自动化测试之token关联登录,在PC端登录公司的后台管理系统或在手机上登录某个APP时,经常会发现登录成功后,返回参数中会包含token,它的值为一段较长的字符串,而后续去请求的请求头中都需要带上这个token作为参数,否则就提示需要先登录。

    这其实就是状态或会话保持的第三种方式token。

     一、 什么是token

    token 由服务端产生,是客户端用于请求的身份令牌。第一次登录成功时,服务端会生成一个包含用户信息的加密字符串token,返回给客户端并保存在本地,后续客户端只需要带上token进行请求即可,无需带上用户名密码。

    token原理简单概括如下:

    1. 用户首次登录成功后,服务端会生成一个token值,服务端会将它保存保存在数据库中,同时也会将它返回给客户端;
    2. 客户端拿到token值后,保存在本地;
    3. 后续客户端再次发送除登录外的其他请求时,会把保存在本地的token值作为参数一起发送给服务端;
    4. 服务端收到客户端的请求后,会拿发送过来的token值与保存在数据库中的token值进行比较;
    5. 如果两个token值相同, 则说明当前用户处于登录状态;
    6. 如果数据库中没有这个token值或者token值已经生效,则需用户重新登录。

    二、token场景处理

    公司某管理后台系统,登录后返回token,接着去请求其他接口时请求头中都需要加上这个token,否则提示请先登录。

    请求该系统的登录接口如下:

    1. import requests
    2. import json
    3. headers = {"Content-Type": "application/json;charset=utf8"}
    4. url = "http://127.0.0.1:5000/login"
    5. _data = {
    6. "username": "刘德华",
    7. "password": "123456"
    8. }
    9. res = requests.post(url=url, headers=headers, json=_data).text
    10. print(res)

    结果如下:

    1. {
    2. "code": 1000,
    3. "msg": "登录成功!",
    4. "token": "sh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730djsh34ljjl08s32730dj"
    5. }

    在对这样的项目做接口自动化测试时,需要先请求登录接口拿到token,再去请求别的接口。每次请求其他接口时先请求一次登录接口,这样做虽然可行,但这样不仅会降低自动化的执行效率,而且每次都请求登录也会对服务器资源造成浪费。

    这里介绍如下两种处理思路。

    1. 思路一

    在执行用例之前,先请求登录接口,并将返回的token值存储在文件中(如yaml文件),后续请求需要用到token值则从该文件。

    python中yaml文件的读写请参考我之前的文章Python读写yaml文件(使用PyYAML库)。

    1、运行接口自动化测试框架,初始化时先请求登录接口,获取token值,并写入指定的yaml文件中。

    1. import requests
    2. import json
    3. import yaml
    4. def get_token():
    5. '''
    6. 请求登录接口,获取token
    7. :return:
    8. '''
    9. headers = {"Content-Type": "application/json;charset=utf8"}
    10. url = "http://127.0.0.1:5000/login"
    11. _data = {
    12. "username": "刘德华",
    13. "password": "123456"
    14. }
    15. res = requests.post(url=url, headers=headers, json=_data).text
    16. res = json.loads(res)
    17. token = res["token"]
    18. return token
    19. def write_yaml(token):
    20. '''
    21. 写入yaml文件
    22. :return:
    23. '''
    24. t_data = {
    25. "token": token
    26. }
    27. with open("yaml文件路径", "w", encoding="utf-8") as f:
    28. yaml.dump(data=t_data, stream=f, allow_unicode=True)
    29. if __name__ == '__main__':
    30. token = get_token() # 获取token
    31. write_yaml(token) # 将token值写入yaml文件

    2、执行测试用例时先读取yaml文件中token值,并将token加入headers中(也有些是将token放在请求参数中,视被测试项目具体情况而定),再发送请求。

    1. import requests
    2. import yaml
    3. import pytest
    4. import json
    5. def read_yaml():
    6. '''
    7. 读yaml文件
    8. :return:
    9. '''
    10. with open('yaml文件路径', 'r', encoding='utf-8') as f:
    11. result = yaml.load(f.read(), Loader=yaml.FullLoader)
    12. token = result["token"]
    13. return token
    14. def test_check_user():
    15. '''
    16. 查询个人信息(需要先登录系统)
    17. :return:
    18. '''
    19. # 先从yaml文件中读取token
    20. token = read_yaml()
    21. # 再将token添加到请求头中
    22. headers = {
    23. "Content-Type": "application/json;charset=utf8",
    24. "token": token
    25. }
    26. url = "http://127.0.0.1:5000/users/3"
    27. res = requests.get(url=url, headers=headers).text
    28. # 返回结果为json格式,转换为字典
    29. res = json.loads(res)
    30. # 断言code是否为1000
    31. assert res["code"] == 1000
    32. if __name__ == '__main__':
    33. pytest.main()

    这里仅仅只是举例说明,而在实际的框架中,我们需要把这些诸如yaml文件的读写这样的函数单独封装在某个模块中,供其他模块调用,这样会代码会更加清晰简洁。

    2、 思路二

    利用pytest中的Fixture函数,作用域设置为session,并返回token值,后续测试方法/函数调用该Fixture函数。

    pytest中Fixture的使用请参考我之前的文章pytest(6)-Fixture(固件)。

    1、首先,在conftest中定义一个作用域为session的Fixture函数,用于请求登录接口返回token。

    1. import pytest
    2. import requests
    3. import json
    4. @pytest.fixture(scope="session")
    5. def get_token_fixture():
    6. '''
    7. 作用域为session的fixture函数,返回token
    8. :return:
    9. '''
    10. headers = {"Content-Type": "application/json;charset=utf8"}
    11. url = "http://127.0.0.1:5000/login"
    12. _data = {
    13. "username": "刘德华",
    14. "password": "123456"
    15. }
    16. res = requests.post(url=url, headers=headers, json=_data).text
    17. res = json.loads(res)
    18. token = res["token"]
    19. return token

    2、接着,测试用例调用该Fixture。

    1. def test_check_user(get_token_fixture):
    2. '''
    3. 查询个人信息(需要先登录系统)
    4. :return:
    5. '''
    6. # 通过Fixture函数g获取et_token_fixture值,即token,再将token添加到请求头中
    7. headers = {
    8. "Content-Type": "application/json;charset=utf8",
    9. "token": get_token_fixture
    10. }
    11. url = "http://127.0.0.1:5000/users/3"
    12. res = requests.get(url=url, headers=headers).text
    13. res = json.loads(res)
    14. print(res)
    15. print(headers)
    16. assert res["code"] == 1000
    17. if __name__ == '__main__':
    18. pytest.main()

    执行测试用例结果如下:

     说明思路二也是可行的,当然这里只执行了一条测试用例,如果执行很多的用例,效果会是怎样还没去验证,大家可以试试看。

    三、总结

    1. 相对于Session/Cookies来说,请求量较大或者涉及第三方接口的系统,使用token更适合。
    2. 有些项目token是放在请求头中发送的,而有一些项目则是放在请求参数里发送的,做接口自动化时要明确是哪种方式。
    3. 接口自动化处理token时这两种思路可任选一种,如果使用pytest框架的话建议尝试思路二。

    最后今天的文章就到这里了哟,喜欢的小伙伴可以点赞收藏加关注哟,希望这篇文章可以帮助到大家哟。

     

  • 相关阅读:
    Linux笔记
    Python的偏函数
    研发效能|DevOps 是运维还是开发?
    字符串总结
    Linux环境基础开发工具使用
    基于飞浆NLP的BERT-finetuning新闻文本分类
    C++断言让程序有了脾气
    Python时间转换:X秒 --> 时:分:秒
    codeforces600E Lomsat gelral【线段树合并/DSU】
    从零入门AI生图原理(一)(Datawhale X 魔搭 AI夏令营)
  • 原文地址:https://blog.csdn.net/qishuzdh/article/details/125412847