From 32fd51380c1025f59ae597156626f02bb1b4474d Mon Sep 17 00:00:00 2001 From: zhouqi Date: Wed, 6 May 2026 17:16:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=94=AE=E5=90=8E?= =?UTF-8?q?=E6=94=BF=E7=AD=96=E7=AE=A1=E7=90=86=E6=8E=A5=E5=8F=A3=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增售后政策管理接口方法到 Dlizhan_interface.py - 新增 AfterSalesPolicyManage.py 业务关键字层 - 新增 Joyhub_AfterSalesPolicy.py 测试用例文件 - 修复 Jenkins Allure 报告路径配置问题 --- .../JoyHub/AfterSalesPolicyManage.py | 252 ++++++++ dulizhan/library/Dlizhan_interface.py | 43 ++ .../接口/JoyHub/Joyhub_AfterSalesPolicy.py | 552 ++++++++++++++++++ dulizhan/test_case/run_tests.py | 12 +- 4 files changed, 854 insertions(+), 5 deletions(-) create mode 100644 dulizhan/library/BusinessKw/JoyHub/AfterSalesPolicyManage.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AfterSalesPolicy.py diff --git a/dulizhan/library/BusinessKw/JoyHub/AfterSalesPolicyManage.py b/dulizhan/library/BusinessKw/JoyHub/AfterSalesPolicyManage.py new file mode 100644 index 0000000..ab234c3 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/AfterSalesPolicyManage.py @@ -0,0 +1,252 @@ +# -*- 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 AfterSalesPolicyManage(DlzhanInterface): + def __init__(self): + super().__init__() + + # ============ 售后政策管理 ============ + + @allure.step("创建售后政策") + def kw_joyhub_after_sales_policy_create_post(self, title, content, lang, brand_id=0, status=1, id=0): + """ + 创建售后政策业务关键字 + :param id: 主键,新增为0 + :param brand_id: 品牌ID + :param title: 标题 + :param content: 内容 + :param lang: 语言 (en 英语 de 德语 ja 日语) + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"创建售后政策 - title: {title}, content: {content[:50]}..., lang: {lang}, brand_id: {brand_id}, status: {status}") + + params = { + "id": id, + "brandId": brand_id, + "title": title, + "content": content, + "lang": lang, + "status": status + } + + resp = self.kw_in_joyhub_after_sales_policy_create_post(**params) + obj_log.info(f"创建售后政策响应: {resp}") + + return resp + + @allure.step("删除售后政策") + def kw_joyhub_after_sales_policy_delete_delete(self, policy_id): + """ + 删除售后政策业务关键字 + :param policy_id: 售后政策ID + :return: 响应结果 + """ + obj_log.info(f"删除售后政策 - policy_id: {policy_id}") + + resp = self.kw_in_joyhub_after_sales_policy_delete_delete(policy_id) + obj_log.info(f"删除售后政策响应: {resp}") + + return resp + + @allure.step("批量删除售后政策") + def kw_joyhub_after_sales_policy_delete_list_delete(self, policy_ids): + """ + 批量删除售后政策业务关键字 + :param policy_ids: 售后政策ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除售后政策 - policy_ids: {policy_ids}") + + resp = self.kw_in_joyhub_after_sales_policy_delete_list_delete(policy_ids) + obj_log.info(f"批量删除售后政策响应: {resp}") + + return resp + + @allure.step("获得售后政策详情") + def kw_joyhub_after_sales_policy_get_get(self, policy_id): + """ + 获得售后政策详情业务关键字 + :param policy_id: 售后政策ID + :return: 响应结果 + """ + obj_log.info(f"获得售后政策详情 - policy_id: {policy_id}") + + resp = self.kw_in_joyhub_after_sales_policy_get_get(policy_id) + obj_log.info(f"获得售后政策详情响应: {resp}") + + return resp + + @allure.step("获得售后政策分页列表") + def kw_joyhub_after_sales_policy_page_get(self, **kwargs): + """ + 获得售后政策分页列表业务关键字 + :param kwargs: 查询参数(title, content, status, page_no, page_size) + :return: 响应结果 + """ + obj_log.info(f"获得售后政策分页列表 - 参数: {kwargs}") + + resp = self.kw_in_joyhub_after_sales_policy_page_get(**kwargs) + obj_log.info(f"获得售后政策分页列表响应: {resp}") + + return resp + + @allure.step("更新售后政策") + def kw_joyhub_after_sales_policy_update_put(self, policy_id, title, content, lang, brand_id=0, status=1): + """ + 更新售后政策业务关键字 + :param policy_id: 售后政策ID + :param brand_id: 品牌ID + :param title: 标题 + :param content: 内容 + :param lang: 语言 (en 英语 de 德语 ja 日语) + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"更新售后政策 - policy_id: {policy_id}, title: {title}, content: {content[:50]}..., lang: {lang}, brand_id: {brand_id}, status: {status}") + + params = { + "id": policy_id, + "brandId": brand_id, + "title": title, + "content": content, + "lang": lang, + "status": status + } + + resp = self.kw_in_joyhub_after_sales_policy_update_put(**params) + obj_log.info(f"更新售后政策响应: {resp}") + + return resp + + # ============ 售后政策-品牌管理 ============ + + @allure.step("创建售后政策-品牌") + def kw_joyhub_after_sales_brand_create_post(self, brand_name, after_sales_policy_id, status=1, id=0): + """ + 创建售后政策-品牌业务关键字 + :param id: 主键,新增为0 + :param brand_name: 品牌名称 + :param after_sales_policy_id: 售后政策ID + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"创建售后政策-品牌 - brand_name: {brand_name}, after_sales_policy_id: {after_sales_policy_id}, status: {status}") + + params = { + "id": id, + "brandName": brand_name, + "afterSalesPolicyId": after_sales_policy_id, + "status": status + } + + resp = self.kw_in_joyhub_after_sales_brand_create_post(**params) + obj_log.info(f"创建售后政策-品牌响应: {resp}") + + return resp + + @allure.step("删除售后政策-品牌") + def kw_joyhub_after_sales_brand_delete_delete(self, brand_id): + """ + 删除售后政策-品牌业务关键字 + :param brand_id: 售后政策-品牌ID + :return: 响应结果 + """ + obj_log.info(f"删除售后政策-品牌 - brand_id: {brand_id}") + + resp = self.kw_in_joyhub_after_sales_brand_delete_delete(brand_id) + obj_log.info(f"删除售后政策-品牌响应: {resp}") + + return resp + + @allure.step("批量删除售后政策-品牌") + def kw_joyhub_after_sales_brand_delete_list_delete(self, brand_ids): + """ + 批量删除售后政策-品牌业务关键字 + :param brand_ids: 售后政策-品牌ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除售后政策-品牌 - brand_ids: {brand_ids}") + + resp = self.kw_in_joyhub_after_sales_brand_delete_list_delete(brand_ids) + obj_log.info(f"批量删除售后政策-品牌响应: {resp}") + + return resp + + @allure.step("获得售后政策-品牌详情") + def kw_joyhub_after_sales_brand_get_get(self, brand_id): + """ + 获得售后政策-品牌详情业务关键字 + :param brand_id: 售后政策-品牌ID + :return: 响应结果 + """ + obj_log.info(f"获得售后政策-品牌详情 - brand_id: {brand_id}") + + resp = self.kw_in_joyhub_after_sales_brand_get_get(brand_id) + obj_log.info(f"获得售后政策-品牌详情响应: {resp}") + + return resp + + @allure.step("获得可用的品牌列表") + def kw_joyhub_after_sales_brand_list_available_get(self): + """ + 获得可用的品牌列表业务关键字 + :return: 响应结果 + """ + obj_log.info("获得可用的品牌列表") + + resp = self.kw_in_joyhub_after_sales_brand_list_available_get() + obj_log.info(f"获得可用的品牌列表响应: {resp}") + + return resp + + @allure.step("获得售后政策-品牌分页列表") + def kw_joyhub_after_sales_brand_page_get(self, **kwargs): + """ + 获得售后政策-品牌分页列表业务关键字 + :param kwargs: 查询参数(brand_name, after_sales_policy_id, status, page_no, page_size) + :return: 响应结果 + """ + obj_log.info(f"获得售后政策-品牌分页列表 - 参数: {kwargs}") + + resp = self.kw_in_joyhub_after_sales_brand_page_get(**kwargs) + obj_log.info(f"获得售后政策-品牌分页列表响应: {resp}") + + return resp + + @allure.step("更新售后政策-品牌") + def kw_joyhub_after_sales_brand_update_put(self, brand_id, brand_name, after_sales_policy_id, status=1): + """ + 更新售后政策-品牌业务关键字 + :param brand_id: 售后政策-品牌ID + :param brand_name: 品牌名称 + :param after_sales_policy_id: 售后政策ID + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"更新售后政策-品牌 - brand_id: {brand_id}, brand_name: {brand_name}, after_sales_policy_id: {after_sales_policy_id}, status: {status}") + + params = { + "id": brand_id, + "brandName": brand_name, + "afterSalesPolicyId": after_sales_policy_id, + "status": status + } + + resp = self.kw_in_joyhub_after_sales_brand_update_put(**params) + obj_log.info(f"更新售后政策-品牌响应: {resp}") + + return resp \ No newline at end of file diff --git a/dulizhan/library/Dlizhan_interface.py b/dulizhan/library/Dlizhan_interface.py index 1fce889..8b71c6d 100644 --- a/dulizhan/library/Dlizhan_interface.py +++ b/dulizhan/library/Dlizhan_interface.py @@ -386,6 +386,49 @@ class DlzhanInterface: def kw_in_joyhub_agreement_update_put(self, is_check='', **kwargs): return self._joyhub_request('PUT', '/admin-api/jh/agreement/update', is_check, '更新协议', **kwargs) + # ============ 售后政策管理接口 ============ + def kw_in_joyhub_after_sales_policy_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/after-sales-policy/create', is_check, '创建售后政策', **kwargs) + + def kw_in_joyhub_after_sales_policy_delete_delete(self, policy_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/after-sales-policy/delete?id={policy_id}', is_check, '删除售后政策') + + def kw_in_joyhub_after_sales_policy_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/after-sales-policy/delete-list?ids={ids_str}', is_check, '批量删除售后政策') + + def kw_in_joyhub_after_sales_policy_get_get(self, policy_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/after-sales-policy/get?id={policy_id}', is_check, '获得售后政策') + + def kw_in_joyhub_after_sales_policy_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/after-sales-policy/page', is_check, '获得售后政策分页', **kwargs) + + def kw_in_joyhub_after_sales_policy_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/after-sales-policy/update', is_check, '更新售后政策', **kwargs) + + # ============ 售后政策-品牌管理接口 ============ + def kw_in_joyhub_after_sales_brand_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/after-sales-brand/create', is_check, '创建售后政策-品牌', **kwargs) + + def kw_in_joyhub_after_sales_brand_delete_delete(self, brand_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/after-sales-brand/delete?id={brand_id}', is_check, '删除售后政策-品牌') + + def kw_in_joyhub_after_sales_brand_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/after-sales-brand/delete-list?ids={ids_str}', is_check, '批量删除售后政策-品牌') + + def kw_in_joyhub_after_sales_brand_get_get(self, brand_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/after-sales-brand/get?id={brand_id}', is_check, '获得售后政策-品牌') + + def kw_in_joyhub_after_sales_brand_list_available_get(self, is_check=''): + return self._joyhub_request('GET', '/admin-api/jh/after-sales-brand/list-available', is_check, '获得可用的品牌列表') + + def kw_in_joyhub_after_sales_brand_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/after-sales-brand/page', is_check, '获得售后政策-品牌分页', **kwargs) + + def kw_in_joyhub_after_sales_brand_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/after-sales-brand/update', is_check, '更新售后政策-品牌', **kwargs) + if __name__ == '__main__': test = DlzhanInterface() diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AfterSalesPolicy.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AfterSalesPolicy.py new file mode 100644 index 0000000..7223215 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AfterSalesPolicy.py @@ -0,0 +1,552 @@ +import pytest +import allure +import logging +import requests +import json +import time +from dulizhan.library.BusinessKw.JoyHub.AfterSalesPolicyManage import AfterSalesPolicyManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 售后政策管理模块") +class TestAfterSalesPolicyManage: + policy_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = AfterSalesPolicyManage() + 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_after_sales_policy_page_get(self): + """测试获得售后政策分页接口""" + with allure.step("1. 准备请求参数"): + params = { + "page_no": 1, + "page_size": 10, + "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_after_sales_policy_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_after_sales_policy_create_and_update(self): + """测试创建和更新售后政策接口""" + with allure.step("1. 先创建一个新品牌供售后政策使用"): + timestamp = int(time.time()) + create_brand_resp = self.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"测试品牌_售后政策_{timestamp}", + after_sales_policy_id=0, + status=1 + ) + if create_brand_resp and create_brand_resp.get("code") == 0: + brand_id = create_brand_resp.get("data") + logging.info(f"创建测试品牌成功,品牌ID: {brand_id}") + else: + pytest.skip(f"创建测试品牌失败: {create_brand_resp}") + + allure.attach(json.dumps({"brand_id": brand_id}, ensure_ascii=False), name="品牌ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 准备创建请求参数"): + params = { + "title": f"测试售后政策_{timestamp}", + "content": f"这是测试售后政策内容_{timestamp}", + "lang": "de", + "brand_id": brand_id, + "status": 1 + } + allure.attach(json.dumps(params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + with allure.step("3. 调用创建接口"): + resp = self.test_case.kw_joyhub_after_sales_policy_create_post(**params) + allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + with allure.step("4. 验证创建响应"): + 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字段不是整数类型" + policy_id = resp["data"] + TestAfterSalesPolicyManage.policy_id = policy_id + logging.info(f"创建售后政策成功,售后政策ID: {policy_id}") + + with allure.step("5. 调用更新接口"): + update_timestamp = int(time.time()) + update_params = { + "policy_id": policy_id, + "title": f"已更新售后政策_{update_timestamp}", + "content": f"已更新售后政策内容_{update_timestamp}", + "lang": "ja", + "brand_id": brand_id, + "status": 2 + } + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_after_sales_policy_update_put(**update_params) + allure.attach(json.dumps(update_resp, ensure_ascii=False, indent=2), name="更新响应数据", attachment_type=allure.attachment_type.JSON) + + with allure.step("6. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"请求失败,code={update_resp.get('code')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新售后政策失败" + logging.info("更新售后政策验证通过") + + @allure.story("验证获得售后政策详情") + @allure.title("测试获得售后政策详情接口") + def test_joyhub_after_sales_policy_get_get(self): + """测试获得售后政策详情接口""" + with allure.step("1. 先创建一个售后政策"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_after_sales_policy_create_post( + title=f"详情测试售后政策_{timestamp}", + content=f"详情测试售后政策内容_{timestamp}", + lang="ja", + brand_id=12, + status=2 + ) + policy_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not policy_id: + pytest.skip("创建测试售后政策失败,跳过详情测试") + + allure.attach(json.dumps({"id": policy_id}, ensure_ascii=False), name="售后政策ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用获得详情接口"): + resp = self.test_case.kw_joyhub_after_sales_policy_get_get(policy_id=policy_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"] == policy_id, "返回的ID与请求的不一致" + logging.info("获得售后政策详情验证通过") + + @allure.story("验证删除售后政策") + @allure.title("测试删除售后政策接口") + def test_joyhub_after_sales_policy_delete_delete(self): + """测试删除售后政策接口""" + with allure.step("1. 先创建一个测试售后政策"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_after_sales_policy_create_post( + title=f"待删除售后政策_{timestamp}", + content=f"待删除售后政策内容_{timestamp}", + lang="en", + brand_id=12, + status=2 + ) + policy_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not policy_id: + pytest.skip("创建测试售后政策失败,跳过删除测试") + + allure.attach(json.dumps({"id": policy_id}, ensure_ascii=False), name="待删除售后政策ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用删除接口"): + resp = self.test_case.kw_joyhub_after_sales_policy_delete_delete(policy_id=policy_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_after_sales_policy_delete_list_delete(self): + """测试批量删除售后政策接口""" + with allure.step("1. 先创建两个测试售后政策"): + timestamp = int(time.time()) + resp1 = self.test_case.kw_joyhub_after_sales_policy_create_post( + title=f"批量删除售后政策1_{timestamp}", + content=f"批量删除售后政策内容1_{timestamp}", + lang="de", + brand_id=12, + status=2 + ) + resp2 = self.test_case.kw_joyhub_after_sales_policy_create_post( + title=f"批量删除售后政策2_{timestamp}", + content=f"批量删除售后政策内容2_{timestamp}", + lang="ja", + brand_id=12, + status=2 + ) + + policy_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None + policy_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None + + if not policy_id1 or not policy_id2: + pytest.skip("创建测试售后政策失败,跳过批量删除测试") + + policy_ids = [policy_id1, policy_id2] + allure.attach(json.dumps({"ids": policy_ids}, ensure_ascii=False), name="待删除售后政策IDs", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用批量删除接口"): + resp = self.test_case.kw_joyhub_after_sales_policy_delete_list_delete(policy_ids=policy_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.feature("管理后台 - 售后政策-品牌管理模块") +class TestAfterSalesBrandManage: + brand_id = None + policy_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = AfterSalesPolicyManage() + 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))) + + # 创建一个售后政策供品牌测试使用 + if cls.token_set: + timestamp = int(time.time()) + # 先创建一个新品牌,确保没有活跃的售后政策 + create_brand_resp = cls.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"品牌测试专用_{timestamp}", + after_sales_policy_id=0, + status=1 + ) + if create_brand_resp and create_brand_resp.get("code") == 0: + brand_id = create_brand_resp.get("data") + logging.info(f"创建测试品牌成功,品牌ID: {brand_id}") + + # 使用新创建的品牌创建售后政策 + create_resp = cls.test_case.kw_joyhub_after_sales_policy_create_post( + title=f"品牌测试售后政策_{timestamp}", + content=f"品牌测试售后政策内容_{timestamp}", + lang="en", + brand_id=brand_id, + status=1 + ) + if create_resp and create_resp.get("code") == 0: + cls.policy_id = create_resp.get("data") + logging.info(f"创建测试售后政策成功,ID: {cls.policy_id}") + else: + logging.warning(f"创建售后政策失败: {create_resp}") + else: + logging.warning(f"创建测试品牌失败: {create_brand_resp}") + + @allure.story("验证获得售后政策-品牌分页") + @allure.title("测试获得售后政策-品牌分页接口") + def test_joyhub_after_sales_brand_page_get(self): + """测试获得售后政策-品牌分页接口""" + with allure.step("1. 准备请求参数"): + params = { + "page_no": 1, + "page_size": 10, + "brand_name": "", + "after_sales_policy_id": "", + "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_after_sales_brand_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_after_sales_brand_create_post(self): + """测试创建售后政策-品牌接口""" + if not self.policy_id: + pytest.skip("未创建测试售后政策,跳过品牌创建测试") + + with allure.step("1. 准备请求参数"): + timestamp = int(time.time()) + params = { + "brand_name": f"测试品牌_{timestamp}", + "after_sales_policy_id": self.policy_id, + "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_after_sales_brand_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字段不是整数类型" + TestAfterSalesBrandManage.brand_id = resp["data"] + logging.info(f"创建售后政策-品牌成功,品牌ID: {TestAfterSalesBrandManage.brand_id}") + + @allure.story("验证获得售后政策-品牌详情") + @allure.title("测试获得售后政策-品牌详情接口") + def test_joyhub_after_sales_brand_get_get(self): + """测试获得售后政策-品牌详情接口""" + if not self.policy_id: + pytest.skip("未创建测试售后政策,跳过品牌详情测试") + + with allure.step("1. 先创建一个售后政策-品牌"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"详情测试品牌_{timestamp}", + after_sales_policy_id=self.policy_id, + status=2 + ) + brand_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not brand_id: + pytest.skip("创建测试品牌失败,跳过详情测试") + + allure.attach(json.dumps({"id": brand_id}, ensure_ascii=False), name="售后政策-品牌ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用获得详情接口"): + resp = self.test_case.kw_joyhub_after_sales_brand_get_get(brand_id=brand_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"] == brand_id, "返回的ID与请求的不一致" + logging.info("获得售后政策-品牌详情验证通过") + + @allure.story("验证更新售后政策-品牌") + @allure.title("测试更新售后政策-品牌接口") + def test_joyhub_after_sales_brand_update_put(self): + """测试更新售后政策-品牌接口""" + if not self.policy_id: + pytest.skip("未创建测试售后政策,跳过品牌更新测试") + + with allure.step("1. 先创建一个售后政策-品牌"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"待更新品牌_{timestamp}", + after_sales_policy_id=self.policy_id, + status=1 + ) + brand_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not brand_id: + pytest.skip("创建测试品牌失败,跳过更新测试") + + allure.attach(json.dumps({"id": brand_id}, ensure_ascii=False), name="售后政策-品牌ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "brand_id": brand_id, + "brand_name": f"已更新品牌_{timestamp}", + "after_sales_policy_id": self.policy_id, + "status": 2 + } + resp = self.test_case.kw_joyhub_after_sales_brand_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_after_sales_brand_delete_delete(self): + """测试删除售后政策-品牌接口""" + if not self.policy_id: + pytest.skip("未创建测试售后政策,跳过品牌删除测试") + + with allure.step("1. 先创建一个测试售后政策-品牌"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"待删除品牌_{timestamp}", + after_sales_policy_id=self.policy_id, + status=2 + ) + brand_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not brand_id: + pytest.skip("创建测试品牌失败,跳过删除测试") + + allure.attach(json.dumps({"id": brand_id}, ensure_ascii=False), name="待删除品牌ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用删除接口"): + resp = self.test_case.kw_joyhub_after_sales_brand_delete_delete(brand_id=brand_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_after_sales_brand_delete_list_delete(self): + """测试批量删除售后政策-品牌接口""" + if not self.policy_id: + pytest.skip("未创建测试售后政策,跳过批量删除品牌测试") + + with allure.step("1. 先创建两个测试售后政策-品牌"): + timestamp = int(time.time()) + resp1 = self.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"批量删除品牌1_{timestamp}", + after_sales_policy_id=self.policy_id, + status=2 + ) + resp2 = self.test_case.kw_joyhub_after_sales_brand_create_post( + brand_name=f"批量删除品牌2_{timestamp}", + after_sales_policy_id=self.policy_id, + status=2 + ) + + brand_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None + brand_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None + + if not brand_id1 or not brand_id2: + pytest.skip("创建测试品牌失败,跳过批量删除测试") + + brand_ids = [brand_id1, brand_id2] + allure.attach(json.dumps({"ids": brand_ids}, ensure_ascii=False), name="待删除品牌IDs", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用批量删除接口"): + resp = self.test_case.kw_joyhub_after_sales_brand_delete_list_delete(brand_ids=brand_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("验证获得可用的品牌列表") + @allure.title("测试获得可用的品牌列表接口") + def test_joyhub_after_sales_brand_list_available_get(self): + """测试获得可用的品牌列表接口""" + with allure.step("1. 调用接口"): + resp = self.test_case.kw_joyhub_after_sales_brand_list_available_get() + allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON) + + with allure.step("2. 验证响应"): + 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"], list), "data字段不是列表类型" + logging.info("获得可用的品牌列表验证通过") \ No newline at end of file diff --git a/dulizhan/test_case/run_tests.py b/dulizhan/test_case/run_tests.py index 9cd9de0..efb93ac 100644 --- a/dulizhan/test_case/run_tests.py +++ b/dulizhan/test_case/run_tests.py @@ -22,8 +22,8 @@ case_dir = os.path.join(project_root, TEST_CASE_DIR) # 报告目录 REPORT_DIR = os.path.join(os.path.dirname(current_file_path), 'reports') -ALLURE_RESULTS_DIR = os.path.join(REPORT_DIR, 'allure-results') -ALLURE_REPORT_DIR = os.path.join(REPORT_DIR, 'allure-report') +ALLURE_RESULTS_DIR = os.path.join(project_root, 'allure-results') +ALLURE_REPORT_DIR = os.path.join(project_root, 'allure-report') ALLURE_PATH = os.path.join(project_root, 'allure', 'allure-2.28.0', 'bin', 'allure.bat') print(ALLURE_REPORT_DIR) @@ -44,11 +44,13 @@ def run_pytest(args_list): # 检测Jenkins环境 is_jenkins = 'JENKINS_URL' in env or 'BUILD_NUMBER' in env if is_jenkins and 'WORKSPACE' in env: - # Jenkins环境下使用绝对路径 + # Jenkins环境下使用绝对路径 - 确保与Jenkins Allure插件配置一致 global ALLURE_RESULTS_DIR, ALLURE_REPORT_DIR - ALLURE_RESULTS_DIR = os.path.join(env['WORKSPACE'], 'dulizhan', 'test_case', 'reports', 'allure-results') - ALLURE_REPORT_DIR = os.path.join(env['WORKSPACE'], 'dulizhan', 'test_case', 'reports', 'allure-report') + # Jenkins配置的路径是 /home/dulizhan/allure-report + ALLURE_RESULTS_DIR = os.path.join(env['WORKSPACE'], 'allure-results') + ALLURE_REPORT_DIR = os.path.join(env['WORKSPACE'], 'allure-report') ensure_dirs() + print(f"Jenkins环境检测到,使用路径: {ALLURE_RESULTS_DIR}") cmd = ['python', '-m', 'pytest'] + args_list print("执行命令: {}".format(' '.join(cmd)))