PC端稳定性测试工具探索

Main

# encoding=utf8
from Action_command import *
from Main_method import *
import time
from datetime import datetime, date, timedelta
import datetime
import os
import threading
from pynput import keyboard
import _thread
from PIL import ImageGrab
import cv2
import cv2 as cv
from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize, VideoCapture
import numpy as np

module = get_config("module", "module")
test_time = get_config("test_time", "time")
test_times = datetime.datetime.now() + datetime.timedelta(hours=float(test_time.strip('h')))
def main(start_tab):
    print("测试时间:", test_time,test_times)
    global flag
    # global test_times
    if check_client_working():
        os.system('taskkill /f /im FTNN.exe')
        time.sleep(1)
    if start_tab == '牛牛圈':
        nnq_window = start_connect_nnq(start_tab)
        while datetime.datetime.now() < test_times:
            check_top(start_tab, nnq_window)
            check_minmax(nnq_window, '牛牛圈')
            if not (check_client_working() and nnq_window.exists()):
                logger2.info("客户端或牛牛圈被关闭")
                flag = True
                nnq_window = start_connect_nnq(start_tab)
            try:
                choice_order_execute(choice_ctrl(nnq_window))
            except Exception as e:
                logger2.info("动作执行失败,尝试重新关联{}".format(e))
                flag = True
                nnq_window = start_connect_nnq(start_tab)
            time.sleep(0.5)

    elif start_tab == '资讯' or start_tab == '消息':
        zx_window = start_connect_zx(start_tab)
        while datetime.datetime.now() < test_times:
            check_top(start_tab, zx_window)
            check_minmax(zx_window, '消息')
            if not check_client_working():
                logger2.info("客户端被关闭")
                flag = True
                zx_window = start_connect_zx(start_tab)
            try:
                choice_order_execute(choice_ctrl(zx_window))
            except Exception as e:
                logger2.info("动作执行失败,尝试重新关联{}".format(e))
                flag = True
                zx_window = start_connect_zx(start_tab)
            time.sleep(1)


def on_press(key):  # 监听按键
    # global test_times
    if key == keyboard.Key.home or datetime.datetime.now() > test_times:
        logger2.info("稳定性测试结束")
        return False  # 返回False,键盘监听结束!

def video_record():  # 录⼊视频
    # global test_times
    global flag
    global logger3
    #test_time = get_config("test_time", "time")
    video_time = get_config("test_time", "video_time")
    more_time = get_config("test_time", "more_time")
    video_address = get_config("path", "video_address")
    # test_times = datetime.datetime.now() + datetime.timedelta(hours=float(test_time.strip('h')))
    video_times = int(video_time.strip('s'))
    more_times = int(more_time.strip('s'))
    while datetime.datetime.now() < test_times:
        flag = False
        name = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')  # 当前的时间(当文件名)

        screen = ImageGrab.grab()  # 获取当前屏幕
        width, high = screen.size  # 获取当前屏幕的大小
        fourcc = VideoWriter_fourcc('X', 'V', 'I', 'D')  # MPEG-4编码,文件后缀可为.avi .asf .mov等
        video = VideoWriter(str(video_address)+'\\%s.avi' % name, fourcc, 15, (width, high))  # (文件名,编码器,帧率,视频宽⾼)
        # print('3秒后开始录制----')  # 可选
        # time.sleep(3)
        logger3.info("开始录制")
        start_time = time.time()
        while True:
            if time.time() - start_time >= video_times:
                # logger3.info("视频自然结束,删除")
                video.release()  # 释放
                # time.sleep(1)
                # os.remove('%s.avi' % name)
                break

            elif flag:
                logger3.info("flag!多录{}秒".format(more_times))
                now_time = time.time()
                now_time_show = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                logger3.info('发生时间:{},文件名:{}'.format(now_time_show, name))
                while True:
                    if time.time() - now_time >= more_times:
                        video.release()  # 释放
                        time.sleep(1)
                        # video_info()
                        break
                    im = ImageGrab.grab()  # 图片为RGB模式
                    imm = cv.cvtColor(np.array(im), cv.COLOR_RGB2BGR)  # 转为opencv的BGR模式
                    video.write(imm)  # 写入
                break

            im = ImageGrab.grab()  # 图片为RGB模式
            imm = cv.cvtColor(np.array(im), cv.COLOR_RGB2BGR)  # 转为opencv的BGR模式
            video.write(imm)  # 写入


if __name__ == '__main__':
    t = threading.Thread(target=main, args=(module,))
    t1 = threading.Thread(target=video_record)
    t.setDaemon(True)  # 设置守护线程必须写在start之前,否则不生效
    t1.setDaemon(True)
    t1.start()
    t.start()
    with keyboard.Listener(on_press=on_press) as listener:
        listener.join()

Main_method

# encoding=utf8
from Action_command import *
from pywinauto.application import Application
import random
import logging
import win32com.client
import pythoncom
import os
import configparser
import time
import win32gui
import win32con
import win32gui as w

global logger3
logging.basicConfig(level=logging.INFO, filename="testlog.levellog", filemode="w",
                    format='%(asctime)s - %(name)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s')
logger1 = logging.getLogger("start_APP")
logger2 = logging.getLogger("action")
logger3 = logging.getLogger("video_record")


# def get_location(start_tab):
#     """
#     获取指定模块window信息
#     :param start_tab:
#     指定模块("牛牛圈","资讯","消息"...)
#     :return:
#     """
#     proDir = os.path.split(os.path.realpath(__file__))[0]
#     configPath = os.path.join(proDir, "config.cfg")
#     path = os.path.abspath(configPath)
#     cf = configparser.ConfigParser()
#     cf.read(path, encoding="utf-8")
#     tab_location = cf.get("TAB", start_tab)
#     dic_location = {}
#     a1 = tab_location.split(',')
#     for i in a1:
#         j, k = i.split("=")
#         dic_location[j] = k
#     return dic_location
def check_minmax(window, start_tab):
    """
    判断测试窗口是否最小化了,恢复窗口
    :param window: 测试窗口
    :param start_tab: 窗口名
    :return:
    """
    try:
        if window.rectangle().left <= -30000 \
                and window.rectangle().right <= -30000 \
                and window.rectangle().top <= -30000 \
                and window.rectangle().bottom <= -30000 and (start_tab == '资讯' or start_tab == '消息'):
            hwnd = win32gui.FindWindow("#32770", "富途牛牛")
            win32gui.ShowWindow(hwnd, win32con.SW_SHOWMAXIMIZED)
        elif window.rectangle().left <= -30000 \
                and window.rectangle().right <= -30000 \
                and window.rectangle().top <= -30000 \
                and window.rectangle().bottom <= -30000 and start_tab == '牛牛圈':
            hwnd = win32gui.FindWindow("SOUIHOST", "牛牛圈")
            win32gui.ShowWindow(hwnd, win32con.SW_SHOWNORMAL)
    except Exception as e:
        logger1.warning("判断测试窗口是否最小化失败{}".format(e))


def check_top(start_tab, window):
    """
    判断窗口是否是在置顶
    :param start_tab:
    :return:
    """
    try:
        if start_tab == '资讯' or start_tab == '消息':
            if w.GetWindowText(w.GetForegroundWindow()) != "富途牛牛":
                hwnd = win32gui.FindWindow("#32770", "富途牛牛")
                win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)
                time.sleep(1)
                win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)
                window.maximize()
        elif start_tab == '牛牛圈':
            if w.GetWindowText(w.GetForegroundWindow()) != "牛牛圈":
                hwnd = win32gui.FindWindow("SOUIHOST", "牛牛圈")
                win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)
                time.sleep(1)
                win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)
    except Exception as e:
        logger1.warning("判断窗口是否是在置顶失败{}".format(e))


def get_config(tab_name, key_name):
    """
    获取配置文件里对应的value值
    :param tab_name: 配置文件[]里的值
    :param key_name: 配置项key
    :return: 配置项key对应的value
    """
    try:
        proDir = os.path.split(os.path.realpath(__file__))[0]
        configPath = os.path.join(proDir, "config.cfg")
        path = os.path.abspath(configPath)
        cf = configparser.ConfigParser()
        cf.read(path, encoding="utf-8")
        value = cf.get(tab_name, key_name)
        return value
    except Exception as e:
        logger1.warning("获取配置文件里对应的value值失败{}".format(e))


def check_client_working():
    """
    判断牛牛是否在运行
    :return:
    """
    try:
        pythoncom.CoInitialize()
        wmi = win32com.client.GetObject('winmgmts:')
        processCodeCov = wmi.ExecQuery('select * from Win32_Process where name=\"%s\"' % ('FTNN.exe'))
        if len(processCodeCov) > 0:
            return True
        else:
            return False

    except Exception as e:
        logger1.warning("判断牛牛进程是否还在运行失败{}".format(e))


global_app = [1]


def start_connect_nnq(start_tab):
    """
    启动客户端关联模块
    :param start_tab:
    指定模块("牛牛圈","资讯","消息"...)
    :return:
    window窗口信息
    """
    global global_app
    global flag
    nn_path = get_config("path", "nn")
    if not check_client_working():
        try:
            logger1.info("*启动富途牛牛app")
            app = Application(backend="uia").start(nn_path)
            global_app[0] = app
            ft_window = app.window(class_name="#32770", title="富途牛牛")
            ft_window.wait('ready', timeout=20, retry_interval=2)
            ft_window.maximize()
            ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
            nnq_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
            logger1.info("**打开{}tab".format(start_tab))
            nnq_ctrl.click_input()
            nnq_window = app.window(class_name='SOUIHOST', auto_id='0_0_LAYOUTncircle_main:')
            nnq_window.wait('ready', timeout=20, retry_interval=2)
            flag = False
        except Exception as e:
            logger1.warning("***打开{}tab失败,重试关联tab窗口{}".format(start_tab, e))
            ft_window = app.window(class_name="#32770", title="富途牛牛")
            ft_window.wait('ready', timeout=20, retry_interval=2)
            ft_window.maximize()
            ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
            nnq_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
            nnq_ctrl.click_input()
            nnq_window = app.window(class_name='SOUIHOST', auto_id='0_0_LAYOUT:ncircle_main')
            nnq_window.wait('ready', timeout=20, retry_interval=2)
            flag = False
    else:
        ft_window = global_app[0].window(class_name="#32770", title="富途牛牛")
        try:
            if not ft_window.exists():
                logger1.info("****app被关闭,重新启动富途牛牛app")
                app = Application(backend="uia").start(nn_path)
                global_app[0] = app
                ft_window = app.window(class_name="#32770", title="富途牛牛")
                ft_window.wait('ready', timeout=20, retry_interval=2)
                ft_window.maximize()
                ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
                nnq_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
                logger1.info("*****打开{}tab".format(start_tab))
                nnq_ctrl.click_input()
                nnq_window = app.window(class_name='SOUIHOST', auto_id='0_0_LAYOUT:ncircle_main')
                nnq_window.wait('ready', timeout=20, retry_interval=2)
                flag = False
            else:
                logger1.warning("******{}tab窗口已关闭,重新打开并关联".format(start_tab))
                ft_window = global_app[0].window(class_name="#32770", title="富途牛牛")
                ft_window.wait('ready', timeout=20, retry_interval=2)
                ft_window.maximize()
                ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
                nnq_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
                nnq_ctrl.click_input()
                nnq_window = global_app[0].window(class_name='SOUIHOST', auto_id='0_0_LAYOUT:ncircle_main')
                nnq_window.wait('ready', timeout=20, retry_interval=2)
                flag = False
        except Exception as e:
            logger1.warning("*******重新打开并关联失败{}".format(e))
    return nnq_window


def start_connect_zx(start_tab):
    """
    启动客户端关联模块
    :param start_tab:
    指定模块("牛牛圈","资讯","消息"...)
    :return:
    window窗口信息
    """
    global global_app
    global flag
    nn_path = get_config("path", "nn")
    if not check_client_working():
        try:
            logger1.info("*启动富途牛牛app")
            app = Application(backend="uia").start(nn_path)
            global_app[0] = app
            ft_window = app.window(class_name="#32770", title="富途牛牛")
            ft_window.wait('ready', timeout=20, retry_interval=2)
            ft_window.maximize()
            ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
            zx_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
            logger1.info("**打开{}tab".format(start_tab))
            zx_ctrl.click_input()
            zx_window = ft_window.children()[1]
            flag = False
        except Exception as e:
            logger1.warning("***打开{}tab失败,重试关联tab窗口{}".format(start_tab, e))
            ft_window = app.window(class_name="#32770", title="富途牛牛")
            ft_window.wait('ready', timeout=20, retry_interval=2)
            ft_window.maximize()
            ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
            zx_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
            zx_ctrl.click_input()
            zx_window = ft_window.children()[1]
            flag = False
    else:
        ft_window = global_app[0].window(class_name="#32770", title="富途牛牛")
        try:
            if not ft_window.exists():
                logger1.info("****app被关闭,重新启动富途牛牛app")
                app = Application(backend="uia").start(nn_path)
                global_app[0] = app
                ft_window = app.window(class_name="#32770", title="富途牛牛")
                ft_window.wait('ready', timeout=20, retry_interval=2)
                ft_window.maximize()
                ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
                zx_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
                logger1.info("*****打开{}tab".format(start_tab))
                zx_ctrl.click_input()
                zx_window = ft_window.children()[1]
                flag = False
            else:
                logger1.warning("******{}tab窗口已关闭,重新打开并关联".format(start_tab))
                ft_window = global_app[0].window(class_name="#32770", title="富途牛牛")
                ft_window.wait('ready', timeout=20, retry_interval=2)
                ft_window.maximize()
                ft_tab_ctrl = ft_window.children()[ft_window.children_texts().index('FTabCtrl')]
                zx_ctrl = ft_tab_ctrl.children()[ft_tab_ctrl.children_texts().index(start_tab)]
                zx_ctrl.click_input()
                zx_window = ft_window.children()[1]
                flag = False
        except Exception as e:
            logger1.warning("*******重新打开并关联失败{}".format(e))
    return zx_window


def choice_ctrl(window):
    """
    获取window下所有控件并选取任意一个
    :param window:
    window窗口信息(start_connect_app()返回的数据)
    :return:
    此窗口下面所有控件的一个列表
    """
    logger2.info("获取此窗口下面所有控件信息:[{}] ".format(window.get_properties()))
    ctrl_list = []

    def recursion(window):
        if len(window.children()) > 0:
            for i in window.children():
                if i.rectangle().left + 1 >= window.rectangle().left \
                        and i.rectangle().right <= window.rectangle().right \
                        and i.rectangle().top + 1 >= window.rectangle().top \
                        and i.rectangle().bottom <= window.rectangle().bottom:
                    ctrl_list.append(i)
                    recursion(i)

    recursion(window)
    return ctrl_list


def choice_order_execute(control_list):
    """

    :param control_list: 控件列表
    :return:
    """
    logger2.info("选取此窗口下面任意一个控件")
    ctrl = random.choice(control_list)
    proDir = os.path.split(os.path.realpath(__file__))[0]
    configPath = os.path.join(proDir, "config.cfg")
    path = os.path.abspath(configPath)
    cf = configparser.ConfigParser()
    cf.read(path, encoding="utf-8")
    orders = []
    for action in cf.items('order'):
        orders.append(list(action)[1])
    k = random.randint(1, len(orders))
    logger2.info("随机选取[{}]种动作对控件进行操作".format(k))
    for avtion in random.choices(orders, k=k):
        eval(avtion)(ctrl)
        time.sleep(0.5)

Action_command

# encoding=utf8
import random
from pywinauto import mouse
import logging
import time

logging.basicConfig(level=logging.INFO, filename="testlog.levellog", filemode="w",
                    format='%(asctime)s - %(name)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s')
logger1 = logging.getLogger("start_APP")
logger2 = logging.getLogger("action")


def click_ctrl(control):
    """
    左键点击
    :param control: 控件
    :return:
    """
    try:
        logger2.info("对此控件进行左键单击:[{}]".format(control.get_properties()))
        rect = control.rectangle()
        cx = int((rect.left + rect.right) / 2)
        cy = int((rect.top + rect.bottom) / 2)
        mouse.click(button='left', coords=(cx, cy))
    except Exception as e:
        logger1.warning("左键点击失败{}".format(e))


def double_click_ctrl(control):
    """
    左键双击命令
    :param control:控件
    :return:
    """
    try:
        logger2.info("对此控件进行左键双击:[{}]".format(control.get_properties()))
        rect = control.rectangle()
        cx = int((rect.left + rect.right) / 2)
        cy = int((rect.top + rect.bottom) / 2)
        mouse.double_click(button='left', coords=(cx, cy))
    except Exception as e:
        logger1.warning("左键双击失败{}".format(e))


def mouse_scroll(control):
    """
    鼠标任意滚动滚轮
    :param control:控件
    :return:
    """
    try:
        distance = random.choice(range(-10, 10))
        rect = control.rectangle()
        cx = int((rect.left + rect.right) / 2)
        cy = int((rect.top + rect.bottom) / 2)
        logger2.info("对此控件鼠标滚轮({}):[{}]".format(control.get_properties(), distance))
        mouse.scroll(coords=(cx, cy), wheel_dist=distance)
    except Exception as e:
        logger1.warning("鼠标滚动失败{}".format(e))


def mouse_press_release(control):
    """
    鼠标拖拽
    :param control:
    :return:
    """
    try:
        ccx = random.choice(range(0, 1910))
        ccy = random.choice(range(0, 1020))
        rect = control.rectangle()
        cx = int((rect.left + rect.right) / 2)
        cy = int((rect.top + rect.bottom) / 2)
        logger2.info("对此控件拖拽({},{}):[{}]".format(ccx, ccy, control.get_properties()))
        mouse.press(button='left', coords=(cx, cy))
        time.sleep(1)
        mouse.release(button='left', coords=(ccx, ccy))
    except Exception as e:
        logger1.warning("鼠标拖拽失败{}".format(e))


def right_click_ctrl(control):
    """
    右键点击
    :param control: 控件
    :return:
    """
    try:
        logger2.info("对此控件进行右键单击:[{}]".format(control.get_properties()))
        rect = control.rectangle()
        cx = int((rect.left + rect.right) / 2)
        cy = int((rect.top + rect.bottom) / 2)
        mouse.right_click(coords=(cx, cy))
    except Exception as e:
        logger1.warning("右键点击失败{}".format(e))


def keyboard_send_keys(control):
    """
    键盘输入
    :param control: 控件
    :return:
    """
    # if 'edit' in control.class_name().lower():
    try:
        control.type_keys('稳定性测试键盘输入')
        logger2.info("对此控件进行键盘输入:[{}]".format(control.get_properties()))
    except Exception as e:
        logger1.warning("键盘输入失败,不可输入控件{}".format(e))
# else:
#    logger2.info("此控件非edit,不进行键盘输入:[{}]".format(control.get_properties()))

# if __name__ == '__main__':
#     dfdf_main()

config.cfg

[order]
order1 : click_ctrl
order2 : double_click_ctrl
order3 : mouse_scroll
order4 : mouse_press_release
order5 : right_click_ctrl
order6 : keyboard_send_keys

[test_time]
#执行总时长
time : 24h
#单个视频录制时间
video_time : 300s
#遇到客户端退出时再多录制时间
more_time : 30s

[path]
#被测客户端安装位置
nn : C:\Program Files (x86)\FTNN\FTNN.exe

#录屏保存地址(安装的稳定性工具里的video文件地址)
video_address : D:\Usopp\python\StabilityTest\stability_test\video


[module]
#需执行的模块  牛牛圈、消息
module : 消息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值