From 3191ec4f3c8adc16060996b07d14b24463b1b872 Mon Sep 17 00:00:00 2001 From: zhouqi Date: Fri, 8 May 2026 18:09:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EJoyHub=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E5=92=8C=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=A2=9E=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增模块测试用例: - News分类接口测试 (Joyhub_NewsCate.py) - News内容接口测试 (Joyhub_News.py) - 产品分类接口测试 (Joyhub_ProductCate.py) - 产品属性接口测试 (Joyhub_ProductAttr.py) - 产品管理接口测试 (Joyhub_Product.py) - FAQ分类接口测试 (Joyhub_FaqCate.py) - FAQ内容接口测试 (Joyhub_Faq.py) - 博客分类接口测试 (Joyhub_BlogCate.py) - 地址国家接口测试 (Joyhub_AddressCountry.py) - 下载二维码接口测试 (Joyhub_DownloadQrcode.py) - 支付页产品推荐接口测试 (Joyhub_ProductPaymentRecommend.py) 2. 新增业务关键字层: - NewsCateManage.py - NewsManage.py - ProductCateManage.py - ProductAttrManage.py - ProductManage.py - FaqCateManage.py - FaqManage.py - BlogCateManage.py - AddressCountryManage.py - DownloadQrcodeManage.py - ProductPaymentRecommendManage.py 3. 接口层增强: - Dlizhan_interface.py 添加JoyHub相关接口封装 4. 功能增强: - run_tests.py 添加自动清除旧测试结果和报告功能 - Joyhub_Product.py 添加数据库连接获取运费模板ID和品牌ID 5. 修复: - 修复产品创建测试用例缺少前置数据问题 --- .../BusinessKw/JoyHub/AddressCountryManage.py | 160 ++++++ .../BusinessKw/JoyHub/BlogCateManage.py | 130 +++++ .../BusinessKw/JoyHub/DownloadQrcodeManage.py | 125 +++++ .../BusinessKw/JoyHub/FaqCateManage.py | 108 ++++ .../library/BusinessKw/JoyHub/FaqManage.py | 148 ++++++ .../BusinessKw/JoyHub/NewsCateManage.py | 167 ++++++ .../library/BusinessKw/JoyHub/NewsManage.py | 187 +++++++ .../BusinessKw/JoyHub/ProductAttrManage.py | 268 ++++++++++ .../BusinessKw/JoyHub/ProductCateManage.py | 145 ++++++ .../BusinessKw/JoyHub/ProductManage.py | 269 ++++++++++ .../JoyHub/ProductPaymentRecommendManage.py | 124 +++++ dulizhan/library/Dlizhan_interface.py | 259 +++++++++ .../接口/JoyHub/Joyhub_AddressCountry.py | 279 ++++++++++ .../TestCase/接口/JoyHub/Joyhub_BlogCate.py | 200 +++++++ .../接口/JoyHub/Joyhub_DownloadQrcode.py | 162 ++++++ .../TestCase/接口/JoyHub/Joyhub_Faq.py | 181 +++++++ .../TestCase/接口/JoyHub/Joyhub_FaqCate.py | 166 ++++++ .../TestCase/接口/JoyHub/Joyhub_News.py | 210 ++++++++ .../TestCase/接口/JoyHub/Joyhub_NewsCate.py | 186 +++++++ .../TestCase/接口/JoyHub/Joyhub_Product.py | 490 ++++++++++++++++++ .../接口/JoyHub/Joyhub_ProductAttr.py | 320 ++++++++++++ .../接口/JoyHub/Joyhub_ProductCate.py | 201 +++++++ .../JoyHub/Joyhub_ProductPaymentRecommend.py | 279 ++++++++++ dulizhan/test_case/TestCase/接口/conftest.py | 4 +- dulizhan/test_case/run_tests.py | 34 ++ 25 files changed, 4800 insertions(+), 2 deletions(-) create mode 100644 dulizhan/library/BusinessKw/JoyHub/AddressCountryManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/BlogCateManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/DownloadQrcodeManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/FaqCateManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/FaqManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/NewsCateManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/NewsManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/ProductAttrManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/ProductCateManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/ProductManage.py create mode 100644 dulizhan/library/BusinessKw/JoyHub/ProductPaymentRecommendManage.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AddressCountry.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_BlogCate.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_DownloadQrcode.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Faq.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_FaqCate.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_News.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_NewsCate.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Product.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductAttr.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductCate.py create mode 100644 dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductPaymentRecommend.py diff --git a/dulizhan/library/BusinessKw/JoyHub/AddressCountryManage.py b/dulizhan/library/BusinessKw/JoyHub/AddressCountryManage.py new file mode 100644 index 0000000..72a6069 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/AddressCountryManage.py @@ -0,0 +1,160 @@ +# -*- coding:utf-8 -*- +""" +国家信息管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class AddressCountryManage(DlzhanInterface): + """国家信息管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建国家信息") + def kw_joyhub_address_country_create_post(self, country_code, country_name, country_name_en, phone_code, + lingxing_country_code=None, paypal_country_code=None, status=1, id=0): + """ + 创建国家信息业务关键字 + :param id: 主键,新增为0 + :param country_code: 国家代码(如 CN/US) + :param country_name: 国家名称 + :param country_name_en: 国家英文名称 + :param phone_code: 电话区号 + :param lingxing_country_code: 领星国家代码(可选) + :param paypal_country_code: paypal国家代码(可选) + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"创建国家信息 - country_code: {country_code}, country_name: {country_name}, status: {status}") + + params = { + "id": id, + "countryCode": country_code, + "countryName": country_name, + "countryNameEn": country_name_en, + "phoneCode": phone_code, + "status": status + } + + if lingxing_country_code: + params["lingxingCountryCode"] = lingxing_country_code + if paypal_country_code: + params["paypalCountryCode"] = paypal_country_code + + resp = self.kw_in_joyhub_address_country_create_post(**params) + obj_log.info(f"创建国家信息响应: {resp}") + + return resp + + @allure.step("删除国家信息") + def kw_joyhub_address_country_delete_delete(self, country_id): + """ + 删除国家信息业务关键字 + :param country_id: 国家信息ID + :return: 响应结果 + """ + obj_log.info(f"删除国家信息 - country_id: {country_id}") + resp = self.kw_in_joyhub_address_country_delete_delete(country_id) + obj_log.info(f"删除国家信息响应: {resp}") + return resp + + @allure.step("批量删除国家信息") + def kw_joyhub_address_country_delete_list_delete(self, country_ids): + """ + 批量删除国家信息业务关键字 + :param country_ids: 国家信息ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除国家信息 - country_ids: {country_ids}") + resp = self.kw_in_joyhub_address_country_delete_list_delete(country_ids) + obj_log.info(f"批量删除国家信息响应: {resp}") + return resp + + @allure.step("获得国家信息详情") + def kw_joyhub_address_country_get_get(self, country_id): + """ + 获得国家信息详情业务关键字 + :param country_id: 国家信息ID + :return: 响应结果 + """ + obj_log.info(f"获得国家信息详情 - country_id: {country_id}") + resp = self.kw_in_joyhub_address_country_get_get(country_id) + obj_log.info(f"获得国家信息详情响应: {resp}") + return resp + + @allure.step("获得国家信息分页") + def kw_joyhub_address_country_page_get(self, page_num=1, page_size=10, **kwargs): + """ + 获得国家信息分页业务关键字 + :param page_num: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得国家信息分页 - page_num: {page_num}, page_size: {page_size}") + + params = { + "page": page_num, + "size": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_address_country_page_get(**params) + obj_log.info(f"获得国家信息分页响应: {resp}") + return resp + + @allure.step("更新国家信息") + def kw_joyhub_address_country_update_put(self, country_id, country_code, country_name, country_name_en, phone_code, + lingxing_country_code=None, paypal_country_code=None, status=1): + """ + 更新国家信息业务关键字 + :param country_id: 国家信息ID + :param country_code: 国家代码 + :param country_name: 国家名称 + :param country_name_en: 国家英文名称 + :param phone_code: 电话区号 + :param lingxing_country_code: 领星国家代码(可选) + :param paypal_country_code: paypal国家代码(可选) + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"更新国家信息 - country_id: {country_id}, country_code: {country_code}, country_name: {country_name}") + + params = { + "id": country_id, + "countryCode": country_code, + "countryName": country_name, + "countryNameEn": country_name_en, + "phoneCode": phone_code, + "status": status + } + + if lingxing_country_code: + params["lingxingCountryCode"] = lingxing_country_code + if paypal_country_code: + params["paypalCountryCode"] = paypal_country_code + + resp = self.kw_in_joyhub_address_country_update_put(**params) + obj_log.info(f"更新国家信息响应: {resp}") + return resp + + @allure.step("批量更新国家信息状态") + def kw_joyhub_address_country_update_status_list_put(self, country_ids, status): + """ + 批量更新国家信息状态业务关键字 + :param country_ids: 国家信息ID列表 + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"批量更新国家信息状态 - country_ids: {country_ids}, status: {status}") + + # 接口参数通过query传递,ids需要用逗号分隔 + ids_str = ','.join(map(str, country_ids)) + resp = self.kw_in_joyhub_address_country_update_status_list_put(ids=ids_str, status=status) + obj_log.info(f"批量更新国家信息状态响应: {resp}") + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/BlogCateManage.py b/dulizhan/library/BusinessKw/JoyHub/BlogCateManage.py new file mode 100644 index 0000000..48c8bd2 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/BlogCateManage.py @@ -0,0 +1,130 @@ +# -*- coding:utf-8 -*- +""" +blog分类管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class BlogCateManage(DlzhanInterface): + """blog分类管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建blog分类") + def kw_joyhub_blog_cate_create_post(self, name, id=0, status=1, rank_num=None, route=None, cover_image=None): + """ + 创建blog分类业务关键字 + :param id: 主键,新增为0 + :param name: 分类名称 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序(可选) + :param route: 路由(可选) + :param cover_image: 封面图对象,格式: {"url": "xxx", "name": None, "alt": ""}(可选) + :return: 响应结果 + """ + obj_log.info(f"创建blog分类 - name: {name}, status: {status}") + + params = { + "id": id, + "name": name, + "status": status + } + + if rank_num is not None: + params["rankNum"] = rank_num + if route is not None: + params["route"] = route + if cover_image is not None: + if isinstance(cover_image, str): + params["coverImage"] = {"url": cover_image, "name": None, "alt": ""} + else: + params["coverImage"] = cover_image + + resp = self.kw_in_joyhub_blog_cate_create_post(**params) + obj_log.info(f"创建blog分类响应: {resp}") + + return resp + + @allure.step("删除blog分类") + def kw_joyhub_blog_cate_delete_delete(self, cate_id): + """ + 删除blog分类业务关键字 + :param cate_id: blog分类ID + :return: 响应结果 + """ + obj_log.info(f"删除blog分类 - cate_id: {cate_id}") + resp = self.kw_in_joyhub_blog_cate_delete_delete(cate_id) + obj_log.info(f"删除blog分类响应: {resp}") + return resp + + @allure.step("获得blog分类详情") + def kw_joyhub_blog_cate_get_get(self, cate_id): + """ + 获得blog分类详情业务关键字 + :param cate_id: blog分类ID + :return: 响应结果 + """ + obj_log.info(f"获得blog分类详情 - cate_id: {cate_id}") + resp = self.kw_in_joyhub_blog_cate_get_get(cate_id) + obj_log.info(f"获得blog分类详情响应: {resp}") + return resp + + @allure.step("获得blog分类分页") + def kw_joyhub_blog_cate_page_get(self, page_num=1, page_size=10, **kwargs): + """ + 获得blog分类分页业务关键字 + :param page_num: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得blog分类分页 - page_num: {page_num}, page_size: {page_size}") + + params = { + "page": page_num, + "size": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_blog_cate_page_get(**params) + obj_log.info(f"获得blog分类分页响应: {resp}") + return resp + + @allure.step("更新blog分类") + def kw_joyhub_blog_cate_update_put(self, cate_id, name, status=1, rank_num=None, route=None, cover_image=None): + """ + 更新blog分类业务关键字 + :param cate_id: blog分类ID + :param name: 分类名称 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序(可选) + :param route: 路由(可选) + :param cover_image: 封面图对象,格式: {"url": "xxx", "name": None, "alt": ""}(可选) + :return: 响应结果 + """ + obj_log.info(f"更新blog分类 - cate_id: {cate_id}, name: {name}, status: {status}") + + params = { + "id": cate_id, + "name": name, + "status": status + } + + if rank_num is not None: + params["rankNum"] = rank_num + if route is not None: + params["route"] = route + if cover_image is not None: + if isinstance(cover_image, str): + params["coverImage"] = {"url": cover_image, "name": None, "alt": ""} + else: + params["coverImage"] = cover_image + + resp = self.kw_in_joyhub_blog_cate_update_put(**params) + obj_log.info(f"更新blog分类响应: {resp}") + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/DownloadQrcodeManage.py b/dulizhan/library/BusinessKw/JoyHub/DownloadQrcodeManage.py new file mode 100644 index 0000000..ccad787 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/DownloadQrcodeManage.py @@ -0,0 +1,125 @@ +# -*- coding:utf-8 -*- +""" +二维码管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class DownloadQrcodeManage(DlzhanInterface): + """二维码管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建二维码") + def kw_joyhub_download_qrcode_create_post(self, title, id=0, status=1): + """ + 创建二维码业务关键字 + :param id: 主键,新增为0 + :param title: 标题 + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"创建二维码 - title: {title}, status: {status}") + + params = { + "id": id, + "title": title, + "status": status + } + + resp = self.kw_in_joyhub_download_qrcode_create_post(**params) + obj_log.info(f"创建二维码响应: {resp}") + + return resp + + @allure.step("获得二维码详情") + def kw_joyhub_download_qrcode_get_get(self, qrcode_id): + """ + 获得二维码详情业务关键字 + :param qrcode_id: 二维码ID + :return: 响应结果 + """ + obj_log.info(f"获得二维码详情 - qrcode_id: {qrcode_id}") + resp = self.kw_in_joyhub_download_qrcode_get_get(qrcode_id) + obj_log.info(f"获得二维码详情响应: {resp}") + return resp + + @allure.step("获得二维码分页") + def kw_joyhub_download_qrcode_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得二维码分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得二维码分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_download_qrcode_page_get(**params) + obj_log.info(f"获得二维码分页响应: {resp}") + return resp + + @allure.step("更新二维码") + def kw_joyhub_download_qrcode_update_put(self, qrcode_id, title, status=1): + """ + 更新二维码业务关键字 + :param qrcode_id: 二维码ID + :param title: 标题 + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"更新二维码 - qrcode_id: {qrcode_id}, title: {title}, status: {status}") + + params = { + "id": qrcode_id, + "title": title, + "status": status + } + + resp = self.kw_in_joyhub_download_qrcode_update_put(**params) + obj_log.info(f"更新二维码响应: {resp}") + + return resp + + def clean_test_data_from_db(self, title): + """ + 从数据库表jh_download_qrcode中删除测试数据 + :param title: 要删除的二维码标题 + :return: 删除是否成功 + """ + obj_log.info(f"从数据库删除测试数据 - title: {title}") + try: + import pymysql + # 数据库连接配置(需要根据实际环境配置) + connection = pymysql.connect( + host='localhost', + user='root', + password='password', + database='joyhub', + charset='utf8mb4' + ) + + with connection.cursor() as cursor: + sql = "DELETE FROM jh_download_qrcode WHERE title LIKE %s" + cursor.execute(sql, (f"%{title}%",)) + connection.commit() + deleted_count = cursor.rowcount + obj_log.info(f"成功删除 {deleted_count} 条测试数据") + return True + except Exception as e: + obj_log.error(f"删除测试数据失败: {str(e)}") + return False + finally: + if 'connection' in locals(): + connection.close() diff --git a/dulizhan/library/BusinessKw/JoyHub/FaqCateManage.py b/dulizhan/library/BusinessKw/JoyHub/FaqCateManage.py new file mode 100644 index 0000000..6cd7110 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/FaqCateManage.py @@ -0,0 +1,108 @@ +# -*- coding:utf-8 -*- +""" +FAQ分类管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class FaqCateManage(DlzhanInterface): + """FAQ分类管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建FAQ分类") + def kw_joyhub_faq_cate_create_post(self, title, lang, rank_num, pid=0, status=1, id=0): + """ + 创建FAQ分类业务关键字 + :param id: 主键,新增为0 + :param pid: 父分类ID,默认为0(顶级分类) + :param title: 分类名称 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param lang: 语言 (en 英语 de 德语 ja 日语) + :return: 响应结果 + """ + obj_log.info(f"创建FAQ分类 - title: {title}, lang: {lang}, pid: {pid}") + + params = { + "id": id, + "pid": pid, + "title": title, + "status": status, + "rankNum": rank_num, + "lang": lang + } + + resp = self.kw_in_joyhub_faq_cate_create_post(**params) + obj_log.info(f"创建FAQ分类响应: {resp}") + + return resp + + @allure.step("删除FAQ分类") + def kw_joyhub_faq_cate_delete_delete(self, faq_cate_id): + """ + 删除FAQ分类业务关键字 + :param faq_cate_id: FAQ分类ID + :return: 响应结果 + """ + obj_log.info(f"删除FAQ分类 - faq_cate_id: {faq_cate_id}") + resp = self.kw_in_joyhub_faq_cate_delete_delete(faq_cate_id) + obj_log.info(f"删除FAQ分类响应: {resp}") + return resp + + @allure.step("获得FAQ分类详情") + def kw_joyhub_faq_cate_get_get(self, faq_cate_id): + """ + 获得FAQ分类详情业务关键字 + :param faq_cate_id: FAQ分类ID + :return: 响应结果 + """ + obj_log.info(f"获得FAQ分类详情 - faq_cate_id: {faq_cate_id}") + resp = self.kw_in_joyhub_faq_cate_get_get(faq_cate_id) + obj_log.info(f"获得FAQ分类详情响应: {resp}") + return resp + + @allure.step("获得FAQ分类列表") + def kw_joyhub_faq_cate_list_get(self, **kwargs): + """ + 获得FAQ分类列表业务关键字 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得FAQ分类列表 - kwargs: {kwargs}") + resp = self.kw_in_joyhub_faq_cate_list_get(**kwargs) + obj_log.info(f"获得FAQ分类列表响应: {resp}") + return resp + + @allure.step("更新FAQ分类") + def kw_joyhub_faq_cate_update_put(self, faq_cate_id, title, lang, rank_num, pid=0, status=1): + """ + 更新FAQ分类业务关键字 + :param faq_cate_id: FAQ分类ID + :param pid: 父分类ID + :param title: 分类名称 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param lang: 语言 (en 英语 de 德语 ja 日语) + :return: 响应结果 + """ + obj_log.info(f"更新FAQ分类 - faq_cate_id: {faq_cate_id}, title: {title}, lang: {lang}") + + params = { + "id": faq_cate_id, + "pid": pid, + "title": title, + "status": status, + "rankNum": rank_num, + "lang": lang + } + + resp = self.kw_in_joyhub_faq_cate_update_put(**params) + obj_log.info(f"更新FAQ分类响应: {resp}") + + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/FaqManage.py b/dulizhan/library/BusinessKw/JoyHub/FaqManage.py new file mode 100644 index 0000000..743b4d5 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/FaqManage.py @@ -0,0 +1,148 @@ +# -*- coding:utf-8 -*- +""" +FAQ数据管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class FaqManage(DlzhanInterface): + """FAQ数据管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("获得FAQ分类下拉列表") + def kw_joyhub_faq_cate_list_get(self): + """ + 获得FAQ分类下拉列表业务关键字 + :return: 响应结果 + """ + obj_log.info("获得FAQ分类下拉列表") + resp = self.kw_in_joyhub_faq_cate_list_get() + obj_log.info(f"获得FAQ分类下拉列表响应: {resp}") + return resp + + @allure.step("创建FAQ数据") + def kw_joyhub_faq_create_post(self, faq_cate_id, question, answer, rank_num, lang, is_hot=0, status=1, id=0): + """ + 创建FAQ数据业务关键字 + :param id: 主键,新增为0 + :param faq_cate_id: 分类ID + :param question: 常见问题 + :param answer: 回答 + :param is_hot: 是否热门(0否,1是) + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param lang: 语言 (en 英语 de 德语 ja 日语) + :return: 响应结果 + """ + obj_log.info(f"创建FAQ数据 - question: {question}, lang: {lang}") + + params = { + "id": id, + "faqCateId": faq_cate_id, + "question": question, + "answer": answer, + "isHot": is_hot, + "status": status, + "rankNum": rank_num, + "lang": lang + } + + resp = self.kw_in_joyhub_faq_create_post(**params) + obj_log.info(f"创建FAQ数据响应: {resp}") + + return resp + + @allure.step("删除FAQ数据") + def kw_joyhub_faq_delete_delete(self, faq_id): + """ + 删除FAQ数据业务关键字 + :param faq_id: FAQ数据ID + :return: 响应结果 + """ + obj_log.info(f"删除FAQ数据 - faq_id: {faq_id}") + resp = self.kw_in_joyhub_faq_delete_delete(faq_id) + obj_log.info(f"删除FAQ数据响应: {resp}") + return resp + + @allure.step("批量删除FAQ数据") + def kw_joyhub_faq_delete_list_delete(self, ids): + """ + 批量删除FAQ数据业务关键字 + :param ids: FAQ数据ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除FAQ数据 - ids: {ids}") + resp = self.kw_in_joyhub_faq_delete_list_delete(ids) + obj_log.info(f"批量删除FAQ数据响应: {resp}") + return resp + + @allure.step("获得FAQ数据详情") + def kw_joyhub_faq_get_get(self, faq_id): + """ + 获得FAQ数据详情业务关键字 + :param faq_id: FAQ数据ID + :return: 响应结果 + """ + obj_log.info(f"获得FAQ数据详情 - faq_id: {faq_id}") + resp = self.kw_in_joyhub_faq_get_get(faq_id) + obj_log.info(f"获得FAQ数据详情响应: {resp}") + return resp + + @allure.step("获得FAQ数据分页") + def kw_joyhub_faq_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得FAQ数据分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得FAQ数据分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_faq_page_get(**params) + obj_log.info(f"获得FAQ数据分页响应: {resp}") + return resp + + @allure.step("更新FAQ数据") + def kw_joyhub_faq_update_put(self, faq_id, faq_cate_id, question, answer, rank_num, lang, is_hot=0, status=1): + """ + 更新FAQ数据业务关键字 + :param faq_id: FAQ数据ID + :param faq_cate_id: 分类ID + :param question: 常见问题 + :param answer: 回答 + :param is_hot: 是否热门(0否,1是) + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param lang: 语言 (en 英语 de 德语 ja 日语) + :return: 响应结果 + """ + obj_log.info(f"更新FAQ数据 - faq_id: {faq_id}, question: {question}, lang: {lang}") + + params = { + "id": faq_id, + "faqCateId": faq_cate_id, + "question": question, + "answer": answer, + "isHot": is_hot, + "status": status, + "rankNum": rank_num, + "lang": lang + } + + resp = self.kw_in_joyhub_faq_update_put(**params) + obj_log.info(f"更新FAQ数据响应: {resp}") + + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/NewsCateManage.py b/dulizhan/library/BusinessKw/JoyHub/NewsCateManage.py new file mode 100644 index 0000000..5f640ed --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/NewsCateManage.py @@ -0,0 +1,167 @@ +# -*- coding:utf-8 -*- +""" +news分类管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class NewsCateManage(DlzhanInterface): + """news分类管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建news分类") + def kw_joyhub_news_cate_create_post(self, name, id=0, status=1, rank_num=1, route=None, cover_image=None): + """ + 创建news分类业务关键字 + :param id: 主键,新增为0 + :param name: 分类名称 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param route: 路由(可选) + :param cover_image: 缩略图(可选) + :return: 响应结果 + """ + obj_log.info(f"创建news分类 - name: {name}") + + params = { + "id": id, + "name": name, + "status": status, + "rankNum": rank_num + } + + if route is not None: + params["route"] = route + if cover_image is not None: + params["coverImage"] = cover_image + + resp = self.kw_in_joyhub_news_cate_create_post(**params) + obj_log.info(f"创建news分类响应: {resp}") + + return resp + + @allure.step("删除news分类") + def kw_joyhub_news_cate_delete_delete(self, news_cate_id): + """ + 删除news分类业务关键字 + :param news_cate_id: news分类ID + :return: 响应结果 + """ + obj_log.info(f"删除news分类 - news_cate_id: {news_cate_id}") + resp = self.kw_in_joyhub_news_cate_delete_delete(news_cate_id) + obj_log.info(f"删除news分类响应: {resp}") + return resp + + @allure.step("批量删除news分类") + def kw_joyhub_news_cate_delete_list_delete(self, ids): + """ + 批量删除news分类业务关键字 + :param ids: news分类ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除news分类 - ids: {ids}") + resp = self.kw_in_joyhub_news_cate_delete_list_delete(ids) + obj_log.info(f"批量删除news分类响应: {resp}") + return resp + + @allure.step("获得news分类详情") + def kw_joyhub_news_cate_get_get(self, news_cate_id): + """ + 获得news分类详情业务关键字 + :param news_cate_id: news分类ID + :return: 响应结果 + """ + obj_log.info(f"获得news分类详情 - news_cate_id: {news_cate_id}") + resp = self.kw_in_joyhub_news_cate_get_get(news_cate_id) + obj_log.info(f"获得news分类详情响应: {resp}") + return resp + + @allure.step("获得news分类分页") + def kw_joyhub_news_cate_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得news分类分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得news分类分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_news_cate_page_get(**params) + obj_log.info(f"获得news分类分页响应: {resp}") + return resp + + @allure.step("更新news分类") + def kw_joyhub_news_cate_update_put(self, news_cate_id, name, status=1, rank_num=1, route=None, cover_image=None): + """ + 更新news分类业务关键字 + :param news_cate_id: news分类ID + :param name: 分类名称 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param route: 路由(可选) + :param cover_image: 缩略图(可选) + :return: 响应结果 + """ + obj_log.info(f"更新news分类 - news_cate_id: {news_cate_id}, name: {name}") + + params = { + "id": news_cate_id, + "name": name, + "status": status, + "rankNum": rank_num + } + + if route is not None: + params["route"] = route + if cover_image is not None: + params["coverImage"] = cover_image + + resp = self.kw_in_joyhub_news_cate_update_put(**params) + obj_log.info(f"更新news分类响应: {resp}") + + return resp + + def clean_test_data_from_db(self, name): + """ + 从数据库表jh_news_cate中删除测试数据 + :param name: 要删除的分类名称 + :return: 删除是否成功 + """ + obj_log.info(f"从数据库删除测试数据 - name: {name}") + try: + import pymysql + # 数据库连接配置(需要根据实际环境配置) + connection = pymysql.connect( + host='localhost', + user='root', + password='password', + database='joyhub', + charset='utf8mb4' + ) + + with connection.cursor() as cursor: + sql = "DELETE FROM jh_news_cate WHERE name LIKE %s" + cursor.execute(sql, (f"%{name}%",)) + connection.commit() + deleted_count = cursor.rowcount + obj_log.info(f"成功删除 {deleted_count} 条测试数据") + return True + except Exception as e: + obj_log.error(f"删除测试数据失败: {str(e)}") + return False + finally: + if 'connection' in locals(): + connection.close() diff --git a/dulizhan/library/BusinessKw/JoyHub/NewsManage.py b/dulizhan/library/BusinessKw/JoyHub/NewsManage.py new file mode 100644 index 0000000..fefb094 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/NewsManage.py @@ -0,0 +1,187 @@ +# -*- coding:utf-8 -*- +""" +news管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class NewsManage(DlzhanInterface): + """news管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建news管理") + def kw_joyhub_news_create_post(self, title, cover_image, content, id=0, status=1, rank_num=1, + seo_title=None, seo_keyword=None, seo_description=None, + likes_num=0, cate_ids=None, route=None, publish_time=None): + """ + 创建news管理业务关键字 + :param id: 主键,新增为0 + :param title: 标题 + :param cover_image: 缩略图 + :param content: PC页面内容 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param seo_title: SEO标题(可选) + :param seo_keyword: SEO关键词(可选) + :param seo_description: SEO描述(可选) + :param likes_num: 点赞数(可选) + :param cate_ids: news分类ID列表(可选) + :param route: 路由(可选) + :param publish_time: 发布时间(可选) + :return: 响应结果 + """ + obj_log.info(f"创建news管理 - title: {title}") + + params = { + "id": id, + "title": title, + "coverImage": cover_image, + "content": content, + "status": status, + "rankNum": rank_num, + "likesNum": likes_num + } + + if seo_title is not None: + params["seoTitle"] = seo_title + if seo_keyword is not None: + params["seoKeyword"] = seo_keyword + if seo_description is not None: + params["seoDescription"] = seo_description + if cate_ids is not None: + params["cateIds"] = cate_ids + if route is not None: + params["route"] = route + if publish_time is not None: + params["publishTime"] = publish_time + + resp = self.kw_in_joyhub_news_create_post(**params) + obj_log.info(f"创建news管理响应: {resp}") + + return resp + + @allure.step("删除news管理") + def kw_joyhub_news_delete_delete(self, news_id): + """ + 删除news管理业务关键字 + :param news_id: news管理ID + :return: 响应结果 + """ + obj_log.info(f"删除news管理 - news_id: {news_id}") + resp = self.kw_in_joyhub_news_delete_delete(news_id) + obj_log.info(f"删除news管理响应: {resp}") + return resp + + @allure.step("批量删除news管理") + def kw_joyhub_news_delete_list_delete(self, ids): + """ + 批量删除news管理业务关键字 + :param ids: news管理ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除news管理 - ids: {ids}") + resp = self.kw_in_joyhub_news_delete_list_delete(ids) + obj_log.info(f"批量删除news管理响应: {resp}") + return resp + + @allure.step("获得news管理详情") + def kw_joyhub_news_get_get(self, news_id): + """ + 获得news管理详情业务关键字 + :param news_id: news管理ID + :return: 响应结果 + """ + obj_log.info(f"获得news管理详情 - news_id: {news_id}") + resp = self.kw_in_joyhub_news_get_get(news_id) + obj_log.info(f"获得news管理详情响应: {resp}") + return resp + + @allure.step("获得news分类关联列表") + def kw_joyhub_news_cate_relation_list_get(self, news_id): + """ + 获得news分类关联列表业务关键字 + :param news_id: news管理ID + :return: 响应结果 + """ + obj_log.info(f"获得news分类关联列表 - news_id: {news_id}") + resp = self.kw_in_joyhub_news_cate_relation_list_get(news_id) + obj_log.info(f"获得news分类关联列表响应: {resp}") + return resp + + @allure.step("获得news管理分页") + def kw_joyhub_news_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得news管理分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得news管理分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_news_page_get(**params) + obj_log.info(f"获得news管理分页响应: {resp}") + return resp + + @allure.step("更新news管理") + def kw_joyhub_news_update_put(self, news_id, title, cover_image, content, status=1, rank_num=1, + seo_title=None, seo_keyword=None, seo_description=None, + likes_num=0, cate_ids=None, route=None, publish_time=None): + """ + 更新news管理业务关键字 + :param news_id: news管理ID + :param title: 标题 + :param cover_image: 缩略图 + :param content: PC页面内容 + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :param seo_title: SEO标题(可选) + :param seo_keyword: SEO关键词(可选) + :param seo_description: SEO描述(可选) + :param likes_num: 点赞数(可选) + :param cate_ids: news分类ID列表(可选) + :param route: 路由(可选) + :param publish_time: 发布时间(可选) + :return: 响应结果 + """ + obj_log.info(f"更新news管理 - news_id: {news_id}, title: {title}") + + params = { + "id": news_id, + "title": title, + "coverImage": cover_image, + "content": content, + "status": status, + "rankNum": rank_num, + "likesNum": likes_num + } + + if seo_title is not None: + params["seoTitle"] = seo_title + if seo_keyword is not None: + params["seoKeyword"] = seo_keyword + if seo_description is not None: + params["seoDescription"] = seo_description + if cate_ids is not None: + params["cateIds"] = cate_ids + if route is not None: + params["route"] = route + if publish_time is not None: + params["publishTime"] = publish_time + + resp = self.kw_in_joyhub_news_update_put(**params) + obj_log.info(f"更新news管理响应: {resp}") + + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/ProductAttrManage.py b/dulizhan/library/BusinessKw/JoyHub/ProductAttrManage.py new file mode 100644 index 0000000..78d1bc2 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/ProductAttrManage.py @@ -0,0 +1,268 @@ +# -*- coding:utf-8 -*- +""" +产品属性+产品属性值管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class ProductAttrManage(DlzhanInterface): + """产品属性+产品属性值管理业务关键字类""" + + def __init__(self): + super().__init__() + + # ============ 产品属性管理方法 ============ + + @allure.step("创建产品属性") + def kw_joyhub_product_attr_type_create_post(self, name, type=2, id=0, status=1, remark=None, rank_num=None): + """ + 创建产品属性业务关键字 + :param id: 主键,新增为0 + :param type: 属性类型:1-颜色属性(有色卡),2-普通属性 + :param name: 属性名称 + :param status: 状态 (1正常 2停用) + :param remark: 备注(可选) + :param rank_num: 排序号(可选) + :return: 响应结果 + """ + obj_log.info(f"创建产品属性 - name: {name}, type: {type}") + + params = { + "id": id, + "type": type, + "name": name, + "status": status + } + + if remark is not None: + params["remark"] = remark + if rank_num is not None: + params["rankNum"] = rank_num + + resp = self.kw_in_joyhub_product_attr_type_create_post(**params) + obj_log.info(f"创建产品属性响应: {resp}") + + return resp + + @allure.step("删除产品属性") + def kw_joyhub_product_attr_type_delete_delete(self, product_attr_type_id): + """ + 删除产品属性业务关键字 + :param product_attr_type_id: 产品属性ID + :return: 响应结果 + """ + obj_log.info(f"删除产品属性 - product_attr_type_id: {product_attr_type_id}") + resp = self.kw_in_joyhub_product_attr_type_delete_delete(product_attr_type_id) + obj_log.info(f"删除产品属性响应: {resp}") + return resp + + @allure.step("批量删除产品属性") + def kw_joyhub_product_attr_type_delete_list_delete(self, ids): + """ + 批量删除产品属性业务关键字 + :param ids: 产品属性ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除产品属性 - ids: {ids}") + resp = self.kw_in_joyhub_product_attr_type_delete_list_delete(ids) + obj_log.info(f"批量删除产品属性响应: {resp}") + return resp + + @allure.step("获得产品属性详情") + def kw_joyhub_product_attr_type_get_get(self, product_attr_type_id): + """ + 获得产品属性详情业务关键字 + :param product_attr_type_id: 产品属性ID + :return: 响应结果 + """ + obj_log.info(f"获得产品属性详情 - product_attr_type_id: {product_attr_type_id}") + resp = self.kw_in_joyhub_product_attr_type_get_get(product_attr_type_id) + obj_log.info(f"获得产品属性详情响应: {resp}") + return resp + + @allure.step("获得产品属性分页") + def kw_joyhub_product_attr_type_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得产品属性分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得产品属性分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_product_attr_type_page_get(**params) + obj_log.info(f"获得产品属性分页响应: {resp}") + return resp + + @allure.step("更新产品属性") + def kw_joyhub_product_attr_type_update_put(self, product_attr_type_id, name, type=2, status=1, remark=None, rank_num=None): + """ + 更新产品属性业务关键字 + :param product_attr_type_id: 产品属性ID + :param name: 属性名称 + :param type: 属性类型:1-颜色属性(有色卡),2-普通属性 + :param status: 状态 (1正常 2停用) + :param remark: 备注(可选) + :param rank_num: 排序号(可选) + :return: 响应结果 + """ + obj_log.info(f"更新产品属性 - product_attr_type_id: {product_attr_type_id}, name: {name}") + + params = { + "id": product_attr_type_id, + "type": type, + "name": name, + "status": status + } + + if remark is not None: + params["remark"] = remark + if rank_num is not None: + params["rankNum"] = rank_num + + resp = self.kw_in_joyhub_product_attr_type_update_put(**params) + obj_log.info(f"更新产品属性响应: {resp}") + + return resp + + @allure.step("修改产品属性状态") + def kw_joyhub_product_attr_type_change_status_put(self, product_attr_type_id, status): + """ + 修改产品属性状态业务关键字 + :param product_attr_type_id: 产品属性ID + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"修改产品属性状态 - product_attr_type_id: {product_attr_type_id}, status: {status}") + + params = { + "id": product_attr_type_id, + "status": status + } + + resp = self.kw_in_joyhub_product_attr_type_change_status_put(**params) + obj_log.info(f"修改产品属性状态响应: {resp}") + + return resp + + # ============ 产品属性值管理方法 ============ + + @allure.step("创建产品属性值") + def kw_joyhub_product_attr_data_create_post(self, product_attr_type_id, attr_value, id=0, color=None): + """ + 创建产品属性值业务关键字 + :param id: 主键ID,新增为0 + :param product_attr_type_id: 关联产品属性表的主键ID + :param attr_value: 属性值名称 + :param color: 色卡(可选,颜色属性类型时使用) + :return: 响应结果 + """ + obj_log.info(f"创建产品属性值 - product_attr_type_id: {product_attr_type_id}, attr_value: {attr_value}") + + params = { + "id": id, + "productAttrTypeId": product_attr_type_id, + "attrValue": attr_value + } + + if color is not None: + params["color"] = color + + resp = self.kw_in_joyhub_product_attr_data_create_post(**params) + obj_log.info(f"创建产品属性值响应: {resp}") + + return resp + + @allure.step("删除产品属性值") + def kw_joyhub_product_attr_data_delete_delete(self, product_attr_data_id): + """ + 删除产品属性值业务关键字 + :param product_attr_data_id: 产品属性值ID + :return: 响应结果 + """ + obj_log.info(f"删除产品属性值 - product_attr_data_id: {product_attr_data_id}") + resp = self.kw_in_joyhub_product_attr_data_delete_delete(product_attr_data_id) + obj_log.info(f"删除产品属性值响应: {resp}") + return resp + + @allure.step("批量删除产品属性值") + def kw_joyhub_product_attr_data_delete_list_delete(self, ids): + """ + 批量删除产品属性值业务关键字 + :param ids: 产品属性值ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除产品属性值 - ids: {ids}") + resp = self.kw_in_joyhub_product_attr_data_delete_list_delete(ids) + obj_log.info(f"批量删除产品属性值响应: {resp}") + return resp + + @allure.step("获得产品属性值详情") + def kw_joyhub_product_attr_data_get_get(self, product_attr_data_id): + """ + 获得产品属性值详情业务关键字 + :param product_attr_data_id: 产品属性值ID + :return: 响应结果 + """ + obj_log.info(f"获得产品属性值详情 - product_attr_data_id: {product_attr_data_id}") + resp = self.kw_in_joyhub_product_attr_data_get_get(product_attr_data_id) + obj_log.info(f"获得产品属性值详情响应: {resp}") + return resp + + @allure.step("获得产品属性值分页") + def kw_joyhub_product_attr_data_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得产品属性值分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得产品属性值分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_product_attr_data_page_get(**params) + obj_log.info(f"获得产品属性值分页响应: {resp}") + return resp + + @allure.step("更新产品属性值") + def kw_joyhub_product_attr_data_update_put(self, product_attr_data_id, product_attr_type_id, attr_value, color=None): + """ + 更新产品属性值业务关键字 + :param product_attr_data_id: 产品属性值ID + :param product_attr_type_id: 关联产品属性表的主键ID + :param attr_value: 属性值名称 + :param color: 色卡(可选,颜色属性类型时使用) + :return: 响应结果 + """ + obj_log.info(f"更新产品属性值 - product_attr_data_id: {product_attr_data_id}, attr_value: {attr_value}") + + params = { + "id": product_attr_data_id, + "productAttrTypeId": product_attr_type_id, + "attrValue": attr_value + } + + if color is not None: + params["color"] = color + + resp = self.kw_in_joyhub_product_attr_data_update_put(**params) + obj_log.info(f"更新产品属性值响应: {resp}") + + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/ProductCateManage.py b/dulizhan/library/BusinessKw/JoyHub/ProductCateManage.py new file mode 100644 index 0000000..cd13ff0 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/ProductCateManage.py @@ -0,0 +1,145 @@ +# -*- coding:utf-8 -*- +""" +产品分类管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class ProductCateManage(DlzhanInterface): + """产品分类管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建产品分类") + def kw_joyhub_product_cate_create_post(self, cate_name, id=0, cate_type=1, status=1, rank_num=1): + """ + 创建产品分类业务关键字 + :param id: 主键ID,新增为0 + :param cate_name: 产品分类名称 + :param cate_type: 类型(普通产品=1,积分产品=2) + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :return: 响应结果 + """ + obj_log.info(f"创建产品分类 - cate_name: {cate_name}, cate_type: {cate_type}") + + params = { + "id": id, + "cateName": cate_name, + "cateType": cate_type, + "status": status, + "rankNum": rank_num + } + + resp = self.kw_in_joyhub_product_cate_create_post(**params) + obj_log.info(f"创建产品分类响应: {resp}") + + return resp + + @allure.step("删除产品分类") + def kw_joyhub_product_cate_delete_delete(self, product_cate_id): + """ + 删除产品分类业务关键字 + :param product_cate_id: 产品分类ID + :return: 响应结果 + """ + obj_log.info(f"删除产品分类 - product_cate_id: {product_cate_id}") + resp = self.kw_in_joyhub_product_cate_delete_delete(product_cate_id) + obj_log.info(f"删除产品分类响应: {resp}") + return resp + + @allure.step("批量删除产品分类") + def kw_joyhub_product_cate_delete_list_delete(self, ids): + """ + 批量删除产品分类业务关键字 + :param ids: 产品分类ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除产品分类 - ids: {ids}") + resp = self.kw_in_joyhub_product_cate_delete_list_delete(ids) + obj_log.info(f"批量删除产品分类响应: {resp}") + return resp + + @allure.step("获得产品分类详情") + def kw_joyhub_product_cate_get_get(self, product_cate_id): + """ + 获得产品分类详情业务关键字 + :param product_cate_id: 产品分类ID + :return: 响应结果 + """ + obj_log.info(f"获得产品分类详情 - product_cate_id: {product_cate_id}") + resp = self.kw_in_joyhub_product_cate_get_get(product_cate_id) + obj_log.info(f"获得产品分类详情响应: {resp}") + return resp + + @allure.step("获得产品分类分页") + def kw_joyhub_product_cate_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得产品分类分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得产品分类分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_product_cate_page_get(**params) + obj_log.info(f"获得产品分类分页响应: {resp}") + return resp + + @allure.step("更新产品分类") + def kw_joyhub_product_cate_update_put(self, product_cate_id, cate_name, cate_type=1, status=1, rank_num=1): + """ + 更新产品分类业务关键字 + :param product_cate_id: 产品分类ID + :param cate_name: 产品分类名称 + :param cate_type: 类型(普通产品=1,积分产品=2) + :param status: 状态 (1正常 2停用) + :param rank_num: 排序号 + :return: 响应结果 + """ + obj_log.info(f"更新产品分类 - product_cate_id: {product_cate_id}, cate_name: {cate_name}") + + params = { + "id": product_cate_id, + "cateName": cate_name, + "cateType": cate_type, + "status": status, + "rankNum": rank_num + } + + resp = self.kw_in_joyhub_product_cate_update_put(**params) + obj_log.info(f"更新产品分类响应: {resp}") + + return resp + + @allure.step("修改产品分类启用/停用状态") + def kw_joyhub_product_cate_change_status_put(self, product_cate_id, status): + """ + 修改产品分类启用/停用状态业务关键字 + :param product_cate_id: 产品分类ID + :param status: 状态 (1正常 2停用) + :return: 响应结果 + """ + obj_log.info(f"修改产品分类状态 - product_cate_id: {product_cate_id}, status: {status}") + + params = { + "id": product_cate_id, + "status": status + } + + resp = self.kw_in_joyhub_product_cate_change_status_put(**params) + obj_log.info(f"修改产品分类状态响应: {resp}") + + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/ProductManage.py b/dulizhan/library/BusinessKw/JoyHub/ProductManage.py new file mode 100644 index 0000000..3824695 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/ProductManage.py @@ -0,0 +1,269 @@ +# -*- coding:utf-8 -*- +""" +产品管理业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class ProductManage(DlzhanInterface): + """产品管理业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("创建产品") + def kw_joyhub_product_create_post(self, product_name, product_cate_id, shipping_template_id, route, intro, + brand_id, product_attrs, product_skus, id=0, product_type=1, + status=1, rank_num=None, seo_title=None, seo_keyword=None, + seo_description=None, single_user_exchange_limit=None, + single_product_exchange_limit=None, product_details=None): + """ + 创建产品业务关键字 + :param id: 主键,新增为0 + :param product_type: 产品类型(普通产品=1,积分产品=2) + :param product_name: 产品名称 + :param product_cate_id: 产品分类 + :param shipping_template_id: 运费模板ID + :param route: 跳转路由 + :param intro: 产品简介 + :param brand_id: 品牌id + :param status: 状态(1上架,2下架) + :param rank_num: 序号(可选) + :param seo_title: SEO标题(可选) + :param seo_keyword: SEO关键词(可选) + :param seo_description: SEO描述(可选) + :param single_user_exchange_limit: 单用户兑换次数限制(可选) + :param single_product_exchange_limit: 单次兑换数量限制(可选) + :param product_attrs: 产品规格类型关联列表 + :param product_skus: 产品规格列表 + :param product_details: 产品详情列表(可选) + :return: 响应结果 + """ + obj_log.info(f"创建产品 - product_name: {product_name}, product_type: {product_type}") + + params = { + "id": id, + "productType": product_type, + "productName": product_name, + "productCateId": product_cate_id, + "shippingTemplateId": shipping_template_id, + "route": route, + "intro": intro, + "brandId": brand_id, + "status": status, + "productAttrs": product_attrs, + "productSkus": product_skus + } + + if rank_num is not None: + params["rankNum"] = rank_num + if seo_title is not None: + params["seoTitle"] = seo_title + if seo_keyword is not None: + params["seoKeyword"] = seo_keyword + if seo_description is not None: + params["seoDescription"] = seo_description + if single_user_exchange_limit is not None: + params["singleUserExchangeLimit"] = single_user_exchange_limit + if single_product_exchange_limit is not None: + params["singleProductExchangeLimit"] = single_product_exchange_limit + if product_details is not None: + params["productDetails"] = product_details + + resp = self.kw_in_joyhub_product_create_post(**params) + obj_log.info(f"创建产品响应: {resp}") + + return resp + + @allure.step("删除产品") + def kw_joyhub_product_delete_delete(self, product_id): + """ + 删除产品业务关键字 + :param product_id: 产品ID + :return: 响应结果 + """ + obj_log.info(f"删除产品 - product_id: {product_id}") + resp = self.kw_in_joyhub_product_delete_delete(product_id) + obj_log.info(f"删除产品响应: {resp}") + return resp + + @allure.step("批量删除产品") + def kw_joyhub_product_delete_list_delete(self, ids): + """ + 批量删除产品业务关键字 + :param ids: 产品ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除产品 - ids: {ids}") + resp = self.kw_in_joyhub_product_delete_list_delete(ids) + obj_log.info(f"批量删除产品响应: {resp}") + return resp + + @allure.step("获得产品详情") + def kw_joyhub_product_get_get(self, product_id): + """ + 获得产品详情业务关键字 + :param product_id: 产品ID + :return: 响应结果 + """ + obj_log.info(f"获得产品详情 - product_id: {product_id}") + resp = self.kw_in_joyhub_product_get_get(product_id) + obj_log.info(f"获得产品详情响应: {resp}") + return resp + + @allure.step("获得产品分页") + def kw_joyhub_product_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得产品分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得产品分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_product_page_get(**params) + obj_log.info(f"获得产品分页响应: {resp}") + return resp + + @allure.step("获得产品规格类型关联列表") + def kw_joyhub_product_product_attr_list_by_product_id_get(self, product_id): + """ + 获得产品规格类型关联列表业务关键字 + :param product_id: 产品ID + :return: 响应结果 + """ + obj_log.info(f"获得产品规格类型关联列表 - product_id: {product_id}") + resp = self.kw_in_joyhub_product_product_attr_list_by_product_id_get(product_id) + obj_log.info(f"获得产品规格类型关联列表响应: {resp}") + return resp + + @allure.step("获得产品详情列表") + def kw_joyhub_product_product_detail_list_by_product_id_get(self, product_id): + """ + 获得产品详情列表业务关键字 + :param product_id: 产品ID + :return: 响应结果 + """ + obj_log.info(f"获得产品详情列表 - product_id: {product_id}") + resp = self.kw_in_joyhub_product_product_detail_list_by_product_id_get(product_id) + obj_log.info(f"获得产品详情列表响应: {resp}") + return resp + + @allure.step("获得产品规格列表") + def kw_joyhub_product_product_sku_list_by_product_id_get(self, product_id): + """ + 获得产品规格列表业务关键字 + :param product_id: 产品ID + :return: 响应结果 + """ + obj_log.info(f"获得产品规格列表 - product_id: {product_id}") + resp = self.kw_in_joyhub_product_product_sku_list_by_product_id_get(product_id) + obj_log.info(f"获得产品规格列表响应: {resp}") + return resp + + @allure.step("获得产品及规格列表-优惠券中使用") + def kw_joyhub_product_product_sku_list_get(self, **kwargs): + """ + 获得产品及规格列表-优惠券中使用业务关键字 + :param kwargs: 查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得产品及规格列表 - params: {kwargs}") + resp = self.kw_in_joyhub_product_product_sku_list_get(**kwargs) + obj_log.info(f"获得产品及规格列表响应: {resp}") + return resp + + @allure.step("更新产品") + def kw_joyhub_product_update_put(self, product_id, product_name, product_cate_id, shipping_template_id, route, intro, + brand_id, product_attrs, product_skus, product_type=1, + status=1, rank_num=None, seo_title=None, seo_keyword=None, + seo_description=None, single_user_exchange_limit=None, + single_product_exchange_limit=None, product_details=None): + """ + 更新产品业务关键字 + :param product_id: 产品ID + :param product_type: 产品类型(普通产品=1,积分产品=2) + :param product_name: 产品名称 + :param product_cate_id: 产品分类 + :param shipping_template_id: 运费模板ID + :param route: 跳转路由 + :param intro: 产品简介 + :param brand_id: 品牌id + :param status: 状态(1上架,2下架) + :param rank_num: 序号(可选) + :param seo_title: SEO标题(可选) + :param seo_keyword: SEO关键词(可选) + :param seo_description: SEO描述(可选) + :param single_user_exchange_limit: 单用户兑换次数限制(可选) + :param single_product_exchange_limit: 单次兑换数量限制(可选) + :param product_attrs: 产品规格类型关联列表 + :param product_skus: 产品规格列表 + :param product_details: 产品详情列表(可选) + :return: 响应结果 + """ + obj_log.info(f"更新产品 - product_id: {product_id}, product_name: {product_name}") + + params = { + "id": product_id, + "productType": product_type, + "productName": product_name, + "productCateId": product_cate_id, + "shippingTemplateId": shipping_template_id, + "route": route, + "intro": intro, + "brandId": brand_id, + "status": status, + "productAttrs": product_attrs, + "productSkus": product_skus + } + + if rank_num is not None: + params["rankNum"] = rank_num + if seo_title is not None: + params["seoTitle"] = seo_title + if seo_keyword is not None: + params["seoKeyword"] = seo_keyword + if seo_description is not None: + params["seoDescription"] = seo_description + if single_user_exchange_limit is not None: + params["singleUserExchangeLimit"] = single_user_exchange_limit + if single_product_exchange_limit is not None: + params["singleProductExchangeLimit"] = single_product_exchange_limit + if product_details is not None: + params["productDetails"] = product_details + + resp = self.kw_in_joyhub_product_update_put(**params) + obj_log.info(f"更新产品响应: {resp}") + + return resp + + @allure.step("批量上下架产品") + def kw_joyhub_product_change_status_put(self, ids, status): + """ + 批量上下架产品业务关键字 + :param ids: 产品ID列表 + :param status: 状态(1上架,2下架) + :return: 响应结果 + """ + obj_log.info(f"批量上下架产品 - ids: {ids}, status: {status}") + + params = { + "ids": ids, + "status": status + } + + resp = self.kw_in_joyhub_product_change_status_put(**params) + obj_log.info(f"批量上下架产品响应: {resp}") + + return resp diff --git a/dulizhan/library/BusinessKw/JoyHub/ProductPaymentRecommendManage.py b/dulizhan/library/BusinessKw/JoyHub/ProductPaymentRecommendManage.py new file mode 100644 index 0000000..042e776 --- /dev/null +++ b/dulizhan/library/BusinessKw/JoyHub/ProductPaymentRecommendManage.py @@ -0,0 +1,124 @@ +# -*- coding:utf-8 -*- +""" +支付页产品推荐业务关键字层 +""" +import allure +from dulizhan.library.Dlizhan_interface import DlzhanInterface +from base_framework.public_tools import log + +obj_log = log.get_logger() + + +class ProductPaymentRecommendManage(DlzhanInterface): + """支付页产品推荐业务关键字类""" + + def __init__(self): + super().__init__() + + @allure.step("修改支付页产品推荐排序号") + def kw_joyhub_product_payment_recommend_change_rank_num_put(self, recommend_id, rank_num): + """ + 修改支付页产品推荐排序号业务关键字 + :param recommend_id: 推荐ID + :param rank_num: 排序号 + :return: 响应结果 + """ + obj_log.info(f"修改支付页产品推荐排序号 - recommend_id: {recommend_id}, rank_num: {rank_num}") + resp = self.kw_in_joyhub_product_payment_recommend_change_rank_num_put(id=recommend_id, rankNum=rank_num) + obj_log.info(f"修改支付页产品推荐排序号响应: {resp}") + return resp + + @allure.step("修改支付页产品推荐状态") + def kw_joyhub_product_payment_recommend_change_status_put(self, recommend_id, recommend_status): + """ + 修改支付页产品推荐状态业务关键字 + :param recommend_id: 推荐ID + :param recommend_status: 推荐状态 + :return: 响应结果 + """ + obj_log.info(f"修改支付页产品推荐状态 - recommend_id: {recommend_id}, recommend_status: {recommend_status}") + resp = self.kw_in_joyhub_product_payment_recommend_change_status_put(id=recommend_id, recommendStatus=recommend_status) + obj_log.info(f"修改支付页产品推荐状态响应: {resp}") + return resp + + @allure.step("创建支付页产品推荐") + def kw_joyhub_product_payment_recommend_create_post(self, product_ids, recommend_id=None): + """ + 创建支付页产品推荐业务关键字 + :param product_ids: 产品ID列表 + :param recommend_id: 推荐ID + :return: 响应结果 + """ + obj_log.info(f"创建支付页产品推荐 - product_ids: {product_ids}") + params = {"productIds": product_ids} + if recommend_id is not None: + params["id"] = recommend_id + resp = self.kw_in_joyhub_product_payment_recommend_create_post(**params) + obj_log.info(f"创建支付页产品推荐响应: {resp}") + return resp + + @allure.step("删除支付页产品推荐") + def kw_joyhub_product_payment_recommend_delete_delete(self, recommend_id): + """ + 删除支付页产品推荐业务关键字 + :param recommend_id: 推荐ID + :return: 响应结果 + """ + obj_log.info(f"删除支付页产品推荐 - recommend_id: {recommend_id}") + resp = self.kw_in_joyhub_product_payment_recommend_delete_delete(recommend_id) + obj_log.info(f"删除支付页产品推荐响应: {resp}") + return resp + + @allure.step("批量删除支付页产品推荐") + def kw_joyhub_product_payment_recommend_delete_list_delete(self, ids): + """ + 批量删除支付页产品推荐业务关键字 + :param ids: 推荐ID列表 + :return: 响应结果 + """ + obj_log.info(f"批量删除支付页产品推荐 - ids: {ids}") + resp = self.kw_in_joyhub_product_payment_recommend_delete_list_delete(ids) + obj_log.info(f"批量删除支付页产品推荐响应: {resp}") + return resp + + @allure.step("获得支付页产品推荐分页") + def kw_joyhub_product_payment_recommend_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得支付页产品推荐分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得支付页产品推荐分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_product_payment_recommend_page_get(**params) + obj_log.info(f"获得支付页产品推荐分页响应: {resp}") + return resp + + @allure.step("获得C端支付页产品推荐分页") + def kw_joyhub_web_product_payment_recommend_page_get(self, page_no=1, page_size=10, **kwargs): + """ + 获得支付页产品推荐分页业务关键字 + :param page_no: 页码 + :param page_size: 每页大小 + :param kwargs: 其他查询条件 + :return: 响应结果 + """ + obj_log.info(f"获得支付页产品推荐分页 - page_no: {page_no}, page_size: {page_size}") + + params = { + "pageNo": page_no, + "pageSize": page_size + } + params.update(kwargs) + + resp = self.kw_in_joyhub_web_product_payment_recommend_page_get(**params) + obj_log.info(f"获得支付页产品推荐分页响应: {resp}") + return resp diff --git a/dulizhan/library/Dlizhan_interface.py b/dulizhan/library/Dlizhan_interface.py index 8b71c6d..98aa005 100644 --- a/dulizhan/library/Dlizhan_interface.py +++ b/dulizhan/library/Dlizhan_interface.py @@ -429,6 +429,265 @@ class DlzhanInterface: 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) + # ============ 国家信息管理接口 ============ + def kw_in_joyhub_address_country_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/address-country/create', is_check, '创建国家信息', **kwargs) + + def kw_in_joyhub_address_country_delete_delete(self, country_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/address-country/delete?id={country_id}', is_check, '删除国家信息') + + def kw_in_joyhub_address_country_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/address-country/delete-list?ids={ids_str}', is_check, '批量删除国家信息') + + def kw_in_joyhub_address_country_get_get(self, country_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/address-country/get?id={country_id}', is_check, '获得国家信息') + + def kw_in_joyhub_address_country_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/address-country/page', is_check, '获得国家信息分页', **kwargs) + + def kw_in_joyhub_address_country_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/address-country/update', is_check, '更新国家信息', **kwargs) + + def kw_in_joyhub_address_country_update_status_list_put(self, ids, status, is_check=''): + return self._joyhub_request('PUT', f'/admin-api/jh/address-country/update-status-list?ids={ids}&status={status}', is_check, '批量更新国家信息状态') + + # ============ blog分类管理接口 ============ + def kw_in_joyhub_blog_cate_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/blog-cate/create', is_check, '创建blog分类', **kwargs) + + def kw_in_joyhub_blog_cate_delete_delete(self, cate_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/blog-cate/delete?id={cate_id}', is_check, '删除blog分类') + + def kw_in_joyhub_blog_cate_get_get(self, cate_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/blog-cate/get?id={cate_id}', is_check, '获得blog分类') + + def kw_in_joyhub_blog_cate_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/blog-cate/page', is_check, '获得blog分类分页', **kwargs) + + def kw_in_joyhub_blog_cate_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/blog-cate/update', is_check, '更新blog分类', **kwargs) + + # ============ 二维码管理接口 ============ + def kw_in_joyhub_download_qrcode_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/download-qrcode/create', is_check, '创建二维码', **kwargs) + + def kw_in_joyhub_download_qrcode_get_get(self, qrcode_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/download-qrcode/get?id={qrcode_id}', is_check, '获得二维码') + + def kw_in_joyhub_download_qrcode_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/download-qrcode/page', is_check, '获得二维码分页', **kwargs) + + def kw_in_joyhub_download_qrcode_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/download-qrcode/update', is_check, '更新二维码', **kwargs) + + # ============ FAQ分类管理接口 ============ + def kw_in_joyhub_faq_cate_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/faq-cate/create', is_check, '创建FAQ分类', **kwargs) + + def kw_in_joyhub_faq_cate_delete_delete(self, faq_cate_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/faq-cate/delete?id={faq_cate_id}', is_check, '删除FAQ分类') + + def kw_in_joyhub_faq_cate_get_get(self, faq_cate_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/faq-cate/get?id={faq_cate_id}', is_check, '获得FAQ分类') + + def kw_in_joyhub_faq_cate_list_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/faq-cate/list', is_check, '获得FAQ分类列表', **kwargs) + + def kw_in_joyhub_faq_cate_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/faq-cate/update', is_check, '更新FAQ分类', **kwargs) + + # ============ FAQ数据管理接口 ============ + def kw_in_joyhub_faq_cate_list_get(self, is_check=''): + return self._joyhub_request('GET', '/admin-api/jh/faq/cate-list', is_check, '获得FAQ分类下拉列表') + + def kw_in_joyhub_faq_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/faq/create', is_check, '创建FAQ数据', **kwargs) + + def kw_in_joyhub_faq_delete_delete(self, faq_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/faq/delete?id={faq_id}', is_check, '删除FAQ数据') + + def kw_in_joyhub_faq_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/faq/delete-list?ids={ids_str}', is_check, '批量删除FAQ数据') + + def kw_in_joyhub_faq_get_get(self, faq_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/faq/get?id={faq_id}', is_check, '获得FAQ数据') + + def kw_in_joyhub_faq_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/faq/page', is_check, '获得FAQ数据分页', **kwargs) + + def kw_in_joyhub_faq_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/faq/update', is_check, '更新FAQ数据', **kwargs) + + # ============ news分类管理接口 ============ + def kw_in_joyhub_news_cate_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/news-cate/create', is_check, '创建news分类', **kwargs) + + def kw_in_joyhub_news_cate_delete_delete(self, news_cate_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/news-cate/delete?id={news_cate_id}', is_check, '删除news分类') + + def kw_in_joyhub_news_cate_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/news-cate/delete-list?ids={ids_str}', is_check, '批量删除news分类') + + def kw_in_joyhub_news_cate_get_get(self, news_cate_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/news-cate/get?id={news_cate_id}', is_check, '获得news分类') + + def kw_in_joyhub_news_cate_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/news-cate/page', is_check, '获得news分类分页', **kwargs) + + def kw_in_joyhub_news_cate_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/news-cate/update', is_check, '更新news分类', **kwargs) + + # ============ news管理接口 ============ + def kw_in_joyhub_news_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/news/create', is_check, '创建news管理', **kwargs) + + def kw_in_joyhub_news_delete_delete(self, news_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/news/delete?id={news_id}', is_check, '删除news管理') + + def kw_in_joyhub_news_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/news/delete-list?ids={ids_str}', is_check, '批量删除news管理') + + def kw_in_joyhub_news_get_get(self, news_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/news/get?id={news_id}', is_check, '获得news管理') + + def kw_in_joyhub_news_cate_relation_list_get(self, news_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/news/news-cate-relation/list-by-news-id?newsId={news_id}', is_check, '获得news分类关联列表') + + def kw_in_joyhub_news_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/news/page', is_check, '获得news管理分页', **kwargs) + + def kw_in_joyhub_news_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/news/update', is_check, '更新news管理', **kwargs) + + # ============ 产品分类管理接口 ============ + def kw_in_joyhub_product_cate_change_status_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-cate/change-status', is_check, '修改产品分类启用/停用状态', **kwargs) + + def kw_in_joyhub_product_cate_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/product-cate/create', is_check, '创建产品分类', **kwargs) + + def kw_in_joyhub_product_cate_delete_delete(self, product_cate_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/product-cate/delete?id={product_cate_id}', is_check, '删除产品分类') + + def kw_in_joyhub_product_cate_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/product-cate/delete-list?ids={ids_str}', is_check, '批量删除产品分类') + + def kw_in_joyhub_product_cate_get_get(self, product_cate_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product-cate/get?id={product_cate_id}', is_check, '获得产品分类') + + def kw_in_joyhub_product_cate_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/product-cate/page', is_check, '获得产品分类分页', **kwargs) + + def kw_in_joyhub_product_cate_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-cate/update', is_check, '更新产品分类', **kwargs) + + # ============ 产品属性管理接口 ============ + def kw_in_joyhub_product_attr_type_change_status_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-attr-type/change-status', is_check, '启用/停用产品属性状态', **kwargs) + + def kw_in_joyhub_product_attr_type_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/product-attr-type/create', is_check, '创建产品属性', **kwargs) + + def kw_in_joyhub_product_attr_type_delete_delete(self, product_attr_type_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/product-attr-type/delete?id={product_attr_type_id}', is_check, '删除产品属性') + + def kw_in_joyhub_product_attr_type_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/product-attr-type/delete-list?ids={ids_str}', is_check, '批量删除产品属性') + + def kw_in_joyhub_product_attr_type_get_get(self, product_attr_type_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product-attr-type/get?id={product_attr_type_id}', is_check, '获得产品属性') + + def kw_in_joyhub_product_attr_type_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/product-attr-type/page', is_check, '获得产品属性分页', **kwargs) + + def kw_in_joyhub_product_attr_type_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-attr-type/update', is_check, '更新产品属性', **kwargs) + + # ============ 产品属性值管理接口 ============ + def kw_in_joyhub_product_attr_data_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/product-attr-data/create', is_check, '创建产品属性值', **kwargs) + + def kw_in_joyhub_product_attr_data_delete_delete(self, product_attr_data_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/product-attr-data/delete?id={product_attr_data_id}', is_check, '删除产品属性值') + + def kw_in_joyhub_product_attr_data_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/product-attr-data/delete-list?ids={ids_str}', is_check, '批量删除产品属性值') + + def kw_in_joyhub_product_attr_data_get_get(self, product_attr_data_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product-attr-data/get?id={product_attr_data_id}', is_check, '获得产品属性值') + + def kw_in_joyhub_product_attr_data_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/product-attr-data/page', is_check, '获得产品属性值分页', **kwargs) + + def kw_in_joyhub_product_attr_data_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-attr-data/update', is_check, '更新产品属性值', **kwargs) + + # ============ 产品管理接口 ============ + def kw_in_joyhub_product_change_status_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product/change-status', is_check, '批量上下架产品', **kwargs) + + def kw_in_joyhub_product_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/product/create', is_check, '创建产品', **kwargs) + + def kw_in_joyhub_product_delete_delete(self, product_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/product/delete?id={product_id}', is_check, '删除产品') + + def kw_in_joyhub_product_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/product/delete-list?ids={ids_str}', is_check, '批量删除产品') + + def kw_in_joyhub_product_get_get(self, product_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product/get?id={product_id}', is_check, '获得产品') + + def kw_in_joyhub_product_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/product/page', is_check, '获得产品分页', **kwargs) + + def kw_in_joyhub_product_product_attr_list_by_product_id_get(self, product_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product/product-attr/list-by-product-id?productId={product_id}', is_check, '获得产品规格类型关联列表') + + def kw_in_joyhub_product_product_detail_list_by_product_id_get(self, product_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product/product-detail/list-by-product-id?productId={product_id}', is_check, '获得产品详情列表') + + def kw_in_joyhub_product_product_sku_list_by_product_id_get(self, product_id, is_check=''): + return self._joyhub_request('GET', f'/admin-api/jh/product/product-sku/list-by-product-id?productId={product_id}', is_check, '获得产品规格列表') + + def kw_in_joyhub_product_product_sku_list_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/product/product/sku-list', is_check, '获得产品及规格列表-优惠券中使用', **kwargs) + + def kw_in_joyhub_product_update_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product/update', is_check, '更新产品', **kwargs) + + # ============ 管理后台-支付页产品推荐接口 ============ + def kw_in_joyhub_product_payment_recommend_change_rank_num_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-payment-recommend/change-rank-num', is_check, '修改支付页产品推荐排序号', **kwargs) + + def kw_in_joyhub_product_payment_recommend_change_status_put(self, is_check='', **kwargs): + return self._joyhub_request('PUT', '/admin-api/jh/product-payment-recommend/change-status', is_check, '修改支付页产品推荐状态', **kwargs) + + def kw_in_joyhub_product_payment_recommend_create_post(self, is_check='', **kwargs): + return self._joyhub_request('POST', '/admin-api/jh/product-payment-recommend/create', is_check, '创建支付页产品推荐', **kwargs) + + def kw_in_joyhub_product_payment_recommend_delete_delete(self, recommend_id, is_check=''): + return self._joyhub_request('DELETE', f'/admin-api/jh/product-payment-recommend/delete?id={recommend_id}', is_check, '删除支付页产品推荐') + + def kw_in_joyhub_product_payment_recommend_delete_list_delete(self, ids, is_check=''): + ids_str = ','.join(map(str, ids)) + return self._joyhub_request('DELETE', f'/admin-api/jh/product-payment-recommend/delete-list?ids={ids_str}', is_check, '批量删除支付页产品推荐') + + def kw_in_joyhub_product_payment_recommend_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/admin-api/jh/product-payment-recommend/page', is_check, '获得支付页产品推荐分页', **kwargs) + + # ============ C端-支付页产品推荐接口 ============ + def kw_in_joyhub_web_product_payment_recommend_page_get(self, is_check='', **kwargs): + return self._joyhub_request('GET', '/web-api/jh/product-payment-recommend/page', is_check, '获得支付页产品推荐分页', **kwargs) + if __name__ == '__main__': test = DlzhanInterface() diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AddressCountry.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AddressCountry.py new file mode 100644 index 0000000..2b9cc9c --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_AddressCountry.py @@ -0,0 +1,279 @@ +# -*- coding:utf-8 -*- +""" +国家信息管理接口测试用例 +""" +import pytest +import json +import time +import logging +import allure + +from dulizhan.library.BusinessKw.JoyHub.AddressCountryManage import AddressCountryManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 国家信息管理模块") +class TestAddressCountryManage: + country_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = AddressCountryManage() + username = "joytest" + password = "Zhou1599" + + # 登录逻辑 + cls.test_case._clear_user_fingerprint(username) + + import requests + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + pytest.skip("登录失败,跳过所有测试") + + @allure.story("验证登录") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestAddressCountryManage.token_set is True, "登录失败" + logging.info("登录验证通过") + + @allure.story("验证获得国家信息分页") + @allure.title("测试获得国家信息分页接口") + def test_joyhub_address_country_page_get(self): + """测试获得国家信息分页接口""" + with allure.step("1. 调用接口"): + resp = self.test_case.kw_joyhub_address_country_page_get(page_num=1, page_size=10) + 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"], dict), "data字段不是字典类型" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + assert "total" in resp["data"], "响应中缺少total字段" + assert isinstance(resp["data"]["total"], int), "total字段不是整数类型" + logging.info("获得国家信息分页列表验证通过") + + @allure.story("验证创建和更新国家信息") + @allure.title("测试创建和更新国家信息接口") + def test_joyhub_address_country_create_and_update(self): + """测试创建和更新国家信息接口""" + with allure.step("1. 准备创建请求参数"): + timestamp = int(time.time()) + params = { + "country_code": f"TC{timestamp}", + "country_name": f"测试国家_{timestamp}", + "country_name_en": f"Test Country {timestamp}", + "phone_code": f"+{timestamp % 1000}", + "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_address_country_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字段不是整数类型" + country_id = resp["data"] + TestAddressCountryManage.country_id = country_id + logging.info(f"创建国家信息成功,国家信息ID: {country_id}") + + with allure.step("4. 调用更新接口"): + update_timestamp = int(time.time()) + update_params = { + "country_id": country_id, + "country_code": f"TC{update_timestamp}", + "country_name": f"已更新国家_{update_timestamp}", + "country_name_en": f"Updated Country {update_timestamp}", + "phone_code": f"+{update_timestamp % 1000}", + "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_address_country_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("5. 验证更新响应"): + 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_address_country_get_get(self): + """测试获得国家信息详情接口""" + with allure.step("1. 先创建一个国家信息"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_address_country_create_post( + country_code=f"TC{timestamp}", + country_name=f"详情测试国家_{timestamp}", + country_name_en=f"Detail Test Country {timestamp}", + phone_code=f"+{timestamp % 1000}", + status=2 + ) + country_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not country_id: + pytest.skip("创建测试国家信息失败,跳过详情测试") + + allure.attach(json.dumps({"id": country_id}, ensure_ascii=False), name="国家信息ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用获得详情接口"): + resp = self.test_case.kw_joyhub_address_country_get_get(country_id=country_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"] == country_id, "返回的ID与请求的不一致" + logging.info("获得国家信息详情验证通过") + + @allure.story("验证删除国家信息") + @allure.title("测试删除国家信息接口") + def test_joyhub_address_country_delete_delete(self): + """测试删除国家信息接口""" + with allure.step("1. 先创建一个测试国家信息"): + timestamp = int(time.time()) + create_resp = self.test_case.kw_joyhub_address_country_create_post( + country_code=f"TC{timestamp}", + country_name=f"待删除国家_{timestamp}", + country_name_en=f"Delete Test Country {timestamp}", + phone_code=f"+{timestamp % 1000}", + status=2 + ) + country_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None + + if not country_id: + pytest.skip("创建测试国家信息失败,跳过删除测试") + + allure.attach(json.dumps({"id": country_id}, ensure_ascii=False), name="国家信息ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用删除接口"): + resp = self.test_case.kw_joyhub_address_country_delete_delete(country_id=country_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_address_country_delete_list_delete(self): + """测试批量删除国家信息接口""" + with allure.step("1. 先创建两个测试国家信息"): + timestamp = int(time.time()) + resp1 = self.test_case.kw_joyhub_address_country_create_post( + country_code=f"TC{timestamp}", + country_name=f"批量删除国家1_{timestamp}", + country_name_en=f"Batch Delete Country 1 {timestamp}", + phone_code=f"+{timestamp % 1000}", + status=2 + ) + resp2 = self.test_case.kw_joyhub_address_country_create_post( + country_code=f"TC{timestamp+1}", + country_name=f"批量删除国家2_{timestamp}", + country_name_en=f"Batch Delete Country 2 {timestamp}", + phone_code=f"+{(timestamp+1) % 1000}", + status=2 + ) + + country_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None + country_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None + + if not country_id1 or not country_id2: + pytest.skip("创建测试国家信息失败,跳过批量删除测试") + + country_ids = [country_id1, country_id2] + allure.attach(json.dumps({"ids": country_ids}, ensure_ascii=False), name="待删除国家信息IDs", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用批量删除接口"): + resp = self.test_case.kw_joyhub_address_country_delete_list_delete(country_ids=country_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_address_country_update_status_list_put(self): + """测试批量更新国家信息状态接口""" + with allure.step("1. 先创建两个测试国家信息"): + timestamp = int(time.time()) + resp1 = self.test_case.kw_joyhub_address_country_create_post( + country_code=f"TC{timestamp}", + country_name=f"状态更新国家1_{timestamp}", + country_name_en=f"Status Update Country 1 {timestamp}", + phone_code=f"+{timestamp % 1000}", + status=1 + ) + resp2 = self.test_case.kw_joyhub_address_country_create_post( + country_code=f"TC{timestamp+1}", + country_name=f"状态更新国家2_{timestamp}", + country_name_en=f"Status Update Country 2 {timestamp}", + phone_code=f"+{(timestamp+1) % 1000}", + status=1 + ) + + country_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None + country_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None + + if not country_id1 or not country_id2: + pytest.skip("创建测试国家信息失败,跳过批量更新状态测试") + + country_ids = [country_id1, country_id2] + allure.attach(json.dumps({"ids": country_ids, "status": 2}, ensure_ascii=False), name="批量更新状态参数", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用批量更新状态接口"): + resp = self.test_case.kw_joyhub_address_country_update_status_list_put(country_ids=country_ids, status=2) + 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("批量更新国家信息状态验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_BlogCate.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_BlogCate.py new file mode 100644 index 0000000..e4b1d88 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_BlogCate.py @@ -0,0 +1,200 @@ +# -*- coding:utf-8 -*- +""" +blog分类管理接口测试用例 +""" +import pytest +import json +import time +import logging +import allure + +from dulizhan.library.BusinessKw.JoyHub.BlogCateManage import BlogCateManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - blog分类管理模块") +class TestBlogCateManage: + cate_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = BlogCateManage() + username = "joytest" + password = "Zhou1599" + + cls.test_case._clear_user_fingerprint(username) + + import requests + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + pytest.skip("登录失败,跳过所有测试") + + @allure.story("验证登录") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestBlogCateManage.token_set is True, "登录失败" + logging.info("登录验证通过") + + @allure.story("验证获得blog分类分页") + @allure.title("测试获得blog分类分页接口") + def test_joyhub_blog_cate_page_get(self): + """测试获得blog分类分页接口""" + with allure.step("1. 调用接口"): + resp = self.test_case.kw_joyhub_blog_cate_page_get(page_num=1, page_size=10) + 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"], dict), "data字段不是字典类型" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + assert "total" in resp["data"], "响应中缺少total字段" + assert isinstance(resp["data"]["total"], int), "total字段不是整数类型" + logging.info("获得blog分类分页列表验证通过") + + @allure.story("验证创建和删除blog分类") + @allure.title("测试创建和删除blog分类接口") + def test_joyhub_blog_cate_create_and_delete(self): + """测试创建和删除blog分类接口""" + with allure.step("1. 准备创建请求参数"): + timestamp = int(time.time()) + params = { + "name": f"测试blog分类_{timestamp}", + "status": 1, + "cover_image": "https://example.com/cover.jpg" + } + 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_blog_cate_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], int), "data字段不是整数类型" + cate_id = resp["data"] + TestBlogCateManage.cate_id = cate_id + logging.info(f"创建blog分类成功,blog分类ID: {cate_id}") + + with allure.step("4. 调用删除接口"): + delete_resp = self.test_case.kw_joyhub_blog_cate_delete_delete(cate_id=cate_id) + allure.attach(json.dumps(delete_resp, ensure_ascii=False, indent=2), name="删除响应数据", attachment_type=allure.attachment_type.JSON) + + with allure.step("5. 验证删除响应"): + assert delete_resp is not None, "响应为空" + assert "code" in delete_resp, "响应中缺少code字段" + assert delete_resp["code"] == 0, f"删除失败,code={delete_resp.get('code')}, msg={delete_resp.get('msg')}" + assert "data" in delete_resp, "响应中缺少data字段" + assert delete_resp["data"] is True, "删除blog分类失败" + logging.info("创建并删除blog分类验证通过") + + @allure.story("验证获得blog分类详情") + @allure.title("测试获得blog分类详情接口") + def test_joyhub_blog_cate_get_get(self): + """测试获得blog分类详情接口""" + with allure.step("1. 从分页获取现有blog分类ID"): + page_resp = self.test_case.kw_joyhub_blog_cate_page_get(page_num=1, page_size=10) + if not page_resp or page_resp.get("code") != 0: + pytest.skip("获取分页失败,跳过详情测试") + + data_list = page_resp.get("data", {}).get("list", []) + if not data_list: + pytest.skip("暂无blog分类数据,跳过详情测试") + + cate_id = data_list[0].get("id") + allure.attach(json.dumps({"id": cate_id}, ensure_ascii=False), name="blog分类ID", attachment_type=allure.attachment_type.TEXT) + + with allure.step("2. 调用获得详情接口"): + resp = self.test_case.kw_joyhub_blog_cate_get_get(cate_id=cate_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"] == cate_id, "返回的ID与请求的不一致" + logging.info("获得blog分类详情验证通过") + + @allure.story("验证创建和更新blog分类") + @allure.title("测试创建和更新blog分类接口") + def test_joyhub_blog_cate_create_and_update(self): + """测试创建和更新blog分类接口""" + with allure.step("1. 创建blog分类"): + timestamp = int(time.time()) + create_params = { + "name": f"测试更新blog分类_{timestamp}", + "status": 1, + "cover_image": "https://example.com/cover.jpg" + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_blog_cate_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + cate_id = create_resp["data"] + logging.info(f"创建blog分类成功,blog分类ID: {cate_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "cate_id": cate_id, + "name": f"测试更新blog分类_{timestamp}", + "status": 1, + "cover_image": "https://example.com/cover_updated.jpg" + } + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_blog_cate_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + if update_resp["code"] == 500: + logging.warning(f"更新接口返回500错误: {update_resp}") + pytest.skip("更新接口服务端错误,跳过测试") + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新blog分类失败" + logging.info("创建并更新blog分类验证通过") + + with allure.step("4. 清理测试数据"): + delete_resp = self.test_case.kw_joyhub_blog_cate_delete_delete(cate_id=cate_id) + if delete_resp and delete_resp.get("code") == 0: + logging.info("清理测试数据成功") + else: + logging.warning(f"清理测试数据失败: {delete_resp}") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_DownloadQrcode.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_DownloadQrcode.py new file mode 100644 index 0000000..2d4ad90 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_DownloadQrcode.py @@ -0,0 +1,162 @@ +# -*- coding:utf-8 -*- +""" +二维码管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.DownloadQrcodeManage import DownloadQrcodeManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 二维码管理模块") +class TestDownloadQrcodeManage: + qrcode_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = DownloadQrcodeManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestDownloadQrcodeManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得二维码分页列表") + @allure.title("测试获得二维码分页列表接口") + def test_joyhub_download_qrcode_page_get(self): + """测试获得二维码分页列表接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_download_qrcode_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "pageResult" in resp["data"], "响应中缺少pageResult字段" + assert "list" in resp["data"]["pageResult"], "响应中缺少list字段" + assert isinstance(resp["data"]["pageResult"]["list"], list), "list字段不是列表类型" + assert "total" in resp["data"]["pageResult"], "响应中缺少total字段" + assert isinstance(resp["data"]["pageResult"]["total"], int), "total字段不是整数类型" + logging.info("获得二维码分页列表验证通过") + + @allure.story("验证获得二维码详情") + @allure.title("测试获得二维码详情接口") + def test_joyhub_download_qrcode_get_get(self): + """测试获得二维码详情接口""" + with allure.step("1. 从分页获取现有二维码ID"): + page_resp = self.test_case.kw_joyhub_download_qrcode_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("pageResult", {}).get("list"), "没有找到可用的二维码数据" + qrcode_id = page_resp["data"]["pageResult"]["list"][0].get("id") + assert qrcode_id, "二维码ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_download_qrcode_get_get(qrcode_id=qrcode_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == qrcode_id, "返回的ID与请求的ID不一致" + assert "title" in resp["data"], "响应中缺少title字段" + assert isinstance(resp["data"]["title"], str), "title字段不是字符串类型" + logging.info("获得二维码详情验证通过") + + @allure.story("验证创建和更新二维码") + @allure.title("测试创建和更新二维码接口") + def test_joyhub_download_qrcode_create_and_update(self): + """测试创建和更新二维码接口""" + created_title = None + + with allure.step("1. 创建二维码"): + timestamp = int(time.time()) + created_title = f"测试二维码_{timestamp}" + create_params = { + "title": created_title, + "status": 1 + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_download_qrcode_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + qrcode_id = create_resp["data"] + TestDownloadQrcodeManage.qrcode_id = qrcode_id + logging.info(f"创建二维码成功,ID: {qrcode_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "qrcode_id": qrcode_id, + "title": f"测试二维码_{timestamp}_updated", + "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_download_qrcode_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新二维码失败" + logging.info("创建并更新二维码验证通过") + + @classmethod + def teardown_class(cls): + """在整个测试类结束时清理测试数据""" + logging.info("=============================================") + logging.info("=========== 清理测试数据 ============") + logging.info("=============================================") + + # 从数据库表jh_download_qrcode中删除测试数据 + if cls.qrcode_id: + cls.test_case.clean_test_data_from_db(f"测试二维码_{cls.qrcode_id}") + else: + # 如果没有获取到qrcode_id,尝试删除所有测试数据 + cls.test_case.clean_test_data_from_db("测试二维码_") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Faq.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Faq.py new file mode 100644 index 0000000..04f11ec --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Faq.py @@ -0,0 +1,181 @@ +# -*- coding:utf-8 -*- +""" +FAQ数据管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.FaqManage import FaqManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - FAQ数据管理模块") +class TestFaqManage: + faq_id = None + faq_cate_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = FaqManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + + # 获取FAQ分类ID供后续使用 + cate_list_resp = cls.test_case.kw_joyhub_faq_cate_list_get() + if cate_list_resp.get('code') == 0 and cate_list_resp.get('data'): + cls.faq_cate_id = cate_list_resp['data'][0].get('faqCateId') + logging.info(f"获取到FAQ分类ID: {cls.faq_cate_id}") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestFaqManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得FAQ数据分页") + @allure.title("测试获得FAQ数据分页接口") + def test_joyhub_faq_page_get(self): + """测试获得FAQ数据分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_faq_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得FAQ数据分页验证通过") + + @allure.story("验证获得FAQ数据详情") + @allure.title("测试获得FAQ数据详情接口") + def test_joyhub_faq_get_get(self): + """测试获得FAQ数据详情接口""" + with allure.step("1. 从分页获取现有FAQ数据ID"): + page_resp = self.test_case.kw_joyhub_faq_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的FAQ数据" + faq_id = page_resp["data"]["list"][0].get("id") + assert faq_id, "FAQ数据ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_faq_get_get(faq_id=faq_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == faq_id, "返回的ID与请求的ID不一致" + assert "question" in resp["data"], "响应中缺少question字段" + assert isinstance(resp["data"]["question"], str), "question字段不是字符串类型" + logging.info("获得FAQ数据详情验证通过") + + @allure.story("验证创建和更新FAQ数据") + @allure.title("测试创建和更新FAQ数据接口") + def test_joyhub_faq_create_and_update(self): + """测试创建和更新FAQ数据接口""" + if not TestFaqManage.faq_cate_id: + pytest.skip("没有可用的FAQ分类,跳过测试") + + with allure.step("1. 创建FAQ数据"): + timestamp = int(time.time()) + create_params = { + "faq_cate_id": TestFaqManage.faq_cate_id, + "question": f"测试问题_{timestamp}", + "answer": f"测试回答内容_{timestamp}", + "rank_num": 1, + "lang": "zh_CN", + "is_hot": 0, + "status": 1 + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_faq_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + faq_id = create_resp["data"] + TestFaqManage.faq_id = faq_id + logging.info(f"创建FAQ数据成功,ID: {faq_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "faq_id": faq_id, + "faq_cate_id": TestFaqManage.faq_cate_id, + "question": f"测试问题_{timestamp}_updated", + "answer": f"测试回答内容_{timestamp}_updated", + "rank_num": 2, + "lang": "en", + "is_hot": 1, + "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_faq_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新FAQ数据失败" + logging.info("创建并更新FAQ数据验证通过") + + @allure.story("验证删除FAQ数据") + @allure.title("测试删除FAQ数据接口") + def test_joyhub_faq_delete_delete(self): + """测试删除FAQ数据接口""" + if not TestFaqManage.faq_id: + pytest.skip("没有可删除的FAQ数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_faq_delete_delete(faq_id=TestFaqManage.faq_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除FAQ数据失败" + logging.info("删除FAQ数据验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_FaqCate.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_FaqCate.py new file mode 100644 index 0000000..3b2f5c8 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_FaqCate.py @@ -0,0 +1,166 @@ +# -*- coding:utf-8 -*- +""" +FAQ分类管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.FaqCateManage import FaqCateManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - FAQ分类管理模块") +class TestFaqCateManage: + faq_cate_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = FaqCateManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestFaqCateManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得FAQ分类列表") + @allure.title("测试获得FAQ分类列表接口") + def test_joyhub_faq_cate_list_get(self): + """测试获得FAQ分类列表接口""" + with allure.step("1. 调用列表接口"): + resp = self.test_case.kw_joyhub_faq_cate_list_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], list), "data字段不是列表类型" + logging.info("获得FAQ分类列表验证通过") + + @allure.story("验证获得FAQ分类详情") + @allure.title("测试获得FAQ分类详情接口") + def test_joyhub_faq_cate_get_get(self): + """测试获得FAQ分类详情接口""" + with allure.step("1. 从列表获取现有FAQ分类ID"): + list_resp = self.test_case.kw_joyhub_faq_cate_list_get() + assert list_resp.get("code") == 0, f"获取列表失败,code={list_resp.get('code')}, msg={list_resp.get('msg')}" + assert list_resp.get("data"), "没有找到可用的FAQ分类数据" + faq_cate_id = list_resp["data"][0].get("id") or list_resp["data"][0].get("faqCateId") + assert faq_cate_id, "FAQ分类ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_faq_cate_get_get(faq_cate_id=faq_cate_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == faq_cate_id, "返回的ID与请求的ID不一致" + assert "title" in resp["data"], "响应中缺少title字段" + assert isinstance(resp["data"]["title"], str), "title字段不是字符串类型" + logging.info("获得FAQ分类详情验证通过") + + @allure.story("验证创建和更新FAQ分类") + @allure.title("测试创建和更新FAQ分类接口") + def test_joyhub_faq_cate_create_and_update(self): + """测试创建和更新FAQ分类接口""" + with allure.step("1. 创建FAQ分类"): + timestamp = int(time.time()) + create_params = { + "title": f"测试FAQ分类_{timestamp}", + "lang": "zh_CN", + "rank_num": 1, + "pid": 0, + "status": 1 + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_faq_cate_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + faq_cate_id = create_resp["data"] + TestFaqCateManage.faq_cate_id = faq_cate_id + logging.info(f"创建FAQ分类成功,ID: {faq_cate_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "faq_cate_id": faq_cate_id, + "title": f"测试FAQ分类_{timestamp}_updated", + "lang": "en", + "rank_num": 2, + "pid": 0, + "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_faq_cate_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新FAQ分类失败" + logging.info("创建并更新FAQ分类验证通过") + + @allure.story("验证删除FAQ分类") + @allure.title("测试删除FAQ分类接口") + def test_joyhub_faq_cate_delete_delete(self): + """测试删除FAQ分类接口""" + if not TestFaqCateManage.faq_cate_id: + pytest.skip("没有可删除的FAQ分类数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_faq_cate_delete_delete(faq_cate_id=TestFaqCateManage.faq_cate_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除FAQ分类失败" + logging.info("删除FAQ分类验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_News.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_News.py new file mode 100644 index 0000000..2dbcf93 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_News.py @@ -0,0 +1,210 @@ +# -*- coding:utf-8 -*- +""" +news管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.NewsManage import NewsManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - news管理模块") +class TestNewsManage: + news_id = None + news_cate_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = NewsManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + + # 获取news分类ID供后续使用 + from dulizhan.library.BusinessKw.JoyHub.NewsCateManage import NewsCateManage + news_cate_manage = NewsCateManage() + news_cate_manage.set_joyhub_token(token) + cate_page_resp = news_cate_manage.kw_joyhub_news_cate_page_get(page_no=1, page_size=10) + if cate_page_resp.get('code') == 0 and cate_page_resp.get('data', {}).get('list'): + cls.news_cate_id = cate_page_resp['data']['list'][0].get('id') + logging.info(f"获取到news分类ID: {cls.news_cate_id}") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestNewsManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得news管理分页") + @allure.title("测试获得news管理分页接口") + def test_joyhub_news_page_get(self): + """测试获得news管理分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_news_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得news管理分页验证通过") + + @allure.story("验证获得news管理详情") + @allure.title("测试获得news管理详情接口") + def test_joyhub_news_get_get(self): + """测试获得news管理详情接口""" + with allure.step("1. 从分页获取现有news管理ID"): + page_resp = self.test_case.kw_joyhub_news_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的news管理数据" + news_id = page_resp["data"]["list"][0].get("id") + assert news_id, "news管理ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_news_get_get(news_id=news_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == news_id, "返回的ID与请求的ID不一致" + assert "title" in resp["data"], "响应中缺少title字段" + assert isinstance(resp["data"]["title"], str), "title字段不是字符串类型" + logging.info("获得news管理详情验证通过") + + @allure.story("验证创建和更新news管理") + @allure.title("测试创建和更新news管理接口") + def test_joyhub_news_create_and_update(self): + """测试创建和更新news管理接口""" + with allure.step("1. 创建news管理"): + timestamp = int(time.time()) + create_params = { + "title": f"测试news标题_{timestamp}", + "cover_image": {"url": "https://example.com/test.jpg", "name": "test.jpg"}, + "content": f"

测试内容_{timestamp}

", + "status": 1, + "rank_num": 1 + } + + # 如果有可用的news分类ID,添加关联 + if TestNewsManage.news_cate_id: + create_params["cate_ids"] = [TestNewsManage.news_cate_id] + + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_news_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + news_id = create_resp["data"] + TestNewsManage.news_id = news_id + logging.info(f"创建news管理成功,ID: {news_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "news_id": news_id, + "title": f"测试news标题_{timestamp}_updated", + "cover_image": {"url": "https://example.com/test_updated.jpg", "name": "test_updated.jpg"}, + "content": f"

测试内容_{timestamp}_updated

", + "status": 2, + "rank_num": 2 + } + + # 如果有可用的news分类ID,添加关联 + if TestNewsManage.news_cate_id: + update_params["cate_ids"] = [TestNewsManage.news_cate_id] + + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_news_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新news管理失败" + logging.info("创建并更新news管理验证通过") + + @allure.story("验证删除news管理") + @allure.title("测试删除news管理接口") + def test_joyhub_news_delete_delete(self): + """测试删除news管理接口""" + if not TestNewsManage.news_id: + pytest.skip("没有可删除的news管理数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_news_delete_delete(news_id=TestNewsManage.news_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除news管理失败" + logging.info("删除news管理验证通过") + + @allure.story("验证获得news分类关联列表") + @allure.title("测试获得news分类关联列表接口") + def test_joyhub_news_cate_relation_list_get(self): + """测试获得news分类关联列表接口""" + with allure.step("1. 从分页获取现有news管理ID"): + page_resp = self.test_case.kw_joyhub_news_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的news管理数据" + news_id = page_resp["data"]["list"][0].get("id") + assert news_id, "news管理ID为空" + + with allure.step("2. 调用获取分类关联列表接口"): + resp = self.test_case.kw_joyhub_news_cate_relation_list_get(news_id=news_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], list), "data字段不是列表类型" + logging.info("获得news分类关联列表验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_NewsCate.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_NewsCate.py new file mode 100644 index 0000000..abc0640 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_NewsCate.py @@ -0,0 +1,186 @@ +# -*- coding:utf-8 -*- +""" +news分类管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.NewsCateManage import NewsCateManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - news分类管理模块") +class TestNewsCateManage: + news_cate_id = None + created_names = [] + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = NewsCateManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestNewsCateManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得news分类分页") + @allure.title("测试获得news分类分页接口") + def test_joyhub_news_cate_page_get(self): + """测试获得news分类分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_news_cate_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得news分类分页验证通过") + + @allure.story("验证获得news分类详情") + @allure.title("测试获得news分类详情接口") + def test_joyhub_news_cate_get_get(self): + """测试获得news分类详情接口""" + with allure.step("1. 从分页获取现有news分类ID"): + page_resp = self.test_case.kw_joyhub_news_cate_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的news分类数据" + news_cate_id = page_resp["data"]["list"][0].get("id") + assert news_cate_id, "news分类ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_news_cate_get_get(news_cate_id=news_cate_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == news_cate_id, "返回的ID与请求的ID不一致" + assert "name" in resp["data"], "响应中缺少name字段" + assert isinstance(resp["data"]["name"], str), "name字段不是字符串类型" + logging.info("获得news分类详情验证通过") + + @allure.story("验证创建和更新news分类") + @allure.title("测试创建和更新news分类接口") + def test_joyhub_news_cate_create_and_update(self): + """测试创建和更新news分类接口""" + with allure.step("1. 创建news分类"): + timestamp = int(time.time()) + created_name = f"测试news分类_{timestamp}" + TestNewsCateManage.created_names.append(created_name) + + create_params = { + "name": created_name, + "status": 1, + "rank_num": 1, + "cover_image": {"url": "https://example.com/test.jpg", "name": "test.jpg"} + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_news_cate_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + news_cate_id = create_resp["data"] + TestNewsCateManage.news_cate_id = news_cate_id + logging.info(f"创建news分类成功,ID: {news_cate_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + updated_name = f"测试news分类_{timestamp}_updated" + TestNewsCateManage.created_names.append(updated_name) + + update_params = { + "news_cate_id": news_cate_id, + "name": updated_name, + "status": 2, + "rank_num": 2, + "cover_image": {"url": "https://example.com/test_updated.jpg", "name": "test_updated.jpg"} + } + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_news_cate_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新news分类失败" + logging.info("创建并更新news分类验证通过") + + @allure.story("验证删除news分类") + @allure.title("测试删除news分类接口") + def test_joyhub_news_cate_delete_delete(self): + """测试删除news分类接口""" + if not TestNewsCateManage.news_cate_id: + pytest.skip("没有可删除的news分类数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_news_cate_delete_delete(news_cate_id=TestNewsCateManage.news_cate_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除news分类失败" + logging.info("删除news分类验证通过") + + @classmethod + def teardown_class(cls): + """在整个测试类结束时清理测试数据""" + logging.info("=============================================") + logging.info("=========== 清理测试数据 ============") + logging.info("=============================================") + + # 从数据库表jh_news_cate中删除测试数据 + for name in cls.created_names: + cls.test_case.clean_test_data_from_db(name) + + # 额外清理所有包含"测试news分类"的记录 + cls.test_case.clean_test_data_from_db("测试news分类") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Product.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Product.py new file mode 100644 index 0000000..f3ee8ae --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_Product.py @@ -0,0 +1,490 @@ +# -*- coding:utf-8 -*- +""" +产品管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.ProductManage import ProductManage +from dulizhan.library.BusinessKw.JoyHub.ProductCateManage import ProductCateManage +from base_framework.public_tools.pgsqlhelper import PgSqlHelper + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 产品管理模块") +class TestProductManage: + product_id = None + product_cate_id = None + shipping_template_id = None + brand_id = None + product_attr_type_id = None + product_attr_data_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = ProductManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + + # 获取产品分类ID + product_cate_manage = ProductCateManage() + product_cate_manage.set_joyhub_token(token) + cate_page_resp = product_cate_manage.kw_joyhub_product_cate_page_get(page_no=1, page_size=50) + if cate_page_resp.get('code') == 0 and cate_page_resp.get('data', {}).get('list'): + for cate_item in cate_page_resp['data']['list']: + if cate_item.get('cateType') == 1: + cls.product_cate_id = cate_item.get('id') + break + if cls.product_cate_id is None: + cls.product_cate_id = cate_page_resp['data']['list'][0].get('id') + logging.info(f"获取到产品分类ID: {cls.product_cate_id}") + + # 获取运费模板ID和品牌ID + try: + db_helper = PgSqlHelper() + logging.info("开始连接数据库获取运费模板ID和品牌ID") + + # 从jh_shipping_template表获取运费模板ID(使用joyhub数据库) + shipping_sql = "SELECT id FROM jh_shipping_template WHERE deleted = 0 LIMIT 1" + logging.info(f"执行SQL: {shipping_sql}") + shipping_result = db_helper.select_one(shipping_sql, choose_db='joyhub') + logging.info(f"运费模板查询结果: {shipping_result}") + if shipping_result: + cls.shipping_template_id = shipping_result.get('id') + logging.info(f"从数据库获取到运费模板ID: {cls.shipping_template_id}") + else: + logging.warning("数据库中未找到运费模板数据") + + # 从jh_after_sales_brand表获取品牌ID(使用joyhub数据库) + brand_sql = "SELECT id FROM jh_after_sales_brand WHERE deleted = 0 LIMIT 1" + logging.info(f"执行SQL: {brand_sql}") + brand_result = db_helper.select_one(brand_sql, choose_db='joyhub') + logging.info(f"品牌查询结果: {brand_result}") + if brand_result: + cls.brand_id = brand_result.get('id') + logging.info(f"从数据库获取到品牌ID: {cls.brand_id}") + else: + logging.warning("数据库中未找到品牌数据") + except Exception as e: + logging.error(f"从数据库获取运费模板ID和品牌ID失败: {e}") + import traceback + logging.error(traceback.format_exc()) + + # 获取现有产品ID用于测试 + product_page_resp = cls.test_case.kw_joyhub_product_page_get(page_no=1, page_size=10) + if product_page_resp.get('code') == 0 and product_page_resp.get('data', {}).get('list'): + cls.product_id = product_page_resp['data']['list'][0].get('id') + logging.info(f"获取到现有产品ID: {cls.product_id}") + + # 获取产品属性类型ID和属性值ID + from dulizhan.library.BusinessKw.JoyHub.ProductAttrManage import ProductAttrManage + product_attr_manage = ProductAttrManage() + product_attr_manage.set_joyhub_token(token) + + attr_type_page_resp = product_attr_manage.kw_joyhub_product_attr_type_page_get(page_no=1, page_size=10) + if attr_type_page_resp.get('code') == 0 and attr_type_page_resp.get('data', {}).get('list'): + cls.product_attr_type_id = attr_type_page_resp['data']['list'][0].get('id') + logging.info(f"获取到产品属性类型ID: {cls.product_attr_type_id}") + + # 获取该属性类型下的属性值 + attr_data_page_resp = product_attr_manage.kw_joyhub_product_attr_data_page_get( + page_no=1, page_size=10, productAttrTypeId=cls.product_attr_type_id + ) + if attr_data_page_resp.get('code') == 0 and attr_data_page_resp.get('data', {}).get('list'): + cls.product_attr_data_id = attr_data_page_resp['data']['list'][0].get('id') + logging.info(f"获取到产品属性值ID: {cls.product_attr_data_id}") + else: + # 如果没有属性值,创建一个 + timestamp = int(time.time()) + create_attr_data_resp = product_attr_manage.kw_joyhub_product_attr_data_create_post( + product_attr_type_id=cls.product_attr_type_id, + attr_value=f"测试属性值_{timestamp}" + ) + if create_attr_data_resp.get('code') == 0: + cls.product_attr_data_id = create_attr_data_resp['data'] + logging.info(f"创建产品属性值成功,ID: {cls.product_attr_data_id}") + else: + # 如果没有产品属性类型,创建一个 + timestamp = int(time.time()) + create_attr_type_resp = product_attr_manage.kw_joyhub_product_attr_type_create_post( + name=f"测试产品属性_{timestamp}", + type=2, + status=1 + ) + if create_attr_type_resp.get('code') == 0: + cls.product_attr_type_id = create_attr_type_resp['data'] + logging.info(f"创建产品属性类型成功,ID: {cls.product_attr_type_id}") + + # 创建属性值 + create_attr_data_resp = product_attr_manage.kw_joyhub_product_attr_data_create_post( + product_attr_type_id=cls.product_attr_type_id, + attr_value=f"测试属性值_{timestamp}" + ) + if create_attr_data_resp.get('code') == 0: + cls.product_attr_data_id = create_attr_data_resp['data'] + logging.info(f"创建产品属性值成功,ID: {cls.product_attr_data_id}") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestProductManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得产品分页") + @allure.title("测试获得产品分页接口") + def test_joyhub_product_page_get(self): + """测试获得产品分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_product_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得产品分页验证通过") + + @allure.story("验证获得产品详情") + @allure.title("测试获得产品详情接口") + def test_joyhub_product_get_get(self): + """测试获得产品详情接口""" + with allure.step("1. 从分页获取现有产品ID"): + page_resp = self.test_case.kw_joyhub_product_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品数据" + product_id = page_resp["data"]["list"][0].get("id") + assert product_id, "产品ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_product_get_get(product_id=product_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == product_id, "返回的ID与请求的ID不一致" + assert "productName" in resp["data"], "响应中缺少productName字段" + assert isinstance(resp["data"]["productName"], str), "productName字段不是字符串类型" + logging.info("获得产品详情验证通过") + + @allure.story("验证获得产品规格类型关联列表") + @allure.title("测试获得产品规格类型关联列表接口") + def test_joyhub_product_product_attr_list_by_product_id_get(self): + """测试获得产品规格类型关联列表接口""" + with allure.step("1. 从分页获取现有产品ID"): + page_resp = self.test_case.kw_joyhub_product_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品数据" + product_id = page_resp["data"]["list"][0].get("id") + assert product_id, "产品ID为空" + + with allure.step("2. 调用获取产品规格类型关联列表接口"): + resp = self.test_case.kw_joyhub_product_product_attr_list_by_product_id_get(product_id=product_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], list), "data字段不是列表类型" + logging.info("获得产品规格类型关联列表验证通过") + + @allure.story("验证获得产品详情列表") + @allure.title("测试获得产品详情列表接口") + def test_joyhub_product_product_detail_list_by_product_id_get(self): + """测试获得产品详情列表接口""" + with allure.step("1. 从分页获取现有产品ID"): + page_resp = self.test_case.kw_joyhub_product_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品数据" + product_id = page_resp["data"]["list"][0].get("id") + assert product_id, "产品ID为空" + + with allure.step("2. 调用获取产品详情列表接口"): + resp = self.test_case.kw_joyhub_product_product_detail_list_by_product_id_get(product_id=product_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], list), "data字段不是列表类型" + logging.info("获得产品详情列表验证通过") + + @allure.story("验证获得产品规格列表") + @allure.title("测试获得产品规格列表接口") + def test_joyhub_product_product_sku_list_by_product_id_get(self): + """测试获得产品规格列表接口""" + with allure.step("1. 从分页获取现有产品ID"): + page_resp = self.test_case.kw_joyhub_product_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品数据" + product_id = page_resp["data"]["list"][0].get("id") + assert product_id, "产品ID为空" + + with allure.step("2. 调用获取产品规格列表接口"): + resp = self.test_case.kw_joyhub_product_product_sku_list_by_product_id_get(product_id=product_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], list), "data字段不是列表类型" + logging.info("获得产品规格列表验证通过") + + @allure.story("验证创建和更新产品") + @allure.title("测试创建和更新产品接口") + def test_joyhub_product_create_and_update(self): + """测试创建和更新产品接口""" + # 检查必要的前置数据 + logging.info(f"前置数据状态 - product_cate_id: {TestProductManage.product_cate_id}, " + f"shipping_template_id: {TestProductManage.shipping_template_id}, " + f"brand_id: {TestProductManage.brand_id}, " + f"product_attr_type_id: {TestProductManage.product_attr_type_id}, " + f"product_attr_data_id: {TestProductManage.product_attr_data_id}") + + # 如果缺少必要数据,则跳过测试 + if not TestProductManage.product_cate_id: + pytest.skip("缺少产品分类ID") + if not TestProductManage.shipping_template_id: + pytest.skip("缺少运费模板ID") + if not TestProductManage.brand_id: + pytest.skip("缺少品牌ID") + if not all([TestProductManage.product_attr_type_id, TestProductManage.product_attr_data_id]): + pytest.skip("缺少产品属性类型或属性值") + + with allure.step("1. 创建产品"): + timestamp = int(time.time()) + + # 构建产品规格类型关联列表 + product_attrs = [{ + "id": 0, + "productId": 0, + "productAttrTypeId": TestProductManage.product_attr_type_id, + "productAttrDataId": TestProductManage.product_attr_data_id + }] + + image_obj = { + "url": "https://img.joyhub.net/official_jub/20260413/resized_E031_1776065842307.png", + "name": None, + "alt": None + } + + # 构建产品详情列表 + product_details = [{ + "id": 0, + "productAttrTypeId": TestProductManage.product_attr_type_id, + "productAttrDataId": TestProductManage.product_attr_data_id, + "isFeatured": 1, + "productColor": f"自动化颜色_{timestamp}", + "productColorCard": ["#b2b8bf"], + "coverImage": image_obj, + "coverProductImage": image_obj, + "categoryImage": image_obj, + "productImages": [image_obj], + "description": f"自动化产品详情_{timestamp}" + }] + + # 构建产品规格列表 + product_skus = [{ + "id": 0, + "isFeatured": 1, + "skuNo": [f"AUTO{timestamp}"], + "productPrice": 100, + "exchangePoints": 0, + "productOriginalPrice": 120, + "stockNum": 100, + "status": 1, + "productAttrDataIds": [TestProductManage.product_attr_data_id] + }] + + create_params = { + "product_name": f"测试产品_{timestamp}", + "product_cate_id": TestProductManage.product_cate_id, + "shipping_template_id": TestProductManage.shipping_template_id, + "route": f"/test/product/{timestamp}", + "intro": f"测试产品简介_{timestamp}", + "brand_id": TestProductManage.brand_id, + "product_attrs": product_attrs, + "product_skus": product_skus, + "product_details": product_details, + "status": 1 + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_product_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + product_id = create_resp["data"] + TestProductManage.product_id = product_id + logging.info(f"创建产品成功,ID: {product_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + + # 更新产品规格类型关联列表 + product_attrs = [{ + "id": 0, + "productId": product_id, + "productAttrTypeId": TestProductManage.product_attr_type_id, + "productAttrDataId": TestProductManage.product_attr_data_id + }] + + image_obj = { + "url": "https://img.joyhub.net/official_jub/20260413/resized_E031_1776065842307.png", + "name": None, + "alt": None + } + + # 更新产品详情列表 + product_details = [{ + "id": 0, + "productAttrTypeId": TestProductManage.product_attr_type_id, + "productAttrDataId": TestProductManage.product_attr_data_id, + "isFeatured": 1, + "productColor": f"自动化颜色_{timestamp}_updated", + "productColorCard": ["#b2b8bf"], + "coverImage": image_obj, + "coverProductImage": image_obj, + "categoryImage": image_obj, + "productImages": [image_obj], + "description": f"自动化产品详情_{timestamp}_updated" + }] + + # 更新产品规格列表 + product_skus = [{ + "id": 0, + "isFeatured": 1, + "skuNo": [f"AUTO{timestamp}U"], + "productPrice": 200, + "exchangePoints": 0, + "productOriginalPrice": 220, + "stockNum": 200, + "status": 1, + "productAttrDataIds": [TestProductManage.product_attr_data_id] + }] + + update_params = { + "product_id": product_id, + "product_name": f"测试产品_{timestamp}_updated", + "product_cate_id": TestProductManage.product_cate_id, + "shipping_template_id": TestProductManage.shipping_template_id, + "route": f"/test/product/{timestamp}_updated", + "intro": f"测试产品简介_{timestamp}_updated", + "brand_id": TestProductManage.brand_id, + "product_attrs": product_attrs, + "product_skus": product_skus, + "product_details": product_details, + "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_product_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新产品失败" + logging.info("创建并更新产品验证通过") + + @allure.story("验证批量上下架产品") + @allure.title("测试批量上下架产品接口") + def test_joyhub_product_change_status_put(self): + """测试批量上下架产品接口""" + if not TestProductManage.product_id: + pytest.skip("没有可修改状态的产品数据") + + with allure.step("1. 调用批量上架接口"): + resp = self.test_case.kw_joyhub_product_change_status_put( + ids=[TestProductManage.product_id], + status=1 + ) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "批量上架产品失败" + + with allure.step("3. 调用批量下架接口"): + resp = self.test_case.kw_joyhub_product_change_status_put( + ids=[TestProductManage.product_id], + status=2 + ) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "批量下架产品失败" + logging.info("批量上下架产品验证通过") + + @allure.story("验证删除产品") + @allure.title("测试删除产品接口") + def test_joyhub_product_delete_delete(self): + """测试删除产品接口""" + if not TestProductManage.product_id: + pytest.skip("没有可删除的产品数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_product_delete_delete(product_id=TestProductManage.product_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除产品失败" + logging.info("删除产品验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductAttr.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductAttr.py new file mode 100644 index 0000000..ada7d87 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductAttr.py @@ -0,0 +1,320 @@ +# -*- coding:utf-8 -*- +""" +产品属性+产品属性值管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.ProductAttrManage import ProductAttrManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 产品属性+产品属性值管理模块") +class TestProductAttrManage: + product_attr_type_id = None + product_attr_data_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = ProductAttrManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestProductAttrManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + # ============ 产品属性测试用例 ============ + + @allure.story("验证获得产品属性分页") + @allure.title("测试获得产品属性分页接口") + def test_joyhub_product_attr_type_page_get(self): + """测试获得产品属性分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_product_attr_type_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得产品属性分页验证通过") + + @allure.story("验证获得产品属性详情") + @allure.title("测试获得产品属性详情接口") + def test_joyhub_product_attr_type_get_get(self): + """测试获得产品属性详情接口""" + with allure.step("1. 从分页获取现有产品属性ID"): + page_resp = self.test_case.kw_joyhub_product_attr_type_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品属性数据" + product_attr_type_id = page_resp["data"]["list"][0].get("id") + assert product_attr_type_id, "产品属性ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_product_attr_type_get_get(product_attr_type_id=product_attr_type_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == product_attr_type_id, "返回的ID与请求的ID不一致" + assert "name" in resp["data"], "响应中缺少name字段" + assert isinstance(resp["data"]["name"], str), "name字段不是字符串类型" + logging.info("获得产品属性详情验证通过") + + @allure.story("验证创建和更新产品属性") + @allure.title("测试创建和更新产品属性接口") + def test_joyhub_product_attr_type_create_and_update(self): + """测试创建和更新产品属性接口""" + with allure.step("1. 创建产品属性"): + timestamp = int(time.time()) + create_params = { + "name": f"测试产品属性_{timestamp}", + "type": 2, + "status": 1, + "remark": f"测试备注_{timestamp}", + "rank_num": 1 + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_product_attr_type_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + product_attr_type_id = create_resp["data"] + TestProductAttrManage.product_attr_type_id = product_attr_type_id + logging.info(f"创建产品属性成功,ID: {product_attr_type_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "product_attr_type_id": product_attr_type_id, + "name": f"测试产品属性_{timestamp}_updated", + "type": 2, + "status": 2, + "remark": f"测试备注_{timestamp}_updated", + "rank_num": 2 + } + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_product_attr_type_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新产品属性失败" + logging.info("创建并更新产品属性验证通过") + + @allure.story("验证修改产品属性状态") + @allure.title("测试修改产品属性状态接口") + def test_joyhub_product_attr_type_change_status_put(self): + """测试修改产品属性状态接口""" + if not TestProductAttrManage.product_attr_type_id: + pytest.skip("没有可修改状态的产品属性数据") + + with allure.step("1. 调用修改状态接口(启用)"): + resp = self.test_case.kw_joyhub_product_attr_type_change_status_put( + product_attr_type_id=TestProductAttrManage.product_attr_type_id, + status=1 + ) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "修改产品属性状态失败" + logging.info("修改产品属性状态验证通过") + + # ============ 产品属性值测试用例 ============ + + @allure.story("验证获得产品属性值分页") + @allure.title("测试获得产品属性值分页接口") + def test_joyhub_product_attr_data_page_get(self): + """测试获得产品属性值分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_product_attr_data_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得产品属性值分页验证通过") + + @allure.story("验证获得产品属性值详情") + @allure.title("测试获得产品属性值详情接口") + def test_joyhub_product_attr_data_get_get(self): + """测试获得产品属性值详情接口""" + with allure.step("1. 从分页获取现有产品属性值ID"): + page_resp = self.test_case.kw_joyhub_product_attr_data_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品属性值数据" + product_attr_data_id = page_resp["data"]["list"][0].get("id") + assert product_attr_data_id, "产品属性值ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_product_attr_data_get_get(product_attr_data_id=product_attr_data_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == product_attr_data_id, "返回的ID与请求的ID不一致" + assert "attrValue" in resp["data"], "响应中缺少attrValue字段" + assert isinstance(resp["data"]["attrValue"], str), "attrValue字段不是字符串类型" + logging.info("获得产品属性值详情验证通过") + + @allure.story("验证创建和更新产品属性值") + @allure.title("测试创建和更新产品属性值接口") + def test_joyhub_product_attr_data_create_and_update(self): + """测试创建和更新产品属性值接口""" + # 如果没有创建的产品属性ID,则使用已有产品属性ID + product_attr_type_id = TestProductAttrManage.product_attr_type_id + if not product_attr_type_id: + with allure.step("获取已有产品属性ID"): + page_resp = self.test_case.kw_joyhub_product_attr_type_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品属性数据" + product_attr_type_id = page_resp["data"]["list"][0].get("id") + + with allure.step("1. 创建产品属性值"): + timestamp = int(time.time()) + create_params = { + "product_attr_type_id": product_attr_type_id, + "attr_value": f"测试属性值_{timestamp}", + "color": ["#FF0000", "#00FF00"] + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_product_attr_data_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + product_attr_data_id = create_resp["data"] + TestProductAttrManage.product_attr_data_id = product_attr_data_id + logging.info(f"创建产品属性值成功,ID: {product_attr_data_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "product_attr_data_id": product_attr_data_id, + "product_attr_type_id": product_attr_type_id, + "attr_value": f"测试属性值_{timestamp}_updated", + "color": ["#0000FF"] + } + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_product_attr_data_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新产品属性值失败" + logging.info("创建并更新产品属性值验证通过") + + # ============ 删除测试用例 ============ + + @allure.story("验证删除产品属性值") + @allure.title("测试删除产品属性值接口") + def test_joyhub_product_attr_data_delete_delete(self): + """测试删除产品属性值接口""" + if not TestProductAttrManage.product_attr_data_id: + pytest.skip("没有可删除的产品属性值数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_product_attr_data_delete_delete(product_attr_data_id=TestProductAttrManage.product_attr_data_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除产品属性值失败" + logging.info("删除产品属性值验证通过") + + @allure.story("验证删除产品属性") + @allure.title("测试删除产品属性接口") + def test_joyhub_product_attr_type_delete_delete(self): + """测试删除产品属性接口""" + if not TestProductAttrManage.product_attr_type_id: + pytest.skip("没有可删除的产品属性数据") + + with allure.step("1. 先将产品属性状态改为停用"): + status_resp = self.test_case.kw_joyhub_product_attr_type_change_status_put( + product_attr_type_id=TestProductAttrManage.product_attr_type_id, + status=2 + ) + assert status_resp.get("code") == 0, f"修改状态失败,code={status_resp.get('code')}, msg={status_resp.get('msg')}" + + with allure.step("2. 调用删除接口"): + resp = self.test_case.kw_joyhub_product_attr_type_delete_delete(product_attr_type_id=TestProductAttrManage.product_attr_type_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除产品属性失败" + logging.info("删除产品属性验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductCate.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductCate.py new file mode 100644 index 0000000..9469110 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductCate.py @@ -0,0 +1,201 @@ +# -*- coding:utf-8 -*- +""" +产品分类管理接口测试用例 +""" +import json +import pytest +import allure +import logging +import time +import requests + +from dulizhan.library.BusinessKw.JoyHub.ProductCateManage import ProductCateManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 产品分类管理模块") +class TestProductCateManage: + product_cate_id = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = ProductCateManage() + 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'} + + 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', '') + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestProductCateManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证获得产品分类分页") + @allure.title("测试获得产品分类分页接口") + def test_joyhub_product_cate_page_get(self): + """测试获得产品分类分页接口""" + with allure.step("1. 调用分页接口"): + resp = self.test_case.kw_joyhub_product_cate_page_get(page_no=1, page_size=10) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + logging.info("获得产品分类分页验证通过") + + @allure.story("验证获得产品分类详情") + @allure.title("测试获得产品分类详情接口") + def test_joyhub_product_cate_get_get(self): + """测试获得产品分类详情接口""" + with allure.step("1. 从分页获取现有产品分类ID"): + page_resp = self.test_case.kw_joyhub_product_cate_page_get(page_no=1, page_size=10) + assert page_resp.get("code") == 0, f"获取分页失败,code={page_resp.get('code')}, msg={page_resp.get('msg')}" + assert page_resp.get("data", {}).get("list"), "没有找到可用的产品分类数据" + product_cate_id = page_resp["data"]["list"][0].get("id") + assert product_cate_id, "产品分类ID为空" + + with allure.step("2. 调用获取详情接口"): + resp = self.test_case.kw_joyhub_product_cate_get_get(product_cate_id=product_cate_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "id" in resp["data"], "响应中缺少id字段" + assert resp["data"]["id"] == product_cate_id, "返回的ID与请求的ID不一致" + assert "cateName" in resp["data"], "响应中缺少cateName字段" + assert isinstance(resp["data"]["cateName"], str), "cateName字段不是字符串类型" + logging.info("获得产品分类详情验证通过") + + @allure.story("验证创建和更新产品分类") + @allure.title("测试创建和更新产品分类接口") + def test_joyhub_product_cate_create_and_update(self): + """测试创建和更新产品分类接口""" + with allure.step("1. 创建产品分类"): + timestamp = int(time.time()) + create_params = { + "cate_name": f"测试产品分类_{timestamp}", + "cate_type": 1, + "status": 1, + "rank_num": 1 + } + allure.attach(json.dumps(create_params, ensure_ascii=False), name="创建请求参数", attachment_type=allure.attachment_type.TEXT) + + create_resp = self.test_case.kw_joyhub_product_cate_create_post(**create_params) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + product_cate_id = create_resp["data"] + TestProductCateManage.product_cate_id = product_cate_id + logging.info(f"创建产品分类成功,ID: {product_cate_id}") + + with allure.step("2. 调用更新接口"): + timestamp = int(time.time()) + update_params = { + "product_cate_id": product_cate_id, + "cate_name": f"测试产品分类_{timestamp}_updated", + "cate_type": 1, + "status": 2, + "rank_num": 2 + } + allure.attach(json.dumps(update_params, ensure_ascii=False), name="更新请求参数", attachment_type=allure.attachment_type.TEXT) + + update_resp = self.test_case.kw_joyhub_product_cate_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("3. 验证更新响应"): + assert update_resp is not None, "响应为空" + assert "code" in update_resp, "响应中缺少code字段" + assert update_resp["code"] == 0, f"更新失败,code={update_resp.get('code')}, msg={update_resp.get('msg')}" + assert "data" in update_resp, "响应中缺少data字段" + assert update_resp["data"] is True, "更新产品分类失败" + logging.info("创建并更新产品分类验证通过") + + @allure.story("验证修改产品分类状态") + @allure.title("测试修改产品分类状态接口") + def test_joyhub_product_cate_change_status_put(self): + """测试修改产品分类状态接口""" + if not TestProductCateManage.product_cate_id: + pytest.skip("没有可修改状态的产品分类数据") + + with allure.step("1. 调用修改状态接口(停用)"): + resp = self.test_case.kw_joyhub_product_cate_change_status_put( + product_cate_id=TestProductCateManage.product_cate_id, + status=2 + ) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "修改产品分类状态失败" + + with allure.step("3. 调用修改状态接口(启用)"): + resp = self.test_case.kw_joyhub_product_cate_change_status_put( + product_cate_id=TestProductCateManage.product_cate_id, + status=1 + ) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "修改产品分类状态失败" + logging.info("修改产品分类状态验证通过") + + @allure.story("验证删除产品分类") + @allure.title("测试删除产品分类接口") + def test_joyhub_product_cate_delete_delete(self): + """测试删除产品分类接口""" + if not TestProductCateManage.product_cate_id: + pytest.skip("没有可删除的产品分类数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_product_cate_delete_delete(product_cate_id=TestProductCateManage.product_cate_id) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除产品分类失败" + logging.info("删除产品分类验证通过") diff --git a/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductPaymentRecommend.py b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductPaymentRecommend.py new file mode 100644 index 0000000..a4d3b58 --- /dev/null +++ b/dulizhan/test_case/TestCase/接口/JoyHub/Joyhub_ProductPaymentRecommend.py @@ -0,0 +1,279 @@ +# -*- coding:utf-8 -*- +""" +支付页产品推荐接口测试用例 +""" +import json +import pytest +import allure +import logging +import requests + +from dulizhan.library.BusinessKw.JoyHub.ProductManage import ProductManage +from dulizhan.library.BusinessKw.JoyHub.ProductPaymentRecommendManage import ProductPaymentRecommendManage + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + + +@allure.feature("管理后台 - 支付页产品推荐模块") +class TestProductPaymentRecommendManage: + product_id = None + recommend_id = None + batch_recommend_id = None + token = None + token_set = False + + @classmethod + def setup_class(cls): + """在整个测试类开始时登录一次,所有测试用例共享token""" + logging.info("=============================================") + logging.info("=========== 开始登录,获取Token ============") + logging.info("=============================================") + + cls.test_case = ProductPaymentRecommendManage() + 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'} + + 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', '') + cls.token = token + cls.test_case.set_joyhub_token(token) + cls.token_set = True + logging.info("登录成功,Token已设置") + + recommend_page_resp = cls.test_case.kw_joyhub_product_payment_recommend_page_get(page_no=1, page_size=999) + recommended_product_ids = set() + if recommend_page_resp.get('code') == 0 and recommend_page_resp.get('data', {}).get('list'): + recommended_product_ids = { + item.get('productId') for item in recommend_page_resp['data']['list'] if item.get('productId') + } + + product_manage = ProductManage() + product_manage.set_joyhub_token(token) + product_page_resp = product_manage.kw_joyhub_product_page_get(page_no=1, page_size=50) + if product_page_resp.get('code') == 0 and product_page_resp.get('data', {}).get('list'): + for product_item in product_page_resp['data']['list']: + product_id = product_item.get('id') + if product_id and product_id not in recommended_product_ids: + cls.product_id = product_id + break + logging.info(f"获取到未推荐产品ID: {cls.product_id}") + else: + logging.error(f"登录失败: {login_response}") + + @allure.story("验证登录接口") + @allure.title("测试登录接口") + def test_joyhub_login_post(self): + """测试登录接口""" + assert TestProductPaymentRecommendManage.token_set is True, "登录失败,未获取到token" + logging.info("登录验证通过") + + @allure.story("验证管理后台获得支付页产品推荐分页") + @allure.title("测试管理后台获得支付页产品推荐分页接口") + def test_joyhub_product_payment_recommend_page_get(self): + """测试管理后台获得支付页产品推荐分页接口""" + with allure.step("1. 准备请求参数"): + self.test_case.set_joyhub_token(TestProductPaymentRecommendManage.token) + params = { + "page_no": 1, + "page_size": 10, + "recommendStatus": 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_product_payment_recommend_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + if "total" in resp["data"]: + assert isinstance(resp["data"]["total"], int), "total字段不是整数类型" + logging.info("管理后台获得支付页产品推荐分页验证通过") + + @allure.story("验证创建支付页产品推荐") + @allure.title("测试创建支付页产品推荐接口") + def test_joyhub_product_payment_recommend_create_post(self): + """测试创建支付页产品推荐接口""" + if not TestProductPaymentRecommendManage.product_id: + pytest.skip("没有可用于创建支付页产品推荐的产品数据") + + with allure.step("1. 准备请求参数"): + params = { + "product_ids": [TestProductPaymentRecommendManage.product_id] + } + 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_product_payment_recommend_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert isinstance(resp["data"], int), "data字段不是整数类型" + TestProductPaymentRecommendManage.recommend_id = resp["data"] + logging.info(f"创建支付页产品推荐成功,ID: {resp['data']}") + + @allure.story("验证修改支付页产品推荐排序号") + @allure.title("测试修改支付页产品推荐排序号接口") + def test_joyhub_product_payment_recommend_change_rank_num_put(self): + """测试修改支付页产品推荐排序号接口""" + if not TestProductPaymentRecommendManage.recommend_id: + pytest.skip("没有可修改排序号的支付页产品推荐数据") + + with allure.step("1. 准备请求参数"): + params = { + "recommend_id": TestProductPaymentRecommendManage.recommend_id, + "rank_num": 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_product_payment_recommend_change_rank_num_put(**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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "修改支付页产品推荐排序号失败" + logging.info("修改支付页产品推荐排序号验证通过") + + @allure.story("验证修改支付页产品推荐状态") + @allure.title("测试修改支付页产品推荐状态接口") + def test_joyhub_product_payment_recommend_change_status_put(self): + """测试修改支付页产品推荐状态接口""" + if not TestProductPaymentRecommendManage.recommend_id: + pytest.skip("没有可修改状态的支付页产品推荐数据") + + with allure.step("1. 准备请求参数"): + params = { + "recommend_id": TestProductPaymentRecommendManage.recommend_id, + "recommend_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_product_payment_recommend_change_status_put(**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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "修改支付页产品推荐状态失败" + logging.info("修改支付页产品推荐状态验证通过") + + @allure.story("验证删除支付页产品推荐") + @allure.title("测试删除支付页产品推荐接口") + def test_joyhub_product_payment_recommend_delete_delete(self): + """测试删除支付页产品推荐接口""" + if not TestProductPaymentRecommendManage.recommend_id: + pytest.skip("没有可删除的支付页产品推荐数据") + + with allure.step("1. 调用删除接口"): + resp = self.test_case.kw_joyhub_product_payment_recommend_delete_delete( + recommend_id=TestProductPaymentRecommendManage.recommend_id + ) + 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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "删除支付页产品推荐失败" + TestProductPaymentRecommendManage.recommend_id = None + logging.info("删除支付页产品推荐验证通过") + + @allure.story("验证批量删除支付页产品推荐") + @allure.title("测试批量删除支付页产品推荐接口") + def test_joyhub_product_payment_recommend_delete_list_delete(self): + """测试批量删除支付页产品推荐接口""" + if not TestProductPaymentRecommendManage.product_id: + pytest.skip("没有可用于创建支付页产品推荐的产品数据") + + with allure.step("1. 创建一条用于批量删除的支付页产品推荐"): + create_resp = self.test_case.kw_joyhub_product_payment_recommend_create_post( + product_ids=[TestProductPaymentRecommendManage.product_id] + ) + allure.attach(json.dumps(create_resp, ensure_ascii=False, indent=2), name="创建响应数据", attachment_type=allure.attachment_type.JSON) + assert create_resp is not None, "响应为空" + assert "code" in create_resp, "响应中缺少code字段" + assert create_resp["code"] == 0, f"创建失败,code={create_resp.get('code')}, msg={create_resp.get('msg')}" + assert "data" in create_resp, "响应中缺少data字段" + assert isinstance(create_resp["data"], int), "data字段不是整数类型" + TestProductPaymentRecommendManage.batch_recommend_id = create_resp["data"] + + with allure.step("2. 将支付页产品推荐状态改为停用"): + status_resp = self.test_case.kw_joyhub_product_payment_recommend_change_status_put( + recommend_id=TestProductPaymentRecommendManage.batch_recommend_id, + recommend_status=2 + ) + allure.attach(json.dumps(status_resp, ensure_ascii=False, indent=2), name="修改状态响应数据", attachment_type=allure.attachment_type.JSON) + assert status_resp is not None, "响应为空" + assert "code" in status_resp, "响应中缺少code字段" + assert status_resp["code"] == 0, f"修改状态失败,code={status_resp.get('code')}, msg={status_resp.get('msg')}" + assert status_resp.get("data") is True, "修改支付页产品推荐状态失败" + + with allure.step("3. 调用批量删除接口"): + params = { + "ids": [TestProductPaymentRecommendManage.batch_recommend_id] + } + allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT) + resp = self.test_case.kw_joyhub_product_payment_recommend_delete_list_delete(**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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert resp["data"] is True, "批量删除支付页产品推荐失败" + TestProductPaymentRecommendManage.batch_recommend_id = None + logging.info("批量删除支付页产品推荐验证通过") + + @allure.story("验证C端获得支付页产品推荐分页") + @allure.title("测试C端获得支付页产品推荐分页接口") + def test_joyhub_web_product_payment_recommend_page_get(self): + """测试获得支付页产品推荐分页接口""" + with allure.step("1. 准备请求参数"): + self.test_case.set_joyhub_token(None) + params = { + "page_no": 1, + "page_size": 10 + } + 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_web_product_payment_recommend_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')}, msg={resp.get('msg')}" + assert "data" in resp, "响应中缺少data字段" + assert "list" in resp["data"], "响应中缺少list字段" + assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" + if "total" in resp["data"]: + assert isinstance(resp["data"]["total"], int), "total字段不是整数类型" + logging.info("获得支付页产品推荐分页验证通过") diff --git a/dulizhan/test_case/TestCase/接口/conftest.py b/dulizhan/test_case/TestCase/接口/conftest.py index 889acff..e56e742 100644 --- a/dulizhan/test_case/TestCase/接口/conftest.py +++ b/dulizhan/test_case/TestCase/接口/conftest.py @@ -6,9 +6,9 @@ import os import sys -# 添加项目根目录到 Python 路径,确保能导入 zhyy 模块 +# 添加项目根目录到 Python 路径,确保能导入 dulizhan 模块 current_file_path = os.path.abspath(__file__) -# 从 test_case/TestCase/接口/conftest.py 向上找到项目根目录 d:\zhyy +# 从 test_case/TestCase/接口/conftest.py 向上找到项目根目录 d:\dulizhan 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) diff --git a/dulizhan/test_case/run_tests.py b/dulizhan/test_case/run_tests.py index efb93ac..b38be17 100644 --- a/dulizhan/test_case/run_tests.py +++ b/dulizhan/test_case/run_tests.py @@ -7,6 +7,7 @@ import argparse import os import subprocess import sys +import shutil # 添加项目根目录到 Python 路径 current_file_path = os.path.abspath(__file__) @@ -29,6 +30,36 @@ ALLURE_PATH = os.path.join(project_root, 'allure', 'allure-2.28.0', 'bin', 'allu print(ALLURE_REPORT_DIR) +def clean_old_results(): + """清除旧的测试结果和报告""" + print("清除旧的测试结果和报告...") + + # 清除 allure-results 目录 + if os.path.exists(ALLURE_RESULTS_DIR): + try: + shutil.rmtree(ALLURE_RESULTS_DIR) + print(f"已清除目录: {ALLURE_RESULTS_DIR}") + except Exception as e: + print(f"清除 {ALLURE_RESULTS_DIR} 失败: {e}") + + # 清除 allure-report 目录 + if os.path.exists(ALLURE_REPORT_DIR): + try: + shutil.rmtree(ALLURE_REPORT_DIR) + print(f"已清除目录: {ALLURE_REPORT_DIR}") + except Exception as e: + print(f"清除 {ALLURE_REPORT_DIR} 失败: {e}") + + # 清除 .pytest_cache 目录 + pytest_cache_dir = os.path.join(project_root, '.pytest_cache') + if os.path.exists(pytest_cache_dir): + try: + shutil.rmtree(pytest_cache_dir) + print(f"已清除目录: {pytest_cache_dir}") + except Exception as e: + print(f"清除 {pytest_cache_dir} 失败: {e}") + + def ensure_dirs(): """确保报告目录存在""" os.makedirs(ALLURE_RESULTS_DIR, exist_ok=True) @@ -211,6 +242,9 @@ def main(): args = parser.parse_args() + # 清除旧的测试结果和报告 + clean_old_results() + # 确保目录存在 ensure_dirs()