如何在pytest自动化用例执行时抓取Android日志

背景

       在执行自动化测试用例时对于失败用例我们经常无法区别到底是开发的bug还是脚本编写的有问题,此时就需要开发通过日志进行确认,但自动化用例一般都会执行的很多条,再回去查找日志时,多数情况早就被冲掉了,本文以pytest框架为例实现Android日志的逐条抓取。

在实现此功能之前我们还要说明一个python 类,这个类的作用是实现类似java静态函数的作用,就是可以跨python模块进行变量的读取和保存,类名为

global_var.py

def init():
    global _my_dict
    _my_dict = {}


def set_value(my_key, my_value):
    _my_dict[my_key] = my_value


def get_value(my_key, my_default_value=None):
    try:
        return _my_dict[my_key]
    except KeyError:
        return my_default_value

在方法类中添加如下方法命名为

utils.py:

import global_var
import subprocess
import threading

def get_android_log_in_thread(pk_name, save_file):
    my_args_list = [(pk_name, save_file)]
    threading_all(my_args_list, 1, get_android_log)


def threading_all(args_list: list, number: int, func):
    print(len(args_list))
    num = len(args_list) // number
    soft_ids = [x for x in range(0, len(args_list), num)]
    threads = []
    len_ids = range(len(soft_ids))
    num_th = len(soft_ids)
    for i in len_ids:
        t = threading.Thread(
            target=run_main,
            args=(
                args_list,
                soft_ids[i],
                soft_ids[i] + num,
                f'thread{i}',
                func,
            ),
            name=f'thread{i}')
        # print(f'thread{i}')
        threads.append(t)
    for i in range(num_th):
        threads[i].start()
        time.sleep(0.5)

def get_android_log(*args):
    pk_name = args[0][0]
    file = args[0][1]
    my_thread_num = args[1]
    # 要执行的终端指令 -s 后面接过滤的tag
    adb_cmd = 'adb logcat | find "' + pk_name + '"'
    try:
        # 创建管道
        pi = subprocess.Popen(adb_cmd, shell=True, stdout=subprocess.PIPE)
        global_var.set_value("pi_out", pi)
        # t用来标记输出行数,每10行刷新到文件中一次
        t = 0
        # 遍历每行
        for my_line in iter(pi.stdout.readline, 'b'):
            # 将得到字节转码成utf-8,然后写入文件
            # 第二个参数防止使用默认参数会报出转换异常, 'ignore'会过滤掉特殊符号
            if not file.closed:
                file.write(my_line.decode('utf-8', 'ignore').replace('\n', ''))
                t = t + 1
                # 当达到10行时,将数据刷到文件中
                if t == 10:
                    t = 0
                    file.flush()
            else:
                return
    except BaseException as e:
        print(str(e))
        return

def invoke(cmd):
    output, errors = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
    my_str = output.decode("utf-8")
    # my_list = my_str.split('\r\n')
    return my_str

def make_dir(my_dir_path):
	if not os.path.exists(my_dir_path):
		os.makedirs(my_dir_path)

在conftest.py文件中添加如下函数:

@pytest.fixture(scope="function", autouse=True)
def save_log(request):
    global_var.init()
    my_case_name = request.node.name
    my_file_name = my_case_name+'_'+util.current_datetime("%Y_%m_%d_%H_%M_%S")+'.txt'
    path = os.path.dirname(__file__)
    make_dir(os.path.join(path, 'Log'))
    my_log_file_path = os.path.join(path, 'Log', my_file_name)
    my_pkg_name = "com.tencent.wework"
    # 以append形式打开(创建)文件
    my_file = open(my_log_file_path, 'a', encoding='utf-8')
    my_list = invoke("adb devices")
    if my_list[1] == '':
        print('没有链接Android手机,无法获取Android切面日志,请确认!')
    else:
        get_android_log_in_thread(my_pkg_name, my_file)
    yield
    if my_file.closed:
        pass
    else:
        my_file.close()
    my_pi_value = global_var.get_value("pi_out")
    if my_pi_value is None:
        print('my_pi_value is None')
        return
    else:
        my_pi_value.terminate()
        print('执行terminate。。。。。。。。。。。。。。。。。。。。。')

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值