网易首页 > 网易号 > 正文 申请入驻

测试用例越写越多管不过来,用Flask+Pytest造一个测试管理平台

0
分享至

随着项目规模的扩大,测试用例的数量和复杂度也会不断增加,如何高效地管理和执行这些测试用例成为一个挑战。本教程将手把手教你使用Flask和Pytest构建一个功能完整的自动化测试用例管理平台。

这个平台具备以下核心功能:

●集中管理测试用例

●创建和管理测试计划

●一键执行测试

●生成详细的测试报告

即使你是编程小白,跟着本教程一步步操作,也能成功搭建出这个平台!



一、环境准备

1.1 安装Python

确保你的电脑已安装Python 3.7或更高版本。打开命令行工具,输入以下命令检查:

python --version

如果未安装,请访问 Python 官网 下载安装。

1.2 创建项目目录

打开命令行,创建项目文件夹并进入:

mkdir test_platformcd test_platform

1.3 创建虚拟环境(推荐)

python -m venv venv

激活虚拟环境

①Windows 系统:

venv\Scripts\activate



②Mac/Linux 系统:

source venv/bin/activate

二、项目结构搭建

2.1 项目目录结构

test_platform/├── app.py # Flask 应用入口├── conftest.py # Pytest 配置文件├── requirements.txt # 依赖包列表├── templates/ # Flask 模板文件│ ├── base.html # 基础模板│ ├── index.html # 测试用例列表页│ ├── plan_list.html # 测试计划列表页│ └── report.html # 测试报告页├── static/ # 静态文件│ └── styles.css # 自定义样式├── test_cases/ # 测试用例目录│ ├── __init__.py│ ├── test_example.py # 示例测试用例│ └── test_api.py # API 测试用例├── test_plans/ # 测试计划存储目录│ └── example_plan.json # 示例测试计划└── reports/ # 测试报告存储目录

手动创建这些目录和文件,或使用以下命令(Windows 系统):

mkdir templates static test_cases test_plans reportstype nul > app.pytype nul > conftest.pytype nul > requirements.txt

三、安装依赖包

3.1 创建 requirements.txt

在 requirements.txt 文件中添加以下内容:

Flask==3.0.0pytest==7.4.3pytest-html==4.1.1Werkzeug==3.0.1

3.2 安装依赖

在命令行中执行:

pip install -r requirements.txt



等待安装完成,这可能需要几分钟时间。

四、编写核心代码

4.1 创建 Flask 应用入口(app.py)

在 app.py 中编写以下代码:

import osimport jsonimport subprocessfrom datetime import datetimefrom flask import Flask, render_template, request, redirect, url_for, jsonifyimport pytestapp = Flask(__name__)# 配置路径TEST_CASES_DIR = 'test_cases'TEST_PLANS_DIR = 'test_plans'REPORTS_DIR = 'reports'# 确保必要的目录存在for directory in [TEST_CASES_DIR, TEST_PLANS_DIR, REPORTS_DIR]: os.makedirs(directory, exist_ok=True)def get_all_test_cases(): """获取所有测试用例""" test_cases = [] ifnot os.path.exists(TEST_CASES_DIR): return test_cases for filename in os.listdir(TEST_CASES_DIR): if filename.startswith('test_') and filename.endswith('.py'): filepath = os.path.join(TEST_CASES_DIR, filename) with open(filepath, 'r', encoding='utf-8') as f: content = f.read() # 简单解析测试函数 test_functions = [line.strip() for line in content.split('\n') if line.strip().startswith('def test_')] for func in test_functions: func_name = func.split('(')[0].replace('def ', '') test_cases.append({ 'file': filename, 'name': func_name, 'path': f'{filename}::{func_name}' }) return test_cases@app.route('/')def index(): """首页 - 显示所有测试用例""" test_cases = get_all_test_cases() return render_template('index.html', test_cases=test_cases)@app.route('/plans')def plan_list(): """测试计划列表页""" plans = [] if os.path.exists(TEST_PLANS_DIR): for filename in os.listdir(TEST_PLANS_DIR): if filename.endswith('.json'): filepath = os.path.join(TEST_PLANS_DIR, filename) with open(filepath, 'r', encoding='utf-8') as f: plan_data = json.load(f) plan_data['filename'] = filename plans.append(plan_data) return render_template('plan_list.html', plans=plans)@app.route('/create_plan', methods=['POST'])def create_plan(): """创建测试计划""" plan_name = request.form.get('plan_name') selected_cases = request.form.getlist('test_cases') ifnot plan_name ornot selected_cases: return jsonify({'error': '计划名称和测试用例不能为空'}), 400 plan_data = { 'name': plan_name, 'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'test_cases': selected_cases } filename = f"{plan_name.replace(' ', '_')}.json" filepath = os.path.join(TEST_PLANS_DIR, filename) with open(filepath, 'w', encoding='utf-8') as f: json.dump(plan_data, f, ensure_ascii=False, indent=2) return redirect(url_for('plan_list'))@app.route('/run_plan/

')def run_plan(plan_name): """执行测试计划""" filepath = os.path.join(TEST_PLANS_DIR, f"{plan_name}.json") ifnot os.path.exists(filepath): return"测试计划不存在", 404 with open(filepath, 'r', encoding='utf-8') as f: plan_data = json.load(f) # 生成报告文件名 report_name = f"report_{plan_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html" report_path = os.path.join(REPORTS_DIR, report_name) # 构建 pytest 命令 test_cases = [os.path.join(TEST_CASES_DIR, case) forcase in plan_data['test_cases']] pytest_args = test_cases + [ f'--html={report_path}', '--self-contained-html', '-v' ] # 执行测试 pytest.main(pytest_args) return redirect(url_for('view_report', report_name=report_name))@app.route('/reports/

')def view_report(report_name): """查看测试报告""" report_path = os.path.join(REPORTS_DIR, report_name) if os.path.exists(report_path): with open(report_path, 'r', encoding='utf-8') as f: report_content = f.read() return report_content return"报告不存在", 404@app.route('/reports_list')def reports_list(): """测试报告列表""" reports = [] if os.path.exists(REPORTS_DIR): for filename in os.listdir(REPORTS_DIR): if filename.endswith('.html'): filepath = os.path.join(REPORTS_DIR, filename) stat = os.stat(filepath) reports.append({ 'name': filename, 'created_at': datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S'), 'size': f"{stat.st_size / 1024:.2f} KB" }) reports.sort(key=lambda x: x['created_at'], reverse=True) return render_template('report.html', reports=reports)if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)

4.2 创建 Pytest 配置文件(conftest.py)

在 conftest.py 中添加以下内容:

import pytestfrom datetime import datetime@pytest.fixture(scope='session')def test_config(): """测试配置信息""" return{ 'base_url': 'http://localhost:5000', 'timeout': 30, 'retry_times': 3 }@pytest.fixture(scope='function')def test_data(): """测试数据""" return{ 'username': 'test_user', 'password': 'test_password', 'email': 'test@example.com' }def pytest_configure(config): """Pytest 配置钩子""" config.addinivalue_line( "markers", "smoke: 冒烟测试用例" ) config.addinivalue_line( "markers", "regression: 回归测试用例" ) config.addinivalue_line( "markers", "api: API 测试用例" )def pytest_html_report_title(report): """自定义报告标题""" report.title = "自动化测试报告"def pytest_html_results_summary(prefix, summary, postfix): """自定义报告摘要""" prefix.extend([f"

测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S

☑️想涨薪、想走得更远,最稳妥的办法永远是投资自己的技能。

☑️可如果行业的天花板已经压到头顶,与其在原地内卷,不如借AI的东风换个赛道。

可以戳⬇️⬇️⬇️

✔️即可加入——>【个人号绿泡泡:annasea0928】领转行、入门、提升、需要的各种干货资料

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
男生4次考公失败后花2.2万元旅行6国,途中看到妈妈朋友圈:老娘扛你看世界,你替老娘圆梦

男生4次考公失败后花2.2万元旅行6国,途中看到妈妈朋友圈:老娘扛你看世界,你替老娘圆梦

沈阳生活圈i
2026-09-12 10:55:32
脸都不要了!湖南洞口孩子买了50元学平险,结果真得癌了,谁料保险公司翻出国际疾病分类,说编码不对,不符合“恶性肿瘤-重度”条款

脸都不要了!湖南洞口孩子买了50元学平险,结果真得癌了,谁料保险公司翻出国际疾病分类,说编码不对,不符合“恶性肿瘤-重度”条款

火山詩话
2026-09-10 10:40:36
随着陈幸同3-2,WTT澳门冠军赛女单八强全部诞生:仅2名中国选手在列

随着陈幸同3-2,WTT澳门冠军赛女单八强全部诞生:仅2名中国选手在列

侧身凌空斩
2026-09-11 22:28:02
国内极端女拳都是惯出来的毛病

国内极端女拳都是惯出来的毛病

浪子说
2026-09-11 07:07:23
日本爆发大规模性病,魔幻景象让人头皮发麻

日本爆发大规模性病,魔幻景象让人头皮发麻

鸣金网
2026-09-11 12:25:34
5天前换主帅!意甲百年老店4-2重生:3连败后获首胜 皇马天才戴帽

5天前换主帅!意甲百年老店4-2重生:3连败后获首胜 皇马天才戴帽

风过乡
2026-09-12 05:51:58
状态值爆表!马斯坦托诺上演帽子戏法,一战追平在皇马进球数

状态值爆表!马斯坦托诺上演帽子戏法,一战追平在皇马进球数

懂球帝
2026-09-12 04:56:18
卡里克否认曼城已是曼市之王!想长期执教曼联,将用与去年不同打法

卡里克否认曼城已是曼市之王!想长期执教曼联,将用与去年不同打法

罗米的曼联博客
2026-09-12 10:23:45
荣耀“魔法画报”事件当事人澄清:事件与荣耀无关

荣耀“魔法画报”事件当事人澄清:事件与荣耀无关

界面新闻
2026-09-11 22:01:06
A股:刚刚,国务院重磅发布,释放强烈信号!下周一将迎来新转变

A股:刚刚,国务院重磅发布,释放强烈信号!下周一将迎来新转变

虎哥闲聊
2026-09-12 00:00:04
前人砍树后人暴晒!某985电院不给本校推免学生保底,原因曝光:去年本校学生放学校鸽子

前人砍树后人暴晒!某985电院不给本校推免学生保底,原因曝光:去年本校学生放学校鸽子

趣笔谈
2026-09-11 10:22:56
成都蓉城相关负责人:韦世豪去国足了,近期不会再回应争议

成都蓉城相关负责人:韦世豪去国足了,近期不会再回应争议

懂球帝
2026-09-11 17:37:11
灭顶之灾?贝森特预告:下周制裁一家大银行!还要让中国无油可买

灭顶之灾?贝森特预告:下周制裁一家大银行!还要让中国无油可买

国际法大视野
2026-09-11 20:18:44
劝所有人赶紧戒烟:现在的香烟,和20年前根本不是一个东西

劝所有人赶紧戒烟:现在的香烟,和20年前根本不是一个东西

周哥一影视
2026-09-12 09:26:00
湖南满族人宋剑仁,因煽动民族仇恨民族歧视被判刑三年半

湖南满族人宋剑仁,因煽动民族仇恨民族歧视被判刑三年半

张可象
2026-09-11 14:05:48
4岁男童摸臀事件闹大了!马来西亚大学收到举报了,回应将会对女子采取必要措施

4岁男童摸臀事件闹大了!马来西亚大学收到举报了,回应将会对女子采取必要措施

小徐讲八卦
2026-09-11 05:52:14
詹妮弗·劳伦斯开Instagram,画风完全失控

詹妮弗·劳伦斯开Instagram,画风完全失控

影视情报室
2026-09-12 00:42:26
土媒:特拉布宗体育正在与瓜迪奥拉就主帅职位展开谈判

土媒:特拉布宗体育正在与瓜迪奥拉就主帅职位展开谈判

懂球帝
2026-09-12 01:13:11
绍兴7个葫芦,摘下没几天又挂回来了!“葫芦爷爷”回应:人家大老远跑来,看不到葫芦,我们心里也过意不去,说实话摘下来是不情愿的

绍兴7个葫芦,摘下没几天又挂回来了!“葫芦爷爷”回应:人家大老远跑来,看不到葫芦,我们心里也过意不去,说实话摘下来是不情愿的

台州交通广播
2026-09-11 23:57:26
最后大决战开始了,也门领导人萨布里宣布,解放也门全境,把伊朗革命卫队以及也门胡塞武装赶出去!

最后大决战开始了,也门领导人萨布里宣布,解放也门全境,把伊朗革命卫队以及也门胡塞武装赶出去!

吃瓜小侦探
2026-09-08 21:38:50
2026-09-12 11:51:00
51Testing软件测试网 incentive-icons
51Testing软件测试网
中国软件测试人的精神家园
1641文章数 13285关注度
往期回顾 全部

科技要闻

苹果折叠屏比小米华为贵5000元,该怎么选

头条要闻

上海7岁女童遭搅拌车辗轧双腿高位截肢 奶奶当场死亡

头条要闻

上海7岁女童遭搅拌车辗轧双腿高位截肢 奶奶当场死亡

体育要闻

老鹰真正的底气来自于什么?

娱乐要闻

港媒曝钟丽淇疑患渐冻症,本人发文

财经要闻

继房子茅台之后 中产的第"神话"也破灭了

汽车要闻

买菜车也有小乐趣 风云T7不止是台合格家用SUV

态度原创

房产
家居
游戏
数码
手机

房产要闻

别再等了!广州改善好房,正在进入“卖一套少一套”时代

家居要闻

2026建博会(广州) 公装联探展交流活动

《塞尔达传说》新作实体封面曝光!背面超帅 顶尖设计

数码要闻

摩米士推出2026新国标磁吸移动电源,298元

手机要闻

三星向Tim Cook赠送Galaxy Z Fold 8 并幽默喊话“欢迎入场”

无障碍浏览 进入关怀版