python接口自动化(四十二)- 项目架构设计之大结局(超详解)

打榜

首先宏哥要拉一下票,希望喜欢宏哥的支持一下,投下你宝贵的6票,投票完成记得抽奖哈,灰常感谢!!!掘金2024年度人气创作者打榜中,快来帮我打榜吧~ activity.juejin.cn/rank/2024/w...

1.登录稀土掘金社区可以获得2票 2.刷题可以获得4票 (1)刷题也比较简单,点击刷题,进入刷题界面,如下图所示:

(2)点击要刷的题目,如下图所示:

(3)进入题目详情内容,点击运行代码图标,即可刷题成功,获得投票次数,如下图所示:

3.投票完成可以进行抽奖

最后要注意每天6票(web)端,可以同时投给一个作者,喜欢宏哥的粉丝和读者可以都投给宏哥,表忠心的时刻到了!!!谢谢各位

1.简介

  这一篇主要是将前边的所有知识做一个整合,把各种各样的砖块---模块(post请求,get请求,logging,参数关联,接口封装等等)垒起来,搭建一个房子。并且有很多小伙伴对于接口项目测试的框架一筹莫展,吵吵着什么时候才可以看到一篇相对于比较完整的项目源码,但是由于完整的项目属于公司内部的代码,这个是说句大实话是没法分享的,这个想必大家都知道吧,不知道入职的时候都签过保密协议吧。所以由于种种原因没办法给小伙伴们分享公司内部的项目源码,就算别人分享了,也只适用于本公司内部的业务。你拿过来也不能用的,需要修修补补。所以用例的代码还是得自己去一个个写,这个宏哥只能分享项目框架,自己在框架里添加自己公司的业务测试用例,使她变的丰满充实,适合自己公司的业务。希望对小伙伴们有所指导或者是启发,好了时间不早了,废话少说,还是尽快进入今天的主题吧---接口项目测试结构(框架)设计。

2.项目结构

2.1关注公众号发送:项目架构设计源码。获取源码下载地址

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:这里存放测试报告

3.run_main

3.1第一步:用discover方法加载所有的测试用例

1、cur_path这个参数是读取当前这个脚本的真实路径,也就是run_main.py的真实路径

2、caseName="case"这个case是存放测试用例的文件夹,如果没有的话,自动创建。如果想运行其它文件夹的用例,就改下caseName这个参数值

3、rule="test*.py"这个是匹配用例脚本名称的规则,默认匹配test开头的所有用例

3.2第二步:生成HTML报告

1.把上一步加载到用例的参数传入这个函数,测试报告的文件名称默认report文件夹:reportName="report

2.如果没有这个report文件夹也没关系,可以自动创建的

3.3第三步:获取最新的测试报告

1.如果第二步生成的测试报告加了时间戳,想找到最新的文件就用第三步

2.如果第二步不加时间戳,只是生成result.html,那这一步其实没卵用,可以忽略

(个人觉得报告用一个名称result.html就行,新的自动覆盖旧的)

3.4第四步:发送测试报告到邮箱

1、像QQ邮箱这种ssl加密的就走SMTP_SSL,用授权码登录

2、其它邮箱就正常账号密码登录,走SMTP

3、最后执行代码

这里邮箱的内容读的配置文件

4.config配置

1、cfg.ini打开,这里写配置文件内容

2、用readConfig.py读取配置文件

3、读取的内容就是传入第二步操作里面需要调用邮箱的配置信息

5.logger

1、logger.py这个文件放到common目录下,封装日志文件的读取

2、日志保存到logs文件夹

3、参开代码:

python 复制代码
 1 # -*- coding:utf-8 -*-
 2 # 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
 3 
 4 # 2.注释:包括记录创建时间,创建人,项目名称。
 5 '''
 6 Created on 2024-12-26
 7 @author: 北京-宏哥     QQ交流群:984942724
 8 Project:项目结构设计
 9 '''
10 # 3.导入模块
11 import logging, time
12 import os
13 
14 # log_path是存放日志的路径
15 cur_path = os.path.dirname(os.path.realpath(__file__))
16 log_path = os.path.join(os.path.dirname(cur_path), 'logs')
17 # 如果不存在这个logs文件夹,就自动创建一个
18 if not os.path.exists(log_path): os.mkdir(log_path)
19 
20 
21 class Log():
22     def __init__(self):
23         # 文件的命名
24         self.logname = os.path.join(log_path, '%s.log' % time.strftime('%Y_%m_%d'))
25         self.logger = logging.getLogger()
26         self.logger.setLevel(logging.DEBUG)
27         # 日志输出格式
28         self.formatter = logging.Formatter('[%(asctime)s] - %(filename)s] - %(levelname)s: %(message)s')
29 
30     def __console(self, level, message):
31         # 创建一个FileHandler,用于写到本地
32         # fh = logging.FileHandler(self.logname, 'a')  # 追加模式  这个是python2的
33         fh = logging.FileHandler(self.logname, 'a', encoding='utf-8')  # 这个是python3的
34         fh.setLevel(logging.DEBUG)
35         fh.setFormatter(self.formatter)
36         self.logger.addHandler(fh)
37 
38         # 创建一个StreamHandler,用于输出到控制台
39         ch = logging.StreamHandler()
40         ch.setLevel(logging.DEBUG)
41         ch.setFormatter(self.formatter)
42         self.logger.addHandler(ch)
43 
44         if level == 'info':
45             self.logger.info(message)
46         elif level == 'debug':
47             self.logger.debug(message)
48         elif level == 'warning':
49             self.logger.warning(message)
50         elif level == 'error':
51             self.logger.error(message)
52         # 这两行代码是为了避免日志输出重复问题
53         self.logger.removeHandler(ch)
54         self.logger.removeHandler(fh)
55         # 关闭打开的文件
56         fh.close()
57 
58     def debug(self, message):
59         self.__console('debug', message)
60 
61     def info(self, message):
62         self.__console('info', message)
63 
64     def warning(self, message):
65         self.__console('warning', message)
66 
67     def error(self, message):
68         self.__console('error', message)
69 
70 
71 if __name__ == "__main__":
72     log = Log()
73     log.info("---测试开始----")
74     log.info("操作步骤1,2,3")
75     log.warning("----测试结束----")

6.case放用例

1、常用的接口,需要检查被调用的单独封装处理,如登录等

2、test开头的用例

7.logs日志查看

1、运行完后日志都会收集到logs文件夹以日期命名

8.生成测试报告

1、这里调用的是HTMLTestRunner生成html的测试报告

9.发送报告到邮箱

1、运行run_main.py就会自动生成报告,然后发送到邮箱了

(这里QQ邮箱的展示是有问题的,一般用企业邮箱的话,是可以正常展示的)

10.小结

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类型。

知道这个原因后,将这一行代码:

less 复制代码
smtp.sendmail(sender, receiver, msg.as_string())

替换为下边这样就可以了:

less 复制代码
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)下令开枪,判处死刑----------运行代码,顺利通过,邮件发出,大功告成

  嘿嘿,时光穿越,当了一回狄仁杰,过了一把神探的瘾,不过那个时候没有枪,应该是大刀举起,砍下人头,但是大晚上一个人害怕,又太血腥,还是穿越到现代拿把枪过去再行刑。好了,时间太晚了。这时候我是不是应该说:"元芳,你怎么看"。。。。。。。。

相关推荐
Draina8 小时前
CBC填充预言攻击-CBC Padding Oracle Crypto Attack
python·安全·web安全·网络安全·密码学·安全性测试
Angel Q.9 小时前
特征提取 | DINO 到 DINOv3
图像处理·python
不如语冰9 小时前
AI大模型入门-pytorch-张量2 tensor创建
python
NPE~10 小时前
[AI]Agent开发——ADK框架使用
人工智能·python·ai·教程·adk·agent开发
矮个史蒂芬10 小时前
统计verilog .v文件中output 的bit数
python
gwf21610 小时前
磨损均衡算法(Wear Leveling)——SSD如何让每块闪存“公平退休“?
运维·数据库·人工智能·python·嵌入式硬件·算法·智能硬件
爱吃提升10 小时前
python 分布式爬虫、爬虫合规与综合实战项目
分布式·爬虫·python
审小匠OpenCPAi10 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
元Y亨H11 小时前
Pandas 解析 Excel 导致的内存溢出(MemoryError)
python·excel
gis开发之家12 小时前
《Vue3 从入门到大神37篇》Vue3 源码详解(七):watch 与 watchEffect 源码对比——副作用是如何被追踪的?
javascript·前端框架·vue3·vue3源码