如何使会员身份类的自动化Case并行执行?

119 阅读2分钟

第一版原文:guotengda1993.github.io/2022/03/07/…

会员身份类的case在执行过程中会有身份状态变化、校验等情况,如果使用同一个测试账号并行的去执行这类case则会导致执行失败,那么如何去解决这个问题呢?

最简单的方法:case分组

不同组case使用不同的账号,每组case串行执行,这样就能串行执行n组case了。但随之而来的就是管理case的成本,case越多,成本越大。纯靠规则来约束case,也难免会遇到新人操作case造成的执行错误。

高阶方案:账号池

实现一个账号池,每个case执行之前先从账号池中取出一个账号,执行完成后,调用账号池接口进行回收(或等待x秒后由账号池自动回收),以此来达到任何case都可并行执行,并发n倍的目的。

账号池设计

代码Demo:

import flask
from flask import Flask
import redis
from flask_apscheduler import APScheduler


# 可用池,每次接口获取账号都从可用池中随机捞取一个
ValidPool = 'xpool:valid'
# 不可用池,又worker自动进行回收重置账号身份
InvalidPool = 'xpool:invalid'
# 账号锁,case占用时对账号进行标记
LockKey = 'xpool:lock_{xid}'


class Config(object):
    JOBS = [
        {
            'id': 'job',
            'func': 'scheduler:reset_worker',
            'trigger': 'interval',
            'seconds': 5
        }
    ]
    SCHEDULER_API_ENABLED = True


app = Flask(__name__)
app.config.from_object(Config())
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()

redis = redis.Redis(host='127.0.0.1', port=6379)


@app.route('/api/get', methods=['GET'])
def get():
    args = flask.request.args.to_dict()
    duration = int(args.get('duration', 30))
    # 从可用池中获取账号
    xid = redis.spop(ValidPool)
    if not xid:
        return {'status': 1, 'msg': 'get nothing in pool'}, 200

    lock = LockKey.format(xid=xid)
    # 锁住账号
    redis.setex(name=lock, time=duration, value='1')
    # 将账号推到不可用池
    redis.sadd(InvalidPool, xid)

    return {'status': 0, 'xid': xid}, 200


def reset(xid):
    # 回收重置逻辑
    print('reset xid: {}'.format(xid))
    return 


def reset_worker():
    xid_list = redis.smembers(InvalidPool)
    if not xid_list:
        return
    for xid in xid_list:
        lock = LockKey.format(xid=xid)
        # 判断是否仍被锁住
        if redis.get(lock):
            continue
        # 重置账号
        reset(xid)
        # 从不可用池中移除
        redis.srem(InvalidPool, xid)
        # 推到可用池中
        redis.sadd(ValidPool, xid)
    return

if __name__ == '__main__':
    app.run(port=8666)