
作为开发人员,我们平时编写代码之前,通常是这样的流程:
在 conf 文件夹下,为 xxx 创建一个子文件夹,并在这个子文件夹里创建 xxx.py 文件 在 data 文件夹下,为 xxx 创建一个子文件夹,并在这个子文件夹里创建 xxx.json 文件 在 page 文件夹下,为 xxx 创建一个子文件夹,并在这个子文件夹里创建 xxx.py 文件 在 scripts 文件夹下,为 xxx 创建一个子文件夹,并在这个子文件夹里创建 test_xxx.py 文件
一顿操作猛如虎,一看战绩零杠五!光新建文件夹就花了10分钟,然后就已经累了😂
尤其很多企业级项目使用了PO模型框架,它的框架清晰,结构完整,可以适用于绝大多数的大型企业的项目;但同时也存在新建项目文件麻烦,维护成本略高等缺陷
这也太不自动化了!我们希望:
既然需求已经明确,那么‘简单’的编码环节就开始了~😏
先说一下如何使用脚本吧,源码放在文章最后。当然老规矩,后台回复“批量创建”也可以获得项目的完整源码
需要将这两个代码放在我们的项目根目录下,以确保脚本可以正常运行
分为 auto_create.py 和 interactive_creator.py 两个脚本
右击运行 interactive_creator.py

输入想创建的文件名称,比如gongzhonghao
若文件名称符合命名规范且不存在,则创建成功

查看项目目录,创建成功

若文件名称不规范(比如出现中文),提示错误

若文件名已存在,则询问覆盖、新建、取消
这么做是为了最大程度地保护我们代码的安全。如果没有文件名是否存在的校验,直接进行新建操作,会带来无法估量的代码损失

最后按照提示,继续新建or退出

注意:由于批量删除操作为非常敏感的操作,本脚本不提供任何的批量删除功能。也提醒小伙伴们尽可能少使用批量删除操作,以免造成无法估量的损失
auto_create.py
import os
import argparse
import re
import shutil
def check_module_exists(module_name):
"""
检查模块是否已经存在
返回存在的目录列表
"""
base_dirs = ['conf', 'data', 'page', 'scripts']
existing_dirs = []
for dir_name in base_dirs:
module_dir = os.path.join(dir_name, module_name)
if os.path.exists(module_dir):
existing_dirs.append(dir_name)
return existing_dirs
def create_project_structure(module_name, force_overwrite=False):
"""
根据模块名称创建标准的项目结构
"""
# 验证输入是否为有效的英文或数字字符
ifnot re.match(r'^[a-zA-Z0-9_]+$', module_name):
print(f"错误: 模块名称 '{module_name}' 只能包含英文字母、数字和下划线")
returnFalse
# 检查模块是否已存在
existing_dirs = check_module_exists(module_name)
if existing_dirs andnot force_overwrite:
print(f"⚠️ 模块 '{module_name}' 在以下目录中已存在: {', '.join(existing_dirs)}")
whileTrue:
choice = input("请选择操作: (1)创建文件,但跳过已有文件 (2)删除并重新创建 (3)取消: ").strip()
if choice == '1':
# 覆盖模式 - 只创建不存在的部分,已存在的保留
return create_with_overwrite(module_name, existing_dirs)
elif choice == '2':
# 删除并重新创建
return recreate_module(module_name)
elif choice == '3':
print("❌ 操作已取消")
returnFalse
else:
print("❌ 无效选择,请输入 1, 2 或 3")
# 如果模块不存在或强制覆盖,直接创建
return create_new_module(module_name)
def create_new_module(module_name):
"""创建新模块"""
base_dirs = {
'conf': f'{module_name}.py',
'data': f'{module_name}.json',
'page': f'{module_name}.py',
'scripts': f'test_{module_name}.py'
}
created_items = []
try:
for dir_name, file_name in base_dirs.items():
# 创建主文件夹
main_dir_path = os.path.join(dir_name, module_name)
os.makedirs(main_dir_path, exist_ok=True)
# 创建对应的文件
file_path = os.path.join(main_dir_path, file_name)
with open(file_path, 'w', encoding='utf-8') as f:
# 根据文件类型添加基本内容
if file_name.endswith('.py'):
if dir_name == 'scripts': # test文件
f.write(generate_test_template(module_name))
else: # 普通py文件
f.write(generate_py_template(module_name, dir_name))
elif file_name.endswith('.json'):
f.write(generate_json_template(module_name))
created_items.append(f" - {file_path}")
print(f"✅ 成功创建模块 '{module_name}' 的完整结构:")
for item in created_items:
print(item)
returnTrue
except Exception as e:
print(f"❌ 创建过程中出现错误: {e}")
returnFalse
def create_with_overwrite(module_name, existing_dirs):
"""覆盖模式 - 只创建不存在的部分"""
base_dirs = {
'conf': f'{module_name}.py',
'data': f'{module_name}.json',
'page': f'{module_name}.py',
'scripts': f'test_{module_name}.py'
}
created_items = []
skipped_items = []
try:
for dir_name, file_name in base_dirs.items():
main_dir_path = os.path.join(dir_name, module_name)
file_path = os.path.join(main_dir_path, file_name)
if dir_name in existing_dirs:
skipped_items.append(f" - {file_path} (已存在,跳过)")
continue
# 创建主文件夹
os.makedirs(main_dir_path, exist_ok=True)
# 创建对应的文件
with open(file_path, 'w', encoding='utf-8') as f:
if file_name.endswith('.py'):
if dir_name == 'scripts':
f.write(generate_test_template(module_name))
else:
f.write(generate_py_template(module_name, dir_name))
elif file_name.endswith('.json'):
f.write(generate_json_template(module_name))
created_items.append(f" - {file_path}")
print(f"✅ 成功创建模块 '{module_name}' 的新增部分:")
for item in created_items:
print(item)
if skipped_items:
print(f"📋 跳过的已存在部分:")
for item in skipped_items:
print(item)
returnTrue
except Exception as e:
print(f"❌ 创建过程中出现错误: {e}")
returnFalse
def recreate_module(module_name):
"""删除并重新创建模块"""
base_dirs = ['conf', 'data', 'page', 'scripts']
try:
# 首先删除所有已存在的模块目录
for dir_name in base_dirs:
module_dir = os.path.join(dir_name, module_name)
if os.path.exists(module_dir):
shutil.rmtree(module_dir)
print(f"🗑️ 已删除: {module_dir}")
# 然后重新创建
return create_new_module(module_name)
except Exception as e:
print(f"❌ 删除和重新创建过程中出现错误: {e}")
returnFalse
def generate_py_template(module_name, dir_type):
"""生成Python文件模板"""
templates = {
'conf': f'''\"\"\"
{module_name} 配置文件
\"\"\"
# 配置项定义
class {module_name.capitalize()}Config:
\"\"\"{module_name} 配置类\"\"\"
# 基础配置
ENABLED = True
TIMEOUT = 30
# 自定义配置
def __init__(self):
pass
# 全局配置实例
config = {module_name.capitalize()}Config()
''',
'page': f'''\"\"\"
{module_name} 页面对象
\"\"\"
class {module_name.capitalize()}Page:
\"\"\"{module_name} 页面操作类\"\"\"
def __init__(self, driver):
self.driver = driver
def open(self):
\"\"\"打开页面\"\"\"
pass
def perform_action(self):
\"\"\"执行操作\"\"\"
pass
# 使用示例
if __name__ == \"__main__\":
pass
'''
}
return templates.get(dir_type, f"# {module_name} {dir_type} file\n")
def generate_test_template(module_name):
"""生成测试文件模板"""
returnf'''\"\"\"
测试模块: {module_name}
\"\"\"
import pytest
import sys
import os
# 添加项目根目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class Test{module_name.capitalize()}:
\"\"\"{module_name} 测试类\"\"\"
def setup_method(self):
\"\"\"测试前置操作\"\"\"
pass
def teardown_method(self):
\"\"\"测试后置操作\"\"\"
pass
def test_{module_name}_basic(self):
\"\"\"测试 {module_name} 基础功能\"\"\"
assert True
def test_{module_name}_advanced(self):
\"\"\"测试 {module_name} 高级功能\"\"\"
assert True
if __name__ == \"__main__\":
pytest.main([__file__, \"-v\"])
'''
def generate_json_template(module_name):
"""生成JSON文件模板"""
returnf'''{{
"{module_name}_config": {{
"enabled": true,
"timeout": 30,
"description": "{module_name} 配置文件"
}},
"test_data": {{
"case_1": {{
"input": "sample_input",
"expected": "sample_output"
}}
}}
}}
'''
def list_existing_modules():
"""列出已存在的模块"""
base_dirs = ['conf', 'data', 'page', 'scripts']
modules = {}
for base_dir in base_dirs:
if os.path.exists(base_dir):
for item in os.listdir(base_dir):
item_path = os.path.join(base_dir, item)
if os.path.isdir(item_path):
if item notin modules:
modules[item] = []
modules[item].append(base_dir)
if modules:
print("\n📁 已存在的模块:")
for module, dirs in sorted(modules.items()):
print(f" - {module} (存在于: {', '.join(dirs)})")
else:
print("\n📁 暂无已存在的模块")
def main():
parser = argparse.ArgumentParser(description='自动化创建测试项目结构')
parser.add_argument('module_name', nargs='?', help='模块名称(英文或数字字符)')
parser.add_argument('--list', '-l', action='store_true', help='列出所有已存在的模块')
parser.add_argument('--force', '-f', action='store_true', help='强制覆盖已存在的模块')
args = parser.parse_args()
if args.list:
list_existing_modules()
return
if args.module_name:
success = create_project_structure(args.module_name, args.force)
if success:
print(f"\n🎉 模块 '{args.module_name}' 处理完成!")
else:
print(f"\n💥 模块 '{args.module_name}' 处理失败!")
else:
# 如果没有提供模块名称,进入交互模式
interactive_mode()
def interactive_mode():
"""交互式模式"""
print("🚀 项目结构自动化创建工具")
print("=" * 50)
whileTrue:
module_name = input("\n请输入模块名称(英文或数字,输入 'quit' 退出): ").strip()
if module_name.lower() == 'quit':
break
ifnot module_name:
print("❌ 模块名称不能为空")
continue
ifnot re.match(r'^[a-zA-Z0-9_]+$', module_name):
print("❌ 模块名称只能包含英文字母、数字和下划线")
continue
# 调用创建函数
success = create_project_structure(module_name)
if success:
print(f"\n✅ 模块 '{module_name}' 处理成功!")
else:
print(f"\n❌ 模块 '{module_name}' 处理失败!")
continue_create = input("\n是否继续创建其他模块?(y/n): ").strip().lower()
if continue_create != 'y':
break
if __name__ == "__main__":
main()
interactive_creator.py
# interactive_creator.py - 交互式创建脚本
import os
import re
def interactive_create():
"""交互式创建项目结构"""
print("🚀 项目结构自动化创建工具")
print("=" * 40)
whileTrue:
module_name = input("\n请输入模块名称(英文或数字,输入 'quit' 退出): ").strip()
if module_name.lower() == 'quit':
break
ifnot module_name:
print("❌ 模块名称不能为空")
continue
ifnot re.match(r'^[a-zA-Z0-9_]+$', module_name):
print("❌ 模块名称只能包含英文字母、数字和下划线")
continue
# 调用创建函数
success = create_project_structure(module_name)
if success:
print(f"\n✅ 模块 '{module_name}' 创建成功!")
else:
print(f"\n❌ 模块 '{module_name}' 创建失败!")
continue_create = input("\n是否继续创建其他模块?(y/n): ").strip().lower()
if continue_create != 'y':
break
if __name__ == "__main__":
# 确保有 create_project_structure 函数
from auto_create import create_project_structure
interactive_create()