接口自动化
-
背景:
如果通过手工测试人员进行手动测试,不仅会浪费大量的人力、物力、资源等信息,而且对产品的测试程度相对来说比较低。因此,测试用例的自动化,即接口自动化(俗称:冒烟测试)显得尤为重要。
-
什么是接口自动化?
接口自动化,其基本原理就是:模拟前端向后台发送http请求,得到响应的请求数据,对数据进行分析,从而判断接口是否正常。
-
目前所做的接口自动化的解决方案的总结概述:
整体使用python框架实现,最底层对post、get、put、delete等请求做了一层封装;对传入的参数和返回的参数做了一层处理;最上层编写测试用例,逻辑实现不需要关心请求是怎样发送过去的。这样进行三层结构的封装,使得测试用例和接口实现最大化的解耦,不必因开发接口的改动而大量修改测试用例。
-
主要使用的技术:
- pytest 框架
- allure 报告生成库
- 断言库 except
- 超时重试库 tenacity
-
pytest的主要特性 —— fixture:
依赖注入的思想
fixture scope:提供了多级缓存,每级缓存对应着不同的有效领域 。[ session, moudle, class, function ]即:
- session 对全局生效,即该 fixture 每次执行测试只会运行一次,用来生成全局的资源。(例如:添加集群或可用区等)
- moudle 对模块生效,每个模块执行一次
- class 对类生效,每个类执行一次
- function 对方法生效,每个用例执行一次
-
代码层次结构:
- 项目C - (主要功能:构造一个请求,将该请求发送到后台接口,并将响应的数据返回。通常情况下,我们不会修改其中的方法,除非开发修改了接口。该项目是和开发的接口一一对应的,承载了所有系统暴露出的接口。是与开发代码之间的唯一接口)
- 项目B - (因为项目D的功能很单一,仅仅是实现发送请求和接收数据,因此在项目C中需要做很多的数据处理、超时重试、案例步骤关联等操作机制,这样做的目的是:使得测试用例开发起来相对来说比较简单,公共的方法都抽取出来,便于维护)
- 项目A - 这个一个测试用例的实现模块,这里还细分为测试用例和配置层。测试用例都写在 xxx_test 文件中,包含用例的各个步骤;此外还有一类文件叫conftest,一些公共的fixture写在里面。
- 项目D - 是一个公用的工具库,一些对系统后台的操作和对数据库的操作工具都在这里面。该项目D是独立的,不依赖于其他的工程。同时,它可以供其他多个工程使用,如果没有满足的工具,可以自己添加到项目D里面。
-
以小见大:
- 写用例首先要将用例的前置条件、执行过程、期望结果写到注释中;allure会根据注释直接在页面中生成报告,方便用例和错误的查找。同时在写用例的过程中也省去了来回切换,查看用例的过程,提高了工作的效率。
- 拿到一个用例之后进行分析,分解出一个个步骤,这里的步骤正对应着allure.step,写的过程结构清晰,可读性好,而且报告中也会根据step来生成。
- 有的时候多个用例会用到同一个方法,这种情况我们最好把公用的写到fixture中,fixture功能是非常强大的,这样可以大大节省了时间,提高效率。
番外——api代码常见问题总结【注意事项】:
- 可调试性
- 日志或者调试信息不清晰,无法告知问题原因;
- 该记录日志的地方不记录日志,或者有日志但不打印异常,出问题不好查;
- 断言不添加描述信息,不利于查问题和后期维护
- 维护性
- 函数参数、返回值无类型描述;
- 或者类型描述不具体,没多少意义,例如:字典的类型描述应该要说明key和value的类型;
- 易调整的、有测试需要的常量应该要提取为运行参数,例如:像外部配置的路径应该要作为运行参数,以方便打桩测试或者环境迁移;
- 函数抽象与重用,例如:有时候需要某个接口里的一部分功能或者逻辑,有些人会倾向于把代码拷贝过来改改,这样久了就会有很多相似的代码。一般比较好的做法应该是把旧接口进行抽象,或者从旧接口里提取功能子集做为新接口
- 协程
- 网络IO需要协程化,避免阻塞主线程;
- 磁盘IO需要协程化,避免阻塞主线程;
- 内部用多线程、多进程实现的协程接口,要通过锁或者信号量限制并发
- 异常
- 异常考虑缺失 [json.dumps接口会抛出TypeError异常;json.loads接口会抛出JSONDecodeError异常];
- 异常捕获范围太粗,容易掩盖问题;异常导致的资源泄露
- 其他
- 异常分支要考虑好对全局的影响,必要时要填充默认值来防止错误扩散;
- 对变量为None的可能没判断好就直接使用;内部实现暴露给用户
ps:感谢过程中小伙伴的指导,如果从菜鸟到老鸟是一段必经之路,我希望能够一直刻骨铭心。