1、日志轮询
Python 的 logging 模块提供了两个支持日志回滚的 FileHandler 类,分别是 RotatingFileHandler 和 TimedRotatingFileHandler.
RotatingFileHandler 的回滚时刻是当日志文件的大小达到一定值。当日志文件的大小达到指定值的时候,RotatingFileHandler 会将日志文件重命名存档,然后打开一个新的日志文件。
TimedRotatingFileHandler 是当某个时刻到来时执行回滚。同 RotatingFileHandler 一样,当回滚时机来临时,TimedRotatingFileHandler 会将日志文件重命名存档,然后打开一个新的日志文件。
from logging.handlers import RotatingFileHandler
fh = RotatingFileHandler(filename, maxBytes=1024*1024*50, backupCount=5)
filename: 自定义日志文件的路径以及文件名, 假定文件名是: error.log
maxBytes: 配置日志文件大小的上限, 单位是字节
backupCount: 配置日志文件的最大数量, backupCount=5, 也就是日志文件error.log 大小达到50M以后, 会自动再创建文件error.log.1, error.log.1大小达到50M以后, 会创建 error.log.2, 以此类推, 一直到 error.log.5,最新的数据都在error.log中,如果已经有5个备份文件了,那么就会所有的新的数据都会存储在error.log里面,error.log只会越来越大
案列:
import logging
import time
from logging.handlers import RotatingFileHandler
logger = logging.getLogger("py36")
# 初始化handler
handler = RotatingFileHandler("py36.log",
maxBytes=100,
backupCount=3,
encoding="utf-8")
logger.addHandler(handler)
# 打印日志
for i in range(100):
logger.warning("生成告警信息{}".format(time.time()))
time.sleep(0.1)
TimedRotatingFileHandler:根据日志输入的时间切割文件也需要准备三个参数,第一个参数when表示生成新文件的时间单位,具体有S、M、H、D分别表示秒、分、时、天,第二个参数interval表示隔多少个单位,第三个参数backupCount还是表示最大的文件数,新生成的文件会在文件名的后面加上时间格式作为后缀。
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger("py36")
handler = TimedRotatingFileHandler("time.log",
when="s",
interval=2,
backupCount=100,
encoding="utf-8")
logger.addHandler(handler)
# 打印日志
for i in range(100):
logger.warning("生成告警信息{}".format(time.time()))
time.sleep(0.3)
2、mock(是一种手段,一种技术,一种思想)提前介入测试,不是真实的对象不能作为最终测试结果
mock测试(mocks)是以可控的方式模拟真实的对象行为。程序员通常创造模拟对象来测试对象本身该具备的行为,很类似汽车设计者使用碰撞测试假人来模拟车辆碰撞中人的动态行为。
之所有使用mock测试,是因为真实场景很难实现或者短期实现起来很困难,主要场景有:
真实对象可能还不存在(接口还没有完成开发);
真实对象很难搭建起来(第三方支付联调);
真实对象的行为很难触发(例如:网络错误);
真实对象速度很慢(例如,一个完整的数据库,在测试之前可能需要初始化);
真实对象可能包含不能用作测试(而不是为实际工作)的信息和方法;
真实的对象是用户界面,或包括用户界面在内;
真实的对象使用了回调机制;
真实的对象的行为是不确定(例如,当前的时间或当前的温度)
pip install pytest-mock
使用内置fixture :mocker
真实场景下的测试:
import requests
import pytest
def visit_api(method,url,json):
resp = requests.request(method=method,
url=url,
json=json)
return resp.json()
def test_real_world():
expected = 2
actual = visit_api("post",
"http://httpbin.org/post",
{"name":"yuz"})
assert expected == actual
当接口没有开发完成时,调用visit_api肯定是会连接失败的,此时可以添加mock代码,mocker.patch可以模拟实际的方法调用,
通过return_value 表示模拟出来的返回值,就算接口无法访问,接口测试也可以通过。import requests
import pytest
def visit_api(method,url,json):
resp = requests.request(method=method,
url=url,
json=json)
return resp
def test_real_world():
expected = 2
actual = visit_api("post",
"http://httpbin.org/post",
{"name":"yuz"})
assert expected == actual
def test_real_world2(mocker): # 内置fixture,需要安装pytest-mock
expected = 2
# 打个补丁
mocker.patch("requests.request",return_value=2)
actual = visit_api("post",
"http://httpbin.org/post",
{"name":"yuz"})
assert expected == actual
有mock的那个测试用例会通过,
客户端的mock:mocker.patch是打补丁,会监听,当调用真实的api时,调用requests.request时,不会实际去调用api,而是直接把return_value=2直接给resp了,所以结果就是通过的。模拟requests.request.
服务端的mock:客户端的api访问代码可以不改动,该怎么访问就怎么访问,造一个假的服务器处理,模拟一个服务器出来,保证我们有个正常的网络请求出来,而且当真实的接口出来后,不需要改动测试用例的代码,只需要
将配置文件中mock的服务器地址改成真实服务器的地址。
1、选用存在的mock平台--fastmock:https://fastmock.site/#/
2、自己写(Flask)
from flask import Flask, request
# 初始化服务对象
app = Flask(__name__)
@app.route('/member/register',methods=['get'])
def register():
# 获取请求参数
username = request.args.get("username")
if not username:
return {"msg":"no username"}
return {"msg":"ok","data":{"token":"adafhoigjreiof"}}
@app.route('/member/login',methods=['post'])
def login():
return {"msg": "ok", "data": {"token": "adafhoigjreiof"}}
if __name__ == '__main__':
app.run()
3、接口的加密
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_v1_5
from base64 import b64decode
def get_sign(ts,token):
s = token[:50] + ts
key = '-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQENQujkLfZfc5Tu9Z1LprzedE O3F7gs+7bzrgPsMl29LX8UoPYvIG8C604CprBQ4FkfnJpnhWu2lvUB0WZyLq6sBr tuPorOc42+gLnFfyhJAwdZB6SqWfDg7bW+jNe5Ki1DtU7z8uF6Gx+blEMGo8Dg+S kKlZFc8Br7SHtbL2tQIDAQAB -----END PUBLIC KEY-----'
public_key = RSA.import_key(key)
cipher = PKCS1_v1_5.new(public_key)
encrypted_bytes = cipher.encrypt(s.encode())
return b64decode(encrypted_bytes).decode()
4、装饰器、生成器、迭代器
装饰器:又叫做修饰器
1、让代码变得美观,优雅;2、扩展函数功能
装饰器:高阶函数,在Python里面函数其实可以作为另外一个函数的参数的和作为另外一个函数的返回值。
import time
def log_time(func):
def wrapper():
print(time.time())
func()
return
return wrapper
# print(log_time(run)())
@log_time
def run():
print("正在运行")
run()
接口自动化测试中用到的装饰器:
@classmethod
@staticmethod
@pytest.mark
@pytest.fixture