feat: 新增JoyHub协议管理和app版本号管理接口测试用例 #1

Merged
zhouqi merged 1 commits from dulizhan into master 2026-05-06 16:02:19 +08:00
5 changed files with 1015 additions and 3 deletions
Showing only changes of commit 354d17989a - Show all commits

View File

@@ -0,0 +1,153 @@
# -*- coding:utf-8 -*-
import os
import sys
current_file_path = os.path.abspath(__file__)
project_root = os.path.abspath(os.path.join(os.path.dirname(current_file_path), '../../../'))
if project_root not in sys.path:
sys.path.insert(0, project_root)
from dulizhan.library.Dlizhan_interface import DlzhanInterface
from base_framework.public_tools import log
import allure
obj_log = log.get_logger()
class AgreementManage(DlzhanInterface):
def __init__(self):
super().__init__()
@allure.step("创建协议")
def kw_joyhub_agreement_create_post(self, type, title, content, terminal="web", lang="en", rank_num=1, status=1, id=0):
"""
创建协议业务关键字
:param id: 主键新增为0
:param type: 类型1隐私协议 2用户协议
:param title: 标题
:param content: 内容
:param terminal: 终端(1web 2app)
:param lang: 语言 (en 英语 de 德语 ja 日语)
:param rank_num: 排序号
:param status: 状态 (1正常 2停用)
:return: 响应结果
"""
obj_log.info(f"创建协议 - type: {type}, title: {title}, content: {content[:50]}..., terminal: {terminal}, lang: {lang}, rank_num: {rank_num}, status: {status}")
params = {
"id": id,
"type": type,
"title": title,
"content": content,
"terminal": terminal,
"lang": lang,
"rankNum": rank_num,
"status": status
}
resp = self.kw_in_joyhub_agreement_create_post(**params)
obj_log.info(f"创建协议响应: {resp}")
return resp
@allure.step("删除协议")
def kw_joyhub_agreement_delete_delete(self, agreement_id):
"""
删除协议业务关键字
:param agreement_id: 协议ID
:return: 响应结果
"""
obj_log.info(f"删除协议 - agreement_id: {agreement_id}")
resp = self.kw_in_joyhub_agreement_delete_delete(agreement_id)
obj_log.info(f"删除协议响应: {resp}")
return resp
@allure.step("批量删除协议")
def kw_joyhub_agreement_delete_list_delete(self, agreement_ids):
"""
批量删除协议业务关键字
:param agreement_ids: 协议ID列表
:return: 响应结果
"""
obj_log.info(f"批量删除协议 - agreement_ids: {agreement_ids}")
resp = self.kw_in_joyhub_agreement_delete_list_delete(agreement_ids)
obj_log.info(f"批量删除协议响应: {resp}")
return resp
@allure.step("导出协议Excel")
def kw_joyhub_agreement_export_excel_get(self, **kwargs):
"""
导出协议Excel业务关键字
:param kwargs: 查询参数type, title, content, status
:return: 响应结果
"""
obj_log.info(f"导出协议Excel - 参数: {kwargs}")
resp = self.kw_in_joyhub_agreement_export_excel_get(**kwargs)
obj_log.info(f"导出协议Excel响应: {resp}")
return resp
@allure.step("获得协议详情")
def kw_joyhub_agreement_get_get(self, agreement_id):
"""
获得协议详情业务关键字
:param agreement_id: 协议ID
:return: 响应结果
"""
obj_log.info(f"获得协议详情 - agreement_id: {agreement_id}")
resp = self.kw_in_joyhub_agreement_get_get(agreement_id)
obj_log.info(f"获得协议详情响应: {resp}")
return resp
@allure.step("获得协议分页列表")
def kw_joyhub_agreement_page_get(self, **kwargs):
"""
获得协议分页列表业务关键字
:param kwargs: 查询参数type, title, content, status, page_no, page_size
:return: 响应结果
"""
obj_log.info(f"获得协议分页列表 - 参数: {kwargs}")
resp = self.kw_in_joyhub_agreement_page_get(**kwargs)
obj_log.info(f"获得协议分页列表响应: {resp}")
return resp
@allure.step("更新协议")
def kw_joyhub_agreement_update_put(self, agreement_id, type, title, content, terminal="web", lang="en", rank_num=1, status=1):
"""
更新协议业务关键字
:param agreement_id: 协议ID
:param type: 类型1隐私协议 2用户协议
:param title: 标题
:param content: 内容
:param terminal: 终端(1web 2app)
:param lang: 语言 (en 英语 de 德语 ja 日语)
:param rank_num: 排序号
:param status: 状态 (1正常 2停用)
:return: 响应结果
"""
obj_log.info(f"更新协议 - agreement_id: {agreement_id}, type: {type}, title: {title}, content: {content[:50]}..., terminal: {terminal}, lang: {lang}, rank_num: {rank_num}, status: {status}")
params = {
"id": agreement_id,
"type": type,
"title": title,
"content": content,
"terminal": terminal,
"lang": lang,
"rankNum": rank_num,
"status": status
}
resp = self.kw_in_joyhub_agreement_update_put(**params)
obj_log.info(f"更新协议响应: {resp}")
return resp

View File

@@ -0,0 +1,202 @@
import logging
import allure
from dulizhan.library.Dlizhan_interface import DlzhanInterface
obj_log = logging.getLogger("logger")
class AppVersionManage(DlzhanInterface):
def __init__(self):
super().__init__()
@allure.step("创建app版本号")
def kw_joyhub_appversion_create_post(self, store_name, version, download_url, is_on, status, id=0):
"""
创建app版本号管理业务关键字
:param id: 主键新增为0
:param store_name: 应用商店
:param version: 版本号
:param download_url: 商城下载地址
:param is_on: 是否上架1是2否
:param status: 状态 (1正常 2停用)
:return: 响应结果
"""
obj_log.info(f"创建app版本号 - storeName: {store_name}, version: {version}, downloadUrl: {download_url}, isOn: {is_on}, status: {status}")
params = {
"id": id,
"storeName": store_name,
"version": version,
"downloadUrl": download_url,
"isOn": is_on,
"status": status
}
resp = self.kw_in_joyhub_appversion_create_post(**params)
obj_log.info(f"创建app版本号响应: {resp}")
return resp
@allure.step("删除app版本号")
def kw_joyhub_appversion_delete_delete(self, appversion_id):
"""
删除app版本号管理业务关键字
:param appversion_id: app版本号编号
:return: 响应结果
"""
obj_log.info(f"删除app版本号 - id: {appversion_id}")
resp = self.kw_in_joyhub_appversion_delete_delete(appversion_id=appversion_id)
obj_log.info(f"删除app版本号响应: {resp}")
return resp
@allure.step("批量删除app版本号")
def kw_joyhub_appversion_delete_list_delete(self, appversion_ids):
"""
批量删除app版本号管理业务关键字
:param appversion_ids: app版本号编号列表
:return: 响应结果
"""
obj_log.info(f"批量删除app版本号 - ids: {appversion_ids}")
resp = self.kw_in_joyhub_appversion_delete_list_delete(ids=appversion_ids)
obj_log.info(f"批量删除app版本号响应: {resp}")
return resp
@allure.step("导出app版本号Excel")
def kw_joyhub_appversion_export_excel_get(self, page_no=1, page_size=10, **kwargs):
"""
导出app版本号管理 Excel业务关键字
:param page_no: 页码
:param page_size: 每页条数
:param store_name: 应用商店
:param version: 版本号
:param download_url: 商城下载地址
:param is_on: 是否上架
:param status: 状态
:return: 响应结果
"""
obj_log.info(f"导出app版本号Excel - pageNo: {page_no}, pageSize: {page_size}")
params = {
"pageNo": page_no,
"pageSize": page_size,
"storeName": kwargs.get("store_name", ""),
"version": kwargs.get("version", ""),
"downloadUrl": kwargs.get("download_url", ""),
"isOn": kwargs.get("is_on", ""),
"status": kwargs.get("status", "")
}
resp = self.kw_in_joyhub_appversion_export_excel_get(**params)
obj_log.info(f"导出app版本号Excel响应: {resp}")
return resp
@allure.step("获得app版本号详情")
def kw_joyhub_appversion_get_get(self, appversion_id):
"""
获得app版本号管理业务关键字
:param appversion_id: app版本号编号
:return: 响应结果
"""
obj_log.info(f"获得app版本号详情 - id: {appversion_id}")
resp = self.kw_in_joyhub_appversion_get_get(appversion_id=appversion_id)
obj_log.info(f"获得app版本号详情响应: {resp}")
return resp
@allure.step("获得导入app版本号模板")
def kw_joyhub_appversion_get_import_template_get(self):
"""
获得导入app版本号管理模板业务关键字
:return: 响应结果
"""
obj_log.info("获得导入app版本号模板")
resp = self.kw_in_joyhub_appversion_get_import_template_get()
obj_log.info(f"获得导入app版本号模板响应: {resp}")
return resp
@allure.step("导入app版本号Excel")
def kw_joyhub_appversion_import_excel_post(self, update_support, user_id=None):
"""
导入app版本号管理Excel业务关键字
:param update_support: 是否支持更新
:param user_id: 创建人-为空则取当前人
:return: 响应结果
"""
obj_log.info(f"导入app版本号Excel - updateSupport: {update_support}, userId: {user_id}")
params = {
"updateSupport": update_support
}
if user_id is not None:
params["userId"] = user_id
resp = self.kw_in_joyhub_appversion_import_excel_post(**params)
obj_log.info(f"导入app版本号Excel响应: {resp}")
return resp
@allure.step("获得app版本号分页列表")
def kw_joyhub_appversion_page_get(self, page_no=1, page_size=10, **kwargs):
"""
获得app版本号管理分页业务关键字
:param page_no: 页码
:param page_size: 每页条数
:param store_name: 应用商店
:param version: 版本号
:param download_url: 商城下载地址
:param is_on: 是否上架
:param status: 状态
:return: 响应结果
"""
obj_log.info(f"获得app版本号分页列表 - pageNo: {page_no}, pageSize: {page_size}")
params = {
"pageNo": page_no,
"pageSize": page_size,
"storeName": kwargs.get("store_name", ""),
"version": kwargs.get("version", ""),
"downloadUrl": kwargs.get("download_url", ""),
"isOn": kwargs.get("is_on", ""),
"status": kwargs.get("status", "")
}
resp = self.kw_in_joyhub_appversion_page_get(**params)
obj_log.info(f"获得app版本号分页列表响应: {resp}")
return resp
@allure.step("更新app版本号")
def kw_joyhub_appversion_update_put(self, appversion_id, store_name, version, download_url, is_on, status):
"""
更新app版本号管理业务关键字
:param appversion_id: 主键
:param store_name: 应用商店
:param version: 版本号
:param download_url: 商城下载地址
:param is_on: 是否上架1是2否
:param status: 状态 (1正常 2停用)
:return: 响应结果
"""
obj_log.info(f"更新app版本号 - id: {appversion_id}, storeName: {store_name}, version: {version}, downloadUrl: {download_url}, isOn: {is_on}, status: {status}")
params = {
"id": appversion_id,
"storeName": store_name,
"version": version,
"downloadUrl": download_url,
"isOn": is_on,
"status": status
}
resp = self.kw_in_joyhub_appversion_update_put(**params)
obj_log.info(f"更新app版本号响应: {resp}")
return resp

View File

@@ -39,7 +39,7 @@ class DlzhanInterface:
def set_joyhub_token(self, token): def set_joyhub_token(self, token):
self.token = token self.token = token
def _joyhub_request(self, method, path, is_check='', note='', **kwargs): def _joyhub_request(self, method, path, is_check='', note='', return_json=True, **kwargs):
url = "{}{}".format(self.joyhub_domain, path) url = "{}{}".format(self.joyhub_domain, path)
headers = self._get_joyhub_headers() headers = self._get_joyhub_headers()
obj_log.info("=========== {} ===========".format(note or path)) obj_log.info("=========== {} ===========".format(note or path))
@@ -58,7 +58,11 @@ class DlzhanInterface:
resp = req_map.get(method.upper(), lambda: None)() resp = req_map.get(method.upper(), lambda: None)()
self._check_resp(is_check, resp) self._check_resp(is_check, resp)
if return_json:
return resp.json() return resp.json()
else:
return resp
def _clear_user_fingerprint(self, username): def _clear_user_fingerprint(self, username):
try: try:
@@ -251,7 +255,7 @@ class DlzhanInterface:
return self._joyhub_request('DELETE', f'/admin-api/jh/banner/delete-list?ids={ids_str}', is_check, '批量删除Banner管理') return self._joyhub_request('DELETE', f'/admin-api/jh/banner/delete-list?ids={ids_str}', is_check, '批量删除Banner管理')
def kw_in_joyhub_banner_get_import_template_get(self, is_check=''): def kw_in_joyhub_banner_get_import_template_get(self, is_check=''):
return self._joyhub_request('GET', '/admin-api/jh/banner/get-import-template', is_check, '获得导入Banner管理模板') return self._joyhub_request('GET', '/admin-api/jh/banner/get-import-template', is_check, '获得导入Banner管理模板', return_json=False)
def kw_in_joyhub_banner_get_get(self, banner_id, is_check=''): def kw_in_joyhub_banner_get_get(self, banner_id, is_check=''):
return self._joyhub_request('GET', f'/admin-api/jh/banner/get?id={banner_id}', is_check, '获得Banner管理详情') return self._joyhub_request('GET', f'/admin-api/jh/banner/get?id={banner_id}', is_check, '获得Banner管理详情')
@@ -262,6 +266,35 @@ class DlzhanInterface:
def kw_in_joyhub_banner_update_put(self, is_check='', **kwargs): def kw_in_joyhub_banner_update_put(self, is_check='', **kwargs):
return self._joyhub_request('PUT', '/admin-api/jh/banner/update', is_check, '更新Banner管理', **kwargs) return self._joyhub_request('PUT', '/admin-api/jh/banner/update', is_check, '更新Banner管理', **kwargs)
# ============ app版本号管理接口 ============
def kw_in_joyhub_appversion_create_post(self, is_check='', **kwargs):
return self._joyhub_request('POST', '/admin-api/jh/appversion/create', is_check, '创建app版本号管理', **kwargs)
def kw_in_joyhub_appversion_delete_delete(self, appversion_id, is_check=''):
return self._joyhub_request('DELETE', f'/admin-api/jh/appversion/delete?id={appversion_id}', is_check, '删除app版本号管理')
def kw_in_joyhub_appversion_delete_list_delete(self, ids, is_check=''):
ids_str = ','.join(map(str, ids))
return self._joyhub_request('DELETE', f'/admin-api/jh/appversion/delete-list?ids={ids_str}', is_check, '批量删除app版本号管理')
def kw_in_joyhub_appversion_export_excel_get(self, is_check='', **kwargs):
return self._joyhub_request('GET', '/admin-api/jh/appversion/export-excel', is_check, '导出app版本号管理 Excel', return_json=False, **kwargs)
def kw_in_joyhub_appversion_get_get(self, appversion_id, is_check=''):
return self._joyhub_request('GET', f'/admin-api/jh/appversion/get?id={appversion_id}', is_check, '获得app版本号管理')
def kw_in_joyhub_appversion_get_import_template_get(self, is_check=''):
return self._joyhub_request('GET', '/admin-api/jh/appversion/get-import-template', is_check, '获得导入app版本号管理模板', return_json=False)
def kw_in_joyhub_appversion_import_excel_post(self, is_check='', **kwargs):
return self._joyhub_request('POST', '/admin-api/jh/appversion/import-excel', is_check, '导入app版本号管理Excel', **kwargs)
def kw_in_joyhub_appversion_page_get(self, is_check='', **kwargs):
return self._joyhub_request('GET', '/admin-api/jh/appversion/page', is_check, '获得app版本号管理分页', **kwargs)
def kw_in_joyhub_appversion_update_put(self, is_check='', **kwargs):
return self._joyhub_request('PUT', '/admin-api/jh/appversion/update', is_check, '更新app版本号管理', **kwargs)
def kw_in_joyhub_user_create_post(self, is_check='', **kwargs): def kw_in_joyhub_user_create_post(self, is_check='', **kwargs):
return self._joyhub_request('POST', '/admin-api/system/user/create', is_check, '创建用户', **kwargs) return self._joyhub_request('POST', '/admin-api/system/user/create', is_check, '创建用户', **kwargs)
@@ -330,6 +363,29 @@ class DlzhanInterface:
def kw_in_joyhub_dept_update_put(self, is_check='', **kwargs): def kw_in_joyhub_dept_update_put(self, is_check='', **kwargs):
return self._joyhub_request('PUT', '/admin-api/system/dept/update', is_check, '更新部门', **kwargs) return self._joyhub_request('PUT', '/admin-api/system/dept/update', is_check, '更新部门', **kwargs)
# ============ 协议管理接口 ============
def kw_in_joyhub_agreement_create_post(self, is_check='', **kwargs):
return self._joyhub_request('POST', '/admin-api/jh/agreement/create', is_check, '创建协议', **kwargs)
def kw_in_joyhub_agreement_delete_delete(self, agreement_id, is_check=''):
return self._joyhub_request('DELETE', f'/admin-api/jh/agreement/delete?id={agreement_id}', is_check, '删除协议')
def kw_in_joyhub_agreement_delete_list_delete(self, ids, is_check=''):
ids_str = ','.join(map(str, ids))
return self._joyhub_request('DELETE', f'/admin-api/jh/agreement/delete-list?ids={ids_str}', is_check, '批量删除协议')
def kw_in_joyhub_agreement_export_excel_get(self, is_check='', **kwargs):
return self._joyhub_request('GET', '/admin-api/jh/agreement/export-excel', is_check, '导出协议 Excel', return_json=False, **kwargs)
def kw_in_joyhub_agreement_get_get(self, agreement_id, is_check=''):
return self._joyhub_request('GET', f'/admin-api/jh/agreement/get?id={agreement_id}', is_check, '获得协议')
def kw_in_joyhub_agreement_page_get(self, is_check='', **kwargs):
return self._joyhub_request('GET', '/admin-api/jh/agreement/page', is_check, '获得协议分页', **kwargs)
def kw_in_joyhub_agreement_update_put(self, is_check='', **kwargs):
return self._joyhub_request('PUT', '/admin-api/jh/agreement/update', is_check, '更新协议', **kwargs)
if __name__ == '__main__': if __name__ == '__main__':
test = DlzhanInterface() test = DlzhanInterface()

View File

@@ -0,0 +1,299 @@
import pytest
import allure
import logging
import requests
import json
import time
from dulizhan.library.BusinessKw.JoyHub.AgreementManage import AgreementManage
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@allure.feature("管理后台 - 协议管理模块")
class TestAgreementManage:
agreement_id = None
token_set = False
@classmethod
def setup_class(cls):
"""在整个测试类开始时登录一次所有测试用例共享token"""
logging.info("=============================================")
logging.info("=========== 开始登录获取Token ============")
logging.info("=============================================")
cls.test_case = AgreementManage()
username = "joytest"
password = "Zhou1599"
cls.test_case._clear_user_fingerprint(username)
url = "https://joyhub-website-manager-api-test.best-envision.com/admin-api/system/auth/login-dev"
payload = {"username": username, "password": password}
headers = {'Content-Type': 'application/json', 'tenant-id': '126'}
try:
response = requests.post(url, json=payload, headers=headers, verify=False, timeout=10)
login_response = response.json()
if login_response and login_response.get('code') == 0:
token = login_response.get('data', {}).get('accessToken', '')
if token:
cls.test_case.set_joyhub_token(token)
cls.token_set = True
logging.info("登录成功获取到Token: {}...".format(token[:20]))
else:
logging.warning("登录成功但未获取到Token")
else:
logging.error("登录失败: {}".format(login_response))
except Exception as e:
logging.error("登录异常: {}".format(str(e)))
@allure.story("验证登录")
@allure.title("测试登录接口")
def test_joyhub_login_post(self):
"""测试登录接口"""
assert self.token_set is True, "登录失败Token未设置"
logging.info("登录验证通过Token已设置")
@allure.story("验证获得协议分页")
@allure.title("测试获得协议分页接口")
def test_joyhub_agreement_page_get(self):
"""测试获得协议分页接口"""
with allure.step("1. 准备请求参数"):
params = {
"page_no": 1,
"page_size": 10,
"type": "",
"title": "",
"content": "",
"status": ""
}
allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用接口"):
resp = self.test_case.kw_joyhub_agreement_page_get(**params)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert "list" in resp["data"], "响应中缺少list字段"
assert "total" in resp["data"], "响应中缺少total字段"
assert isinstance(resp["data"]["list"], list), "list字段不是列表类型"
assert isinstance(resp["data"]["total"], int), "total字段不是整数类型"
logging.info("获得协议分页列表验证通过")
@allure.story("验证创建协议")
@allure.title("测试创建协议接口")
def test_joyhub_agreement_create_post(self):
"""测试创建协议接口"""
with allure.step("1. 准备请求参数"):
timestamp = int(time.time())
params = {
"type": 1,
"title": f"测试协议_{timestamp}",
"content": f"这是测试协议内容_{timestamp}",
"terminal": "web",
"lang": "de",
"rank_num": timestamp % 1000,
"status": 2
}
allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用接口"):
resp = self.test_case.kw_joyhub_agreement_create_post(**params)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert isinstance(resp["data"], int), "data字段不是整数类型"
TestAgreementManage.agreement_id = resp["data"]
logging.info(f"创建协议成功协议ID: {TestAgreementManage.agreement_id}")
@allure.story("验证获得协议详情")
@allure.title("测试获得协议详情接口")
def test_joyhub_agreement_get_get(self):
"""测试获得协议详情接口"""
with allure.step("1. 先创建一个协议"):
timestamp = int(time.time())
create_resp = self.test_case.kw_joyhub_agreement_create_post(
type=2,
title=f"详情测试协议_{timestamp}",
content=f"详情测试协议内容_{timestamp}",
terminal="app",
lang="ja",
rank_num=(timestamp % 1000) + 1000,
status=1
)
agreement_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
if not agreement_id:
pytest.skip("创建测试协议失败,跳过详情测试")
allure.attach(json.dumps({"id": agreement_id}, ensure_ascii=False), name="协议ID", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用获得详情接口"):
resp = self.test_case.kw_joyhub_agreement_get_get(agreement_id=agreement_id)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert isinstance(resp["data"], dict), "data字段不是字典类型"
assert "id" in resp["data"], "响应中缺少id字段"
assert resp["data"]["id"] == agreement_id, "返回的ID与请求的不一致"
logging.info("获得协议详情验证通过")
@allure.story("验证更新协议")
@allure.title("测试更新协议接口")
def test_joyhub_agreement_update_put(self):
"""测试更新协议接口"""
with allure.step("1. 先创建一个协议"):
timestamp = int(time.time())
create_resp = self.test_case.kw_joyhub_agreement_create_post(
type=1,
title=f"待更新协议_{timestamp}",
content=f"待更新协议内容_{timestamp}",
terminal="app",
lang="de",
rank_num=(timestamp % 1000) + 2000,
status=1
)
agreement_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
if not agreement_id:
pytest.skip("创建测试协议失败,跳过更新测试")
allure.attach(json.dumps({"id": agreement_id}, ensure_ascii=False), name="协议ID", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用更新接口"):
timestamp = int(time.time())
update_params = {
"agreement_id": agreement_id,
"type": 2,
"title": f"已更新协议_{timestamp}",
"content": f"已更新协议内容_{timestamp}",
"terminal": "web",
"lang": "ja",
"rank_num": (timestamp % 1000) + 3000,
"status": 2
}
resp = self.test_case.kw_joyhub_agreement_update_put(**update_params)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert resp["data"] is True, "更新协议失败"
logging.info("更新协议验证通过")
@allure.story("验证删除协议")
@allure.title("测试删除协议接口")
def test_joyhub_agreement_delete_delete(self):
"""测试删除协议接口"""
with allure.step("1. 先创建一个测试协议"):
timestamp = int(time.time())
create_resp = self.test_case.kw_joyhub_agreement_create_post(
type=1,
title=f"待删除协议_{timestamp}",
content=f"待删除协议内容_{timestamp}",
terminal="web",
lang="ja",
rank_num=(timestamp % 1000) + 4000,
status=2
)
agreement_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
if not agreement_id:
pytest.skip("创建测试协议失败,跳过删除测试")
allure.attach(json.dumps({"id": agreement_id}, ensure_ascii=False), name="待删除协议ID", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用删除接口"):
resp = self.test_case.kw_joyhub_agreement_delete_delete(agreement_id=agreement_id)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert resp["data"] is True, "删除协议失败"
logging.info("删除协议验证通过")
@allure.story("验证批量删除协议")
@allure.title("测试批量删除协议接口")
def test_joyhub_agreement_delete_list_delete(self):
"""测试批量删除协议接口"""
with allure.step("1. 先创建两个测试协议"):
timestamp = int(time.time())
resp1 = self.test_case.kw_joyhub_agreement_create_post(
type=2,
title=f"批量删除协议1_{timestamp}",
content=f"批量删除协议内容1_{timestamp}",
terminal="app",
lang="de",
rank_num=(timestamp % 1000) + 5000,
status=2
)
resp2 = self.test_case.kw_joyhub_agreement_create_post(
type=1,
title=f"批量删除协议2_{timestamp}",
content=f"批量删除协议内容2_{timestamp}",
terminal="app",
lang="ja",
rank_num=(timestamp % 1000) + 6000,
status=2
)
agreement_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None
agreement_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None
if not agreement_id1 or not agreement_id2:
pytest.skip("创建测试协议失败,跳过批量删除测试")
agreement_ids = [agreement_id1, agreement_id2]
allure.attach(json.dumps({"ids": agreement_ids}, ensure_ascii=False), name="待删除协议IDs", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用批量删除接口"):
resp = self.test_case.kw_joyhub_agreement_delete_list_delete(agreement_ids=agreement_ids)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert resp["data"] is True, "批量删除协议失败"
logging.info("批量删除协议验证通过")
@allure.story("验证导出Excel")
@allure.title("测试导出协议Excel接口")
def test_joyhub_agreement_export_excel_get(self):
"""测试导出协议Excel接口"""
with allure.step("1. 准备请求参数"):
params = {
"type": "",
"title": "",
"content": "",
"status": ""
}
allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用导出Excel接口"):
resp = self.test_case.kw_joyhub_agreement_export_excel_get(**params)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert resp.status_code == 200, f"请求失败status_code={resp.status_code}"
assert len(resp.content) > 0, "响应内容为空"
logging.info("导出协议Excel验证通过")

View File

@@ -0,0 +1,302 @@
import pytest
import allure
import logging
import requests
import json
import time
from dulizhan.library.BusinessKw.JoyHub.AppVersionManage import AppVersionManage
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@allure.feature("管理后台 - app版本号管理模块")
class TestAppVersionManage:
appversion_id = None
token_set = False
@classmethod
def setup_class(cls):
"""在整个测试类开始时登录一次所有测试用例共享token"""
logging.info("=============================================")
logging.info("=========== 开始登录获取Token ============")
logging.info("=============================================")
cls.test_case = AppVersionManage()
username = "joytest"
password = "Zhou1599"
cls.test_case._clear_user_fingerprint(username)
url = "https://joyhub-website-manager-api-test.best-envision.com/admin-api/system/auth/login-dev"
payload = {"username": username, "password": password}
headers = {'Content-Type': 'application/json', 'tenant-id': '126'}
try:
response = requests.post(url, json=payload, headers=headers, verify=False, timeout=10)
login_response = response.json()
if login_response and login_response.get('code') == 0:
token = login_response.get('data', {}).get('accessToken', '')
if token:
cls.test_case.set_joyhub_token(token)
cls.token_set = True
logging.info("登录成功获取到Token: {}...".format(token[:20]))
else:
logging.warning("登录成功但未获取到Token")
else:
logging.error("登录失败: {}".format(login_response))
except Exception as e:
logging.error("登录异常: {}".format(str(e)))
@allure.story("验证登录")
@allure.title("测试登录接口")
def test_joyhub_login_post(self):
"""测试登录接口"""
assert self.token_set is True, "登录失败Token未设置"
logging.info("登录验证通过Token已设置")
@allure.story("验证获得app版本号分页")
@allure.title("测试获得app版本号管理分页接口")
def test_joyhub_appversion_page_get(self):
"""测试获得app版本号管理分页接口"""
with allure.step("1. 准备请求参数"):
params = {
"page_no": 1,
"page_size": 10,
"store_name": "",
"version": "",
"download_url": "",
"is_on": "",
"status": ""
}
allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用接口"):
resp = self.test_case.kw_joyhub_appversion_page_get(**params)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert "list" in resp["data"], "响应中缺少list字段"
assert "total" in resp["data"], "响应中缺少total字段"
assert isinstance(resp["data"]["list"], list), "list字段不是列表类型"
assert isinstance(resp["data"]["total"], int), "total字段不是整数类型"
logging.info("获得app版本号分页列表验证通过")
@allure.story("验证创建app版本号")
@allure.title("测试创建app版本号管理接口")
def test_joyhub_appversion_create_post(self):
"""测试创建app版本号管理接口"""
with allure.step("1. 准备请求参数"):
timestamp = int(time.time())
params = {
"store_name": "App Store",
"version": f"1.0.{timestamp % 1000}",
"download_url": "https://www.example.com/download",
"is_on": 1,
"status": 1
}
allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用接口"):
resp = self.test_case.kw_joyhub_appversion_create_post(**params)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert isinstance(resp["data"], int), "data字段不是整数类型"
TestAppVersionManage.appversion_id = resp["data"]
logging.info(f"创建app版本号成功app版本号ID: {TestAppVersionManage.appversion_id}")
@allure.story("验证获得app版本号详情")
@allure.title("测试获得app版本号详情接口")
def test_joyhub_appversion_get_get(self):
"""测试获得app版本号详情接口"""
with allure.step("1. 先创建一个app版本号"):
timestamp = int(time.time())
create_resp = self.test_case.kw_joyhub_appversion_create_post(
store_name="Google Play",
version=f"2.0.{timestamp % 1000}",
download_url="https://www.example.com/download",
is_on=1,
status=1
)
appversion_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
if not appversion_id:
pytest.skip("创建测试app版本号失败跳过详情测试")
allure.attach(json.dumps({"id": appversion_id}, ensure_ascii=False), name="app版本号 ID", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用获得详情接口"):
resp = self.test_case.kw_joyhub_appversion_get_get(appversion_id=appversion_id)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert isinstance(resp["data"], dict), "data字段不是字典类型"
assert "id" in resp["data"], "响应中缺少id字段"
assert resp["data"]["id"] == appversion_id, "返回的ID与请求的不一致"
logging.info("获得app版本号详情验证通过")
@allure.story("验证更新app版本号")
@allure.title("测试更新app版本号管理接口")
def test_joyhub_appversion_update_put(self):
"""测试更新app版本号管理接口"""
with allure.step("1. 先创建一个app版本号"):
timestamp = int(time.time())
create_resp = self.test_case.kw_joyhub_appversion_create_post(
store_name="Huawei Store",
version=f"3.0.{timestamp % 1000}",
download_url="https://www.example.com/download",
is_on=1,
status=1
)
appversion_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
if not appversion_id:
pytest.skip("创建测试app版本号失败跳过更新测试")
allure.attach(json.dumps({"id": appversion_id}, ensure_ascii=False), name="app版本号 ID", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用更新接口"):
timestamp = int(time.time())
update_params = {
"appversion_id": appversion_id,
"store_name": "Updated Store",
"version": f"4.0.{timestamp % 1000}",
"download_url": "https://www.updated-example.com/download",
"is_on": 2,
"status": 2
}
resp = self.test_case.kw_joyhub_appversion_update_put(**update_params)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert resp["data"] is True, "更新app版本号失败"
logging.info("更新app版本号验证通过")
@allure.story("验证删除app版本号")
@allure.title("测试删除app版本号管理接口")
def test_joyhub_appversion_delete_delete(self):
"""测试删除app版本号管理接口"""
with allure.step("1. 先创建一个测试app版本号"):
timestamp = int(time.time())
create_resp = self.test_case.kw_joyhub_appversion_create_post(
store_name="Test Store",
version=f"5.0.{timestamp % 1000}",
download_url="https://www.example.com/download",
is_on=1,
status=2
)
appversion_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None
if not appversion_id:
pytest.skip("创建测试app版本号失败跳过删除测试")
allure.attach(json.dumps({"id": appversion_id}, ensure_ascii=False), name="待删除app版本号 ID", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用删除接口"):
resp = self.test_case.kw_joyhub_appversion_delete_delete(appversion_id=appversion_id)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert resp["data"] is True, "删除app版本号失败"
logging.info("删除app版本号验证通过")
@allure.story("验证批量删除app版本号")
@allure.title("测试批量删除app版本号管理接口")
def test_joyhub_appversion_delete_list_delete(self):
"""测试批量删除app版本号管理接口"""
with allure.step("1. 先创建两个测试app版本号"):
timestamp = int(time.time())
resp1 = self.test_case.kw_joyhub_appversion_create_post(
store_name="Batch Store 1",
version=f"6.0.{timestamp % 1000}",
download_url="https://www.example.com/download",
is_on=1,
status=2
)
resp2 = self.test_case.kw_joyhub_appversion_create_post(
store_name="Batch Store 2",
version=f"7.0.{timestamp % 1000 + 1}",
download_url="https://www.example.com/download",
is_on=1,
status=2
)
appversion_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None
appversion_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None
if not appversion_id1 or not appversion_id2:
pytest.skip("创建测试app版本号失败跳过批量删除测试")
appversion_ids = [appversion_id1, appversion_id2]
allure.attach(json.dumps({"ids": appversion_ids}, ensure_ascii=False), name="待删除app版本号 IDs", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用批量删除接口"):
resp = self.test_case.kw_joyhub_appversion_delete_list_delete(appversion_ids=appversion_ids)
allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert "code" in resp, "响应中缺少code字段"
assert resp["code"] == 0, f"请求失败code={resp.get('code')}"
assert "data" in resp, "响应中缺少data字段"
assert resp["data"] is True, "批量删除app版本号失败"
logging.info("批量删除app版本号验证通过")
@allure.story("验证获得导入模板")
@allure.title("测试获得导入app版本号管理模板接口")
def test_joyhub_appversion_get_import_template_get(self):
"""测试获得导入app版本号管理模板接口"""
with allure.step("1. 调用获得导入模板接口"):
resp = self.test_case.kw_joyhub_appversion_get_import_template_get()
with allure.step("2. 验证响应"):
assert resp is not None, "响应为空"
assert resp.status_code == 200, f"请求失败status_code={resp.status_code}"
assert len(resp.content) > 0, "响应内容为空"
logging.info("获得导入app版本号模板验证通过")
@allure.story("验证导出Excel")
@allure.title("测试导出app版本号管理Excel接口")
def test_joyhub_appversion_export_excel_get(self):
"""测试导出app版本号管理Excel接口"""
with allure.step("1. 准备请求参数"):
params = {
"page_no": 1,
"page_size": 10,
"store_name": "",
"version": "",
"download_url": "",
"is_on": "",
"status": ""
}
allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT)
with allure.step("2. 调用导出Excel接口"):
resp = self.test_case.kw_joyhub_appversion_export_excel_get(**params)
with allure.step("3. 验证响应"):
assert resp is not None, "响应为空"
assert resp.status_code == 200, f"请求失败status_code={resp.status_code}"
assert len(resp.content) > 0, "响应内容为空"
logging.info("导出app版本号Excel验证通过")