Pytest接口測試框架實戰項目搭建(三)—— 統一登錄處理

一、前言

  業務系統的登錄均要經過統一登錄系統S,本篇演示統一登錄處理,一個是內部業務系統C(其餘內部業務系統AB用的都是相同賬號密碼),一個是外部用戶使用的系統W,因爲賬號密碼以及headers信息都不一樣,所以要分開處理登錄。這裏要先貼一下請求要用到的數據。

  說明:登錄進了S系統,拿到token即可直接請求內部業務系統ABC的接口,同理外部業務系統W亦是如此。所以本篇主要講述的是如何登錄S系統

1、conf/config.ini

  接口請求時需要拿到配置文件中的域名地址,env可切換環境,即不用改業務代碼,直接改配置文件即可適配不同測試環境的接口自動化測試。

     y_api_url,是業務系統ABCW的接口域名,s_api_url是登錄系統S的接口域名。

[ENV]
env = QA1

[QA1]
y_api_url = https://qa1-api.y.cn
s_api_url = https://qa-s-xxx.cn

[QA2]
y_api_url = https://qa1-api.y.cn
s_api_url = https://qa-s-xxx.cn

2、data/userInfo.yaml

  要拿到登錄token,需要先登錄S系統,S登錄接口是嵌入到各個業務系統,所以請求體是一樣的只是賬號密碼不一樣,故要分開來,內部業務系統ABC均可用s_login_info的用戶信息,外部業務系統W用的是w_login_info的用戶信息。

QA1:
  s_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉該參數,password傳輸可不加密
    username: zhangsan
    password: 1231234
    verification:

  w_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉該參數,password傳輸可不加密
    username: lisi
    password: 123456
    verification:

QA2:
  s_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉該參數,password傳輸可不加密
    username: zhangsan111
    password: 1231234
    verification:

  w_login_info:
    loginFromServer: 'https://qa-xxx.cn/#/'
    loginFromSystemCode: S
    #passwordVersion: 1 #去掉該參數,password傳輸可不加密
    username: lisi222
    password: 123456
    verification:

3、data/headers.json

  內部業務系統ABC均可用s_login_info的用戶信息,外部業務系統W用的是w_login_info的用戶信息,其實請求體是一樣的只是賬號密碼不一樣,所以要分開來。

{
  "QA1": {
    "s_login_headers": {
      "Content-Type": "application/x-www-form-urlencoded",
      "Accept": "application/json, text/plain, */*"
    },
    "s_headers": {
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    },
    "c_headers": {
      "T-Id": "7",
      "System-Code": "C",
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    },
    "w_headers": {
      "T-Id": "12095",
      "System-Code": "W",
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    }
  },
  "QA2": {
    "s_login_headers": {
      "Content-Type": "application/x-www-form-urlencoded",
      "Accept": "application/json, text/plain, */*"
    },
    "c_headers": {
      "T-Id": "7",
      "System-Code": "C",
      "Content-Type": "application/json;charset=UTF-8",
      "Accept": "application/json, text/plain, */*",
      "sToken": ""
    }
  }
}

4、conf/api_path.py

  該文件存儲的是項目中用到的所有接口路徑,目前只展示統一登錄需要用到的api。

# -*- coding:utf-8 -*-
'''
@Date:2022/10/3  20:56
@Author:一加一
'''

from tools.operate_config import OperateConfig
from urllib.parse import urljoin

class ApiPath:

    '''管理api地址'''

    def __init__(self,env=None):
        if env is None:
            self.env = OperateConfig().get_node_value('ENV', 'env')
        else:
            self.env = env
self.s_api_url = OperateConfig().get_node_value(self.env, 's_api_url') #讀取配置文件config.ini 的s系統接口域名 # s系統 api self.s_login_url = urljoin(self.s_api_url, "/saas-xxx/login") #登錄 self.s_exchangeToken_url = urljoin(self.s_api_url, "/saas-xxx/exchangeToken") #生成sToken self.employee_paging_list = urljoin(self.s_api_url,"/saas-xxx/list") #查詢員工列表獲取companyId

二、封裝方法:獲取JSON

  要登錄的話肯定要涉及接口請求了,所以這裏首先封裝下讀取json文件的方法,具體如下。

1、tools/get_userjson.py

  tools文件夾下新建get_userjson.py文件,源碼如下:

  • get_yaml主要用於讀取data/userInfo.yaml裏的用戶信息
  • OperateConfig主要讀取config.ini裏的域名地址
from tools.operate_config import get_yaml,OperateConfig

class GetuserJson:

    def __init__(self, env=None):
        if env is None:
            env = OperateConfig().get_node_value('ENV', 'env')
        self.env = env
        self.user_info = get_yaml(self.env)

    # 統一登錄系統s 登陸的用戶信息
    def  get_s_login_info(self):
        s_login_info = self.user_info['s_login_info']
        return s_login_info

    # 業務系統W 登陸的用戶信息
    def  get_w_login_info(self):
        w_login_info = self.user_info['w_login_info']
        return w_login_info

2、tools/get_headerjson.py

  tools文件夾下新建get_headerjson.py文件,源碼如下:

  • 用於登錄S系統用到的:get_s_login_headers,獲取headers.json里名爲"s_login_headers”的json串
  • 用於S系統查詢公司id用到的:get_s_headers,獲取headers.json里名爲"s_headers”的json串
  • 用於登錄成功將獲取到的token值set進去:set_s_headers,往json文件裏set字段值
# -*- coding:utf-8 -*-
from conf.setting import CASE_DATA_PATH
from tools.operate_json import OperationJson
import os
from tools.operate_config import get_yaml,OperateConfig

class GetHeaderjson:

    def __init__(self,env=None):
        if env is not None:
            self.env = env
        else:
            self.env = OperateConfig().get_node_value('ENV', 'env')
        self.headers_json = os.path.join(CASE_DATA_PATH, "headers.json")

    def get_s_login_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env,"s_login_headers")
    def get_s_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env,"s_headers")
    def set_s_headers(self,s_token):
        OperationJson(self.headers_json).write_datas(s_token,self.env, "s_headers", "sToken")
def get_c_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env,"c_headers")
    def set_c_headers(self,s_token):
        OperationJson(self.headers_json).write_datas(s_token,self.env, "c_headers", "sToken")

    def get_w_headers(self):
        return OperationJson(self.headers_json).key_get_data(self.env, "w_headers")
    def set_w_headers(self,s_token):
        OperationJson(self.headers_json).write_datas(s_token,self.env, "w_headers", "sToken")
    def set_w_headers_companyId(self,companyId):
        OperationJson(self.headers_json).write_datas(companyId,self.env, "w_headers", "T-Id")

三、統一登錄處理conftest.py

1、conftest.py源碼如下

  conftest文件之前的博客有講過,常用來處理用例的前置條件,文件名稱是pytest框架寫死的,即是在執行用例前框架會先執行一次conftest.py的代碼。

  框架思想:

  1)內部業務系統 儲如ABC,接口請求時header的token需要實時獲取,所以需要在接口請求前先完成登錄,並且將登錄後成功的token值set到headers.json裏相應json串對應的token字段,如此token便不會過期,永遠都是最新的,可看test_s_login函數處理。

  2)外部業務系統W,同理token需要取最新,以及接口請求頭的T-Id也是,所以需要在接口請求前先完成登錄,並且登錄成功後將最新的tooken,T-id值set到headers.json裏相應json串對應的token字段,可看test_w_login函數處理。

'''
@Date:2022/10/2  14:22
@Author:一加一
'''

import pytest
from tools.common import *
from tools.get_headerjson import GetHeaderjson
from conf.api_path import ApiPath
from tools.get_userjson import GetuserJson
from tools.get_wjson import *
'''處理登錄:統一登錄S、業務系統登錄W'''

# 實例化對象
api_path = ApiPath()
get_header = GetHeaderjson(None)
get_userinfo = GetuserJson(None)
get_wjson = GetwJson(None)


@pytest.fixture(scope="session",autouse=True)
def test_s_login():
    # s登錄:用戶名密碼登錄
    url = api_path.s_login_url #調用api_path方法獲取url
    headers = get_header.get_s_login_headers() #調用get_header獲取s系統接口請求頭
    data = get_userinfo.get_s_login_info() #調用get_userinfo獲取入參
    res_json = Common.r_post_form(url=url, headers=headers, data=data)
    # 獲取code
    code = res_json['data'].split('?')[-1]

    # 生成stoken
    res_json = Common.r_post_form(url=api_path.s_exchangeToken_url,headers=get_header.get_s_login_headers(),data=code)
    # 將生成的sToken寫入headers.json文件
    get_header.set_c_headers(res_json['data']['sToken'])
    get_header.set_p_headers(res_json['data']['sToken'])

@pytest.fixture(scope="session",autouse=True)
def test_w_login():
    # s登錄:用戶名密碼登錄
    url = api_path.s_login_url #調用api_path方法獲取url
    headers = get_header.get_s_login_headers() #調用get_header獲取s請求頭
    data = get_userinfo.get_w_login_info() #調用get_userinfo獲取入參
    res_json = Common.r_post_form(url=url, headers=headers, data=data)
    # 獲取code
    code = res_json['data'].split('?')[-1]

    # 生成stoken
    res_json = Common.r_post_form(url=api_path.s_exchangeToken_url,headers=get_header.get_s_login_headers(),data=code)
    # 將生成的sToken寫入headers.json文件
    get_header.set_w_headers(res_json['data']['sToken'])
    get_header.set_s_headers(res_json['data']['sToken'])

    # 查詢s系統員工列表獲取T-id寫入headers.json文件的T-Id
    res_json = Common.r_s_post(url=api_path.employee_paging_list,
                             headers=get_header.get_s_headers(),
                             json=get_wjson.get_w_companyId())
    # 將響應結果轉換成json格式
    rep_json = res_json.json()
    # 斷言
    Common.assert_s_code_message(rep_json)
    # 將生成的companyId寫入headers.json文件(w_headers對應的T-Id)
    TenantId = str(rep_json['data']['pageData'][0]['companyId'])
    get_header.set_w_headers_companyId(TenantId)

四、新建測試用例 testcase/test_case.py

  主要用於調試執行用例前是否會先處理conftest.py代碼,以及調試conftest.py的登錄代碼

'''
@Date:2022/11/12  13:35
@Author:一加一
'''

import allure

@allure.feature("測試業務")
@allure.story("測試訂單")
class TestCase:
    @allure.title("case1:獲取列表")
    def test_case1(self):
        with allure.step("step1:獲取列表"):
            print("測試第一步")
        with allure.step("step2:獲取響應結果"):
            print("測試第二步")

 五、執行test_case.py文件後,生成的日誌如下

  由日誌可知用例執行前會正確先執行conftest.py的代碼

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章