已合并
门禁、流水整改四:完善 UT, ST 执行逻辑 #1678
AtomGit-Bot创建于 2024年9月13日
门禁、流水整改四:完善 UT, ST 执行逻辑 #1678
已合并
AtomGit-Bot创建于 2024年9月13日
refs/pull/1678/head合入到master
6 个文件变更+138-60
@@ -8,7 +8,7 @@ def read_files_from_txt(txt_file):
8 8 
9 9 
10def is_examples(file):10def is_examples(file):
11- return file.startswith("example/")11+ return file.startswith("examples/")
12 12 
13 13 
14def is_pipecase(file):14def is_pipecase(file):
@@ -19,17 +19,22 @@ def is_markdown(file):
19 return file.endswith(".md")19 return file.endswith(".md")
20 20 
21 21 
22-def skip_ci_file(files, skip_cond):22+def is_image(file):
23+ return file.endswith(".jpg") or file.endswith(".png")
24+ 
25+ 
26+def is_ut(file):
27+ return file.startswith("tests/ut")
28+ 
29+ 
30+def skip_ci(files, skip_conds):
23 for file in files:31 for file in files:
24- if not any(condition(file) for condition in skip_cond):32+ if not any(condition(file) for condition in skip_conds):
25 return False33 return False
26 return True34 return True
27 35 
28 36 
29-def alter_skip_ci():37+def choose_skip_ci(raw_txt_file):
30- parent_dir = Path(__file__).absolute().parents[2]
31- raw_txt_file = os.path.join(parent_dir, "modify.txt")
32- 
33 if not os.path.exists(raw_txt_file):38 if not os.path.exists(raw_txt_file):
34 return False39 return False
35 40
@@ -37,10 +42,22 @@ def alter_skip_ci():
37 skip_conds = [42 skip_conds = [
38 is_examples,43 is_examples,
39 is_pipecase,44 is_pipecase,
40- is_markdown45+ is_markdown,
46+ is_image
41 ]47 ]
42 48 
43- return skip_ci_file(file_list, skip_conds)49+ return skip_ci(file_list, skip_conds)
50+ 
51+ 
52+def filter_exec_ut(raw_txt_file):
53+ file_list = read_files_from_txt(raw_txt_file)
54+ filter_conds = [
55+ is_ut
56+ ]
57+ for file in file_list:
58+ if not any(condition(file) for condition in filter_conds):
59+ return False, None
60+ return True, file_list
44 61 
45 62 
46def acquire_exitcode(command):63def acquire_exitcode(command):
@@ -53,16 +70,25 @@ def acquire_exitcode(command):
53# UT test, run with pytest70# UT test, run with pytest
54# =============================71# =============================
55 72 
56-class UT_Test:73+class UTTest:
57- 
58 def __init__(self):74 def __init__(self):
59- 75+ self.base_dir = Path(__file__).absolute().parents[1]
60- base_dir = Path(__file__).absolute().parent.parent76+ self.test_dir = os.path.join(self.base_dir, 'tests')
61- test_dir = os.path.join(base_dir, 'tests')77+ self.ut_files = os.path.join(
62- self.ut_file = os.path.join(test_dir, "ut")78+ self.base_dir, self.test_dir, "ut"
79+ )
63 80
64- def run_ut(self):81+ def run_ut(self, raw_txt_file=None):
65- command = f"pytest -x {self.ut_file}"82+ if raw_txt_file is not None and os.path.exists(raw_txt_file):
83+ filtered_results = filter_exec_ut(raw_txt_file)
84+ 
85+ if filtered_results[0]:
86+ filtered_files = filtered_results[1]
87+ full_path = [os.path.join(self.base_dir, file) for file in filtered_files]
88+ exsit_ut_files = [file for file in full_path if os.path.exists(file) and file.endswith(".py")]
89+ self.ut_files = " ".join(exsit_ut_files)
90+ 
91+ command = f"pytest -x {self.ut_files}"
66 code = acquire_exitcode(command)92 code = acquire_exitcode(command)
67 if code == 0:93 if code == 0:
68 print("UT test success")94 print("UT test success")
@@ -75,16 +101,14 @@ class UT_Test:
75# ST test, run with sh.101# ST test, run with sh.
76# ===============================================102# ===============================================
77 103 
78-class ST_Test:104+class STTest:
79-
80 def __init__(self):105 def __init__(self):
106+ self.base_dir = Path(__file__).absolute().parents[1]
107+ self.test_dir = os.path.join(self.base_dir, 'tests')
81 108 
82- base_dir = Path(__file__).absolute().parent.parent109+ self.st_dir = "st"
83- test_dir = os.path.join(base_dir, 'tests')
84- 
85- st_dir = "st"
86 self.st_shell = os.path.join(110 self.st_shell = os.path.join(
87- test_dir, st_dir, "st_run.sh"111+ self.test_dir, self.st_dir, "st_run.sh"
88 )112 )
89 113 
90 def run_st(self):114 def run_st(self):
@@ -95,19 +119,25 @@ class ST_Test:
95 exit(1)119 exit(1)
96 120 
97 121 
98-def run_tests():122+def run_tests(raw_txt_file):
99- ut = UT_Test()123+ ut = UTTest()
100- st = ST_Test()124+ st = STTest()
101- 125+ if filter_exec_ut(raw_txt_file)[0]:
102- ut.run_ut()126+ ut.run_ut(raw_txt_file)
103- st.run_st()127+ else:
128+ ut.run_ut()
129+ st.run_st()
104 130 
105 131 
106def main():132def main():
107- if alter_skip_ci():133+ parent_dir = Path(__file__).absolute().parents[2]
134+ raw_txt_file = os.path.join(parent_dir, "modify.txt")
135+ 
136+ skip_signal = choose_skip_ci(raw_txt_file)
137+ if skip_signal:
108 print("Skipping CI")138 print("Skipping CI")
109 else:139 else:
110- run_tests()140+ run_tests(raw_txt_file)
111 141 
112if __name__ == "__main__":142if __name__ == "__main__":
113 main()143 main()
@@ -269,7 +269,7 @@
269 269 
270① 贡献脚本用例请放置于 `st/shell_scripts` 文件夹下,命名规则为 **{模型名}_{切分策略}** 或者 **{模型名}_{特性名称}**, 如 `llama2_tp2_pp4_vpp2_ptd.sh`,请贡献者严格对齐;270① 贡献脚本用例请放置于 `st/shell_scripts` 文件夹下,命名规则为 **{模型名}_{切分策略}** 或者 **{模型名}_{特性名称}**, 如 `llama2_tp2_pp4_vpp2_ptd.sh`,请贡献者严格对齐;
271 271 
272-② 注意脚本用例中不需要单独重定向log,日志收集工作已在 `run.sh` 中统一管理;272+② 注意脚本用例中不需要单独重定向log,日志收集工作已在 `st_run.sh` 中统一管理;
273 273 
274③ 标杆数据请放置于 `st/baseline_results` 文件夹下,**命名保证完全与 shell 脚本对齐**,否则自动化脚本执行将扫描不到;274③ 标杆数据请放置于 `st/baseline_results` 文件夹下,**命名保证完全与 shell 脚本对齐**,否则自动化脚本执行将扫描不到;
275 275 
Rtests/conftest.pytests/pipeline/conftest.py+0-25
@@ -43,28 +43,3 @@ def pytest_fixture_setup(fixturedef, request):
43 dist_fixture_class(request)43 dist_fixture_class(request)
44 44 
45 45 
46-# we still want to configure path argument by ourselves
47-# for different prefix_name of different scripts so we use this method.
48-# One more thing, as you can see, it has more scalibility.
49-def pytest_addoption(parser: pytest.Parser):
50- parser.addoption("--baseline-json", action="store", default=None,
51- help="Path to the baseline JSON file")
52- parser.addoption("--generate-log", action="store", default=None,
53- help="Path to the generate log file")
54- parser.addoption("--generate-json", action="store", default=None,
55- help="Path to the generate JSON file")
56- 
57- 
58-@pytest.fixture(autouse=True)
59-def baseline_json(request: pytest.FixtureRequest):
60- return request.config.getoption("--baseline-json")
61- 
62- 
63-@pytest.fixture(autouse=True)
64-def generate_log(request: pytest.FixtureRequest):
65- return request.config.getoption("--generate-log")
66- 
67- 
68-@pytest.fixture(autouse=True)
69-def generate_json(request: pytest.FixtureRequest):
70- return request.config.getoption("--generate-json")
@@ -23,8 +23,8 @@ find "$BASE_DIR" -mindepth 1 -maxdepth 1 -type d | while read -r dir; do
23 fi23 fi
24 24 
25 # begin to execute the logic of compare25 # begin to execute the logic of compare
26- echo "$(dirname "$BASE_DIR")/st/st_utils/test_ci_st.py"26+ echo "$(dirname "$BASE_DIR")/test_tools/test_ci_st.py"
27- pytest -x $(dirname "$BASE_DIR")/st/st_utils/test_ci_st.py \27+ pytest -x $(dirname "$BASE_DIR")/test_tools/test_ci_st.py \
28 --baseline-json $BASELINE_DIR/$name.json \28 --baseline-json $BASELINE_DIR/$name.json \
29 --generate-log $GENERATE_LOG_DIR/$name.log \29 --generate-log $GENERATE_LOG_DIR/$name.log \
30 --generate-json $GENERATE_JSON_DIR/$name.json30 --generate-json $GENERATE_JSON_DIR/$name.json
@@ -0,0 +1,28 @@
1+import pytest
2+ 
3+ 
4+# we still want to configure path argument by ourselves
5+# for different prefix_name of different scripts so we use this method.
6+# One more thing, as you can see, it has more scalibility.
7+def pytest_addoption(parser: pytest.Parser):
8+ parser.addoption("--baseline-json", action="store", default=None,
9+ help="Path to the baseline JSON file")
10+ parser.addoption("--generate-log", action="store", default=None,
11+ help="Path to the generate log file")
12+ parser.addoption("--generate-json", action="store", default=None,
13+ help="Path to the generate JSON file")
14+ 
15+ 
16+@pytest.fixture(autouse=True)
17+def baseline_json(request: pytest.FixtureRequest):
18+ return request.config.getoption("--baseline-json")
19+ 
20+ 
21+@pytest.fixture(autouse=True)
22+def generate_log(request: pytest.FixtureRequest):
23+ return request.config.getoption("--generate-log")
24+ 
25+ 
26+@pytest.fixture(autouse=True)
27+def generate_json(request: pytest.FixtureRequest):
28+ return request.config.getoption("--generate-json")
@@ -0,0 +1,45 @@
1+# Copyright (c) Microsoft Corporation.
2+#
3+# This source code is licensed under the Apache license found in the
4+# LICENSE file in the root directory of this source tree.
5+ 
6+# copied from https://github.com/microsoft/DeepSpeed/blob/master/tests/conftest.py
7+# reworked/refactored some parts to make it run.
8+import pytest
9+ 
10+ 
11+def pytest_configure(config):
12+ config.option.color = "yes"
13+ config.option.durations = 0
14+ config.option.durations_min = 1
15+ config.option.verbose = True
16+ 
17+ 
18+# Override of pytest "runtest" for DistributedTest class
19+# This hook is run before the default pytest_runtest_call
20+@pytest.hookimpl(tryfirst=True)
21+def pytest_runtest_call(item):
22+ # We want to use our own launching function for distributed tests
23+ if getattr(item.cls, "is_dist_test", False):
24+ dist_test_class = item.cls()
25+ dist_test_class(item._request)
26+ item.runtest = lambda: True # Dummy function so test is not run twice
27+ 
28+ 
29+# We allow DistributedTest to reuse distributed environments. When the last
30+# test for a class is run, we want to make sure those distributed environments
31+# are destroyed.
32+def pytest_runtest_teardown(item, nextitem):
33+ if getattr(item.cls, "reuse_dist_env", False) and not nextitem:
34+ dist_test_class = item.cls()
35+ for num_procs, pool in dist_test_class._pool_cache.items():
36+ dist_test_class._close_pool(pool, num_procs, force=True)
37+ 
38+ 
39+@pytest.hookimpl(tryfirst=True)
40+def pytest_fixture_setup(fixturedef, request):
41+ if getattr(fixturedef.func, "is_dist_fixture", False):
42+ dist_fixture_class = fixturedef.func()
43+ dist_fixture_class(request)
44+ 
45+