python接口自动化(四十二)- 项目结构设计之大结局(超详解)
简介
这一篇主要是将前边的所有知识做一个整合,把各种各样的砖块---模块(post请求,get请求,logging,参数关联,接口封装等等)垒起来,搭建一个房子。并且有很多小伙伴对于接口项目测试的框架一筹莫展,吵吵着什么时候才可以看到一篇相对于比较完整的项目源码,但是由于完整的项目属于公司内部的代码,这个是说句大实话是没法分享的,这个想必大家都知道吧,不知道入职的时候都签过保密协议吧。所以由于种种原因没办法给小伙伴们分享公司内部的项目源码,就算别人分享了,也只适用于本公司内部的业务。你拿过来也不能用的,需要修修补补。所以用例的代码还是得自己去一个个写,这个宏哥只能分享项目框架,自己在框架里添加自己公司的业务测试用例,使她变的丰满充实,适合自己公司的业务。希望对小伙伴们有所指导或者是启发,好了时间不早了,废话少说,还是尽快进入今天的主题吧---接口项目测试结构(框架)设计。
一、项目结构
1、新建一个工程(一定要创建工程),工程名称自己定义,如:hongge_jiekou
2、在工程的跟目录新建一个脚本:run_main.py,用来执行全部用例
3、在工程下创建以下几个pakage包:
--case:这个包放test开头的测试用例,也可以放一些封装接口的方法,如:login(如果封装的接口比较多,也可以单独放一个包,可以命名为:framework,当然了可以随便但是要见名知义,不要奇葩、不要关键字等等)
--common:这个包放一些公共的方法,如:读取excel文件方法,读取mysql、oracle,logger.py这个是封装日志的输入
--config:cfg.ini这里是配置文件,如邮箱的一些参数:收件人,发件人,密码等,readConfig.py用于读取配置文件
--logs:这里存放日志信息
--report:这里存放测试报告
二、run_main
第一步:用discover方法加载所有的测试用例
1、cur_path这个参数是读取当前这个脚本的真实路径,也就是run_main.py的真实路径
2、caseName="case"这个case是存放测试用例的文件夹,如果没有的话,自动创建。如果想运行其它文件夹的用例,就改下caseName这个参数值
3、rule="test*.py"这个是匹配用例脚本名称的规则,默认匹配test开头的所有用例
第二步:生成HTML报告
1.把上一步加载到用例的参数传入这个函数,测试报告的文件名称默认report文件夹:reportName="report
2.如果没有这个report文件夹也没关系,可以自动创建的
第三步:获取最新的测试报告
1.如果第二步生成的测试报告加了时间戳,想找到最新的文件就用第三步
2.如果第二步不加时间戳,只是生成result.html,那这一步其实没卵用,可以忽略
(个人觉得报告用一个名称result.html就行,新的自动覆盖旧的)
第四步:发送测试报告到邮箱
1、像QQ邮箱这种ssl加密的就走SMTP_SSL,用授权码登录
2、其它邮箱就正常账号密码登录,走SMTP
3、最后执行代码
这里邮箱的内容读的配置文件
三、config配置
1、cfg.ini打开,这里写配置文件内容
2、用readConfig.py读取配置文件
3、读取的内容就是传入第二步操作里面需要调用邮箱的配置信息
四、logger
1、logger.py这个文件放到common目录下,封装日志文件的读取
2、日志保存到logs文件夹
3、参开代码:
# -*- coding:utf- -*- # .先设置编码,utf-8可支持中英文,如上,一般放在第一行 # .注释:包括记录创建时间,创建人,项目名称。 ''' Created on -- @author: 北京-宏哥 QQ交流群: Project:项目结构设计 ''' # .导入模块 import logging, time import os # log_path是存放日志的路径 cur_path = os.path.dirname(os.path.realpath(__file__)) log_path = os.path.join(os.path.dirname(cur_path), 'logs') # 如果不存在这个logs文件夹,就自动创建一个 if not os.path.exists(log_path): os.mkdir(log_path) class Log(): def __init__(self): # 文件的命名 self.logname = os.path.join(log_path, '%s.log' % time.strftime('%Y_%m_%d')) self.logger = logging.getLogger() self.logger.setLevel(logging.DEBUG) # 日志输出格式 self.formatter = logging.Formatter('[%(asctime)s] - %(filename)s] - %(levelname)s: %(message)s') def __console(self, level, message): # 创建一个FileHandler,用于写到本地 # fh = logging.FileHandler(self.logname, 'a') # 追加模式 这个是python2的 fh = logging.FileHandler(self.logname, 'a', encoding='utf-8') # 这个是python3的 fh.setLevel(logging.DEBUG) fh.setFormatter(self.formatter) self.logger.addHandler(fh) # 创建一个StreamHandler,用于输出到控制台 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(self.formatter) self.logger.addHandler(ch) if level == 'info': self.logger.info(message) elif level == 'debug': self.logger.debug(message) elif level == 'warning': self.logger.warning(message) elif level == 'error': self.logger.error(message) # 这两行代码是为了避免日志输出重复问题 self.logger.removeHandler(ch) self.logger.removeHandler(fh) # 关闭打开的文件 fh.close() def debug(self, message): self.__console('debug', message) def info(self, message): self.__console('info', message) def warning(self, message): self.__console('warning', message) def error(self, message): self.__console('error', message) if __name__ == "__main__": log = Log() log.info("---测试开始----") log.info("操作步骤1,2,3") log.warning("----测试结束----")
五、case放用例
1、常用的接口,需要检查被调用的单独封装处理,如登录等
2、test开头的用例
六、logs日志查看
1、运行完后日志都会收集到logs文件夹以日期命名
七、生成测试报告
1、这里调用的是HTMLTestRunner生成html的测试报告
八、发送报告到邮箱
1、运行run_main.py就会自动生成报告,然后发送到邮箱了
(这里QQ邮箱的展示是有问题的,一般用企业邮箱的话,是可以正常展示的)
九、小结
1、问题:在python3.7中使用sendmail进行邮件发送,mailInfo["to"]为逗号分隔的str类型,结果只有第一个邮件地址能收到邮件。将邮箱前后对调后,还是第一个邮箱可以收到测试报告,后边的邮箱收不到邮件。
折腾好久,邮件里可以看到收件人有多个,实际上始终只能第一个收件人可以收到邮件。经多次搜索,发现是这样:email中收件人和sendmail中的收件人是没啥联系的。
sendmail中收件人,它的格式应该为list。这个为实际的收件人地址。
而msg['To'] 格式是字符串(str)。这个只是为了邮件中打印出来而已。
sendmail查源码,python/lib/smtplib.py大概690行左右,或者搜索tolist。
解决方法:经过多次测试发现MIMEText()["to"]的数据类型与sendmail(from_addrs,to_addrs,...)的to_addrs不同;前者为str类型,多个地址使用逗号分隔,后者为list类型。
知道这个原因后,将这一行代码:
smtp.sendmail(sender, receiver, msg.as_string())
替换为下边这样就可以了:
smtp.sendmail(sender, receiver.split(','), msg.as_string())
当然了,以上是个人的愚见,如果你有更巧妙的解决办法,欢迎指教和讨论。
2、问题:在边写边做的过程中,遇到的另为一个奇葩的问题就是,在配置文件里加上中文的注释之后,老是报编码错误,报错如下:
这个也折腾了好久,由于时间太晚了,实在是不想折腾了,所以就想着,那我不加注释了,先让代码跑起来再说了,但是这个问题一直困扰着我,如果不解决,以后遇到类似的问题,人家非要你加注释,你绕都绕不过,怎么办???吾日三省吾身,自己问自己。完了还
是没办法,自己放不过自己,还是解决吧。完了自己 冷静了一下,静下心来捋了一下思路,由于胡子不够长,所有就只能摸摸自己头,冷静分析了一下:
(1)分析问题(bug)--------读取配置文件报编码错误,那就一定是在读取配置文件的时候,没有注意编码的问题导致出错
(2)解决问题(bug)--------读取配置文件的时候,加上编码encoding="utf-8" 即可
(3)定位问题(bug)--------全部代码,读取配置文件的只有邮箱信息,邮箱信息又在readconfig.py文件里,问题范围有缩小了,怀疑对象有缩小了,目标嫌疑人已经锁定,下一步找出证据,判他死刑
(4)用证据说话----------------查看读取配置文件时,是否有编码问题,没有注意,果不其然是这个问题 :
(5)弹药上膛-------------加上编码 encoding="utf-8" 即可
(6)下令开枪,判处死刑----------运行代码,顺利通过,邮件发出,大功告成
嘿嘿,时光穿越,当了一回狄仁杰,过了一把神探的瘾,不过那个时候没有枪,应该是大刀举起,砍下人头,但是大晚上一个人害怕,又太血腥,还是穿越到现代拿把枪过去再行刑。好了,时间太晚了。这时候我是不是应该说:“元芳,你怎么看”。。。。。。。。
python接口自动化(四十二)- 项目结构设计之大结局(超详解)的更多相关文章
- python接口自动化(十八)--重定向(Location)(详解)
简介 在实际工作中,有些接口请求完以后会重定向到别的url,而你却需要重定向前的url.URL主要是针对虚拟空间而言,因为不是自己独立管理的服务器,所以无法正常进行常规的操作.但是自己又不希望通过主域 ...
- python接口自动化(十二)--https请求(SSL)(详解)
简介 本来最新的requests库V2.13.0是支持https请求的,但是一般写脚本时候,我们会用抓包工具fiddler,这时候会 报:requests.exceptions.SSLError: [ ...
- python接口自动化(十一)--发送post【data】(详解)
简介 前面登录博客园的是传 json 参数,由于其登录机制的改变没办法演示,然而在工作中有些登录不是传 json 的,如 jenkins 的登录,这里小编就以jenkins 登录为案例,传 data ...
- Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验
Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高 ...
- 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高
第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...
- “全栈2019”Java第四十九章:重载与重写对比详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java多线程第十二章:后台线程setDaemon()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- python接口自动化(十)--post请求四种传送正文方式(详解)
简介 post请求我在python接口自动化(八)--发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等.我们要知道post请求四种传送正文方式首先需要先 ...
- Spring Cloud(十二):Spring Cloud Zuul 限流详解(附源码)(转)
前面已经介绍了很多zuul的功能,本篇继续介绍它的另一大功能.在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选 ...
随机推荐
- apache 的rewrite函数配置伪静态
配置伪静态目的:对于访问比较长的uri,利于网站搜索工具更容易记住,换句话利于SEO 在配置文件中添加或找到 <IfModule mod_rewrite.c> </IfModule& ...
- django xadmin的使用和改造
django本身自带一个强大的admin后台管理系统,但是管理起来并不是很方便.这里介绍下xadmin,xadmin是基于bootstrap和admin的一个更强大的后台管理系统 github地址ht ...
- Spark map-side-join 关联优化
在spark中要进行join操作,如果在shuffle的时候进行join效率较低.如果满足 所需要join的表中有一张表较小,那么可以考虑在map端进行join操作. 转载:http://blog.c ...
- 2017.10.13 unable to open debugger port(127.0.0.1:10308)
参考来自:http://blog.csdn.net/qq_34360219/article/details/76169653 1.场景 突然间IDEA就跑不起项目了,报了如下的错误:unable to ...
- SpringMVC 文本文件下载的配置
页面: <fieldset> <legend>Download annotator list</legend> <img src="pages/to ...
- JavaScript取指定时区的时间
// 北京是getZoneTime(8),纽约是getZoneTime(-5),班加罗尔是getZoneTime(5.5). 偏移值是本时区相对于格林尼治所在时区的时区差值 function getZ ...
- Angular 学习笔记——ng-repeat&filter
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <met ...
- JAVA Eclipse如何修改Android程序名称
Values中修改strings.xml中的app_name即可 注意他是连接到AndroidManifest.xml文件的
- Android学习(十九)Dialog对话框
一.什么是Dialog对话框 对话框是当前页面中弹出的一个小窗口,用于显示重要的提示信息,提示用户输入信息,确认信息,或者显示某种状态,如下载进度,退出提示等等.用户需要与对话框进行交互,才能回到原窗 ...
- Laravel之Eloquent ORM关联
一.一对一 1.主对从(hasOne) 从User模型中取出用户的手机 User模型中: /** * 获取关联到用户的手机 */ public function phone() { return $t ...