| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 | #-*- coding:utf-8 -*-import os, sys, timeimport xlrdimport xlwtimport sqlite3import jsonfrom ssat_sdk.picture.feature_detect import FeatureDetectfrom ssat_sdk.utils import LoggingUtilfrom ssat_sdk.picture import image_util class CExcelData():    def __init__(self):        # 编号;        self.num = 0        # 类型;        self.type = ''        # 控件id;        self.ctrlid = ''        # 类型描述;        self.desc = ''        # 类型事件;        self.event = ''        # 类型参数;        self.params = ''        # 类型结果;        self.typeresult = ''        # 事件结果;        self.eventresult = ''        def getdata(self, data):        if data is not None:            self.num, self.type, self.ctrlid, self.desc, self.event, self.params, self.typeresult, self.eventresult = tuple(data)    #end-fun    def tolist(self):        return [self.num, self.type, self.ctrlid, self.desc, self.event, self.params, self.typeresult, self.eventresult]    #end-funclass CImgView():    def __init__(self):        # 图元id;        self.id = ''        # 图元名称;        self.name = ''        # 图元类型:按钮、滑块        self.type = ''        # 图元领空区域;        self.airspace = []        # 图元未选时图标区域;        self.iconarea = []        # 图元未选时文本区域;        self.textarea = []        # 图元未选时文本内容;        self.textcontent = ''        # 图元未选时图标内容:使用路径;        self.iconcontent = ''        # 图元选中时图标区域;        self.iconarea2 = []        # 图元选中时文本区域;        self.textarea2 = []        # 图元选中时的文件内容;        self.textcontent2 = ''        # 图元选中时的图标内容;        self.iconcontent2 = ''        # 展开键;        self.openkey = ''        # 返回键;        self.returnkey = ''        # 弹出键;        self.popkey = ''        # 图元所属图区id;        self.areaid = 0        # 图元关联图区id;        self.nextareaid = 0        def getdata(self,data):        self.id = data[0]        self.name = data[1]        self.type = data[2]        self.airspace = [] if data[3] is None else json.loads(data[3])        self.iconarea = [] if data[4] is None else json.loads(data[4])        self.textarea = [] if data[5] is None else json.loads(data[5])        self.textcontent = data[6]        self.iconcontent = data[7]        self.iconarea2 = data[8]        self.textarea2 = data[9]        self.textcontent2 = data[10]        self.iconcontent2 = data[11]        self.openkey = data[12]        self.returnkey = data[13]        self.popkey = data[14]        self.areaid = data[15]        self.nextareaid = data[16]class CImgArea():    def __init__(self):        self.id = ''        self.name = ''        self.isroot = False        self.popkey = ''        self.returnkey = ''        self.examplepic = ''        self.coodinate = []        self.bgproperty = ''        self.uidtype = ''        self.uidcontent = ''        self.uidarea = []        self.layouttype = ''        self.direction = ''        self.method = ''        self.refcoordFocusArea = []        self.refcoordIconArea = []        self.refcoordTextArea = []        self.methodParam = {}        self.layoutParam = {}        self.ocrParam = []        def getdata(self, data):        self.id = data[0]        self.name = data[1]        self.isroot = data[2]        self.popkey = data[3]        self.returnkey = data[4]        self.examplepic = data[5]        self.coodinate = [] if data[6] is None else json.loads(data[6])        self.bgproperty = data[7]        self.uidtype = data[8]        self.uidcontent = data[9]        self.uidarea = data[10]        self.layouttype = data[11]        self.direction = data[12]        self.method = data[13]        self.refcoordFocusArea = [] if data[14] is None else json.loads(data[14])        self.refcoordIconArea = [] if data[15] is None else json.loads(data[15])        self.refcoordTextArea = [] if data[16] is None else json.loads(data[16])        self.methodParam = {} if data[17] is None else json.loads(data[17])        self.layoutParam = {} if data[18] is None else json.loads(data[18])        self.ocrParam = [] if data[19] is None else json.loads(data[19])    #end-funclass CParameters():    def __init__(self):        self.id = 0        self.areaid = 0        self.method = ''        self.params = ''        def getdata(self,data):        self.id = data[0]        self.areaid = data[1]        self.method = data[2]        self.params = data[3]        if self.method == u'全局二值化':            print(u'全局二值化')        elif self.method == u'局部二值化':            pass        elif self.method == u'方差二值化':            pass        elif self.method == u'模板匹配':            pass        elif self.method == u'形状匹配':            pass    #end-funclass CExecutor():    def __init__(self, xls_path, db_path):        # db连接对象;        self.conn = None        # 游标;        self.cursor = None        # excel路径;        self.xls_path = xls_path        # db路径;        self.db_path = db_path        # excel数据;        self.xls_data = []        # 识别类对象;        self.feature = FeatureDetect()    #end-fun        def read_excel(self, path = None):        if path is None:            path = self.xls_path        #end-if        # 打开文件;        wb = xlrd.open_workbook(filename=path)        if wb is None:            return        #通过索引获取表格;        sheet1 = wb.sheet_by_index(0)        for i in range(1, sheet1.nrows):            # 获取行内容;            rows = sheet1.row_values(i)            data = CExcelData()            data.getdata(rows)            self.xls_data.append(data)        #end-for    #end-fun    def get_conn(self, path = None):        if path is None:            path = self.db_path        #end-if        if os.path.exists(path) and os.path.isfile(path) :            self.conn = sqlite3.connect(path)        #end-if    #end-fun    def get_cursor(self) :        if self.conn is not None:            self.cursor = self.conn.cursor()        else:            self.cursor = self.get_conn().cursor()    #end-fun    def fetchone(self, sql, data) :        if self.conn is None:            return        if sql is not None and sql != '' :            if data is not None :                #Do this instead                d = (data, )                cu = self.cursor                cu.execute(sql, d)                rec = cu.fetchall()                return rec            else:                print('the [{}] equal None!'.format(data))                return None        else:            print('the [{}] is empty or equal None!'.format(sql))            return None    #end-fun    def getImgViewData(self,id):        sql = "SELECT ImgView.Id,"\        "ImgView.Name,"\        "ImgView.Type,"\        "ImgView.AirspaceArea,"\        "ImgView.IconArea,"\        "ImgView.TextArea,"\        "ImgView.TextContent,"\        "ImgView.IconContent,"\        "ImgView.IconArea2,"\        "ImgView.TextArea2,"\        "ImgView.TextContent2,"\        "ImgView.IconContent2,"\        "ImgView.OpenKey,"\        "ImgView.ReturnKey,"\        "ImgView.PopKey,"\        "ImgView.AreaId,"\        "ImgView.NextAreaId "\        "FROM ImgView WHERE id = ?"        # 获取记录集;        record = self.fetchone(sql, id)         data = CImgView()        if record is not None:            if len(record) > 0:                data.getdata(record[0])                return data        return None    #end-fun    def getImgAreaData(self, id):        sql = "SELECT ImgArea.Id,"\        "ImgArea.Name,"\        "ImgArea.IsRoot,"\        "ImgArea.PopKey,"\        "ImgArea.ReturnKey,"\        "ImgArea.ExamplePicture,"\        "ImgArea.Coordinate,"\        "ImgArea.BackgroundProperties,"\        "ImgArea.UIdType,"\        "ImgArea.UIdContent,"\        "ImgArea.UIdArea,"\        "ImgArea.LayoutType,"\        "ImgArea.Direction,"\        "ImgArea.Method,"\        "ImgArea.refcoordFocusArea,"\        "ImgArea.refcoordIconArea,"\        "ImgArea.refcoordTextArea,"\        "ImgArea.MethodParam,"\        "ImgArea.LayoutParam,"\        "ImgArea.OCRParam "\        "FROM ImgArea WHERE id = ?"        # 获取记录集;        record = self.fetchone(sql, id)         data = CImgArea()        if record is not None:            if len(record) > 0:                data.getdata(record[0])                return data        return None    #end-fun    def getParameters(self, areaid):        sql = "SELECT Parameter.Id,"\        "Parameter.AreaId,"\        "Parameter.Method,"\        "Parameter.Parameters "\        "FROM Parameter WHERE AreaId = ?"        # 获取记录集;        record = self.fetchone(sql, areaid)         data = CParameters()        if record is not None:            if len(record) > 0:                data.getdata(record[0])                return data        return None    #end-fun    # 1、找到加返回True,否则False    # 2、返回当前焦点坐标;    def doVerifyOnTargetCtrl(self, pel_data, map_data):        # 截图,原图路径;        screenshot = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "TVShot_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")        self.feature.vp.takePicture(screenshot)        # 根据方法分类执行;        if map_data.method == u"全局二值化":            contour = self.feature.getGrayBinaryContour(screenshot,                                                         map_data.coodinate,                                                         map_data.methodParam['gray'],                                                         255,                                                         map_data.methodParam['inside'],                                                         map_data.methodParam['min-peri'],                                                        map_data.methodParam['max-peri'],                                                        map_data.methodParam['min-area'],                                                        map_data.methodParam['max-area'],)            # 是否找到轮廓;            if contour is None:                return False, [], screenshot                        # 获取文本坐标;            textbox = self.feature.getObjAbsoluteBox(contour, map_data.refcoordFocusArea, map_data.refcoordTextArea)            # ocr识别;            ocrImgPath = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "OCR_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")            image_util.saveCropPic(screenshot, ocrImgPath, textbox)            result, text = self.feature.OCR.findPicStr(pel_data.textcontent, ocrImgPath, map_data.ocrParam[0], map_data.ocrParam[1], map_data.ocrParam[2])            # 返回结果;            return result, contour, screenshot        elif map_data.method == u"局部二值化":            pass        elif map_data.method == u"方差二值化":            pass        elif map_data.method == u"模板匹配":            # 模板匹配函数需要改造;            setting = {'method': 5, 'colorType': 0, 'thresholdVal': 0, 'thresholdMaxVal': 255, 'matchVal': map_data.methodParam['match'] }            match_result = self.feature.matchSingleImage(screenshot, map_data.coodinate, map_data.methodParam['tempdir'], setting)            if match_result is None:                return False, [], screenshot            else:                # 获取文本坐标;                textbox = self.feature.getObjAbsoluteBox(match_result['coordinate'], map_data.refcoordFocusArea, map_data.refcoordTextArea)                # ocr识别;                ocrImgPath = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "OCR_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")                image_util.saveCropPic(screenshot, ocrImgPath, textbox)                result, text = self.feature.OCR.findPicStr(pel_data.textcontent, ocrImgPath, map_data.ocrParam[0], map_data.ocrParam[1], map_data.ocrParam[2])                # 返回结果;                return result, match_result['coordinate'], screenshot        elif map_data.method == u"形状匹配":            pass        # 不存在的方法,直接返回False;        return False, [], screenshot    #end-fun    # 判断是否在目标图区上;    # 根据唯一标识内容来判断;    def doVerifyOnTargetMapArea(self, map_data):        result, coodr = False, []        # 截图,原图路径;        screenshot = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "TVShot_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")        self.feature.vp.takePicture(screenshot)        if map_data.uidtype == u"图标":            # 模板匹配函数需要改造;            setting = {'method': 5, 'colorType': 0, 'thresholdVal': 0, 'thresholdMaxVal': 255, 'matchVal': map_data.methodParam['match'] }            match_result = self.feature.matchSingleImage(screenshot, map_data.coodinate, map_data.methodParam['tempdir'], setting)            if match_result is None:                return False, [], screenshot            else:                return True, match_result['coordinate'], screenshot        elif map_data.uidtype == u"文本":            pass        elif map_data.uidtype == u"颜色":            pass        elif map_data.uidtype == u"轮廓":            pass        elif map_data.uidtype == u"形状":            pass        elif map_data.uidtype == u"":            pass         # 返回结果;        return result, coodr, screenshot    # 执行事件;    def doCtrlEvent(self, xls_data, pel_data, map_data):        # 执行前截图分析;        screenshot = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "TVShot_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")        self.feature.vp.takePicture(screenshot)        # 类型判断;        if pel_data.type == u"滑块":            if xls_data.event == u"编辑":                if map_data.layouttype == u"图独":                    # 获取文本坐标;                    textbox = self.feature.getObjAbsoluteBox(map_data.coodinate, map_data.refcoordFocusArea, map_data.refcoordTextArea)                    # ocr识别;                    ocrImgPath = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "OCR_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")                    image_util.saveCropPic(screenshot, ocrImgPath, textbox)                    text = self.feature.OCR.getStrWithImgProcess(ocrImgPath, map_data.ocrParam[2], map_data.ocrParam[0], map_data.ocrParam[1])                    if text is not None and text is not '':                        count = int(xls_data.params) - int(text)                         if count > 0:                            self.feature.redRat3.sendKey('right', count, 0.1)                        elif count < 0:                            self.feature.redRat3.sendKey('left', abs(count), 0.1)                        # 执行后截图分析;                        screenshot = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "TVShot_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")                        self.feature.vp.takePicture(screenshot)                        # 验证结果是否正确;# ocr识别;                        ocrImgPath = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "OCR_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")                        image_util.saveCropPic(screenshot, ocrImgPath, textbox)                        text = self.feature.OCR.getStrWithImgProcess(ocrImgPath, map_data.ocrParam[2], map_data.ocrParam[0], map_data.ocrParam[1])                        if text is not None and text is not '':                            if int(xls_data.params) == int(text):                                return True, textbox, screenshot                                                return False, textbox, screenshot                    else:                        print('ocr convert error!')                        return False, textbox, screenshot                #end-if            elif xls_data.event == u"单击":                self.feature.redRat3.sendKey(pel_data.openkey)                # 是否成功进入关联图区;            elif xls_data.event == u"返回":                self.feature.redRat3.sendKey(pel_data.returnkey)                # 是否成功返回上层图区;            elif xls_data.event == u"弹出":                self.feature.redRat3.sendKey(pel_data.popkey)                # 是否成功弹出某图区;            #end-if        elif pel_data.type == u"按钮":            if xls_data.event == u"单击":                self.feature.redRat3.sendKey(pel_data.openkey)                # 是否成功进入关联图区;            elif xls_data.event == u"返回":                self.feature.redRat3.sendKey(pel_data.returnkey)                # 是否成功返回上层图区;            elif xls_data.event == u"弹出":                self.feature.redRat3.sendKey(pel_data.popkey)                # 是否成功弹出某图区;        elif pel_data.type == u"编辑框":            pass                # 默认返回True;        return True, [], screenshot    #end-fun    # 根据布局方式,到达目标控件;    def doMove2TargetCtrl(self, pel_data, map_data):        print pel_data.id, pel_data.name, pel_data.areaid, map_data.id, map_data.name        key, result, curbox, lastbox, screenshot = '', False, [], [], ''        if map_data.layouttype == u"网格":            pass        elif map_data.layouttype == u"纵向列表":            # 开始位置;用于循环列表;            beginbox = []            # 默认遍历方向;            key = 'down'            # 遍历计数;            count = 0            # 是否逆序遍历;            isAdverse = False            while True:                result, curbox, screenshot = self.doVerifyOnTargetCtrl(pel_data, map_data)                # 找到目标焦点;                if result is True:                    break                               # 正序遍历;                if isAdverse is False:                    # 当前焦点框与上次焦点框相同,认为到达边界端;                    if curbox == lastbox:                        key = 'up'#改变寻路方向;                        # 标记已开始逆序                        isAdverse = True                        # 根据count计数,直接返回原本位置;                        self.feature.redRat3.sendKey(key,count,0.2)                                        # 循环列表完成一次遍历回到beginbox;                    if curbox == beginbox:                        break                else:                    # 已逆序,且再次到达另一边界端;                    if curbox == lastbox:                        break                                # 记录起始位置;                if beginbox == []:                    beginbox = curbox                                # 记录本次位置;                lastbox = curbox                # 下一位置;                self.feature.redRat3.sendKey(key)            #end-while        elif map_data.layouttype == u"横向列表":            # 开始位置;用于循环列表;            beginbox = []            # 默认遍历方向;            key = 'right'            # 遍历计数;            count = 0            # 是否逆序遍历;            isAdverse = False            while True:                result, curbox, screenshot = self.doVerifyOnTargetCtrl(pel_data, map_data)                # 找到目标焦点;                if result is True:                    break                # 正序遍历;                if isAdverse is False:                    # 当前焦点框与上次焦点框相同,认为到达边界端;                    if curbox == lastbox:                        key = 'left'  # 改变寻路方向;                        # 标记已开始逆序                        isAdverse = True                        # 根据count计数,直接返回原本位置;                        self.feature.redRat3.sendKey(key, count, 0.2)                    # 循环列表完成一次遍历回到beginbox;                    if curbox == beginbox:                        break                else:                    # 已逆序,且再次到达另一边界端;                    if curbox == lastbox:                        break                # 记录起始位置;                if beginbox == []:                    beginbox = curbox                # 记录本次位置;                lastbox = curbox                # 下一位置;                self.feature.redRat3.sendKey(key)            # end-while        elif map_data.layouttype == u"标签列表":            pass        elif map_data.layouttype == u"图独":            return True, [], screenshot        # 返回结果以及坐标;        return result, curbox, screenshot    #end-fun    # 结果比较;    def doResultComparison(self, row, xls_data):        result, desc = True, ''        # 解析json为字典;        try:            data = json.loads(row.params)        except Exception, e:            data = {}            desc = str(e)        if data is None or data == {}:            return False, u'Json参数解析出错=%s'%('数据有误' if desc == '' else desc)        # 根据描述选择方法;        if row.event == u"示例":            # [{"num":13},{"num":8}]            param1 = data[0]            param2 = data[1]            # 解析对应的参数;            for r in xls_data:                if r.num == param1['num']:                    param1["data"] = r.eventresult                if r.num == param2['num']:                    param2['data'] = r.eventresult            #end-for            print param1,param2        elif row.event == u"明暗对比":            pass        elif row.event == u"":            pass        elif row.event == u"":            pass        elif row.event == u"":            pass        elif row.event == u"":            pass        elif row.event == u"":            pass        elif row.event == u"":            pass        elif row.event == u"":            pass                # 默认返回值;        return result, desc    #end-fun        # 保存结果;    def doSaveResult(self, xls_data, save_path):        # 创建工作簿;        book = xlwt.Workbook()        # 创建sheet;        sheet = book.add_sheet(u'result', cell_overwrite_ok=True)        # 创建标题行;        row0 = [u'编号',u'类型', u'控件ID',u'描述',u'事件',u'事件参数',u'类型结果',u'事件结果']        for i in range(len(row0)):            sheet.write(0, i, row0[i], style = xlwt.XFStyle())                index = 1        # 写入其他数据;        for row in xls_data:            l = row.tolist()            for j in range(len(l)):                sheet.write(index, j, l[j], style = xlwt.XFStyle())            index += 1        #end-for        # 保存xls;        book.save(save_path)    #end-fun    def run(self):        # 读取xls        self.read_excel()        # 打开数据库;        self.get_conn()        # 获取游标;        self.get_cursor()                # 遍历excel数据;        for row in self.xls_data:            if row.type == u'控件操作':                # 获取图元信息;                pel_data = self.getImgViewData(row.ctrlid)                if pel_data is not None:                    # 获取图元图区信息;                    map_data = self.getImgAreaData(pel_data.areaid)                    print pel_data, map_data, row                    if map_data is not None:                        # 执行弹出按键;                        # 注:如果多个控件连续且都在同一个根图区时,多次执行会出问题,需完善这里的判断机制;                        if map_data.isroot == 1:                            if self.doVerifyOnTargetMapArea(map_data)[0] is False:                                self.feature.redRat3.sendKey(map_data.popkey)                                self.feature.redRat3.sendKey('down')                        # 到达目标图元;                        result, coodr, screenshot = self.doMove2TargetCtrl(pel_data, map_data)                        # 结果;                        row.typeresult = u'{"结果":%s, "坐标":%s, "图像":%s}'%('True' if result is True else 'False', str(coodr), screenshot)                        if result is True:                            # 执行图元事件;                            result, coodr, screenshot = self.doCtrlEvent(row, pel_data, map_data)                            row.eventresult = u'{"结果":%s, "坐标":%s, "图像":%s}'%('True' if result is True else 'False', str(coodr), screenshot)                        else:                            print("unable find target ctrl")                            break                    else:                        print('map data is none')                        break                else:                    print('pel data is none')                    break                #end-if            elif row.type == u'结果比较':                result, desc = self.doResultComparison(row, self.xls_data)                row.eventresult = u'{"结果":%s, "描述":%s}'%('True' if result is True else 'False', desc)            elif row.type == u"截屏":                # 默认截屏一张;                screenshot = os.path.join(LoggingUtil.getCaseRunLogDirPath(), "TVShot_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".png")                self.feature.vp.takePicture(screenshot)                row.typeresult = screenshot        #end-for        # 保存结果;        self.doSaveResult(self.xls_data, r'D:\result.xls')    #end-funif __name__ == "__main__":    executor = CExecutor(r'F:\scbc-sat\command.xlsx', r'F:\scbc-sat\ui.db')    executor.run()
 |