#!/usr/bin/python # -*- coding: utf-8 -*- # --------------------------------------------------------------------------------------------------------- # Author : Ulrich Carmesin # Source : gitea.ucarmesin.de # --------------------------------------------------------------------------------------------------------- import os import traceback import basic.toolHandling import tools.data_tool import tools.job_const as J import tools.data_const as D import basic.constants as B import model.entity import tools.config_tool import tools.job_tool import tools.path_tool import tools.path_const as P import model.entity import model.story import model.datatable import model.step import model.factory import tools.file_type TABLE_NAMES = ["application", "ap_project", "ap_component"] STORAGES = [model.entity.STORAGE_FILE, model.entity.STORAGE_DB] """ used storage in priority sortage, so: if file then read_fcts / if db then select-fcts """ DEFAULT_SYNC = model.entity.SYNC_FULL_GIT2DB TABLE_NAME = B.SUBJECT_APP """ system-name for this entity """ FIELD_ID = "tcid" LIST_SUB_DESCRIPT = [D.DATA_ATTR_USECASE_DESCR, D.DATA_ATTR_STORY_DESCR] FILE_EXTENSION = D.DFILE_TYPE_YML UNIQUE_FIELDS = [D.FIELD_NAME] """ unique business field as human identifer """ IDENTIFYER_FIELDS = [FIELD_ID] """ unique technical field as technical identifer """ class Testcase(model.entity.Entity): """ Generally this object can be stored as a file with data or in a database. references: application -> story -> story variant -> comp.step subtables steps -> comp.step tables -> comp.table """ FIELD_ID = "tcid" LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_APP, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] LIST_NODES = [B.NODE_ATTRIBUTES] LIST_SUBTABLES = [B.SUBJECT_VARIANTS, B.SUBJECT_USECASES, B.SUBJECT_STORIES, B.SUBJECT_DATATABLES, B.SUBJECT_STEPS] tcid = "" name = "" description = "" project = "" reference = "" attributes = "" stories = {} tables = {} steps = {} def read_unique_names(self, job, project, application, gran, args, ttype: str=""): """ reads the entity-names from file-storage :param job: :param opt. project: select-criteria if used and defined :param opt. application: select-criteria if used and defined :param opt. gran: granularity values testcase / testsuite / testplan :param opt. args additional args :return: list of entity-names """ if project == "": project = getattr(job.par, B.SUBJECT_PROJECT) path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_TDATA], project, B.SUBJECT_TESTCASES) outList = self.getDirlist(job, path, "") return outList def read_entity(self, job, name): """ reads the entity from the file-system :param job: :param name: :return: """ # r = tools.config_tool.select_config_path(job, P.KEY_TESTCASE, "TC0001") # ttype=testcase => Aufteilung der Testspec in Bloecke und separater Aufruf zur Pruefung der Bloecke config = self.getConfig(job, P.KEY_TESTCASE, name, tools.config_tool.get_plain_filename(job, name), B.SUBJECT_TESTCASE) self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) return self @staticmethod def rebuild_data(job, data: dict) -> dict: """ gets the subtable-tag from filecsv and sets the subtables in order to workable entity-elements :param job: :param data: :return: """ data = tools.file_type.popSubjectsNode(job, data) # data = tools.file_type.popNameNode(job, data) data = Testcase.buildHeadAttributes(job, data, Testcase.LIST_FIELDS, Testcase.LIST_SUBTABLES) return data @staticmethod def buildHeadAttributes(job, data: dict, fields: list, subtables: list) -> dict: """ workaround for _head:attr resp _option:attr :param data: :param head: :return: """ outdata = {} attributes = {} subtable = {} xsubtable = {} try: for k in data: if k in [B.DATA_NODE_HEAD, B.DATA_NODE_OPTION]: if k not in outdata: outdata[k] = {} xkeys = [] for l in data[k]: a = l.split("-") val = data[k][l] if tools.data_tool.getPluralKeyword(a[0]) in B.LIST_SUBJECTS \ and tools.data_tool.getSingularKeyword(a[0]) in fields: outdata[tools.data_tool.getSingularKeyword(a[0])] = tools.data_tool.splitDelimitedValues(val)[0] elif tools.data_tool.getPluralKeyword(a[0]) in B.LIST_SUBJECTS \ and tools.data_tool.getPluralKeyword(a[0]) in subtables: xsubtable = Testcase.setSubtable(job, xsubtable, l, val, outdata) #outdata[tools.data_tool.getPluralKeyword(a[0])] = subtable elif k == B.DATA_NODE_OPTION: attributes[l] = data[k][l] else: outdata[k][l] = data[k][l] elif k in B.LIST_DATA_NODE and tools.data_tool.getPluralKeyword(k) in subtables: outdata[tools.data_tool.getPluralKeyword(k)] = data[k] else: outdata[k] = data[k] if len(outdata[B.DATA_NODE_OPTION]) == 0: outdata.pop(B.DATA_NODE_OPTION) if len(outdata[B.DATA_NODE_HEAD]) == 0: outdata.pop(B.DATA_NODE_HEAD) outdata[B.NODE_ATTRIBUTES] = attributes for k in xsubtable: if k == "xkeys": continue outdata[k] = xsubtable[k] except Exception as e: print(traceback.format_exc()) pass return outdata @staticmethod def setSubtable(job, xsubtable, key: str, val: str, data: dict): a = key.split("-") if tools.data_tool.getPluralKeyword(a[0]) not in xsubtable: xkeys = [] subtable = {} for x in tools.data_tool.splitDelimitedValues(val): if x == "" or x[:1] == "#": break subtable[x] = {D.FIELD_NAME: x} xkeys.append(x) else: subtable = xsubtable[tools.data_tool.getPluralKeyword(a[0])] i = 0 vals = tools.data_tool.splitDelimitedValues(val) xkeys = xsubtable["xkeys"] for x in xkeys: subtable[x][a[1]] = vals[i] i += 1 xsubtable["xkeys"] = xkeys xsubtable[tools.data_tool.getPluralKeyword(a[0])] = subtable return xsubtable @staticmethod def check_data(job, data: dict) -> dict: checkNodes = {} checkNodes[tools.file_type.MUST_NODES] = [B.SUBJECT_APP, B.SUBJECT_DATATABLES, B.SUBJECT_STEPS, B.SUBJECT_VARIANTS, B.NODE_ATTRIBUTES] checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_OPTION, B.DATA_NODE_DATA, B.DATA_NODE_FIELDS, B.DATA_NODE_HEADER] checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_USECASES, B.SUBJECT_STORIES] return tools.file_type.check_nodes(job, data, checkNodes) def select_entity(self, job, name): """ reads the entity from the database it should get the same result like read_entity :param job: :param name: :return: """ return self.read_entity(job, name) def select_testcase(job, project, testcase): """ to select a concrete testcase :param job: :param project: :param testcase: :return: """ jobProj = None if hasattr(job.par, B.PAR_PROJ): jobProj = getattr(job.par, B.PAR_PROJ) setattr(job.par, B.PAR_PROJ, project) path = tools.path_tool.compose_path(job, P.P_TDROOT, None) specpath = os.path.join(path, testcase, D.DFILE_TESTCASE_NAME + ".csv") spec = model.entity.read_spec(job, testcase, J.GRAN_TS, specpath) if jobProj is None: delattr(job.par, B.PAR_PROJ) else: setattr(job.par, B.PAR_PROJ, jobProj) print("select_testcase "+str(spec)) return spec def select_testcases(job, projList, appList): out = {} jobProj = None if hasattr(job.par, B.PAR_PROJ): jobProj = getattr(job.par, B.PAR_PROJ) for proj in projList: setattr(job.par, B.PAR_PROJ, proj) path = tools.path_tool.compose_path(job, P.P_TDROOT, None) if os.path.exists(path): for d in os.listdir(path): if not os.path.isdir(os.path.join(path, d)): continue if d[0:1] == "_": continue specpath = os.path.join(path, d, D.DFILE_TESTCASE_NAME + ".csv") spec = model.entity.read_spec(job, d, J.GRAN_TS, specpath) if spec is None: continue out[d] = spec out[d][B.SUBJECT_PROJECTS] = [proj] if jobProj is None: delattr(job.par, B.PAR_PROJ) else: setattr(job.par, B.PAR_PROJ, jobProj) return out