From a7f70d65ed8cd8f326e59aae58316c91e5dbdb0c Mon Sep 17 00:00:00 2001 From: mikigo Date: Wed, 27 Sep 2023 17:46:59 +0800 Subject: [PATCH] =?UTF-8?q?fix:=201=E3=80=81=E6=94=AF=E6=8C=81=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E5=8F=8D=E5=90=91=E5=90=8C=E6=AD=A5=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description: Log: --- docs/RELEASE.md | 8 +- docs/框架功能介绍/标签自动同步.md | 51 +++++++++-- manage.py | 29 +++++- setting/globalconfig.ini | 5 + setting/globalconfig.py | 1 + src/cmdctl.py | 2 +- src/pms/csv2pms.py | 91 +++++++++++++++++++ src/pms/pms2csv.py | 4 +- src/rtk/_base.py | 2 + 9 files changed, 180 insertions(+), 13 deletions(-) create mode 100644 src/pms/csv2pms.py diff --git a/docs/RELEASE.md b/docs/RELEASE.md index 6c11d26..cd1f0aa 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -4,6 +4,8 @@ new +- 支持标签反向同步:将 `csv` 中的标签同步到 `pms` ; + - 解除子项目的工程名称以 `autotest_` 开头的限制,子项目工程名称可以为任意名称; 配置文件 `globalconfig.ini` 中的 `APP_NAME` 和命令行参数 `-a/--app` 仅支持传入工程名称的全称: @@ -18,7 +20,7 @@ new youqu manage.py run -a apps/autotest_deepin_music ``` - 从 `apps` 开头可以获得命令行补全,使用更加便捷。 + 输入以 `apps` 开头可以获得命令行补全,使用更加便捷。 - 新增导入全局配置对象: @@ -38,6 +40,10 @@ new - 增加了在线文档的显示宽度; +fix + +- 修复从 `pms` 标签【设备类型】为 `null` 时,同步到 `csv` 文件写入为 `null`; + ## 2.2.3(2023/9/15) new diff --git a/docs/框架功能介绍/标签自动同步.md b/docs/框架功能介绍/标签自动同步.md index 28fc6cc..88a2d9d 100644 --- a/docs/框架功能介绍/标签自动同步.md +++ b/docs/框架功能介绍/标签自动同步.md @@ -4,7 +4,7 @@ 支持自动同步脚本 `ID`(用例 `py` 文件的 `ID`)到 `CSV` 文件; -【使用方法一】 +**【使用方法一】** 配置文件方式,通过一下几个配置来控制: @@ -18,9 +18,13 @@ PY_ID_TO_CSV = yes 如果不存在 `CSV` 文件会直接创建一个并写入用例脚本的 `ID`; -此功能默认会将 `CSV` 文件中多余的ID行删掉,以处理人工删除了用例脚本文件,但 `CSV` 文件里面对应的 `ID` 行未删除的问题; +此功能默认会将 `CSV` 文件中多余的 `ID` 行删掉,以处理人工删除了用例脚本文件,但 `CSV` 文件里面对应的 `ID` 行未删除的问题; -【使用方法二】 +```sh +youqu manage.py csvctl +``` + +**【使用方法二】** 命令行参数的方式: @@ -32,11 +36,11 @@ youqu manage.py csvctl -p2c 每次操作会将 `CSV` 文件先备份到 `report/pyid2csv_back` 目录下; -### 2. 从PMS自动同步标签信息 +### 2. 从PMS自动同步标签到CSV 用于自动同步 `PMS` 用例标签数据至本地 `CSV` 文件; -【使用方法一】 +**【使用方法一】** 配置文件方式,通过以下几个配置来控制: @@ -44,6 +48,7 @@ youqu manage.py csvctl -p2c APP_NAME = # 这个参数可填可不填,但是填了可以提高用例的执行速度,因为在用例收集阶段可以指定到具体的应用库。(下同) PMS_USER = # PMS的用户名 PMS_PASSWORD = # PMS的密码 +CSV_NAME_TO_PMS = ``` 在 `[pmsctl-pms_link_csv]` 节点下指定 `CSV` 文件名与 `PMS` 用例模块的对应关系,比如: @@ -69,7 +74,7 @@ youqu manage.py pmsctl -p2c 每次执行时原 `CSV` 文件会自动备份在 `report` 目录下,因此你不用担心脚本执行导致你的数据丢失。 -【使用方法二】 +**【使用方法二】** 按照我们一贯的风格,你也可以不去管配置文件,完全通过命令行参数传入: @@ -79,6 +84,40 @@ youqu manage.py pmsctl -p2c -u ut00xxxx -p you_password -plc music:81 每次操作会将 `CSV` 文件先备份到 `report/pms2csv_back` 目录下; +### 3. 从CSV文件同步标签到PMS + +用于将 `CSV` 文件中的标签同步到 `PMS` 用例库用例中; + +**【使用方法一】** + +配置文件方式,通过一下几个配置来控制: + +```ini +APP_NAME = +# PMS的用户名 +PMS_USER = +# PMS的密码 +PMS_PASSWORD = +;需要同步到pms的csv文件名称,不加.csv后缀 +;如果要做反向同步此参数必传; +;如果不传此参数可以扫描所有的csv文件,但是此操作太危险,暂时不考虑; +CSV_NAME_TO_PMS = +``` + +配置好后,在命令行执行: + +```shell +youqu manage.py pmsctl -c2p +``` + +**【使用方法二】** + +完全通过命令行参数传入: + +```shell +youqu manage.py pmsctl -c2p -a apps/autotest_com_deepin_lianliankan/ -c lianliankan -u my_user -p my_pwd +``` + ## 导出CSV文件 框架提供导出指定标签用例的功能: diff --git a/manage.py b/manage.py index 77ded57..f8ff2a0 100644 --- a/manage.py +++ b/manage.py @@ -24,6 +24,7 @@ from setting.globalconfig import GlobalConfig from src.startapp import StartApp from src import logger from src.pms.pms2csv import Pms2Csv +from src.pms.csv2pms import Csv2Pms from src.rtk._base import SubCmd from src.rtk._base import Args from src.rtk.local_runner import LocalRunner @@ -81,6 +82,8 @@ class Manage: pyid2csv=None, export_csv_file=None, pms2csv=None, + csv2pms=None, + csv_name=None, pms_link_csv=None, send2task=None, ): @@ -124,6 +127,8 @@ class Manage: self.default_pyid2csv = pyid2csv self.default_export_csv_file = export_csv_file self.default_pms2csv = pms2csv + self.default_csv2pms = csv2pms + self.default_csv_name = csv_name self.default_pms_link_csv = pms_link_csv self.default_send2task = send2task @@ -374,9 +379,8 @@ class Manage: """pms相关功能命令行参数""" sub_parser_pms.add_argument( "-a", "--app", default="", - help="应用名称:deepin-music 或 autotest_deepin_music 或 apps/autotest_deepin_music" + help="应用名称:apps/autotest_deepin_music 或 autotest_deepin_music" ) - sub_parser_pms.add_argument( "-u", "--pms_user", default="", help="pms 用户名" ) @@ -391,6 +395,14 @@ class Manage: "-p2c", "--pms2csv", action='store_const', const=True, default=False, help="从PMS爬取用例标签到csv文件" ) + sub_parser_pms.add_argument( + "-c2p", "--csv2pms", action='store_const', const=True, default=False, + help="将csv文件里面的标签同步到PMS" + ) + sub_parser_pms.add_argument( + "-c", "--csv_name", default="", + help="将csv文件里面的标签同步到PMS时csv文件的名称" + ) sub_parser_pms.add_argument( "--send2task", choices=["yes", ""], @@ -409,6 +421,8 @@ class Manage: Args.pms_user.value: args.pms_user or self.default_pms_user, Args.pms_password.value: args.pms_password or self.default_pms_password, Args.pms2csv.value: args.pms2csv or self.default_pms2csv, + Args.csv2pms.value: args.csv2pms or self.default_csv2pms, + Args.csv_name.value: args.csv_name or self.default_csv_name, Args.pms_link_csv.value: args.pms_link_csv or self.default_pms_link_csv, Args.send2task.value: args.send2task or self.default_send2task, Args.task_id.value: args.task_id or GlobalConfig.TASK_ID, @@ -421,6 +435,13 @@ class Manage: password=pms_kwargs.get(Args.pms_password.value) or GlobalConfig.PMS_PASSWORD, pms_link_csv=pms_kwargs.get(Args.pms_link_csv.value), ).write_new_csv() + elif pms_kwargs.get(Args.csv2pms.value): + Csv2Pms( + app_name=pms_kwargs.get(Args.app_name.value), + user=pms_kwargs.get(Args.pms_user.value) or GlobalConfig.PMS_USER, + password=pms_kwargs.get(Args.pms_password.value) or GlobalConfig.PMS_PASSWORD, + csv_name=pms_kwargs.get(Args.csv_name.value), + ).post_to_pms() elif ( pms_kwargs.get(Args.send2task.value) and pms_kwargs.get(Args.task_id.value) @@ -430,6 +451,8 @@ class Manage: Send2Pms.case_res_path(pms_kwargs.get(Args.task_id.value)), Send2Pms.data_send_result_csv(pms_kwargs.get(Args.trigger.value)) ) + else: + raise ValueError @staticmethod def start_app(startapp=None): @@ -443,7 +466,7 @@ class Manage: """csv相关功能命令参数""" sub_parser_csv.add_argument( "-a", "--app", default="", - help="应用名称:deepin-music 或 autotest_deepin_music 或 apps/autotest_deepin_music" + help="应用名称:apps/autotest_deepin_music 或 autotest_deepin_music" ) sub_parser_csv.add_argument( "-k", "--keywords", default="", help="用例的关键词" diff --git a/setting/globalconfig.ini b/setting/globalconfig.ini index 323e0d9..439fdbe 100644 --- a/setting/globalconfig.ini +++ b/setting/globalconfig.ini @@ -203,6 +203,11 @@ EXPORT_CSV_FILE = ;导出 case_list.csv 文件时配置的字段名,用例名称默认存在第一列,无需添加 EXPORT_CSV_HEARD = 用例级别,用例类型,测试级别,是否跳过 +;需要同步到pms的csv文件名称,不加.csv后缀 +;如果要做反向同步此参数必传; +;如果不传此参数可以扫描所有的csv文件,但是此操作太危险,暂时不考虑; +CSV_NAME_TO_PMS = + [log_cli] ;日志相关配置(不打印构造函数和魔法函数的功能说明) diff --git a/setting/globalconfig.py b/setting/globalconfig.py index 9790965..102c6da 100644 --- a/setting/globalconfig.py +++ b/setting/globalconfig.py @@ -136,6 +136,7 @@ class _GlobalConfig: PY_ID_TO_CSV = csv_cfg.get_bool("PY_ID_TO_CSV", default=False) EXPORT_CSV_FILE = csv_cfg.get("EXPORT_CSV_FILE", default="") EXPORT_CSV_HEARD = csv_cfg.get("EXPORT_CSV_HEARD", default="用例级别,用例类型,测试级别,是否跳过").replace(" ", "") + CSV_NAME_TO_PMS = csv_cfg.get("CSV_NAME_TO_PMS", default="") # [log_cli] log_cli = GetCfg(GLOBAL_CONFIG_FILE_PATH, "log_cli") diff --git a/src/cmdctl.py b/src/cmdctl.py index 48374e8..5ab8cfb 100644 --- a/src/cmdctl.py +++ b/src/cmdctl.py @@ -221,7 +221,7 @@ class CmdCtl: ) @classmethod - def kill_process(cls, process, grep_list: str = None): + def kill_process(cls, process, grep_list: [list, tuple] = None): """ 杀进程 :param process: 进程名 diff --git a/src/pms/csv2pms.py b/src/pms/csv2pms.py new file mode 100644 index 0000000..723c969 --- /dev/null +++ b/src/pms/csv2pms.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# _*_ coding:utf-8 _*_ + +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. + +# SPDX-License-Identifier: GPL-2.0-only +import os +from urllib.parse import urlencode + +from setting import conf +from setting.globalconfig import FixedCsvTitle +from src.pms._base import _Base +from src.rtk._base import transform_app_name + + +class Csv2Pms(_Base): + __author__ = "mikigo" + + config_error_log = "请检查您传递的 '命令行参数' 或 setting/globalconfig.ini 里的配置项" + + def __init__( + self, + app_name: str = None, + user: str = None, + password: str = None, + csv_name=None + ): + super().__init__(user=user, password=password) + self.username = user + self.password = user + self.base_url = "https://pms.uniontech.com" + self.walk_dir = ( + f"{conf.APPS_PATH}/{transform_app_name(app_name)}" + if app_name + else conf.APPS_PATH + ) + self.csv_name = csv_name or conf.CSV_NAME_TO_PMS + + if not self.csv_name: + raise EnvironmentError(self.config_error_log) + + def get_csv_info(self): + csv_path = None + for root, _, files in os.walk(self.walk_dir): + for file in files: + if f"{self.csv_name}.csv" == file: + csv_path = f"{root}/{file}" + if csv_path is None: + raise FileNotFoundError(self.config_error_log) + + with open(csv_path, "r", encoding="utf-8") as f: + txt_list = f.readlines() + + csv_heads = txt_list[0].strip().split(",") + csv_head_index_map = {} + for index, title in enumerate(csv_heads): + for i in FixedCsvTitle: + if i.value == title.strip(): + csv_head_index_map[i.name] = { + "head_name": i.value, + "head_index": index, + } + + taglines = [txt.strip().split(",") for txt in txt_list[1:]] + return csv_head_index_map, taglines + + def post_to_pms(self): + csv_head_index_map, taglines = self.get_csv_info() + + def csv_map(x): + return csv_head_index_map.get(x).get('head_index') + + for i in taglines: + case_id = i[csv_map(FixedCsvTitle.case_id.name)] + edit_url = f"{self.base_url}/testcase-edit-{case_id}.html" + data = { + 'isAutomation': '是', + } + if i[csv_map(FixedCsvTitle.device_type.name)] in ("PPL", "COL"): + data["deviceType"] = i[csv_map(FixedCsvTitle.device_type.name)] + if i[csv_map(FixedCsvTitle.case_from.name)] == "是": + data["caseSource"] = "是" + if i[csv_map(FixedCsvTitle.online_obj.name)] == "CICD": + data["lineCD"] = "是" + bytes_data = urlencode(data).encode("utf-8") + res = self.rx.session.open( + fullurl=edit_url, + data=bytes_data, + timeout=10 + ) + print(f"{case_id}-{data}—{res.status}") diff --git a/src/pms/pms2csv.py b/src/pms/pms2csv.py index fa5e283..77745b2 100644 --- a/src/pms/pms2csv.py +++ b/src/pms/pms2csv.py @@ -23,7 +23,7 @@ from src.rtk._base import transform_app_name class Pms2Csv(_Base): """获取pms数据同步到本地csv文件""" - __author__ = "huangmingqiang@uniontech.com" + __author__ = "mikigo" config_error_log = "请检查您传递的 '命令行参数' 或 setting/globalconfig.ini 里的配置项" @@ -96,7 +96,7 @@ class Pms2Csv(_Base): "case_type": case_type, "case_from": "BUG" if case_from == "是" else "", "device_type": device_type.split("(")[0] - if device_type or device_type != "null" + if device_type and device_type != "null" else "", "online_obj": "CICD" if online_obj == "是" else "", } diff --git a/src/rtk/_base.py b/src/rtk/_base.py index 0d03058..c01faa0 100644 --- a/src/rtk/_base.py +++ b/src/rtk/_base.py @@ -67,8 +67,10 @@ class Args(Enum): pyid2csv = "pyid2csv" export_csv_file = "export_csv_file" pms2csv = "pms2csv" + csv2pms = "csv2pms" pms_link_csv = "pms_link_csv" send2task = "send2task" + csv_name = "csv_name" def transform_app_name(app_name):