diff --git a/pytest/pyproject.toml b/pytest/pyproject.toml index 5aeec76..6535501 100644 --- a/pytest/pyproject.toml +++ b/pytest/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "testsolar-pytestx" -version = "0.1.78" +version = "0.1.79" description = "Pytest tool for TestSolar" authors = [ {name = "asiazhang2002", email = "asiazhang2002@gmail.com"}, diff --git a/pytest/src/testsolar_pytestx/converter.py b/pytest/src/testsolar_pytestx/converter.py index 2f963d2..38cee7e 100644 --- a/pytest/src/testsolar_pytestx/converter.py +++ b/pytest/src/testsolar_pytestx/converter.py @@ -5,6 +5,7 @@ from loguru import logger CASE_DRIVE_SEPARATOR = "→" +NAME_ATTR_PREFIX = "name=" def selector_to_pytest(test_selector: str) -> str: @@ -18,26 +19,34 @@ def selector_to_pytest(test_selector: str) -> str: # 只要出现 /[ 就说明该 selector 是一个真实的参数化用例节点, # 即使数据驱动数据中包含 "="(例如 sample_rate=0),也不应该被误判为属性筛选 data_drive_flag = "/[" + # 数据驱动里的 & 属于数据内容(例如 [demand_name=测试&author_name=xx]), + # 只有不含数据驱动标记时,& 才表示属性筛选:tests/hello_test.py?name=xxxTest&tag=prod + is_attr_filter = data_drive_flag not in testcase if "&" in testcase: testcase_attrs = testcase.split("&") for attr in testcase_attrs: - if "name=" in attr: # tests/hello_test.py?name=xxxTest&tag=prod - testcase = attr[5:] + # 属性名只会出现在片段开头,不能用 in 判断:数据驱动中的参数名 + # (例如 demand_name=测试、product_name=xx)同样包含 name=, + # 误判后 attr[len(NAME_ATTR_PREFIX):] 会把用例名截断 + if is_attr_filter and attr.startswith(NAME_ATTR_PREFIX): + # tests/hello_test.py?name=xxxTest&tag=prod + testcase = attr[len(NAME_ATTR_PREFIX) :] break - elif "=" not in attr: # tests/hello_test.py?xxxTest& + elif is_attr_filter and "=" not in attr: + # tests/hello_test.py?xxxTest&tag=prod testcase = attr break else: # 所有属性均包含 "=",无法区分属性筛选与参数化用例 - if data_drive_flag not in testcase: + if is_attr_filter: # 不含数据驱动标记,判定为纯属性筛选 # tests/hello_test.py?test_hello_world&tag=prod return path else: - if testcase.startswith("name="): # tests/hello_test.py?name=xxxTest - testcase = testcase[5:] - elif "=" in testcase and data_drive_flag not in testcase: + if testcase.startswith(NAME_ATTR_PREFIX): # tests/hello_test.py?name=xxxTest + testcase = testcase[len(NAME_ATTR_PREFIX) :] + elif "=" in testcase and is_attr_filter: # tests/hello_test.py?tag=prod # 注意:参数化数据中可能包含 "=",例如 # tests/test_asr_websocket.py?TestAsrWebSocket/test_sample_rate_parametrized/[0-default-sample_rate=0-False] diff --git a/pytest/tests/test_converter.py b/pytest/tests/test_converter.py index f459445..0632a02 100644 --- a/pytest/tests/test_converter.py +++ b/pytest/tests/test_converter.py @@ -90,6 +90,35 @@ def test_selector_to_pytest_with_equal_sign_in_http_datadrive(self): "tests/test_asr_http.py::TestASRRecognize::test_recognize_audio_format[summary_context-base64-pcm]", ) + def test_selector_to_pytest_with_name_attr_in_datadrive(self): + # 回归场景:数据驱动中包含 & 且参数名以 name= 结尾(demand_name=/mcn_name=/product_name=) + # 不能被当成属性筛选,否则用例名会被截断(attr[5:]) + re = selector_to_pytest( + "tests/qq/settlement/test_settlement.py?TestSettlementWalletMcnSettleFlow/test_settlement_wallet_mcn_settle_flow/[demand_name=测试&author_name=频道--发布&author_id=14124598&pay_status=2-expected=code:0]" + ) + self.assertEqual( + re, + "tests/qq/settlement/test_settlement.py::TestSettlementWalletMcnSettleFlow::test_settlement_wallet_mcn_settle_flow[demand_name=\\u6d4b\\u8bd5&author_name=\\u9891\\u9053--\\u53d1\\u5e03&author_id=14124598&pay_status=2-expected=code:0]", + ) + + # name= 出现在后面的参数上,同样不能截断用例名 + re = selector_to_pytest( + "tests/qq/settlement/test_settlement.py?TestSettlementWalletAuthorPersonalSettleFlow/test_settlement_wallet_author_personal_settle_flow/[pay_status=2&demand_name=测试&demand_type=3-expected=code:0]" + ) + self.assertEqual( + re, + "tests/qq/settlement/test_settlement.py::TestSettlementWalletAuthorPersonalSettleFlow::test_settlement_wallet_author_personal_settle_flow[pay_status=2&demand_name=\\u6d4b\\u8bd5&demand_type=3-expected=code:0]", + ) + + re = selector_to_pytest( + "tests/qq/settlement/test_settlement.py?TestSettlementBfcPersonList/test_settlement_bfc_person_list/[pay_status=2&mcn_name=中国移动通信集团江苏有限公司-expected=code:0]" + ) + self.assertTrue( + re.startswith( + "tests/qq/settlement/test_settlement.py::TestSettlementBfcPersonList::test_settlement_bfc_person_list[pay_status=2&mcn_name=" + ) + ) + def test_selector_to_pytest_with_utf8_string(self): re = selector_to_pytest( "/data/tests/tests/test_data_drive_zh_cn.py?aa/bb/test_include/[中文-中文汉字]" diff --git a/pytest/testtool.yaml b/pytest/testtool.yaml index 782c684..e4c171b 100644 --- a/pytest/testtool.yaml +++ b/pytest/testtool.yaml @@ -2,7 +2,7 @@ schemaVersion: 1.0 name: pytest nameZh: pytest自动化测试 lang: python -version: '0.1.78' +version: '0.1.79' langType: INTERPRETED description: |- pytest是一个成熟的全功能Python测试工具,可以帮助您编写更好的程序。此测试工具允许您在TestSolar上运行pytest。 diff --git a/pytest/uv.lock b/pytest/uv.lock index 71bdd35..f7b903a 100644 --- a/pytest/uv.lock +++ b/pytest/uv.lock @@ -463,7 +463,7 @@ wheels = [ [[package]] name = "testsolar-pytestx" -version = "0.1.78" +version = "0.1.79" source = { virtual = "." } dependencies = [ { name = "coverage" },