tep0.6.0更新聊聊pytest变量接口用例3个级别复用
tep是一款测试工具,在pytest测试框架基础上集成了第三方包,提供项目脚手架,帮助以写Python代码方式,快速实现自动化项目落地。fixture是pytest核心技术,本文聊聊如何使用fixture完成变量、接口、用例3个级别复用。
tep是一款测试工具,在pytest测试框架基础上集成了第三方包,提供项目脚手架,帮助以写Python代码方式,快速实现自动化项目落地。fixture是pytest核心技术,本文聊聊如何使用fixture完成变量、接口、用例3个级别复用。
本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 本文开发内容 用例管理是对用例进行增删改查,按照前面文章的思路,把它做出来应该不难,如果你已经自己写好了,那么可以和本文提交的代码比较下看看。除了增删改查,用例管理还需要提供运行用例的入口,在操作列添加一个运行按钮,单条用例运行,并弹窗展示运行结果。用例列表需要能看到每条用例执行情况,添加表格列用于展示,其中“运行结果”列要有超链接,点击查看上次运行结果。为了避免修改别人用例出错,还需要有个复制用例功能。除了在线编辑,平台应支持下载项目环境到本地,无缝切换到PyCharm,让新用户快速上手。综上所述,本文开发内容如下: 用例增删改查。 运行按钮,点击后弹出“运行用例结果”。 添加表格展示列,其中“运行结果”用颜色区分不同结果状态:passed,failed,error,点击超链接后弹出“查看用例结果”。 复制按钮,点击后生成一条复制的新用例。 新增/编辑页面,添加运行按钮。 运行/查看页面,添加编辑按钮。 下载环境到本地。 工作量主要在前端,后端先做一部分。 编写后端代码 编辑teprunner/urls.py,添加路由: 除了增删改查,还添加了2个接口,一个用于获取用例运行的结果,一个用于复制测试用例。 编辑teprunner/models.py,添加模型: 第一个Model是Case,没有定义name字段,实际上用例ID和用例描述已经够用了,name不知道填什么,有点多余。第二个Model是CaseResult,会记录运行结果,这个运行结果是从pytest执行日志最后一行的Summary截取出来的,比如1 passed,1 failed,耗时也是从Summary截取出来的。output存放代码运行后打到控制台的输出日志。最后三个字段记录运行环境、运行人和运行时间,运行时间取的数据库记录被添加/更新的时间。添加好以后迁移到数据库中: python manage.py makemigrations python manage.py migrate 编辑teprunner/serializers.py,添加序列化器,第一个序列化器是CaseSerializer: 只关联了Case模型的字段。 第二个序列化器是CaseListSerializer: 它主要用来返回用例列表的数据,除了用例本身,还需要用例结果。serializers.SerializerMethodField用于自定义序列化字段,定义好字段后,在下面添加get_前缀+字段名的方法,这是Django的规则,然后在方法内部添加取值代码,比如get_result(),instance是指Meta.model定义的模型,这里就等同于Case,通过instance.id获取到Case.id并赋值给case_id变量,从CaseResult的对象中过滤case_id匹配的用例结果,按运行时间倒序,取最新1条结果的result字段的值。其他字段的处理是类似的,runTime这里做了下日期格式化: 第三个序列化器是CaseResultSerializer: 只关联了CaseResult模型的字段,runTime同样做了日期格式化。从这里也能更清晰的看到,instance就是指的自己! 新建teprunner/views/case.py文件,添加视图,先把简单的两个视图做了,第一个视图是case_result: 这里是个知识点,采用@api_view注解的函数视图,如果想用序列化器,那么采用这种方式。 第二个视图是copy_case: 根据case_id查找到现有Case对象,在case.desc后面添加--复制后缀,其他字段数据复用,保存,就完成复制用例了。 第三个视图是CaseViewSet: 继承了ModelViewSet,重写了list列表查询,因为如果不重写,默认返回的结果是serializer_class = CaseSerializer序列化器的内容。我们需要的是CaseListSerializer这个序列化器的内容。这里也是一个知识点!如果想在类视图中,使用serializer_class以外的序列化器加分页,采用这种方式。 重写的list方法首先添加了project_id、case_id、desc、api四个过滤条件,与前端的当前项目、用例ID搜索框、用例描述搜索框、API路径搜索框一一对应。__icontains表示包含,相当于模糊匹配,i忽略大小写。接着用到了自定义分页的类,按照统一的分页格式,返回序列化器的数据。 最后,重写了update方法,用现有的创建人进行更新。 编写前端代码 编辑router/index.js,添加路由: 编辑views/teprunner/index.vue,添加菜单项: 新建views/teprunner/case/CaseManagement.vue文件,增删改查基础代码不再另加赘述,挑选新代码: 在运行结果列,添加了超链接,点击后打开用例结果弹窗,这个弹窗查看和运行用例都会用到,用第一个参数type做区分: getResultColor方法返回颜色样式: 由于用例结果弹窗和用例列表表格都会有这个字段,于是把resultColor方法提取到了utils/commonMethods.js文件中: CaseManagement.vue是一个父组件,它有3个子组件,如下图所示: 通过import后,添加标签代码引入: 是否显示弹窗通过DialogFormVisible的true/false来控制,DialogTitle指定弹窗标题。:开头是父组件向子组件传值, @开头是接受子组件发过来的emit事件通知,从而调用父组件中方法。这样就把这几个组件绑定在一起了! 从这里开始,这几个组件之间的关系会稍微有点绕,读不懂的话多结合源码看看! ...
本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 本文开发内容 现在正式进入测试相关功能开发。teprunner测试平台底层是pytest,中间层是tep,还没了解的朋友可以先看看tep的文章,整个平台的设计思路和后面用例的执行都会基于这个工具。tep的测试用例是放在.py文件里面的,全局变量或者说环境变量是引用的env_vars,公共函数和复用接口是引用的fixtures,在做成平台后,需要把这两个部分独立为两个功能模块。多个项目的接口自动化数据需要隔离开来,要有个项目管理功能。本文将开发四个用例前置模块: 后台管理–项目管理 接口自动化–语法说明 接口自动化–环境变量 接口自动化–fixtures 语法说明给出了环境变量、fixtures、用例示例(单个接口、多个接口–增删改查)、请求方法(get、post、put、delete)的使用方法。 编写后端代码 先创建名为teprunner的app: django-admin startapp teprunner 在settings的INSTALLED_APPS中添加配置让app生效: 并在urls.py添加路由: 编辑user/fixtures/user.json,添加一个接口自动化的菜单: 截图只截了管理员,测试和开发角色,也需要添加上。access均为true,这三个角色都可以访问。添加后把数据同步到数据库: python manage.py loaddata user 编辑teprunner/models.py,新增模型: 包括了项目、环境变量和fixture三张表。Project.env_config用于给项目配置多个环境。不同项目不同环境的环境变量不一样,在EnvVar中添加了project_id和env_name,并按(“project_id”, “env_name”, “name”)作为唯一键,不允许重复。不同项目的fixtures不同,不关心环境,在Fixture中只添加了project_id。 Fixture.code用于存放代码,字段类型为models.TextField,容纳更多字符。 models编写好后,迁移到数据库: python manage.py makemigrations python manage.py migrate 新建teprunner/serializers.py文件,新增序列化器: 数据库字段的命名是用的下划线,接口返回前端和前端传参是用的驼峰,所以这里通过source这种方式给env_config、project_id、env_name、creator_nickname进行了序列化器的重命名。为了前端更方便处理,使用serializers.CharField把int转化为了str,由于请求时id非必须,增加参数required=False。 teprunner会有很多视图,写在一个文件里面有点臃肿,这里创建views文件夹,新增views/project.py项目视图: Django REST framework的ModelViewSet视图类能节省很多代码,只需要三行就把项目增删改查接口做了。project_env是函数视图,请求方法为GET,它的作用是返回项目环境列表,当前项目和当前环境,默认为第一个项目和第一个环境。 前端需要切换不同项目和不同环境,下拉框数据来源于这个接口。 新建views/envvar.py新增环境变量视图: 环境变量跟项目和环境是强关联的,需要根据项目环境进行过滤,所以重写了list方法,从前端请求拿到curProjectId和curEnvName,通过EnvVar.objects.filter进行过滤。from django.db.models import Q支持多种过滤条件,这在后面的代码中还能看到,比如模糊匹配。 新建views/fixture.py新增fixture视图: fixture跟项目是强关联的,需要根据项目进行过滤,所以重写了list方法,从前端请求拿到curProjectId,通过Fixture.objects.filter进行过滤。Fixture有个creatorNickname字段,新增fixture时使用的是当前登录用户的昵称,修改fixture时需要用已保存的创建者,重写update方法来实现这个处理。 最后,新建teprunner/urls.py文件,把视图添加到路由中: 编写前端代码 编辑package.json,添加依赖: fixtures是代码形式的,这是测试平台第一次使用代码编辑组件。添加依赖后记得执行npm install进行安装。 编辑router/index.js: 添加接口自动化的路由,并把home重定向改为语法说明路由。children表示子路由。path是路由地址。meta.title用于显示菜单名。 编辑views/console/index.vue: 添加项目管理菜单。新建ProjectManagement.vue和AddProject.vue,添加项目管理增删改查代码,跟用户管理类似,不再另加赘述。值得注意的是环境配置placeholder="请输入环境英文名(多个环境英文逗号分隔)",因为tep.env_vars.mapping会用到环境名作为key,所以只能用英文名! 编辑components/WrapComponent.vue,添加一个插槽: ...
tep的设计理念是让人人都可以用Python写自动化,本文就来介绍如何用tep完成增删改查接口自动化。
本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 系统架构 前端、后端、pytest均以Docker容器运行服务,单独的容器化执行引擎,项目环境隔离,即用即取,用完即弃,简单,高效。 前端容器:页面交互,请求后端,展示HTML报告 后端容器:接收前端请求,启动任务,构建镜像,触发运行pytest,挂载HTML报告 pytest容器:拉取项目代码,指定目录执行,生成HTML报告 说明:构建镜像目前是在宿主机启动后端服务来执行docker命令的,暂未支持Kubernetes编排。宿主机安装了Docker,启动服务后,可以执行docker命令。如果采用容器部署后端,容器里面不包含Docker,无法构建,个人想法是可以借助K8S来编排,当前版本还未实现 系统流程 支持2种运行模式配置:容器和本地。 容器模式:判断是否支持docker,如果支持,构建pytest镜像,在构建时,通过git拉取项目代码,再运行容器,按照指定目录执行pytest,生成测试报告,并将报告文件挂载到后端。如果不支持,降级为本地运行。 本地模式:模拟容器行为,在本地目录拉取代码,执行pytest,生成测试报告。 效果展示 任务管理: 容器模式: 本地模式: 平台大改造 pytestx平台更轻、更薄,移除了用例管理、任务关联用例相关功能代码,只保留真正的任务调度功能,backend的requirements.txt解耦,只保留后端依赖,pytest相关依赖转移到tep-project。 那如何管理用例呢?约定大于配置,我们约定pytest项目已经通过目录维护好了一个稳定的自动化用例集,也就是说需要通过平台任务调度的用例,都统一存放在目录X下,这些用例基本不需要维护,可以每日稳定执行,然后将目录X配置到平台任务信息中,按指定目录执行用例集。对于那些不够稳定的用例,就不能放到目录X下,需要调试好以后再纳入。 为什么不用marker?pytest的marker确实可以给测试用例打标记,也有人是手动建立任务和用例进行映射,这些方式都不如维护一个稳定的自动化用例集方便,在我们公司平台上,也是维护用例集,作为基础用例集。使用pytest项目同理。 核心代码 一键部署 #!/bin/bash PkgName='backend' Dockerfile='./deploy/Dockerfile.backend' DockerContext=./ echo "Start build image..." docker build -f $Dockerfile -t $PkgName $DockerContext if [ $? -eq 0 ] then echo "Build docker image success" echo "Start run image..." docker run -p 8000:80 $PkgName else echo "Build docker image failed" fi FROM python:3.8 ENV LANG C.UTF-8 ENV TZ=Asia/Shanghai RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone WORKDIR /app COPY ./backend . RUN pip install -r ./requirements.txt -i \ https://pypi.tuna.tsinghua.edu.cn/simple \ --default-timeout=3000 CMD ["python", "./manage.py", "runserver", "0.0.0.0:80"] 数据库表 ...
本文是一篇过渡,在进行用例管理模块开发之前,有必要把入门篇开发完成的代码部署到Linux系统Docker中,把部署流程走一遍,这个过程对后端设计有决定性影响。
本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 背景 在2022年7月6日我曾组织过一次开源测试平台开发报名,有50+人报名,到2023年1月28日项目暂停,如大家在Gittee看到的,除我以外,只有1个人真正提交了代码:奉孝。 原因如其中一位同学所说:“感觉我们大部份还是缺少从0到1的经验,负责的内容有时候不要知道从哪下手,又少了点积极性”。描述得很贴切,可能刚开始动力很足,但因为缺少经验,不够积极,最后实践不了。说的很好,就是做不到。也很无奈。 二次启动,分为2个阶段,第一个阶段是学习阶段,我带着大家一起把teprunner平台从0到1开发一遍,把需要掌握的知识先学一遍,保证有一定基础,挑战能够独立完成模块开发。第二个阶段是开发阶段,共同完成EasyPytest测试平台开发,学以致用,加深对前后端分离项目开发的理解,具有真实的平台开发实践。 学习阶段 你都不维护了,我为什么还要学teprunner?Django没意思?我想学FastAPI? teprunner有一套完整教程,包括前后端源码、11篇电子书教程、2小时视频讲解,虽然我因为工作原因没有继续维护teprunner,但是它仍然非常适合初学者入门学习测试开发,掌握里面的知识,对于后续学习其他技术,都有很大帮助。我的技术提升除了二刷《流畅的Python》和编写了tep开源工具,最大的提升就是完成了teprunner测试平台开发,如果你也能自己动手完成一遍,一定有极大提升。 Django、Flask、FastAPI、SpringBoot,我认为从入门者角度来说,Django是最适合的,它属于开箱即用的框架,很多东西都给你准备好了,你用就行,避免刚开始就陷入环境搭建,三方库拼装、数据库维护的麻烦中,降低理解门槛和操作难度。学会了Django,再学其他的,也很简单,一通百通。刚开始学习,学哪个不是最重要的,最重要的是先学会一个,迈出第一步。以我的经验来说,学习成熟框架Django是个正确选择。 开发阶段 EasyPytest的后端把Django切换为了FastAPI,掌握了Django,再对比FastAPI,就能对后端开发框架有更深入的理解。就像我学Python和Java一样,只学一门百思不得其解,对比一看,豁然开朗。目前已经完成了登录、首页、用户管理的开发,Gitee也有相应源码。未来的规划,是做teprunner的升级版,实现pytest平台化,80%工作本地开发脚本,20%工作交给平台编排运行。 报名方式 添加微信cekaigang,备注参加平台开发,进群。 现开启学习阶段报名: 按需选择,10元/节,录播+直播集中答疑。报名后会获得一份录播+一次集中答疑直播+一个每节课源码。每节课源码跟GitHub上源码不同,只会包含当前这节课进度的源码,一步一步的看到测试平台是如何开发出来的。 课表链接: https://eqgvpqzl6c.feishu.cn/mindnotes/bmncndM8oei2B0MIFE1RMrGuKjd 开发阶段报名需至少参与一节学习课程,从优秀学员或积极学员中选择,时间另行通知。 当然,如果你已经具备奉孝这样的技术能力和积极性,欢迎直接与我联系,请提供你的开源项目地址或在Gitee提交Pull Requests,以证明能够独立完成模块开发,直接参与EP平台共建。
温馨提示:开发指南,根据V2.0.0编写,不随版本更新维护,仅供入门参考。最新实现请结合教程和源码阅读,教程会在版本发布后维护。
如果没有这次全量数据对比工具,那么也许这个历史问题会继续隐藏着,直到发生线上事故才暴露出来,毕竟人工抽样验证发现的概率只有5.8%。
本书作者:测试开发刚哥,文章版权归个人所有,未经授权请勿转载。 概览 脚手架: 目录: 用例代码: """ 测试登录到下单流程,需要先启动后端服务 """ test_data = { "查询SKU": { "skuName": "电子书" }, "添加购物车": { "skuId": 123, "skuNum": 2 }, "下单": { "orderId": 222, "payAmount": "0.2" }, "支付": { "skuId": 123, "price": 0.1, "skuNum": 2, "totalPrice": 0.2 }, } case_vars = dict() def test(http, login_headers, file_data): # 搜索商品 url = file_data["domain"] + "/api/tasks/mock/searchSku" body = test_data["查询SKU"] response = http("get", url=url, headers=login_headers, params=body) assert response.status_code < 400 case_vars["skuId"] = response.jsonpath("$.skuId") case_vars["skuPrice"] = response.jsonpath("$.price") # 添加购物车 url = file_data["domain"] + "/api/tasks/mock/addCart" body = test_data["添加购物车"] body["skuId"] = case_vars["skuId"] response = http("post", url=url, headers=login_headers, json=body) assert response.status_code < 400 case_vars["skuNum"] = response.jsonpath("$.skuNum") case_vars["totalPrice"] = response.jsonpath("$.totalPrice") # 下单 url = file_data["domain"] + "/api/tasks/mock/order" body = test_data["下单"] body["skuId"] = case_vars["skuId"] body["price"] = case_vars["skuPrice"] body["skuNum"] = case_vars["skuNum"] body["totalPrice"] = case_vars["totalPrice"] response = http("post", url=url, headers=login_headers, json=body) assert response.status_code < 400 case_vars["orderId"] = response.jsonpath("$.orderId") # 支付 url = file_data["domain"] + "/api/tasks/mock/pay" body = test_data["支付"] body["orderId"] = case_vars["orderId"] response = http("post", url=url, headers=login_headers, json=body) assert response.status_code < 400 assert response.jsonpath("$.success") == "true" 页面下载脚手架 启动平台前后端服务后,从页面下载脚手架,平台会拉取开源项目tep-project最新代码,打成压缩包,生成下载文件,弹窗下载。 ...