diff --git a/TestCase/FAQ/test_01_article.py b/TestCase/FAQ/test_01_article.py new file mode 100644 index 0000000000000000000000000000000000000000..4e35d65da2b82efdccbbd8759846dd755229ab30 --- /dev/null +++ b/TestCase/FAQ/test_01_article.py @@ -0,0 +1,13 @@ +import pytest +from Utils import yaml_handler +from Utils import req_handler +from TestData.FAQ.faq_test_data import faqData + +class TestFAQ: + + yaml_path = r'FAQ\article.yaml' + yaml_data = yaml_handler.yaml_handler.get_case(yaml_path) + @pytest.mark.parametrize('case',yaml_data) + def test_article(self,case): + req_handler.ReqHandler.send_requests(case=case,var_class=faqData) + print(case) \ No newline at end of file diff --git a/TestData/FAQ/faq_test_data.py b/TestData/FAQ/faq_test_data.py new file mode 100644 index 0000000000000000000000000000000000000000..358d70610eaf937662e8fb173fd32c9bd644f86f --- /dev/null +++ b/TestData/FAQ/faq_test_data.py @@ -0,0 +1,6 @@ +from Utils.global_variate import Global + +class faqData(Global): + pass + + diff --git a/TestFile/FAQ/article_list_select.py b/TestFile/FAQ/article_list_select.py new file mode 100644 index 0000000000000000000000000000000000000000..4ca28711e7271f4c17c54d65562fae7d170edf89 --- /dev/null +++ b/TestFile/FAQ/article_list_select.py @@ -0,0 +1,43 @@ +from Utils.sql_handler import test_env_conn +from TestData.FAQ.faq_test_data import faqData + +all_article_list_select_sql = f'select * from `article` where brand_id = {faqData.brandId} and is_delete = 0' +all_article_list_select_result = test_env_conn.select_many_value(all_article_list_select_sql) +all_article_num = len(all_article_list_select_result) +shop_article_list_select_sql = f'select * from `article` where brand_id = {faqData.brandId} and shop_id = {faqData.shopId} and is_delete = 0' +shop_article_list_select_result = test_env_conn.select_many_value(shop_article_list_select_sql) +shop_article_num = len(shop_article_list_select_result) +setattr(faqData,'all_article_num',all_article_num) +setattr(faqData,'shop_article_num',shop_article_num) +article = shop_article_list_select_result[0] +article_id = article['id'] +article_category_id = article['article_category_id'] +article_title = article['title'] +article_title = article_title.replace("'","\\'") +article_sort = article['sort'] +article_content = article['content'] +article_content = article_content.replace("'","\\'") +article_content = article_content.replace("\n","\\n'") +article_is_published = article['is_publish'] +article_is_popular = article['is_popular'] +article_meta_title = article['meta_title'] if article['meta_title'] else '' +article_meta_description = article['meta_description'] if article['meta_description'] else '' +article_view_count = article['views'] +article_evaluate_good = article['article_evaluate_good'] +article_evaluate_bad = article['article_evaluate_bad'] +setattr(faqData,'article_id',article_id) +setattr(faqData,'article_category_id',article_category_id) +setattr(faqData,'article_title',article_title) +setattr(faqData,'article_sort',article_sort) +setattr(faqData,'article_content',article_content) +setattr(faqData,'article_is_published',article_is_published) +setattr(faqData,'article_is_popular',article_is_popular) +setattr(faqData,'article_meta_title',article_meta_title) +setattr(faqData,'article_meta_description',article_meta_description) +setattr(faqData,'article_view_count',article_view_count) +setattr(faqData,'article_view_count_add',article_view_count + 1) +setattr(faqData,'article_evaluate_good',article_evaluate_good) +setattr(faqData,'article_evaluate_good_add',article_evaluate_good + 1) +setattr(faqData,'article_evaluate_bad',article_evaluate_bad) +setattr(faqData,'article_evaluate_bad_add',article_evaluate_bad + 1) + diff --git a/TestFile/FAQ/article_url_update.py b/TestFile/FAQ/article_url_update.py new file mode 100644 index 0000000000000000000000000000000000000000..3e14298a84808c679683f9e4ae48012643d5d1f5 --- /dev/null +++ b/TestFile/FAQ/article_url_update.py @@ -0,0 +1,7 @@ +from Utils.sql_handler import test_env_conn +from TestData.FAQ.faq_test_data import faqData + + +url = faqData.faqUrl +url = url.replace('helpPath=/',f'helpPath=/article/wquery/{faqData.article_title}') +setattr(faqData,'faqUrl',url) \ No newline at end of file diff --git a/TestFile/FAQ/popular_article_update.py b/TestFile/FAQ/popular_article_update.py new file mode 100644 index 0000000000000000000000000000000000000000..09c616f897c0c3275f2c370a554fe0037c405d6f --- /dev/null +++ b/TestFile/FAQ/popular_article_update.py @@ -0,0 +1,5 @@ +from Utils.sql_handler import test_env_conn +from TestData.FAQ.faq_test_data import faqData + +popular_article_update_sql = f'update `article` set is_popular = 0 where brand_id = {faqData.brandId} and shop_id = {faqData.shopId} and is_popular = 1' +test_env_conn.execute_sql(sql=popular_article_update_sql) diff --git a/Utils/req_handler.py b/Utils/req_handler.py index 50e38706297287978b4867256d8918e057b38276..1719023ce251b290995b0a45782f4f8cac30c1f5 100644 --- a/Utils/req_handler.py +++ b/Utils/req_handler.py @@ -154,6 +154,10 @@ class ReqHandler: assert value in res_path_value elif assert_way == 'ain':#ain代表返回值在断言值中 assert res_path_value in value + elif assert_way == 'not_in': + assert value not in res_path_value + elif assert_way == 'a_not_in': + assert res_path_value not in value elif assert_way == 'exec': exec(value) except AssertionError: diff --git a/Utils/webhook_handler.py b/Utils/webhook_handler.py new file mode 100644 index 0000000000000000000000000000000000000000..db213b9ade1f7a0293c467b8c1b281250b2a3a51 --- /dev/null +++ b/Utils/webhook_handler.py @@ -0,0 +1,48 @@ +import requests +import time +import hmac +import hashlib +import base64 +import urllib.parse + + +timestamp = str(round(time.time() * 1000)) +secret = 'SEC9d91939234e83369cba32c0ca4bcd9af60b5b1f69424d6fabd36f48d572a151c' +secret_enc = secret.encode('utf-8') +string_to_sign = '{}\n{}'.format(timestamp, secret) +string_to_sign_enc = string_to_sign.encode('utf-8') +hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() +sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) + + + +class webhookHandler: + + def __init__(self,webhookUrl = f"https://oapi.dingtalk.com/robot/send?access_token=22fda27990b00841c3201c20649c0a8abb6da82d8472b6f6154ef4cd9dadb33f×tamp={timestamp}&sign={sign}"): + self.webhookUrl = webhookUrl + + + def sendAutotestReport(self,result,second): + local_time = time.localtime(time.time()) + current_date_time_str = time.strftime('%Y-%m-%d %H:%M:%S', local_time) + data = { + "msgtype": "markdown", + "markdown": { + "title":"#willdesk接口自动化测试报告", + "text": "#### 本次接口自动化测试结果如下 \n > ###### 用例总数:%s\n > ###### 成功用例数量:%s\n > ###### 失败用例数量:%s\n > ###### 报错用例数量:%s\n > ###### 跳过用例数量:%s \n > ###### 耗时:%s秒\n > ###### 报告生成时间:%s [测试报告](https://www.baidu.com)"%(result._numcollected,len(result.stats.get('passed', [])),len(result.stats.get('failed', [])),len(result.stats.get('error', [])),len(result.stats.get('skipped', [])),second,current_date_time_str) + }, + } + res = requests.post(url=self.webhookUrl,json=data) + print(res.json()) + + def sendMsg(self,text,msgtype): + data = { + "msgtype": msgtype, + "text": { + "content": text + } + } + res = requests.post(url=self.webhookUrl,data=data) + + +webhook = webhookHandler() \ No newline at end of file diff --git a/YamlCase/FAQ/article.yaml b/YamlCase/FAQ/article.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6849086c7e24c2bd0b443422a545c1b27c0e1a16 --- /dev/null +++ b/YamlCase/FAQ/article.yaml @@ -0,0 +1,149 @@ +api1: + title: 检查列表文章数量 + url: /api/v1/helpcenter/buser/GetFaqList?v=${v} + method: get + before_sql: FAQ/article_list_select.py + expected: + - eq: {"$.code": 0} + - exec: {"code" : "assert len(res.json()['data']['articleList']) == ${all_article_num}"} + - exec: {"code" : "assert len([article for article in res.json()['data']['articleList'] if article['shopId'] == ${shopId}]) == ${shop_article_num}"} + +api2: + title: 检查文章信息 + url: /api/v1/helpcenter/buser/GetFaqList?v=${v} + method: get + expected: + - eq: {"$.code": 0} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].title": "${article_title}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].articleCategoryId": "${article_category_id}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].sort": "${article_sort}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].content": "${article_content}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].isPublish": "${article_is_published}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].isPopular": "${article_is_popular}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].metaTitle": "${article_meta_title}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].metaDescription": "${article_meta_description}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].views": "${article_view_count}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].articleEvaluateGood": "${article_evaluate_good}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].articleEvaluateBad": "${article_evaluate_bad}"} + +api3: + title: 设置文章为隐藏状态 + url: /api/v1/faq/updatePublish + method: post + data: {"isPublish":2,"id":"${article_id}","v":"${v}"} + expected: + - eq: {"$.code": 0} + +api4: + title: 设置文章为非特色文章 + url: /api/v1/faq/updatePopular + before_sql: FAQ/popular_article_update.py + method: post + data: {"isPopular":2,"id":"${article_id}","v":"${v}"} + expected: + - eq: {"$.code": 0} + +api5: + title: 检查文章信息 + url: /api/v1/helpcenter/buser/GetFaqList?v=${v} + method: get + expected: + - eq: { "$.code": 0} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].isPublish": 2} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].isPopular": 2} + +api6: + title: C端-检查文章是否隐藏 + url: /api/v1/client/faq/getHelpCenter?shopId=${shopId}&v=${v} + method: get + expected: + - eq: {"$.code": 0} + - exec: {"code" : "assert ${article_id} not in [article['id'] for article in res.json()['data']['list']]"} + +api7: + title: C端-检查文章是否为非特色文章 + url: /api/v1/client/faq/getPopularFaq?shopId=${shopId}&v=${v} + method: get + expected: + - eq: {"$.code": 0} + - exec: {"code" : "assert ${article_id} not in [article['id'] for article in res.json()['data']['list']]"} + +api8: + title: 设置文章为公开状态 + url: /api/v1/faq/updatePublish + method: post + data: {"isPublish":1,"id":"${article_id}","v":"${v}"} + expected: + - eq: {"$.code": 0} + +api9: + title: 设置文章为特色文章 + url: /api/v1/faq/updatePopular + before_sql: FAQ/popular_article_update.py + method: post + data: {"isPopular":1,"id":"${article_id}","v":"${v}"} + expected: + - eq: {"$.code": 0} + +api10: + title: 检查文章信息 + url: /api/v1/helpcenter/buser/GetFaqList?v=${v} + method: get + expected: + - eq: { "$.code": 0} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].isPublish": 1} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].isPopular": 1} + +api11: + title: C端-检查是否特色文章 + url: /api/v1/client/faq/getPopularFaq?shopId=${shopId}&v=${v} + method: get + set_value: {"faqUrl" : "$.data.list[?(@.id == '${article_id}')].faqUrl"} + expected: + - eq: {"$.code": 0} + - eq: {"$.data.list[?(@.id == '${article_id}')].articleCategoryId" : "${article_category_id}"} + - eq: {"$.data.list[?(@.id == '${article_id}')].content" : "${article_content}"} + - eq: {"$.data.list[?(@.id == '${article_id}')].title" : "${article_title}"} + +api12: + title: C端-检查是否公开文章 + url: /api/v1/client/faq/getHelpCenter?shopId=${shopId}&v=${v} + method: get + expected: + - eq: {"$.code": 0 } + - eq: {"$.data.list[?(@.id == '${article_category_id}')].articleList[?(@.id == '${article_id}')].title" : "${article_title}"} + - eq: {"$.data.list[?(@.id == '${article_category_id}')].articleList[?(@.id == '${article_id}')].sort": "${article_sort}"} + +api13: + title: 访问文章,增加阅读量 + url: /api/v1/client/faq/getFaqArticle?id=${article_id}&shopId=${shopId}&v=${v} + method: get + expected: + - eq: {"$.code": 0} + +api14: + title: 点赞文章 + url: /api/v1/faq/articleEvaluation + method: post + data: {"evaluationType":1,"id":"${article_id}"} + expected: + - eq: {"$.code": 0} + +api15: + title: 差评文章 + url: /api/v1/faq/articleEvaluation + method: post + data: {"evaluationType":2,"id":"${article_id}"} + expected: + - eq: {"$.code": 0} + + +api16: + title: 检查文章信息 + url: /api/v1/helpcenter/buser/GetFaqList?v=${v} + method: get + expected: + - eq: {"$.code": 0} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].articleEvaluateBad": "${article_evaluate_bad_add}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].articleEvaluateGood": "${article_evaluate_good_add}"} + - eq: {"$.data.articleList[?(@.id == '${article_id}')].views": "${article_view_count_add}"} \ No newline at end of file diff --git a/conftest.py b/conftest.py index 2d348a7c66de66fa1c72dde911ad998cf279b35f..df533d9e74a11e8337702f962a559a4bd1f88138 100644 --- a/conftest.py +++ b/conftest.py @@ -6,6 +6,8 @@ import re from Utils import config_handler from Utils import global_variate from Utils import websocket_handler +from _pytest import terminal +from Utils import webhook_handler session = requests.session() def willdesk_login(): @@ -105,6 +107,19 @@ async def get_client_id(): await asyncio.gather(asyncio.create_task(websocket_handler.ws_willdesk.get_client_id()),asyncio.create_task(websocket_handler.ws_client.get_client_id())) +def pytest_terminal_summary(terminalreporter, exitstatus, config): + '''收集测试结果''' + print("total:", terminalreporter._numcollected) + print('passed:', len(terminalreporter.stats.get('passed', []))) + print('failed:', len(terminalreporter.stats.get('failed', []))) + print('error:', len(terminalreporter.stats.get('error', []))) + print('skipped:', len(terminalreporter.stats.get('skipped', []))) + # terminalreporter._sessionstarttime 会话开始时间 + duration = time.time() - terminalreporter._sessionstarttime + print('total times:', round(duration,2), 'seconds') + webhook_handler.webhook.sendAutotestReport(result=terminalreporter,second=round(duration,2)) + + loop = websocket_handler.loop @pytest.fixture(scope='session',autouse=True) def call_fixture():