import pytest import allure import logging import requests import json import time from dulizhan.library.BusinessKw.JoyHub.BannerManage import BannerManage logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') @allure.feature("管理后台 - Banner管理模块") class TestBannerManage: banner_id = None token_set = False @classmethod def setup_class(cls): """在整个测试类开始时登录一次,所有测试用例共享token""" logging.info("=============================================") logging.info("=========== 开始登录,获取Token ============") logging.info("=============================================") cls.test_case = BannerManage() username = "joytest" password = "Zhou1599" cls.test_case._clear_user_fingerprint(username) url = "https://joyhub-website-manager-api-test.best-envision.com/admin-api/system/auth/login-dev" payload = {"username": username, "password": password} headers = {'Content-Type': 'application/json', 'tenant-id': '126'} try: response = requests.post(url, json=payload, headers=headers, verify=False, timeout=10) login_response = response.json() if login_response and login_response.get('code') == 0: token = login_response.get('data', {}).get('accessToken', '') if token: cls.test_case.set_joyhub_token(token) cls.token_set = True logging.info("登录成功,获取到Token: {}...".format(token[:20])) else: logging.warning("登录成功但未获取到Token") else: logging.error("登录失败: {}".format(login_response)) except Exception as e: logging.error("登录异常: {}".format(str(e))) @allure.story("验证登录") @allure.title("测试登录接口") def test_joyhub_login_post(self): """测试登录接口""" assert self.token_set is True, "登录失败,Token未设置" logging.info("登录验证通过,Token已设置") @allure.story("验证获得Banner分页") @allure.title("测试获得Banner管理分页接口") def test_joyhub_banner_page_get(self): """测试获得Banner管理分页接口""" with allure.step("1. 准备请求参数"): params = { "page_no": 1, "page_size": 10, "position": "", "title": "", "platform": "", "lang": "", "banner_type": "", "status": "" } allure.attach(json.dumps(params, ensure_ascii=False), name="请求参数", attachment_type=allure.attachment_type.TEXT) with allure.step("2. 调用接口"): resp = self.test_case.kw_joyhub_banner_page_get(**params) allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON) with allure.step("3. 验证响应"): assert resp is not None, "响应为空" assert "code" in resp, "响应中缺少code字段" assert resp["code"] == 0, f"请求失败,code={resp.get('code')}" assert "data" in resp, "响应中缺少data字段" assert "list" in resp["data"], "响应中缺少list字段" assert "total" in resp["data"], "响应中缺少total字段" assert isinstance(resp["data"]["list"], list), "list字段不是列表类型" assert isinstance(resp["data"]["total"], int), "total字段不是整数类型" logging.info("获得Banner分页列表验证通过") @allure.story("验证创建Banner") @allure.title("测试创建Banner管理接口") def test_joyhub_banner_create_post(self): """测试创建Banner管理接口""" with allure.step("1. 准备请求参数"): timestamp = int(time.time()) params = { "position": f"home_{timestamp}", "platform": 1, "lang": "en", "rank_num": timestamp % 1000, "banner_type": "promotion", "status": 1, "interval_time": 5, "title": f"测试Banner_{timestamp}", "sub_title": "测试副标题", "image": {'url': 'https://www.toendi.com/static/image/cd94c191561c4a37a04c78fca2913851.webp', 'name': 'Test Banner', 'mime_type': 'image/webp'}, "link": "https://example.com" } 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_banner_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字段不是整数类型" TestBannerManage.banner_id = resp["data"] logging.info(f"创建Banner成功,Banner ID: {TestBannerManage.banner_id}") @allure.story("验证获得Banner详情") @allure.title("测试获得Banner详情接口") def test_joyhub_banner_get_get(self): """测试获得Banner详情接口""" with allure.step("1. 先创建一个Banner"): timestamp = int(time.time()) create_resp = self.test_case.kw_joyhub_banner_create_post( position=f"detail_test_{timestamp}", platform=1, lang="en", rank_num=timestamp % 1000, banner_type="promotion", status=1, interval_time=5, title=f"详情测试Banner_{timestamp}" ) banner_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None if not banner_id: pytest.skip("创建测试Banner失败,跳过详情测试") allure.attach(json.dumps({"id": banner_id}, ensure_ascii=False), name="Banner ID", attachment_type=allure.attachment_type.TEXT) with allure.step("2. 调用获得详情接口"): resp = self.test_case.kw_joyhub_banner_get_get(banner_id=banner_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"] == banner_id, "返回的ID与请求的不一致" logging.info("获得Banner详情验证通过") @allure.story("验证更新Banner") @allure.title("测试更新Banner管理接口") def test_joyhub_banner_update_put(self): """测试更新Banner管理接口""" with allure.step("1. 先创建一个Banner"): timestamp = int(time.time()) create_resp = self.test_case.kw_joyhub_banner_create_post( position=f"update_test_{timestamp}", platform=1, lang="en", rank_num=timestamp % 1000, banner_type="promotion", status=1, interval_time=5, title=f"待更新Banner_{timestamp}" ) banner_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None if not banner_id: pytest.skip("创建测试Banner失败,跳过更新测试") allure.attach(json.dumps({"id": banner_id}, ensure_ascii=False), name="Banner ID", attachment_type=allure.attachment_type.TEXT) with allure.step("2. 调用更新接口"): timestamp = int(time.time()) update_params = { "banner_id": banner_id, "position": f"updated_position_{timestamp}", "platform": 2, "lang": "de", "rank_num": (timestamp % 1000) + 1, "banner_type": "updated_type", "status": 2, "interval_time": 10, "title": f"已更新Banner_{timestamp}", "sub_title": "已更新副标题", "image": {'url': 'https://www.toendi.com/static/image/updated.webp', 'name': 'Updated Banner', 'mime_type': 'image/webp'}, "link": "https://updated-example.com" } resp = self.test_case.kw_joyhub_banner_update_put(**update_params) allure.attach(json.dumps(resp, ensure_ascii=False, indent=2), name="响应数据", attachment_type=allure.attachment_type.JSON) with allure.step("3. 验证响应"): assert resp is not None, "响应为空" assert "code" in resp, "响应中缺少code字段" assert resp["code"] == 0, f"请求失败,code={resp.get('code')}" assert "data" in resp, "响应中缺少data字段" assert resp["data"] is True, "更新Banner失败" logging.info("更新Banner验证通过") @allure.story("验证删除Banner") @allure.title("测试删除Banner管理接口") def test_joyhub_banner_delete_delete(self): """测试删除Banner管理接口""" with allure.step("1. 先创建一个测试Banner"): timestamp = int(time.time()) create_resp = self.test_case.kw_joyhub_banner_create_post( position=f"delete_test_{timestamp}", platform=1, lang="en", rank_num=timestamp % 1000, banner_type="promotion", status=2, interval_time=5, title=f"待删除Banner_{timestamp}" ) banner_id = create_resp.get("data") if create_resp and create_resp.get("code") == 0 else None if not banner_id: pytest.skip("创建测试Banner失败,跳过删除测试") allure.attach(json.dumps({"id": banner_id}, ensure_ascii=False), name="待删除Banner ID", attachment_type=allure.attachment_type.TEXT) with allure.step("2. 调用删除接口"): resp = self.test_case.kw_joyhub_banner_delete_delete(banner_id=banner_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, "删除Banner失败" logging.info("删除Banner验证通过") @allure.story("验证批量删除Banner") @allure.title("测试批量删除Banner管理接口") def test_joyhub_banner_delete_list_delete(self): """测试批量删除Banner管理接口""" with allure.step("1. 先创建两个测试Banner"): timestamp = int(time.time()) resp1 = self.test_case.kw_joyhub_banner_create_post( position=f"batch_delete_1_{timestamp}", platform=1, lang="en", rank_num=timestamp % 1000, banner_type="promotion", status=2, interval_time=5, title=f"批量删除Banner1_{timestamp}" ) resp2 = self.test_case.kw_joyhub_banner_create_post( position=f"batch_delete_2_{timestamp}", platform=1, lang="en", rank_num=timestamp % 1000 + 1, banner_type="promotion", status=2, interval_time=5, title=f"批量删除Banner2_{timestamp}" ) banner_id1 = resp1.get("data") if resp1 and resp1.get("code") == 0 else None banner_id2 = resp2.get("data") if resp2 and resp2.get("code") == 0 else None if not banner_id1 or not banner_id2: pytest.skip("创建测试Banner失败,跳过批量删除测试") banner_ids = [banner_id1, banner_id2] allure.attach(json.dumps({"ids": banner_ids}, ensure_ascii=False), name="待删除Banner IDs", attachment_type=allure.attachment_type.TEXT) with allure.step("2. 调用批量删除接口"): resp = self.test_case.kw_joyhub_banner_delete_list_delete(banner_ids=banner_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, "批量删除Banner失败" logging.info("批量删除Banner验证通过")