#!/usr/bin/python # -*- coding: utf-8 -*- # --------------------------------------------------------------------------------------------------------- # Author : Ulrich Carmesin # Source : gitea.ucarmesin.de # --------------------------------------------------------------------------------------------------------- import os import basic.toolHandling 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" FIELD_NAME = D.FIELD_NAME FIELD_DESCRIPTION = B.SUBJECT_DESCRIPTION FIELD_REFERENCE = B.SUBJECT_REFERENCE FIELD_PROJECT = B.SUBJECT_PROJECT FIELD_APPLICATION = B.SUBJECT_APP LIST_FIELDS = [FIELD_ID, FIELD_NAME, FIELD_DESCRIPTION, FIELD_REFERENCE, FIELD_PROJECT] """ list of object-attributes """ LIST_NODES = [B.NODE_ATTRIBUTES] SUB_USECASE = B.SUBJECT_USECASES SUB_STORIES = B.SUBJECT_STORIES SUB_STEPS = "steps" SUB_TABLES = "tables" LIST_SUBTABLES = { # with additional attributes for the subtable B.SUBJECT_APPS: [], SUB_TABLES: [D.DATA_ATTR_DATE], SUB_STEPS: [], SUB_USECASE: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE], SUB_STORIES: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE] } LIST_SUB_DESCRIPT = [D.DATA_ATTR_USECASE_DESCR, D.DATA_ATTR_STORY_DESCR] FILE_EXTENSION = D.DFILE_TYPE_YML UNIQUE_FIELDS = [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_APPS, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] LIST_NODES = [B.NODE_ATTRIBUTES] tcid = "" name = "" description = "" project = "" reference = "" attributes = "" stories = {} tables = {} steps = {} def __init__(self, job, project, name=""): """ to be initialized by readSpec :param job: """ self.job = job if len(project) > 1: self.project = project if len(name) > 1: self.name = name self.read_entity(job, name) def read_unique_names(self, job, project, application, gran, args): """ 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, LIST_FIELDS, LIST_NODES, LIST_SUBTABLES) return self @staticmethod def rebuild_data(job, tdata: dict) -> dict: """ gets the subtable-tag from filecsv and sets the subtables in order to workable entity-elements :param job: :param tdata: :return: """ outData = {} subtables = {} arguments = {} for k in tdata: if k in [B.DATA_NODE_TABLES]: outData[k[1:]] = tdata[k] elif k in [B.DATA_NODE_OPTION, "_head"]: outData[k[1:]] = {} for e in tdata[k]: ka = str(e).split("-") if ka[0] in B.LIST_SUBJECTS: # not necceassary, because here are single-names with fieldname ka[0] = ka[0][:-1] if len(ka) == 1: # add reference name to potential subtable ka.append("name") if ka[0]+"s" in B.LIST_SUBJECTS: # standard table form: step: { _header: [], _data: [{}, {}, ..] } if ka[0] in subtables: subject = subtables[ka[0]] sublist = subject[B.DATA_NODE_DATA] header = subject[B.DATA_NODE_HEADER] else: enty = model.factory.get_entity_object(job, ka[0], {}) header = enty.getFieldList() + enty.getNodeList() sublist = [] subject = {} subject[B.DATA_NODE_DATA] = sublist subject[B.DATA_NODE_HEADER] = header #subtables[ka[0]] string = str(tdata[k][e]) values = str(tdata[k][e]).split(D.INTERNAL_DELIMITER) i = 0 for v in values: if len(v) < 1: continue if len(sublist) > i: subtable = sublist[i] else: subtable = {} sublist.append(subtable) subtable[ka[1]] = v sublist[i] = subtable i += 1 subject[B.DATA_NODE_DATA] = sublist subtables[ka[0]] = subject else: # attributes arguments[e] = tdata[k][e] elif k in B.SUBJECT_STORY: outData[B.SUBJECT_STORIES] = tdata[k] elif k in B.LIST_SUBJECTS: outData[k] = tdata[k] elif k in B.LIST_DATA_NODE: outData[k[1:]] = tdata[k] elif k[1:] in Testcase.LIST_FIELDS: outData[k[1:]] = tdata[k] else: raise Exception("unknown tag in csv-data: "+k) for s in subtables: outData[s] = subtables[s] outData[B.NODE_ATTRIBUTES] = arguments return outData @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.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 getFieldList(self): """ returns a list of scalar attributes :return: LIST_FIELDS """ return LIST_FIELDS def getNodeList(self): """ returns a list of sub-nodes - which can be persisted in a clob-field :return: LIST_NODES """ return LIST_NODES def getSubtableList(self): """ returns a list of sub-tables :return: LIST_SUBTABLES """ return LIST_SUBTABLES def getName(self): """ returns the name - maybe build from other attributes :return: """ return self.name def getIDName(self): """ it returns the name as unique-id - maybe build from few attributes :return: """ return self.name def xxread_entity(self, job, name): """ reads the entity from the file-system :param job: :param name: :return: """ pathname = tools.config_tool.select_config_path(job, P.KEY_TESTCASE, name, "") print(pathname) (fname, ext) = os.path.splitext(pathname) fi = basic.toolHandling.getFileTool(job, None, ext[1:]) tdata = fi.load_file(pathname, ttype=D.CSV_SPECTYPE_DATA) stories = [] docs = [] attributes = {} pass if B.DATA_NODE_HEAD in tdata: for h in D.LIST_HEAD_ATTR: if h in tdata[B.DATA_NODE_HEAD]: setattr(self, h, tdata[B.DATA_NODE_HEAD][h]) else: job.m.logWarn("Keine Head-Daten in Testcase "+name) if B.DATA_NODE_OPTION in tdata: for o in tdata[B.DATA_NODE_OPTION]: if o in [D.OPT_ATTR_UCID, D.OPT_ATTR_USECASE]: pass elif o in [D.OPT_ATTR_STORYID, D.OPT_ATTR_STORY]: if len(stories) < 1: story = model.story.Story(job) stories.append(story) else: story = stories[0] setattr(story, model.story.FIELDS[o], tdata[B.DATA_NODE_OPTION][o]) elif o in D.LIST_OPT_ATTR: setattr(self, o, tdata[B.DATA_NODE_OPTION][o]) else: attributes[o] = tdata[B.DATA_NODE_OPTION][o] else: job.m.logWarn("Keine Option-Daten in Testcase "+name) if len(attributes) > 0: self.attributes = attributes if len(stories) > 0: self.story = stories pass if B.DATA_NODE_STEPS in tdata: for s in tdata[B.DATA_NODE_STEPS]: if s in B.LIST_DATA_NODE: continue step = model.step.Step(job, project=job.par.project, name=s) pass if B.DATA_NODE_TABLES in tdata: for t in tdata[B.DATA_NODE_TABLES]: table = model.datatable.Datatable(job, project=job.par.project, name=t) pass # for o in tdata[B.option # header = tdata[B.DATA_NODE_STEPS][] LIST # reference # # for t in tdata[B.tables #raise Exception(B.EXCEPT_NOT_IMPLEMENT) 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: """ raise Exception(B.EXCEPT_NOT_IMPLEMENT) 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