前一阶段整理了自己理解的接口自动化项目框架的优化版本,这次把遗漏的环境切换和配置文件读取部分给完善了,如有小过半需要代码的,两篇文章直接复制代码即可。话不多说,进入代码的世界…
配置文件的读取
项目目录中有一个settings.py文件,这里是专门放一些配置数据的,读取到后再进行处理获取需要的值
先看setting.py文件的内容:
from pathlib import Path, PurePath
# 获取项目根目录
BASE_DIR = PurePath(Path(__file__).parent)
# 用于判断是否往企业微信发送测试报告:True是发送、False是不发送
IS_SEND = True
# 设置运行的环境变量
ENVIRONMENT = "PRO" # 环境变量值分别为 测试:TEST;预发布:PRE;生产:PRO
# 接口请求域名
HOST = "http://apis.juhe.cn"
# 设置头信息指定域名和Content-Type类型
HEADERS = {
'Content-Type': 'application/json'}
# 环境IP配置
BASE_HOST = {
"test": None,
"pre": None,
"pro": None,
}
# 数据库配置
DATABASES = {
"pro": {
"host": "8.136.250.157", "port": 1234, "user": "root", "passwd": "test.2016", "db": "testing"},
}
# yaml文件路径
YAML_FILE_PATH = {
"api_idiom": BASE_DIR.joinpath("testDatas", "idiom_modules.yml"),
"api_match": BASE_DIR.joinpath("testDatas", "match_modules.yml"),
}
# 日志存放目录
LOGGING_PATH = BASE_DIR.joinpath("logs", f"logfile.text")
# 日志记录配置
LOGGING_CONFIG = {
"version": 1,
"root": {
"level": "DEBUG",
"handlers": ["file", "console"]
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "ERROR",
"formatter": "console_formatters"
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"formatter": "file_formatters",
"filename": LOGGING_PATH,
"level": "DEBUG",
"maxBytes": 100,
"backupCount": 5,
"encoding": "utf-8"
}
},
"formatters": {
"console_formatters": {
"format": "%(asctime)s [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s",
"datefmt": "%Y%m%d %H:%M:%S"
},
"file_formatters": {
'format': "%(asctime)s [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s- %(pathname)s",
"datefmt": "%Y%m%d %H:%M:%S"
}
}
}
名词解释:
-
BASE_DIR是项目的根路径
-
IS_SEND是判断邮件的发送
-
ENVIRONMENT是切换环境
-
HOST是请求的域名
-
HEADERS是默认请求头
-
BASE_HOST是环境IP
-
DATABASES是数据库配置
-
YAML_FILE_PATH是读取yaml文件的路径
-
LOGGING_PATH是日志文件的路径
-
LOGGING_CONFIG日志的配置
是如何读取settings.py中的配置的呢,这也是借鉴了django框架的懒加载,当然我这是简化版的懒加载(可能还没达到懒加载,哈哈…)。这段代码是放置在apiTest/common/init.py中的:
# apiTest/common/__init__.py
import importlib
__all__ = ["setting"]
class LazySetting:
def __init__(self, settings_module):
_mod = importlib.import_module(settings_module)
self._explicit_settings = set()
for setting in dir(_mod):
if setting.isupper():
setting_value = getattr(_mod, setting)
if isinstance(setting, (list, tuple)):
raise TypeError("类型不符合要求!")
setattr(self, setting, setting_value)
self._explicit_settings.add(setting)
def _is_overridden(self, setting):
return setting in self._explicit_settings
def get_setting(self, name):
for i in self._explicit_settings:
if self._is_overridden(i) and (name == i):
return getattr(self, i)
setting = LazySetting("settings")
这段代码,大家可自行理解,我怕解释不清楚,让大家搞混掉了,其实实际操作一下就能看懂个大概了。
settings.py文件中的数据就被拿到了,然后再去进行处理,处理成自己需要的那种:
# apiTest/common/readEnvironment.py
import os
import common
_DATA = common.setting.get_setting
__all__ = ["MappingRelation"]
class Config:
def __getitem__(self, key):
"""
魔术方法,把类变成字典取值
:param key:
:return:
"""
return self.__getattribute__(key)
class Test_DATA(Config):
"""
测试环境配置信息
"""
HOST = _DATA("HOST")
HEADERS = _DATA("HEADERS")
YAML_PATH = _DATA("YAML_FILE_PATH")
LMS_LOGGING = _DATA("LOGGING_CONFIG")
BASE_URL = _DATA("BASE_HOST")["test"]
_DATABASE = _DATA("_DATABASES")["pro"]
class Pre_DATA(Config):
"""
预发布环境配置信息
"""
HOST = _DATA("HOST")
HEADERS = _DATA("HEADERS")
YAML_PATH = _DATA("YAML_FILE_PATH")
LMS_LOGGING = _DATA("LOGGING_CONFIG")
BASE_URL = _DATA("BASE_HOST")["pre"]
_DATABASE = _DATA("_DATABASES")["pro"]
class Pro_DATA(Config):
"""
线上环境配置信息
"""
HOST = _DATA("HOST")
HEADERS = _DATA("HEADERS")
YAML_PATH = _DATA("YAML_FILE_PATH")
LMS_LOGGING = _DATA("LOGGING_CONFIG")
BASE_URL = _DATA("BASE_HOST")["pro"]
_DATABASE = _DATA("_DATABASES")["pro"]
class MappingRelation:
# 设置映射关系
_mapping = {
'PRO': Pro_DATA,
'PRE': Pre_DATA,
'TEST': Test_DATA
}
@property
def map(self):
# 返回映射关系
env = os.environ.get('ENV', _DATA("ENVIRONMENT")).upper() # 配置文件中读取环境变量
return self._mapping[env]() # 获取指定的环境
名词解释:
-
_DATA是common.setting.get_setting方法赋值的变量
-
Config类是写了两个魔术方法,getitem是可变成下标取值的样式,而getattribute是属性拦截器
-
Test_DATA子类继承了Congif类,配置的是测试环境
-
Pre_DATA子类继承了Congif类,配置的是预发环境
-
Pro_DATA子类继承了Congif类,配置的是生产环境
-
MappingRelation类是映射上述三个子类,读取配置文件中的环境变量,去返回对应的环境数据
这里处理完成后,再去编写一个.py文件,专门调用MappingRelation类来获取对应的数据:
# apiTest/common/mapMnvironment.py
from urllib import parse
from common.readEnvironment import MappingRelation
__all__ = ["MapEnvironment"]
class MapEnvironment:
_config = MappingRelation().map
@classmethod
def _command(cls, info):
"""
远程执行命令
:param info:
:return:
"""
return info
@classmethod
def base_url(cls, url):
"""
获取url信息并执行替换操作
:param url:
:return:
"""
if cls._command(cls._config.BASE_URL):
u = parse.urlparse(url)
scheme, netloc, path, params, query = u.scheme, u.netloc, u.path, u.params, u.query
return f'{
scheme}://{
netloc.replace(netloc, cls._command(cls._config.BASE_URL))}{
path}?{
params}{
query}'
else:
return url
@property
def base_db(cls):
"""
获取数据库连接环境账号
:return:
"""
return cls._command(cls._config.DATABASE)
@property
def host(cls):
"""
获取域名
:return:
"""
return cls._command(cls._config.HOST)
@property
def headers(cls):
"""
获取头部信息
:return:
"""
return cls._command(cls._config.HEADERS)
@property
def yaml_path(cls):
"""
读取yaml文件路径
:return:
"""
return cls._command(cls._config.YAML_PATH)
@property
def lms_logging(cls):
"""
读取日志配置
:return:
"""
return cls._command(cls._config.LMS_LOGGING)
if __name__ == '__main__':
print(MapEnvironment().host)
这里处理完成后,各处需要参数的类或函数,就直接引入这个类,拿对应的数据即可。
需要注意的是,如果你settings.py配置文件中需要增加新参数,就得在这两个.py文件中进行增加获取数据的方法,不然就是只是增加,没有起到任何作用。
日志配置
日志的配置也是根据上述两个类,读取到settings.py配置文件的日志配置(这里的日志配置,官网有详细介绍,也是减少代码的一种好处,在公众号中也写了该文章,有兴趣的可以翻阅下):
# apiTest/common/logLogging.py
import logging.config
from common.mapMnvironment import MapEnvironment
class LogLogging:
_logging_conf = MapEnvironment().lms_logging
def __init__(self):
logging.config.dictConfig(self._logging_conf)
self.logger = logging.getLogger()
self.logger.setLevel(logging.ERROR)
@property
def get_logger(self):
return self.logger
do_logger = LogLogging().get_logger
封装的一个日志获取类,代码和配置作了分离,是不是看起来都简洁了呢,哈哈…
发送企业微信报告
import jenkins
import requests
from functools import partialmethod
from common.mapMnvironment import MapEnvironment
class WeChat:
_map = MapEnvironment()
@classmethod
def _message_info(cls, project, end, total, passing, succeed, failing, error, address: str):
"""
需要发送到企业微信的文案信息
:param project: 项目名称
:param end: 指定端[web、app、h5]
:param total: 总计
:param passing: 通过率
:param succeed: 通过数
:param failing: 失败数
:param error: 错误数
:param address: 链接地址->放一个链接信息
:return: 返回data信息
"""
data = {
"msgtype": "markdown", # 消息类型,此时固定为markdown
"markdown": {
"content": "#### **提醒!自动化测试反馈**\n###### **请相关同事注意,及时跟进!**\n"
"> 项目名称:<font color=\"comment\">{}</font> \n"
"> 测试用例总数:<font color=\"comment\">{}</font>,测试用例通过率:<font color=\"comment\">{}</font>\n"
"> **--------------------运行详情--------------------**\n"
"**环境:**<font color=\"comment\"> {} </font>,**端:**<font color=\"comment\">{}</font>\n"
"> **成功数:**<font color=\"comment\">{}</font>,**失败数:**<font color=\"comment\">{}</font>,"
" **错误数:**<font color=\"comment\">{}</font>\n"
"> **报告链接:** [jenkins测试报告,鼠标点击此处查看]({})".format(project, total, passing,
cls._map.environment, end, succeed, failing,
error, address)
# 加粗:**需要加粗的字**
# 引用:> 需要引用的文字
# 字体颜色(只支持3种内置颜色)
# 标题 (支持1至6级标题,注意#与文字中间要有空格)
# 绿色:info、灰色:comment、橙红:warning
}
}
return data
@classmethod
def send_message(cls, project, end, total, passing, succeed, failing, error, address):
"""
请求发送接口
:param project: 项目名称
:param end: 指定端,管理端、APP端等
:param total: 总计
:param passing: 通过率
:param succeed: 通过数
:param failing: 失败数
:param error: 错误数
:param address: 链接地址->放一个链接信息
:return:
"""
# 获取报告文案信息
data = cls._message_info(project, end, total, passing, succeed, failing, error, address)
# 请求接口,开始发送请求
with requests.Session() as session:
response = session.post(url=cls._map.wechat, json=data, verify=False)
return response.json()
这个发送企业微信报告,因为牵扯到项目的一些东西,只提供参考,上述两个方法稍微修改下即可使用。
以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的赞赏、点赞、在看+分享哟,谢谢!
下面是一份配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
这些都可以以在公众号:伤心的辣条 ! 免费领取,还有一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中资料包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
学习不要孤军奋战,最好是能抱团取暖,相互成就一起成长,群众效应的效果是非常强大的,大家一起学习,一起打卡,会更有学习动力,也更能坚持下去。你可以加入我们的测试技术交流扣扣群:914172719(里面有各种软件测试资源和技术讨论)
喜欢软件测试的小伙伴们,如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
好文推荐
转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!