Compare commits
	
		
			74 Commits 
		
	
	
	
				 211 changed files with 14193 additions and 5318 deletions
			
			
		| @ -1,6 +0,0 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project version="4"> | |||
|   <component name="VcsDirectoryMappings"> | |||
|     <mapping directory="$PROJECT_DIR$" vcs="Git" /> | |||
|   </component> | |||
| </project> | |||
| @ -0,0 +1,133 @@ | |||
| import os.path | |||
| import re | |||
| 
 | |||
| import basic.component | |||
| import basic.constants as B | |||
| import basic.toolHandling | |||
| import tools.config_tool | |||
| import tools.data_const as D | |||
| import tools.file_tool | |||
| import tools.filecsv_fcts | |||
| import model.table | |||
| import model.factory | |||
| import tools.value_tool | |||
| import tools.data_tool | |||
| 
 | |||
| COMP_NAME = B.ATTR_INST_TESTSERVER | |||
| 
 | |||
| # class Testserver(basic.component.Component): | |||
| class Testserver: | |||
|     """ | |||
|     the Testserver represents the workspace with all resources for the automation | |||
| 
 | |||
|     """ | |||
|     tables = {} | |||
|     __instance = None | |||
|     __writeDB = True | |||
| 
 | |||
|     def __init__(self, job): | |||
|         """ | |||
|         collect all resources into this object | |||
|         :param job: | |||
|         """ | |||
|         print('init '+COMP_NAME) | |||
|         self.m = job.m | |||
|         self.conf = {} | |||
|         if B.TOPIC_NODE_DB in job.conf: | |||
|             self.conf[B.TOPIC_CONN] = {} | |||
|             self.conf[B.TOPIC_CONN][B.TOPIC_NODE_DB] = {} | |||
|             for attr in B.LIST_DB_ATTR: | |||
|                 if attr in job.conf[B.TOPIC_NODE_DB]: | |||
|                     self.conf[B.TOPIC_CONN][B.TOPIC_NODE_DB][attr] = job.conf[B.TOPIC_NODE_DB][attr] | |||
|         # TODO was muss auf dem Testserver initial geladen werden? | |||
|         self.model = {} | |||
|         Testserver.__instance = self | |||
|         for s in B.LIST_SUBJECTS: | |||
|             self.model[tools.data_tool.getSingularKeyword(s)] = model.factory.get_entity_object(job, s, {}) | |||
|         pass | |||
| 
 | |||
|     @staticmethod | |||
|     def getInstance(job): | |||
|         if Testserver.__instance == None: | |||
|             return Testserver(job) | |||
| 
 | |||
| 
 | |||
|     def createAdminDBTables(self, job): | |||
|         """ | |||
|         creates the complete data-model in the database. it contains: | |||
|         * the model for administration | |||
|         * the model of each project: | |||
|         * * root-tables - defined in testcases TODO wie allgemein deklariert, special components/config | |||
|         * * comp-artifacts - it could contain build-rules for building from testcase-spec | |||
|         :param job: | |||
|         :return: | |||
|         """ | |||
|         tables = {} | |||
|         if B.TOPIC_NODE_DB in job.conf: | |||
|             self.dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) | |||
|         else: | |||
|             return "No DB in job-config" | |||
|         # the model for administration | |||
|         for m in self.model.keys(): | |||
|             print("\n==== model " + m) | |||
|             self.createDBTable(job, B.ATTR_INST_TESTSERVER, B.ATTR_INST_TESTSERVER, m) | |||
|             enty = self.model[m] | |||
|             for t in enty.getSubtableNames(): | |||
|                 print("subtable "+t) | |||
|                 self.createDBTable(job, B.ATTR_INST_TESTSERVER, B.ATTR_INST_TESTSERVER, t) | |||
| 
 | |||
|     def createProjectDBTables(self, job): | |||
|         """ | |||
|         creates the complete data-model in the database. it contains: | |||
|         * the model for administration | |||
|         * the model of each project: | |||
|         * * root-tables - defined in testcases TODO wie allgemein deklariert, special components/config | |||
|         * * comp-artifacts - it could contain build-rules for building from testcase-spec | |||
|         :param job: | |||
|         :return: | |||
|         """ | |||
|         tables = {} | |||
| 
 | |||
|         path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_PROGRAM], "model") | |||
|         fct = basic.toolHandling.getFileTool(job, None, "csv") | |||
|         for m in sorted(os.listdir(path)): | |||
|             if not re.match(r".*?\.csv", m): | |||
|                 print("sonstig "+m) | |||
|                 continue | |||
|             print("model "+m) | |||
|             modelPath = os.path.join(path, m) | |||
|             modelDoc = fct.load_file(modelPath, D.CSV_SPECTYPE_DATA) | |||
|             table = model.table.Table(job, project="", application="", component=COMP_NAME, name=m[:-4]) | |||
|             sql = table.get_schema(tableName=m[:-4], tableObject=table)  # [B.DATA_NODE_TABLES][m[:-4]] | |||
|             job.m.logInfo(sql) | |||
|             tables[m[:-4]] = modelDoc | |||
|             for s in sql.split(";\n"): | |||
|                 if len(s) < 3: | |||
|                     continue | |||
|                 try: | |||
|                     self.dbi.execStatement(s+";", job.conf[B.TOPIC_NODE_DB]) | |||
|                     print("SQL executed: "+s) | |||
|                 except Exception as e: | |||
|                     raise Exception("Fehler bei createSchema "+s) | |||
| 
 | |||
|     def createDBTable(self, job, project, context, tablename): | |||
|         """ | |||
|         creates a table in the database | |||
|         :param job: | |||
|         :return: | |||
|         """ | |||
|         args = {} | |||
|         args["context"] = context | |||
|         table = model.table.Table(job) | |||
|         table = table.read_entity(job, tablename, args=args) | |||
|         sql = table.get_schema(tablename, model.table.TYPE_ADMIN)  # [B.DATA_NODE_TABLES][m[:-4]] | |||
|         job.m.logInfo(sql) | |||
|         for s in sql.split(";\n"): | |||
|             if len(s) < 3: | |||
|                 continue | |||
|             try: | |||
|                 if self.__writeDB: | |||
|                     self.dbi.execStatement(s + ";", job.conf[B.TOPIC_NODE_DB]) | |||
|                 print("SQL executed: " + s) | |||
|             except Exception as e: | |||
|                 raise Exception("Fehler bei createSchema " + s) | |||
| @ -0,0 +1,48 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.toolHandling | |||
| import tools.data_const as D | |||
| import basic.constants as B | |||
| import model.entity | |||
| 
 | |||
| class Connection(model.entity.Entity): | |||
|     name = "" | |||
|     description = "" | |||
|     application = "" | |||
|     usecase = [] | |||
|     story = [] | |||
|     tables = {} | |||
|     steps = [] | |||
| 
 | |||
|     def __init__(self, job): | |||
|         """ | |||
|         to be initialized by readSpec | |||
|         :param job: | |||
|         """ | |||
|         self.job = job | |||
| 
 | |||
| 
 | |||
|     def get_schema(self, table=""): | |||
|         dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] | |||
|         dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) | |||
|         print(str(dbi)) | |||
|         sql = dbi.getCreateTable("connection") | |||
|         sql += dbi.getSchemaAttribut("cnid", "id")+"," | |||
|         sql += dbi.getSchemaAttribut("environment", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("component", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("type", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("ip", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("port", D.TYPE_INT)+"," | |||
|         sql += dbi.getSchemaAttribut("hostname", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("dompath", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut(B.NODE_ATTRIBUTES, D.TYPE_TEXT)+"," | |||
|         sql += self.getHistoryFields() | |||
|         sql += ");\n" | |||
|         sql += dbi.getSchemaIndex("connection", "environment") + "\n" | |||
|         sql += self.getHistoryIndex("connection") | |||
|         return sql | |||
|         #dbi.execStatement(sql) | |||
| @ -1,109 +0,0 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| """ | |||
| this module implements the functionality of a test-step | |||
| which is defined in the test-specification | |||
| and is executed by any executer | |||
| there are 2 kinds of test-step | |||
| a) execute specific component in the job | |||
| b) execute specific test-entity in the test-suite-execution | |||
| """ | |||
| import basic.constants as B | |||
| import utils.data_const as D | |||
| import utils.i18n_tool | |||
| 
 | |||
| LIST_ARGS = [ | |||
|     "start",   # for starting the specified main-program | |||
|     "fct"      # for calling the specified component-function | |||
| ] | |||
| 
 | |||
| class Step: | |||
|     comp = "" | |||
|     refLine = ""    # in a: references the data-line(s) to be executed | |||
|     execStep = ""   # in a,b: executes only if the step is set in the job | |||
|     args = {} | |||
|     """ | |||
|     the class contains each attribute of a test-step | |||
|     """ | |||
|     def __init__(self): | |||
|         self.comp = "" | |||
|         self.refLine = "" | |||
|         self.execStep = "" | |||
|         self.args = {} | |||
| 
 | |||
|     def getStepText(self, job): | |||
|         text = self.comp+D.CSV_DELIMITER+str(self.execStep)+D.CSV_DELIMITER+self.refLine | |||
|         for k in self.args: | |||
|             text += D.CSV_DELIMITER+k+":"+self.args[k] | |||
|         return text+"\n" | |||
| 
 | |||
| def parseOldStep(job, fields): | |||
|     step = {} | |||
|     step[B.DATA_NODE_COMP] = fields[D.STEP_COMP_I] | |||
|     step[B.ATTR_EXEC_REF] = fields[D.STEP_EXECNR_I] | |||
|     step[B.ATTR_DATA_REF] = fields[D.STEP_REFNR_I] | |||
|     step[B.ATTR_STEP_ARGS] = {} | |||
|     if D.STEP_ARGS_I == D.STEP_LIST_I: | |||
|         args = "" | |||
|         for i in range(D.STEP_ARGS_I, len(fields)): | |||
|             if len(fields[i]) < 1: | |||
|                 continue | |||
|             if fields[i][0:1] == "#": | |||
|                 continue | |||
|             args += "," + fields[i] | |||
|         args = args[1:] | |||
|     else: | |||
|         args = fields[D.STEP_ARGS_I] | |||
|     a = args.split(",") | |||
|     for arg in a: | |||
|         print("arg " + arg) | |||
|         b = arg.split(":") | |||
|         if len(b) < 2: | |||
|             raise Exception(D.EXCP_MALFORMAT + "" + l) | |||
|         step[B.ATTR_STEP_ARGS][b[0]] = b[1] | |||
|     # data[B.DATA_NODE_STEPS].append(step) | |||
|     return step | |||
| 
 | |||
| def parseStep(job, fields): | |||
|     step = Step() | |||
|     step.comp = fields[D.STEP_COMP_I] | |||
|     step.execStep = fields[D.STEP_EXECNR_I] | |||
|     step.refLine = fields[D.STEP_REFNR_I] | |||
|     setattr(step, B.ATTR_DATA_REF, step.refLine) | |||
|     if D.STEP_ARGS_I == D.STEP_LIST_I: | |||
|         args = "" | |||
|         for i in range(D.STEP_ARGS_I, len(fields)): | |||
|             if len(fields[i]) < 1: | |||
|                 continue | |||
|             if fields[i][0:1] == "#": | |||
|                 continue | |||
|             args += "," + fields[i] | |||
|         args = args[1:] | |||
|     else: | |||
|         args = fields[D.STEP_ARGS_I] | |||
|     a = args.split(",") | |||
|     for arg in a: | |||
|         print("arg " + arg) | |||
|         b = arg.split(":") | |||
|         if len(b) < 2: | |||
|             raise Exception(D.EXCP_MALFORMAT + "" + str(fields)) | |||
|         step.args[b[0]] = b[1] | |||
|         if b[0] in LIST_ARGS: | |||
|             setattr(step, b[0], b[1]) | |||
|     # data[B.DATA_NODE_STEPS].append(step) | |||
|     return step | |||
| 
 | |||
| def getStepHeader(job): | |||
|     text = "# " | |||
|     text += utils.i18n_tool.I18n.getInstance(job).getText(f"{D.CSV_BLOCK_STEP=}", job) | |||
|     text += ";"+utils.i18n_tool.I18n.getInstance(job).getText(f"{D.STEP_ATTR_COMP=}", job) | |||
|     text += ";"+utils.i18n_tool.I18n.getInstance(job).getText(f"{D.STEP_ATTR_EXECNR=}", job) | |||
|     text += ";"+utils.i18n_tool.I18n.getInstance(job).getText(f"{D.STEP_ATTR_REFNR=}", job) | |||
|     text += ";"+utils.i18n_tool.I18n.getInstance(job).getText(f"{D.STEP_ATTR_ARGS=}", job) | |||
|     return text + ";..;;;\n" | |||
| 
 | |||
| 
 | |||
| @ -0,0 +1,52 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.toolHandling | |||
| import utils.data_const as D | |||
| import basic.constants as B | |||
| import model.entity | |||
| 
 | |||
| class Testexecution(model.entity.Entity): | |||
|     name = "" | |||
|     description = "" # from testplan, testsuite, testcase | |||
|     release = "" | |||
|     path = "" | |||
|     level = "" # testplan, testsuite, testcase | |||
|     entities = {} | |||
| 
 | |||
|     def __init__(self, job): | |||
|         """ | |||
|         to be initialized by readSpec | |||
|         :param job: | |||
|         """ | |||
|         self.job = job | |||
| 
 | |||
|     def get_schema(self): | |||
|         dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] | |||
|         dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) | |||
|         sql = dbi.getCreateTable("testexecution") | |||
|         sql += dbi.getSchemaAttribut("teid", "id")+"," | |||
|         sql += dbi.getSchemaAttribut("name", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut(B.SUBJECT_REFERENCE, D.TYPE_TEXT)+"," | |||
|         sql += dbi.getSchemaAttribut("prelease", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("type", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("entity", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("path", D.TYPE_STRING)+"," | |||
|         sql += dbi.getSchemaAttribut("starttime", D.TYPE_TIME)+"," | |||
|         sql += dbi.getSchemaAttribut("finishtime", D.TYPE_TIME)+"," | |||
|         sql += dbi.getSchemaAttribut(B.NODE_ATTRIBUTES, D.TYPE_TEXT)+"," | |||
|         sql += self.getHistoryFields() | |||
|         sql += ");\n" | |||
|         sql += dbi.getSchemaIndex("testexecution", "release") + "\n" | |||
|         sql += self.getHistoryIndex("testplan") | |||
|         for attr in ["entity"]: | |||
|             sql += dbi.getSchemaSubtable("te", [{"attr":attr, "atype": D.TYPE_STR}, | |||
|                                                 {"attr":"type", "atype": D.TYPE_STR}, | |||
|                                                 {"attr":"path", "atype": D.TYPE_STRING}, | |||
|                                                 {"attr":B.NODE_ATTRIBUTES, "atype": D.TYPE_TEXT}])+"\n" | |||
|             sql += dbi.getSchemaIndex(dbi.getSubTableName("te", attr), | |||
|                                       dbi.getSubTableId(dbi.getSubTableName("te", attr), attr))+"\n" | |||
|         return sql | |||
| @ -0,0 +1,69 @@ | |||
| Durch den Test soll die Qualität der Anwendung systematisch (Testabdeckung) nachgewiesen | |||
| und (mittels Regressionen) langfristig sichergestellt werden. | |||
| 
 | |||
| 
 | |||
| Rollen - sind jetzt beschrieben, ok | |||
| 
 | |||
| Testobjekte | |||
| 
 | |||
| logischer Testfall | |||
| Testfall in Managementsicht, aus den User-Story-Akzeptanzkriterien abgeleitet | |||
| Diese werden auf allen Ebenen reportet, insb. deren Status. | |||
| 
 | |||
| physischer Testfall | |||
| Testfall in Spezifikations- und Ausführungssicht | |||
| konkreter auszuführender Testfall, die einzelnen Testschritte müssen spezifiziert/konfiguriert und protokolliert werden. | |||
| Arten physischer Testfälle: | |||
| * automatisierter Testfall | |||
| Alle Einzelschritte werden entsprechend des Automatisierungsframeworks im git-Repo spezifiziert. Entsprechend der Spezifikation wird der Testfall ausgeführt. | |||
| * manueller Testfall | |||
| Alle Einzelschritte werden detailliert (in Jira-..) spezifiziert. Entsprechend der Spezifikation wird der Testfall ausgeführt. | |||
| * explorativer Testfall | |||
| Die wesentlichen Schritt-Sequenzen werden detailliert (in Jira-..) spezifiziert. Von der Spezifikation kann und soll bei der Durchführung variiert werden. Die wesentlichen Schritte werden protokolliert. | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| Test im Software-Prozess | |||
| 
 | |||
| @pre: Komponenten-/Unittests durch Entwickler:innen | |||
| 
 | |||
| Q1: Lieferung entgegennehmen | |||
| * Entschlüsseln | |||
| * Programm: Artefakte verifizieren mittels md5-Hash | |||
| * Lieferung in git-Repo pushen | |||
| << Exit wenn Lieferung nicht gelesen werden kann | |||
| 
 | |||
| Q2: Statischer Test | |||
| --> NFA Wartbarkeit | |||
| * Vollständigkeit prüfen >>> gitVerteiler | |||
| * Code-Analyse >>> SonarQube | |||
| << Exit bei Fehlen wesentlicher Programme (auch Fehlbennung gelten als Fehlen!) | |||
| << Warnung bei Unvollständigkeit | |||
| 
 | |||
| Q3: Installierbarkeit | |||
| --> NFA Installierbarkeit, Portierbarkeit | |||
| * Kubernetes-Container >>> JEE-Plattform? | |||
| * DB-Scripte auf Hive ausfuehren ? | |||
| * Cloudera-1-Rechner-Maschine >>> Linux-Maschine | |||
| * DevOps-Installation ** Testfälle hierzu beschreiben! | |||
| << Exit bei Nicht-Installierbarkeit | |||
| 
 | |||
| Q4: System-/Smoketest | |||
| * Bedienelemente | |||
| * dynamischer Smoketest (minimale Testfälle, v.a. Gutfälle) | |||
| * minimaler GUI-Test >>> | |||
| << Exit bei technischen Blockern | |||
| 
 | |||
| Q5: Regressions-/Progressionstest | |||
| --> Funktionaler Test, Sicherheitstest | |||
| * funktionale Regression (umfassende Testfälle, vollständige Äquivalenzklassen) | |||
| * erweiterte Testfälle zu neuen Funktionen | |||
| * Sichtbarkeit, Sperrkonstellationen >>> | |||
| << Exit bei groben Fehlfunktionen | |||
| 
 | |||
| Q6: Nutzbarkeit | |||
| --> NFA Usability, Performance, Last | |||
| * manuelle Benutzbarkeit, edu@ETU | |||
| << Exit wenn die Nutzung unbrauchbar ist | |||
| << Warnungen | |||
| @ -0,0 +1,321 @@ | |||
| application: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - apid | |||
|   - name | |||
|   - description | |||
|   - reference | |||
|   - attributes | |||
|   - inscommit | |||
|   - insauthor | |||
|   - instime | |||
|   - updcommit | |||
|   - updauthor | |||
|   - updtime | |||
|   - actual | |||
|   apid: | |||
|     _field: apid | |||
|     type: pk | |||
|   name: | |||
|     _field: name | |||
|     type: str | |||
|     index: I | |||
|   description: | |||
|     _field: description | |||
|     type: string | |||
|   reference: | |||
|     _field: reference | |||
|     type: str | |||
|   attributes: | |||
|     _field: attributes | |||
|     type: string | |||
|   insauthor: | |||
|     _field: insauthor | |||
|     type: str | |||
|   inscommit: | |||
|     _field: inscommit | |||
|     type: str | |||
|   instime: | |||
|     _field: instime | |||
|     type: time | |||
|   updauthor: | |||
|     _field: updauthor | |||
|     type: str | |||
|   updcommit: | |||
|     _field: updcommit | |||
|     type: str | |||
|   updtime: | |||
|     _field: updtime | |||
|     type: time | |||
|   actual: | |||
|     _field: actual | |||
|     type: int | |||
|     index: I | |||
| ap_component: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - apcomid | |||
|   - apid | |||
|   - component | |||
|   apcomid: | |||
|     _field: apcomid | |||
|     type: pk | |||
|   apid: | |||
|     _field: apid | |||
|     type: int | |||
|     index: I | |||
|   component: | |||
|     _field: component | |||
|     type: str | |||
|     index: I | |||
| ap_application: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - apappid | |||
|   - apid | |||
|   - application | |||
|   apappid: | |||
|     _field: apappid | |||
|     type: pk | |||
|   apid: | |||
|     _field: apid | |||
|     type: int | |||
|     index: I | |||
|   application: | |||
|     _field: component | |||
|     type: str | |||
|     index: I | |||
| ap_project: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - approid | |||
|   - apid | |||
|   - project | |||
|   - description | |||
|   - reference | |||
|   approid: | |||
|     _field: apid | |||
|     type: pk | |||
|   apid: | |||
|     _field: apid | |||
|     type: int | |||
|     index: I | |||
|   project: | |||
|     _field: project | |||
|     type: str | |||
|     index: I | |||
|   description: | |||
|     _field: description | |||
|     type: string | |||
|   reference: | |||
|     _field: reference | |||
|     type: str | |||
| environment: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - enid | |||
|   - name | |||
|   - description | |||
|   - reference | |||
|   - attributes | |||
|   - inscommit | |||
|   - insauthor | |||
|   - instime | |||
|   - updcommit | |||
|   - updauthor | |||
|   - updtime | |||
|   - actual | |||
|   enid: | |||
|     _field: enid | |||
|     type: pk | |||
|   name: | |||
|     _field: name | |||
|     type: str | |||
|     index: I | |||
|   description: | |||
|     _field: description | |||
|     type: string | |||
|   reference: | |||
|     _field: reference | |||
|     type: str | |||
|   attributes: | |||
|     _field: attributes | |||
|     type: string | |||
|   insauthor: | |||
|     _field: insauthor | |||
|     type: str | |||
|   inscommit: | |||
|     _field: inscommit | |||
|     type: str | |||
|   instime: | |||
|     _field: instime | |||
|     type: time | |||
|   updauthor: | |||
|     _field: updauthor | |||
|     type: str | |||
|   updcommit: | |||
|     _field: updcommit | |||
|     type: str | |||
|   updtime: | |||
|     _field: updtime | |||
|     type: time | |||
|   actual: | |||
|     _field: actual | |||
|     type: int | |||
|     index: I | |||
| en_project: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - enproid | |||
|   - enid | |||
|   - project | |||
|   enproid: | |||
|     _field: enproid | |||
|     type: pk | |||
|   enid: | |||
|     _field: enid | |||
|     type: int | |||
|     index: I | |||
|   project: | |||
|     _field: project | |||
|     type: str | |||
|     index: I | |||
| en_component: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - encomid | |||
|   - enid | |||
|   - component | |||
|   - instance | |||
|   - type | |||
|   - ip | |||
|   - port | |||
|   - hostname | |||
|   - dompath | |||
|   - user | |||
|   - password | |||
|   - attributes | |||
|   encomid: | |||
|     _field: encomid | |||
|     type: pk | |||
|   enid: | |||
|     _field: enid | |||
|     index: I | |||
|     type: int | |||
|   component: | |||
|     _field: component | |||
|     index: I | |||
|     type: str | |||
|   instance: | |||
|     _field: instance | |||
|     type: int | |||
|   type: | |||
|     _field: type | |||
|     type: str | |||
|   ip: | |||
|     _field: ip | |||
|     type: str | |||
|   port: | |||
|     _field: port | |||
|     type: str | |||
|   hostname: | |||
|     _field: hostname | |||
|     type: str | |||
|   dompath: | |||
|     _field: dompath | |||
|     type: str | |||
|   user: | |||
|     _field: user | |||
|     type: str | |||
|   password: | |||
|     _field: password | |||
|     type: str | |||
|   attributes: | |||
|     _field: attributes | |||
|     type: string | |||
| component: | |||
|   _header: | |||
|   - _field | |||
|   - type | |||
|   - format | |||
|   - index | |||
|   _fields: | |||
|   - coid | |||
|   - name | |||
|   - description | |||
|   - reference | |||
|   - attributes | |||
|   - inscommit | |||
|   - insauthor | |||
|   - instime | |||
|   - updcommit | |||
|   - updauthor | |||
|   - updtime | |||
|   - actual | |||
|   coid: | |||
|     _field: apid | |||
|     type: pk | |||
|   name: | |||
|     _field: name | |||
|     type: str | |||
|     index: I | |||
|   description: | |||
|     _field: description | |||
|     type: string | |||
|   reference: | |||
|     _field: reference | |||
|     type: str | |||
|   attributes: | |||
|     _field: attributes | |||
|     type: string | |||
|   insauthor: | |||
|     _field: insauthor | |||
|     type: str | |||
|   inscommit: | |||
|     _field: inscommit | |||
|     type: str | |||
|   instime: | |||
|     _field: instime | |||
|     type: time | |||
|   updauthor: | |||
|     _field: updauthor | |||
|     type: str | |||
|   updcommit: | |||
|     _field: updcommit | |||
|     type: str | |||
|   updtime: | |||
|     _field: updtime | |||
|     type: time | |||
|   actual: | |||
|     _field: actual | |||
|     type: int | |||
|     index: I | |||
| 
 | |||
| 
 | 
| @ -0,0 +1,94 @@ | |||
| # This is a sample Python script. | |||
| import os | |||
| import traceback | |||
| import sys | |||
| import yaml | |||
| import basic.program | |||
| import basic.constants as B | |||
| import basic.message | |||
| import tools.path_const as P | |||
| import tools.config_tool as config_tool | |||
| import tools.file_tool as file_tool | |||
| import model.entity | |||
| import model.factory | |||
| #import model.table | |||
| 
 | |||
| PROGRAM_NAME = "check_configuration" | |||
| 
 | |||
| def startPyJob(job): | |||
|     try: | |||
|         job.m.logDebug("--- start " + PROGRAM_NAME + " ------>>>>") | |||
|         components = job.par.component.split(",") | |||
|         for c in components: | |||
|             job.m.logInfo("------------------------------------------\ncheck component "+c) | |||
|             checkComponent(job, c) | |||
|         job.m.setMsg("Job " + PROGRAM_NAME + " fertig") | |||
|         job.m.logDebug("<<<<<<<<----- " + PROGRAM_NAME + " ------") | |||
|     except Exception as e: | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.setFatal(str(e)) | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.logDebug("execpt "+traceback.format_exc()) | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
| 
 | |||
| def checkComponent(job, componentName): | |||
|     """ | |||
|     checks the configurations of the component | |||
|     :param job: | |||
|     :param componentName: | |||
|     :return: | |||
|     """ | |||
|     import model.component | |||
|     configPath = config_tool.getExistingPath(job, [os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_COMPS], componentName, "CONFIG")]) | |||
|     configTree = file_tool.read_file_dict(job, configPath, job.m) | |||
|     for x in model.component.LIST_CP_SUBJECTS: | |||
|         if "conf" not in configTree: | |||
|             job.m.setError(componentName + ": root conf is not set: ") | |||
|             break | |||
|         if x not in configTree["conf"]: | |||
|             job.m.setError(componentName + ": subject is not set: " + x) | |||
|         else: | |||
|             for c in configTree["conf"][x]: | |||
|                 if c == "none": | |||
|                     if len(configTree["conf"][x]) != 1: | |||
|                         job.m.setWarn("none is not the only subject in "+x) | |||
|                     continue | |||
|     comps = model.component.select_components(job, None, None) | |||
|     job.m.logInfo("Komponenten pruefen") | |||
|     for c in configTree["conf"][model.component.CP_SUBJECT_COMPS]: | |||
|         if c in ["none"]: | |||
|             continue | |||
|         if c not in comps: | |||
|             job.m.setError(componentName + ": component " + c + " does not exist") | |||
|         job.m.logInfo("- " + componentName + " uses component " + c) | |||
|     job.m.logInfo("Steps pruefen") | |||
|     for v in configTree["conf"][model.component.CP_SUBJECT_STEPS]: | |||
|         if v == "none": | |||
|             continue | |||
|         job.m.logInfo("- "+componentName + " uses variant "+v) | |||
|     job.m.logInfo("Tabellen pruefen") | |||
|     tables = model.table.select_tables(job, None, None) | |||
|     for t in configTree["conf"][model.component.CP_SUBJECT_TABLES]: | |||
|         if t == "none": | |||
|             continue | |||
|         if t in tables: | |||
|             job.m.logInfo("- "+componentName + " uses table " + t) | |||
|         else: | |||
|             job.m.setError(componentName + ": table " + t + " ist not defined.") | |||
|     job.m.logInfo("Artefakte pruefen") | |||
|     for a in configTree["conf"][model.component.CP_SUBJECT_ARTS]: | |||
|         if t == "none": | |||
|             continue | |||
|         job.m.logInfo("- "+componentName + " uses artifact " + a) | |||
| 
 | |||
| 
 | |||
| if __name__ == '__main__': | |||
|     job = basic.program.Job(PROGRAM_NAME) | |||
|     print ("job "+str(job.__dict__)) | |||
|     job.startJob() | |||
|     if job.m.isRc("fatal"): | |||
|         job.stopJob() | |||
|     # now in theory the program is runnable | |||
|     startPyJob(job) | |||
|     job.stopJob() | |||
| # See PyCharm help at https://www.jetbrains.com/help/pycharm/ | |||
| @ -0,0 +1,60 @@ | |||
| # This is a sample Python script. | |||
| import sys# | |||
| # import jsonpickle # pip install jsonpickle | |||
| import yaml # pip install pyyaml | |||
| import basic.program | |||
| import basic.componentHandling | |||
| import basic.message | |||
| #import utils.tdata_tool | |||
| import traceback | |||
| 
 | |||
| PROGRAM_NAME = "check_specification" | |||
| 
 | |||
| def startPyJob(job): | |||
|     try: | |||
|         job.m.logDebug("--- start " + PROGRAM_NAME + " ------>>>>") | |||
|         job.m.setMsg("Job " + PROGRAM_NAME + " fertig") | |||
|         if hasattr(job.par, "testcase"): | |||
|             testcase = getattr(job.par, "testcase") | |||
|             print("Check testcase "+testcase) | |||
|         elif hasattr(job.par, "testsuite"): | |||
|             testsuite = getattr(job.par, "testsuite") | |||
|             print("Check testsuite "+testsuite) | |||
|         elif hasattr(job.par, "testplan"): | |||
|             testplan = getattr(job.par, "testplan") | |||
|             print("Check testplan "+testplan) | |||
|         job.m.logDebug("<<<<<<<<----- " + PROGRAM_NAME + " ------") | |||
|     except Exception as e: | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.setFatal(str(e)) | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.logDebug("execpt "+traceback.format_exc()) | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
| 
 | |||
| def checkHead(job): | |||
|     pass | |||
| 
 | |||
| if __name__ == '__main__': | |||
|     x = basic.program.Job(PROGRAM_NAME) | |||
|     print ("x "+str(x)) | |||
|     x.startJob() | |||
|     x.m.logDebug(str(vars(x.par)) + "\n" + str(vars(x.conf))) | |||
|     if x.m.isRc("fatal"): | |||
|         x.stopJob() | |||
|         exit(x.m.rc * (-1) + 3) | |||
|     # now in theory the program is runnable | |||
|     x.m.setMsg("# job initialized") | |||
|     cm = basic.componentHandling.ComponentManager.getInstance(x) | |||
|     print("cm "+str(cm)) | |||
|     cm.initComponents() | |||
|     comps = cm.getComponents(x, PROGRAM_NAME) | |||
|     x.m.setMsg("# Components initialized with these relevant components " + str(comps)) | |||
|     for c in comps: | |||
|         comp = cm.getComponent(c) | |||
|         print(str(comp)) | |||
|         comp.check_Instance() | |||
|         x.m.merge(comp.m) | |||
|         comp.confs["function"][PROGRAM_NAME] = comp.m.topmessage | |||
| 
 | |||
|     x.stopJob() | |||
| # See PyCharm help at https://www.jetbrains.com/help/pycharm/ | |||
| @ -0,0 +1,115 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| """ | |||
| program to clean the workspace : | |||
| * remove old debug-files | |||
| """ | |||
| import os | |||
| import re | |||
| import shutil | |||
| import sys | |||
| import traceback | |||
| import basic.program | |||
| import basic.constants as B | |||
| import tools.date_tool as date_tool | |||
| import tools.path_tool as path_tool | |||
| import tools.job_tool as job_tool | |||
| 
 | |||
| LIMIT_DEBUG_FILES = -7 | |||
| PROGRAM_NAME = "clean_workspace" | |||
| 
 | |||
| def startPyJob(job): | |||
|     try: | |||
|         job.m.logDebug("--- start " + PROGRAM_NAME + " ------>>>>") | |||
|         # remove debug-files | |||
|         removeDebugFiles(job) | |||
|         # clean and archive log-files | |||
|         cleanLogFiles(job) | |||
|         job.m.setMsg("Job " + PROGRAM_NAME + " fertig") | |||
|         job.m.logDebug("<<<<<<<<----- " + PROGRAM_NAME + " ------") | |||
|     except Exception as e: | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.setFatal(str(e)) | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.logDebug("execpt "+traceback.format_exc()) | |||
|         job.m.logDebug("+++++++++++++++++++++++++++++++++++++++++++++") | |||
| 
 | |||
| def removeDebugFiles(job): | |||
|     """ | |||
|     to remove debug-files in any relevant folder | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     job.m.logInfo("# # remove log-files # # #") | |||
|     limit = date_tool.getActdate(date_tool.F_LOG, LIMIT_DEBUG_FILES)[0:8] | |||
|     path = job.conf[B.TOPIC_PATH][B.ATTR_PATH_DEBUG] | |||
|     cleanFolder(job, path, limit) | |||
|     path = os.path.join(B.HOME_PATH, "temp") | |||
|     cleanFolder(job, path, limit) | |||
| 
 | |||
| def cleanFolder(job, path, limit): | |||
|     """ | |||
|     remove all files in the folder with a log-date older than limit | |||
|     :param job: | |||
|     :param path: | |||
|     :param limit: | |||
|     :return: | |||
|     """ | |||
|     date_regex = r"(.*)_(\d{8})_\d{6}" | |||
|     cntRm = 0 | |||
|     cntMv = 0 | |||
|     cntAll = 0 | |||
|     for f in os.listdir(path): | |||
|         cntAll += 1 | |||
|         if re.match(date_regex, f): | |||
|             res = re.search(date_regex, f) | |||
|             fileType = str(res.group(1)) | |||
|             fileDate = str(res.group(2)) | |||
|             if fileType in ["debug", "log", "start_dialog"]: | |||
|                 if fileDate >= limit: | |||
|                     continue | |||
|                 job.m.logInfo("remove " + os.path.join(path, f)) | |||
|                 os.remove(os.path.join(path, f)) | |||
|                 cntRm += 1 | |||
|             else: | |||
|                 fileYear = fileDate[0:4] | |||
|                 actYear = date_tool.getActdate(date_tool.F_LOG)[0:4] | |||
|                 archivPath = os.path.join(path, fileYear) | |||
|                 if fileYear < actYear: | |||
|                     if not os.path.exists(archivPath): | |||
|                         os.mkdir(archivPath) | |||
|                     if not os.path.isdir(archivPath): | |||
|                         raise Exception("archiv-folder is not a directory: " + archivPath) | |||
|                     shutil.move(os.path.join(path, f), os.path.join(archivPath, f)) | |||
|                     cntMv += 1 | |||
|     job.m.setMsg(str(cntRm) + " / " + str(cntAll) + " files removed in " + path) | |||
|     job.m.setMsg(str(cntMv) + " / " + str(cntAll) + " files moved from " + path) | |||
| 
 | |||
| def cleanLogFiles(job): | |||
|     """ | |||
|     searches all log-folder in test-documents and remove the oldest log-files except the newest | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     job.m.logInfo("# # clean log-files # # #") | |||
|     limit = date_tool.getActdate(date_tool.F_LOG, LIMIT_DEBUG_FILES)[0:8] | |||
|     path = path_tool.compose_path(job, "{job.par.wsdir}/{log}", None) | |||
|     cleanFolder(job, path, limit) | |||
|     environments = job_tool.select_environment(job, "", "ALL") | |||
|     for env in environments: | |||
|         jobEnv = "" | |||
|         if hasattr(job.par, "environment"): | |||
|             jobEnv = getattr(job.par, "environment") | |||
|         setattr(job.par, "environment", env) | |||
|         path = path_tool.compose_path(job, "{envlog}", None) | |||
|         cleanFolder(job, path, limit) | |||
|         setattr(job.par, "environment", jobEnv) | |||
|     pass | |||
| 
 | |||
| if __name__ == '__main__': | |||
|     job = basic.program.Job(PROGRAM_NAME) | |||
|     startPyJob(job) | |||
| @ -0,0 +1,56 @@ | |||
| # program to copy dummy-file as testcase-results | |||
| # ------------------------------------------------------------------------------------------------------------- | |||
| """ | |||
| 
 | |||
| """ | |||
| import os | |||
| import shutil | |||
| import basic.program | |||
| import utils.path_tool | |||
| import utils.file_tool | |||
| import basic.constants as B | |||
| import utils.tdata_tool | |||
| import basic.componentHandling | |||
| import utils.path_const as P | |||
| import basic.message as message | |||
| 
 | |||
| 
 | |||
| PROGRAM_NAME = "copy_appdummy" | |||
| PROGRAM_DUMMY = "collect_testcase" | |||
| 
 | |||
| def startPyJob(job): | |||
|     cm = basic.componentHandling.ComponentManager.getInstance(job) | |||
|     cm.initComponents() | |||
|     comps = cm.getComponents(PROGRAM_DUMMY) | |||
|     job.m.setMsg("# Components initialized with these relevant components " + str(comps)) | |||
|     cm = basic.componentHandling.ComponentManager.getInstance(job, "init") | |||
|     print("cm " + str(cm)) | |||
|     cm.initComponents() | |||
|     comps = cm.getComponents(PROGRAM_DUMMY) | |||
|     for c in comps: | |||
|         comp = cm.getComponent(c) | |||
|         for cond in ["pre", "post"]: | |||
|             tdatapath = utils.path_tool.composePattern(job, "{td"+cond+"exec}", comp) | |||
|             envapppath = utils.path_tool.composePattern(job, "{tc"+cond+"cond}", comp) | |||
|             if os.path.exists(tdatapath): | |||
|                 files = utils.file_tool.getFiles(job.m, job, tdatapath, ".+\.csv", None) | |||
|                 for f in files: | |||
|                     # shutil.copy() | |||
|                     print("cp " + os.path.join(tdatapath, f) + " " + os.path.join(envapppath, f)) | |||
|                     utils.file_tool.mkPaths(job, os.path.join(envapppath, f), job.m) | |||
|                     shutil.copy(os.path.join(tdatapath, f), os.path.join(envapppath, f)) | |||
|             print(tdatapath) | |||
| 
 | |||
| # Press the green button in the gutter to run the script. | |||
| if __name__ == '__main__': | |||
|     print(PROGRAM_NAME) | |||
|     x = basic.program.Job(PROGRAM_NAME) | |||
|     x.startJob() | |||
|     x.m.logDebug(str(vars(x.par)) + "\n" + str(vars(x.conf))) | |||
|     if x.m.isRc("fatal"): | |||
|         x.stopJob() | |||
|         exit(x.m.rc * (-1) + 3) | |||
|     startPyJob(x) | |||
|     x.stopJob() | |||
| # See PyCharm help at https://www.jetbrains.com/help/pycharm/ | |||
| 
 | |||
| @ -0,0 +1,319 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import json | |||
| import os | |||
| import datetime | |||
| import re | |||
| import subprocess | |||
| import traceback | |||
| 
 | |||
| import yaml | |||
| 
 | |||
| INSTALLED = False | |||
| try: | |||
|     import basic.program | |||
|     INSTALLED = True | |||
| except: | |||
|     INSTALLED = False | |||
| 
 | |||
| PROGRAM_NAME = "install_workspace" | |||
| CONFIG_FORMAT = "yml" | |||
| BASIS_FORMAT = "json" | |||
| 
 | |||
| REPO_NAME = "_name" | |||
| REPO_URL = "url" | |||
| REPO_BRANCH = "_branch" | |||
| 
 | |||
| 
 | |||
| job = None | |||
| # ----------------------------------------------------------------------------------------- | |||
| # Miniimplementierung des Programmeahmens | |||
| class Logger: | |||
|     """ | |||
|     Kurzversion des Messages mit Standardfunktionen | |||
|     * opel_logs() | |||
|     * close_logs() | |||
|     * log_info() | |||
|     * log_error() | |||
|     """ | |||
|     def __init__(self, job, level, logTime, comp): | |||
|         self.openLog(job, logTime) | |||
| 
 | |||
|     def openLog(self, job, logTime): | |||
|         # job, level, logTime, componente | |||
|         home = getHome() | |||
|         path = os.path.join(home, "log") | |||
|         if not os.path.exists(path): | |||
|             os.mkdir(path) | |||
|         logpath = os.path.join(home, "log", job.program+"_"+logTime+".txt") | |||
|         print("logpath "+logpath) | |||
|         self.logfile = open(logpath, "w") | |||
| 
 | |||
|     def logInfo(self, text): | |||
|         self.logfile.write(text + "\n") | |||
|     def logWarn(self, text): | |||
|         self.logfile.write("WARN: "+text + "\n") | |||
|     def setMsg(self, text): | |||
|         self.logfile.write(text + "\n") | |||
|     def logError(self, text): | |||
|         self.logfile.write("ERROR:" + text + "\n") | |||
|         print("ERROR:" + text) | |||
| 
 | |||
|     def closeLog(self): | |||
|         self.logfile.close() | |||
| 
 | |||
| class ActJob: | |||
|     """ | |||
|     Kurzversion des Jobs mit Standardfunktionen | |||
|     * start_job()       startet Job mit Messaging | |||
|     * set_parameter()   setzt Parameter aus args oder aus Aufruf | |||
|     * stop_job()        startet Job mit Messaging | |||
|     """ | |||
|     def __init__(self, program): | |||
|         self.program = program | |||
|         self.start = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |||
|         self.jobid = 100000 | |||
|         self.conf = {} | |||
|         self.par = {} | |||
| 
 | |||
|     def startJob(self): | |||
|         self.m = Logger(self, "info", self.start, None) # job, level, logTime, componente | |||
|         text = "# # # Start Job " + self.start + " # # # " | |||
|         self.m.logInfo(text) | |||
|         print(text) | |||
| 
 | |||
|     def stopJob(self): | |||
|         self.ende = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |||
|         text = "# # # Stop Job " + self.start + " - " + self.ende + " # # # " | |||
|         self.m.logInfo(text) | |||
|         self.m.closeLog() | |||
|         print(text) | |||
| 
 | |||
|     def getDebugLevel(self, tool): | |||
|         return 0 | |||
| 
 | |||
|     def debug(self, verify, text): | |||
|         self.m.logInfo(text) | |||
| 
 | |||
|     def setParameter(self, args): | |||
|         for k in args: | |||
|             setattr(self, k, args[k]) | |||
| 
 | |||
| 
 | |||
| # ----------------------------------------------------------------------------------------- | |||
| # Standardsteuerung Hauptverarbeitung | |||
| def startPyJob(job): | |||
|     """ | |||
|     Steuerung der Hauptverarbeitung, aufrufbar vom Programm selbst oder aus job_tool | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     job.m.logInfo("startPyJob gestertet ") | |||
|     try: | |||
|         setParameter(job) | |||
|         readConfig(job) | |||
|         createFolders(job) | |||
|         createGit(job) | |||
|         createBasisConfig(job) | |||
|         createDb(job) | |||
|     except Exception as e: | |||
|         job.m.logError("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.logError(str(e)) | |||
|         job.m.logError("+++++++++++++++++++++++++++++++++++++++++++++") | |||
|         job.m.logError("execpt "+traceback.format_exc()) | |||
|         job.m.logError("+++++++++++++++++++++++++++++++++++++++++++++") | |||
| 
 | |||
| # ----------------------------------------------------------------------------------------- | |||
| # konkrete Verarbeitungsroutinen | |||
| def setParameter(job): | |||
|     job.m.logInfo("--- setze Parameter ") | |||
| 
 | |||
| def readConfig(job): | |||
|     job.m.logInfo("--- suche config-Datei ") | |||
|     args = {} | |||
|     args["home"] = getHome() | |||
|     configPath = "" | |||
|     for p in os.listdir(args["home"]): | |||
|         print(p) | |||
|         path = os.path.join(args["home"], p) | |||
|         if os.path.isfile(path) and "workspace" in p: | |||
|             configPath = path | |||
|             break | |||
|     if len(configPath) < 1: | |||
|         raise Exception("Keine Konfiguration gefunden in "+args["home"]) | |||
|     with open(configPath, 'r') as file: | |||
|         doc = yaml.full_load(file) | |||
|     file.close() | |||
|     for k in doc: | |||
|         args[k] = doc[k] | |||
|         job.conf[k] = doc[k] | |||
|     home = getHome() | |||
|     for k in job.conf["paths"]: | |||
|         job.conf["paths"][k] = os.path.join(home, job.conf["paths"][k]) | |||
|     job.setParameter(args) | |||
| 
 | |||
| def createFolders(job): | |||
|     job.m.logInfo("--- erstelle Verzeichnisse ") | |||
|     for p in job.paths: | |||
|         path = os.path.join(job.home, job.paths[p]) | |||
|         createFolder(job, path) | |||
| 
 | |||
| def createFolder(job, path): | |||
|     if not os.path.exists(path): | |||
|         os.mkdir(path) | |||
|         job.m.logInfo("Verzeichnis angelegt: "+ path) | |||
|     elif not os.path.isdir(path): | |||
|         job.m.logError("Verzeichnisname existiert und ist kein Verzeichnis "+ path) | |||
|     else: | |||
|         job.m.logInfo("Verzeichnis existiert: " + path) | |||
| 
 | |||
| # -------------------------------------------------------------------------------------- | |||
| # git_tool | |||
| # -------------------------------------------------------------------------------------- | |||
| 
 | |||
| def createGit(job): | |||
|     job.m.logInfo("--- erstelle und aktualisiere git-Repos ") | |||
|     repos = {} | |||
|     local = {} | |||
|     attr = { | |||
|         REPO_NAME: "", | |||
|         REPO_BRANCH: "" | |||
|     } | |||
|     # erstelle Repoliste mit den Attributen: name, branch, url | |||
|     for r in job.repos: | |||
|         if r in attr: | |||
|             attr[r] = job.repos[r] | |||
|         else: | |||
|             repo = {} | |||
|             for a in job.repos[r]: | |||
|                 repo[a] = job.repos[r][a] | |||
|             repos[r] = repo | |||
|     for k in attr: | |||
|         a = k | |||
|         for r in repos: | |||
|             if a not in repos[r]: | |||
|                 repos[r][a] = attr[k] | |||
|     for r in repos: | |||
|         repo = repos[r] | |||
|         path = os.path.join(job.home, job.paths[r]) | |||
|         if os.path.exists(path): | |||
|             local[REPO_URL] = os.path.join(job.home, job.paths[r]) | |||
|             local[REPO_BRANCH] = repo[REPO_BRANCH] | |||
|             local[REPO_NAME] = repo[REPO_NAME] | |||
|             rpath = os.path.join(local[REPO_URL], ".git") | |||
|             if os.path.exists(rpath): | |||
|                 job.m.logInfo("Repo existiert bereits "+r) | |||
|             else: | |||
|                 job.m.logInfo("Repo erzeugen "+r) | |||
|                 initGit(job, local, repo) | |||
|             updateLocal(job, local, repo) | |||
|         else: | |||
|             job.m.logError("Verzeichnis existiert nicht: " + path) | |||
| 
 | |||
| def initGit(job, local, repo, bare=False): | |||
|     job.m.logInfo("--- initialisiere git-Repo "+str(repo)+","+str(local)) | |||
|     os.chdir(local[REPO_URL]) | |||
|     cmd = "git init " | |||
|     if bare: | |||
|         cmd += " --bare" | |||
|     execCmd(job, cmd) | |||
|     cmd = "git checkout " + local[REPO_BRANCH] | |||
|     execCmd(job, cmd) | |||
|     cmd = "git remote add " + repo[REPO_NAME] + " " + repo[REPO_URL] | |||
|     execCmd(job, cmd) | |||
|     os.chdir(job.home) | |||
| 
 | |||
| def execCmd(job, cmd): | |||
|     job.m.logInfo(cmd) | |||
|     text = "" | |||
|     process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) | |||
|     btext = process.communicate()[0] | |||
|     text = btext.decode('utf-8') | |||
|     job.m.logInfo(text) | |||
|     return text | |||
| 
 | |||
| def checkoutLocal(job, local): | |||
|     os.chdir(local[REPO_URL]) | |||
|     cmd = "git checkout " + local[REPO_BRANCH] | |||
|     text = execCmd(job, cmd) | |||
|     return text | |||
| 
 | |||
| def updateLocal(job, local, repo): | |||
|     job.m.logInfo("--- aktualisiere git-Repo "+str(repo)+","+str(local)) | |||
|     text = checkoutLocal(job, local) | |||
| #    if len(text) > 0 and re.match(r"[MA]\s\w+", text): | |||
|     match = re.search(r"([DMA])\s(\S+)", text) | |||
|     if match is not None: | |||
|         os.chdir(job.home) | |||
|         job.m.logError("ERROR: lokales Repo " + local[REPO_URL] + ", " + local[REPO_BRANCH] + " hat uncommited Aenderungen") | |||
|         print("regex gefunden") | |||
|         return | |||
|     cmd = "git pull " + repo[REPO_NAME] + " " + repo[REPO_BRANCH] | |||
|     text = execCmd(job, cmd) | |||
|     job.m.logInfo(text) | |||
|     os.chdir(job.home) | |||
| 
 | |||
| def updateRemote(job, local, repo): | |||
|     job.m.logInfo("--- aktualisiere git-Repo "+str(repo)+","+str(local)) | |||
|     text = checkoutLocal(job, local) | |||
|     cmd = "git push " + repo[REPO_NAME] + " " + repo[REPO_BRANCH] | |||
|     text = execCmd(job, cmd) | |||
|     os.chdir(job.home) | |||
| 
 | |||
| def createBasisConfig(job): | |||
|     job.m.logInfo("--- erstelle Basis-Koniguration ") | |||
|     config = {} | |||
|     config["basic"] = {} | |||
|     config["basic"]["paths"] = {} | |||
|     config["basic"]["paths"]["home"] = job.home | |||
|     for p in job.paths: | |||
|         path = os.path.join(job.home, job.paths[p]) | |||
|         config["basic"]["paths"][p] = path | |||
|     for p in ["temp", "config"]: | |||
|         path = os.path.join(job.home, p) | |||
|         createFolder(job, path) | |||
|         config["basic"]["paths"][p] = path | |||
|     if BASIS_FORMAT == "yml": | |||
|         path = os.path.join(job.home, "config", "basis.json") | |||
|         with open(path, 'w', encoding="utf-8") as file: | |||
|             doc = yaml.dump(config, file) | |||
|             file.write(doc) | |||
|         file.close() | |||
|     elif BASIS_FORMAT == "json": | |||
|         path = os.path.join(job.home, "config", "basis.json") | |||
|         with open(path, 'w', encoding="utf-8") as file: | |||
|             doc = json.dumps(config, indent=4) | |||
|             file.write(doc) | |||
|         file.close() | |||
| 
 | |||
| def createDb(job): | |||
|     if "db" in job.conf: | |||
|         import basic.connection | |||
|         import basic.Testserver | |||
| 
 | |||
|         testserver = basic.Testserver.Testserver(job) | |||
|         testserver.createAdminDBTables(job) | |||
| 
 | |||
| def getHome(): | |||
|     home = os.getcwd() | |||
|     if home[-7:] == "program": | |||
|         home = home[0:-8] | |||
|     return home | |||
| 
 | |||
| 
 | |||
| # ----------------------------------------------------------------------------------------- | |||
| # Pythonstandard Programmaufruf | |||
| # Job-Objekt erzeugen und beenden | |||
| if __name__ == '__main__': | |||
|     if INSTALLED: | |||
|         #job = basic.program.Job(PROGRAM_NAME) | |||
|         job = ActJob(PROGRAM_NAME) | |||
|     else: | |||
|         job = ActJob(PROGRAM_NAME) | |||
|     job.startJob() | |||
|     startPyJob(job) | |||
|     job.stopJob() | |||
| @ -0,0 +1,280 @@ | |||
| #!/usr/bin/python | |||
| # program to execute programs for a testcases or for a testsuite | |||
| # PARAM from INPUT:  --granularity --application --environment --testcase/testsuite | |||
| # main functions | |||
| #  + input_param()  : cache-actjob --> user-input -->  local-param | |||
| #  + start_job()    : local-param --> cache-actjob --> start-param | |||
| # --------------------------------------------------- | |||
| 
 | |||
| """ | |||
| 
 | |||
| """ | |||
| import os.path | |||
| import json | |||
| import re | |||
| 
 | |||
| import basic.program | |||
| import basic.constants as B | |||
| import tools.job_tool | |||
| import tools.file_tool | |||
| import tools.data_const as D | |||
| import tools.date_tool | |||
| import tools.path_tool | |||
| import tools.path_const as P | |||
| 
 | |||
| tempJob = {} | |||
| 
 | |||
| PROGRAM_NAME = "service" | |||
| 
 | |||
| DLG_TESTCASE = "Testfall" | |||
| DLG_TESTSUITE = "Testsuite" | |||
| DLG_COMPLETE = "Komplettausfuehrung" | |||
| LIST_DLG_GRAN = [DLG_TESTCASE, DLG_TESTSUITE] | |||
| DLG_START_QUESTION = "was soll getestet werden" | |||
| # DLG_TESTPLAN = "Testplan" | |||
| DLG_ENVIRONMENT = "Umgebung" | |||
| DLG_APPLICATION = "Anwendung" | |||
| DLG_REDO = "wiederholen" | |||
| DLG_CONTINUE = "fortsetzen" | |||
| DLG_DUMMY_STEP = "Dummy-Schritt" | |||
| DLG_NEWJOB = "neuer Job" | |||
| 
 | |||
| JOB_NR = { | |||
|     DLG_TESTSUITE : { | |||
|         "start": "init_testsuite", | |||
|         "init_testsuite": { | |||
|             "jobnr": "0" }, | |||
|         "execute_testsuite": { | |||
|             "jobnr": "1"}, | |||
|         "collect_testsuite": { | |||
|             "jobnr": "2"}, | |||
|         "compare_testsuite": { | |||
|             "jobnr": "3"}, | |||
|         "finish_testsuite": { | |||
|             "jobnr": "4"} | |||
|     }, | |||
|     DLG_TESTCASE: { | |||
|         "start": "init_testcase", | |||
|         "init_testcase": { | |||
|             "jobnr": "5" }, | |||
|         "execute_testcase": { | |||
|             "jobnr": "6" }, | |||
|         "collect_testcase": { | |||
|             "jobnr": "7" }, | |||
|         "copy_appdummy": { | |||
|             "jobnr": "8" }, | |||
|         "compare_testcase": { | |||
|             "jobnr": "9" }, | |||
|     }, | |||
|     "check_environment": { | |||
|         "jobnr": "10" }, | |||
|     "test_executer": { | |||
|         "jobnr": "11"}, | |||
| } | |||
| 
 | |||
| JOB_LIST = [ | |||
|     "init_testsuite",     # 0 | |||
|     "execute_testsuite",  # 1 | |||
|     "collect_testsuite",  # 2 | |||
|     "compare_testsuite",  # 3 | |||
|     "finish_testsuite",   # 4 | |||
|     "init_testcase",      # 5 | |||
|     "execute_testcase",   # 6 | |||
|     "collect_testcase",   # 7 | |||
|     "copy_appdummy",         # 8 | |||
|     "compare_testcase",   # 9 | |||
|     "check_environment",  # 10 | |||
|     "test_executer"       # 11 | |||
| ] | |||
| 
 | |||
| appList = [] | |||
| envList = [] | |||
| entities = {} | |||
| entities[DLG_TESTCASE] = {} | |||
| entities[DLG_TESTSUITE] = {} | |||
| 
 | |||
| def readContext(job): | |||
|     for k in job.conf[B.SUBJECT_APPS]: | |||
|         appList.append(k) | |||
|     path = job.conf[B.TOPIC_PATH][B.ATTR_PATH_ENV] | |||
|     if os.path.exists(path): | |||
|         for d in os.listdir(path): | |||
|             print ("-- "+d) | |||
|             if not os.path.isdir(os.path.join(path, d)): | |||
|                 continue | |||
|             if d[0:1] == "_": | |||
|                 continue | |||
|             envList.append(d) | |||
|     path = job.conf[B.TOPIC_PATH][B.ATTR_PATH_TDATA] | |||
|     if os.path.exists(path): | |||
|         for d in os.listdir(path): | |||
|             print("tdata path "+d) | |||
|             if not os.path.isdir(os.path.join(path, d)): | |||
|                 print("continue a") | |||
|                 continue | |||
|             if d[0:1] == "_": | |||
|                 print("continue b") | |||
|                 continue | |||
|             specpath = os.path.join(path, d, D.DFILE_TESTCASE_NAME + ".csv") | |||
|             readSpec(job, d, DLG_TESTCASE, specpath) | |||
|             specpath = os.path.join(path, d, D.DFILE_TESTSUITE_NAME + ".csv") | |||
|             readSpec(job, d, DLG_TESTSUITE, specpath) | |||
| 
 | |||
| def readSpec(job, testentity, testgran, specpath): | |||
|     print("spec "+specpath) | |||
|     if not os.path.isfile(specpath): | |||
|         print("continue c") | |||
|         return | |||
|     text = tools.file_tool.read_file_text(job, specpath, job.m) | |||
|     print("-----------\n"+text+"\n------------------") | |||
|     if re.match(r".*?depricated;[jJyY]", text): | |||
|         return | |||
|     if re.match(r".*\nhead:application;", text): | |||
|         print("## app gematcht") | |||
|         res = re.search(r".*head:application;(.+)\n", text) | |||
|         apps = res.group(1).replace(";", ",").split(",") | |||
|         print("# "+str(apps)) | |||
|         for a in apps: | |||
|             if len(a) < 1: | |||
|                 break | |||
|             if a not in entities[testgran]: | |||
|                 entities[testgran][a] = [] | |||
|             print(a+" in "+testentity+" "+testgran+" -- "+str(entities)) | |||
|             entities[testgran][a].append(testentity) | |||
| 
 | |||
| def printProc(job, process): | |||
|     print("--------------------------------------------------") | |||
|     for k in process: | |||
|         print("| {0:15s} : {1}".format(k, process[k])) | |||
|     print("--------------------------------------------------") | |||
| 
 | |||
| 
 | |||
| def restartActualProcess(job): | |||
|     """ | |||
|     check if an actual process is open | |||
|     :return: | |||
|     """ | |||
|     path = tools.path_tool.getActualJsonPath(job) | |||
|     if os.path.exists(path): | |||
|         actProc = tools.file_tool.read_file_dict(job, path, job.m) | |||
|         print("restartActJob "+str(actProc)) | |||
|         printProc(job, actProc) | |||
|         step = int(actProc["step"]) | |||
|         if actProc["program"] == "test_executer": | |||
|             if step > 5: | |||
|                 dialogProcess(job) | |||
|             else: | |||
|                 actProc["step"] = str(step+1) | |||
|                 tools.job_tool.start_child_process(job, actProc) | |||
|                 restartActualProcess(job) | |||
|         selection = [DLG_NEWJOB, DLG_REDO] | |||
| 
 | |||
|         nr = int(JOB_NR[actProc["gran"]][actProc["program"]]["jobnr"]) | |||
|         if (actProc["gran"] == DLG_TESTSUITE and nr < 4) or (actProc["gran"] == DLG_TESTCASE and nr < 9): | |||
|             selection.append(DLG_CONTINUE) | |||
|         if nr == 7: | |||
|             selection.append(DLG_DUMMY_STEP) | |||
|         choice = getChoice(job, selection, DLG_ENVIRONMENT) | |||
|         print(choice) | |||
|         if choice == DLG_REDO: | |||
|             tools.job_tool.start_child_process(job, actProc) | |||
|             restartActualProcess(job) | |||
|         elif choice == DLG_DUMMY_STEP: | |||
|             actProc["program"] = JOB_LIST[nr+1] | |||
|             tools.job_tool.start_child_process(job, actProc) | |||
|             restartActualProcess(job) | |||
|         elif choice == DLG_CONTINUE: | |||
|             if nr == 7: | |||
|                 nr = 9 | |||
|             else: | |||
|                 nr += 1 | |||
|             print (" act nr "+str(nr)) | |||
|             actProc["step"] = str(step + 1) | |||
|             actProc["program"] = JOB_LIST[nr] | |||
|             tools.job_tool.start_child_process(job, actProc) | |||
|         elif choice == DLG_NEWJOB: | |||
|             dialogProcess(job) | |||
|     else: | |||
|         dialogProcess(job) | |||
| 
 | |||
| 
 | |||
| def dialogProcess(job): | |||
|     """ | |||
|     dialog for selection and starting a process | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     process = {} | |||
|     index = 0 | |||
|     print("create new process") | |||
|     selection = [] | |||
|     selection = LIST_DLG_GRAN | |||
|     if DLG_TESTCASE + " - " + DLG_COMPLETE not in selection: | |||
|         selection.append(DLG_TESTCASE + " - " + DLG_COMPLETE) | |||
|     if DLG_TESTSUITE + " - " + DLG_COMPLETE not in selection: | |||
|         selection.append(DLG_TESTSUITE + " - " + DLG_COMPLETE) | |||
|     choice = getChoice(job, LIST_DLG_GRAN, DLG_START_QUESTION) | |||
|     if DLG_COMPLETE in choice: | |||
|         process["gran"] = choice[0:-3-len(DLG_COMPLETE)] | |||
|         process["program"] = "test_executer" | |||
|         process["step"] = 1 | |||
|     else: | |||
|         process["gran"] = choice | |||
|         process["program"] = JOB_NR[process["gran"]]["start"] | |||
|         process["step"] = 1 | |||
|     if len(appList) == 1: | |||
|         process["app"] = appList[0] | |||
|     else: | |||
|         process["app"] = getChoice(job, appList, DLG_ENVIRONMENT) | |||
|     # | |||
|     if len(envList) == 1: | |||
|         process["env"] = envList[0] | |||
|     else: | |||
|         process["env"] = getChoice(job, envList, DLG_ENVIRONMENT) | |||
|     # | |||
|     if len(entities[process["gran"]][process["app"]]) == 1: | |||
|         process["entity"] = entities[process["gran"]][process["app"]][0] | |||
|     else: | |||
|         process["entity"] = getChoice(job, entities[process["gran"]][process["app"]], process["gran"]) | |||
|     print(str(process)) | |||
|     setattr(job.par, B.PAR_ENV, process["env"]) | |||
|     setattr(job.par, B.PAR_APP, process["app"]) | |||
|     if process["gran"] == DLG_TESTCASE: | |||
|         setattr(job.par, B.PAR_TESTCASE, process["entity"]) | |||
|         setattr(job.par, B.PAR_TCTIME, tools.date_tool.getActdate(tools.date_tool.F_DIR)) | |||
|         path = tools.path_tool.composePattern(job, "{"+P.P_TCBASE+"}", None) | |||
|         process[B.PAR_TCDIR] = path | |||
|     elif process["gran"] == DLG_TESTSUITE: | |||
|         setattr(job.par, B.PAR_TESTSUITE, process["entity"]) | |||
|         setattr(job.par, B.PAR_TSTIME, tools.date_tool.getActdate(tools.date_tool.F_DIR)) | |||
|         path = tools.path_tool.composePattern(job, "{"+P.P_TSBASE+"}", None) | |||
|         process[B.PAR_TSDIR] = path | |||
|     tools.job_tool.start_child_process(job, process) | |||
|     restartActualProcess(job) | |||
| 
 | |||
| def getChoice(job, choiselist, description): | |||
|     index = 0 | |||
|     print("+------------- "+description+" ----------") | |||
|     print('| | {:2d} : {:60s}'.format(0, "exit")) | |||
|     for k in choiselist: | |||
|         index += 1 | |||
|         print('| | {:2d} : {:60s}'.format(index, k)) | |||
|     print("+-----------------------------------------------") | |||
|     choice = input("Auswahl 1-" + str(index) + ": ") | |||
|     if not choice.isnumeric(): | |||
|         print("FEHLER Fehleingabe "+choice) | |||
|         getChoice(job, choiselist, description) | |||
|     elif int(choice) < 1: | |||
|         exit(0) | |||
|     elif int(choice) > index: | |||
|         print("FEHLER Fehleingabe "+choice) | |||
|         getChoice(job, choiselist, description) | |||
|     else: | |||
|         return choiselist[int(choice) - 1] | |||
| 
 | |||
| 
 | |||
| 
 | |||
| if __name__ == '__main__': | |||
|     job = basic.program.Job(PROGRAM_NAME, "", {}) | |||
|     readContext(job) | |||
|     restartActualProcess(job) | |||
| @ -0,0 +1,140 @@ | |||
| """ | |||
| Dieses Programm durchlaeuft das angegebene Programmverzeichnis und ermittelt zu jeder Datei den md5-Hash. | |||
| Wenn neben diesem Programm eine Datei *md5Hash.txt liegt, werden die Werte gegen diese Datei verglichen. | |||
| weitere Feature: | |||
| * in Anwendung ueberfuehren, z.B. eine jar | |||
| * aufrubar ueber cli und Dialog | |||
| * config zu Standardeingaben --path, --work; | |||
| * --name mit Aufbauregel Release + Name | |||
| * Namensliste hinterlegen mit: unterverzeichnis, repo-name und repo-branch | |||
| * Methoden zum Annehmen einer Lieferung (unzip Subzips, pruefen, git-push nach korrekter Pruefung | |||
| * Methoden zum Erzeugen einer Lieferung | |||
| Definition *_md5protokoll.txt: datei \t md5checksum \n | |||
| """ | |||
| import argparse | |||
| import datetime | |||
| import hashlib | |||
| import os | |||
| 
 | |||
| def openLog(args): | |||
|     startTime = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |||
|     path = os.path.join(getattr(args, "work"), getattr(args, "name") + "_" + startTime + ".txt") | |||
|     logfile = open(path, 'w', encoding="utf-8") | |||
|     logfile.write("* * * * * * * * * *  PROTOKOLLL MD5-Checksum-Pruefung  * * * * * * * * * * * * * * *\n") | |||
|     logfile.write("Name: " + getattr(args, "name") + "\n") | |||
|     logfile.write("Path: " + getattr(args, "path") + "\n") | |||
|     logfile.write("Dir : " + getattr(args, "dir") + "\n") | |||
|     return logfile | |||
| 
 | |||
| def openResult(args, mode, suffix): | |||
|     path = os.path.join(getattr(args, "work"), getattr(args, "name") + "_"+suffix+".txt") | |||
|     if mode == "r" and not os.path.exists(path): | |||
|         return None | |||
|     resultfile = open(path, mode, encoding="utf-8") | |||
|     return resultfile | |||
| 
 | |||
| def traverseDir(logfile, resultfile, path, rootpath): | |||
|     logfile.write("traverse " + path + "\n") | |||
|     for f in sorted(os.listdir(path)): | |||
|         if f[:1] == ".": | |||
|             continue | |||
|         if f[:2] == "__": | |||
|             continue | |||
|         if os.path.isfile(os.path.join(path, f)): | |||
|             fname = os.path.join(path, f) | |||
|             lname = fname.replace(rootpath, "") | |||
|             logfile.write(". " + lname + "\n") | |||
|             resultfile.write(lname + "\t" + getMD5Hash(fname) + "\n") | |||
|         elif os.path.isdir(os.path.join(path, f)): | |||
|             traverseDir(logfile, resultfile, os.path.join(path, f), rootpath) | |||
| 
 | |||
| def getMD5Hash(path): | |||
|     hash_md5 = hashlib.md5() | |||
|     with open(path, "rb") as f: | |||
|         for chunk in iter(lambda: f.read(4096), b""): | |||
|             hash_md5.update(chunk) | |||
|     return hash_md5.hexdigest() | |||
| 
 | |||
| def compareLists(logfile, args): | |||
|     protokollfile = openResult(args, "r", "md5protokoll") | |||
|     if protokollfile is None: | |||
|         logfile.write("Kein Vergleich, da Protokolldatei fehlt! \n") | |||
|         return | |||
|     resultfile = openResult(args, "r", "md5result") | |||
|     protLines = protokollfile.readlines() | |||
|     protokollfile.close() | |||
|     resultLines = resultfile.readlines() | |||
|     resultfile.close() | |||
|     p = 0 | |||
|     r = 0 | |||
|     error = False | |||
|     while (True): | |||
|         # print("p " + str(p) + " r " + str(r)) | |||
|         if len(protLines) > p: | |||
|             protRow = protLines[p].replace("\r","").split("\t") | |||
|         else: | |||
|             protRow = None | |||
|         if len(resultLines) > r: | |||
|             resRow = resultLines[r].replace("\r","").split("\t") | |||
|         else: | |||
|             resRow = None | |||
|         if protRow is None and resRow is None: | |||
|             break | |||
|         elif protRow is None and resRow is not None: | |||
|             error = True | |||
|             logfile.write("ERROR Result " + resRow[0] + ": ist ueberzaehlig\n") | |||
|             r += 1 | |||
|         elif resRow is not None and resRow is not None and protRow[0] > resRow[0]: | |||
|             error = True | |||
|             logfile.write("ERROR Result " + resRow[0] + ": ist ueberzaehlig\n") | |||
|             r += 1 | |||
|         elif resRow is None and protRow is not None: | |||
|             error = True | |||
|             logfile.write("ERROR Protokoll " + protRow[0] + ": ist ueberzaehlig\n") | |||
|             p += 1 | |||
|         elif protRow is not None and resRow is not None and protRow[0] < resRow[0]: | |||
|             error = True | |||
|             logfile.write("ERROR Protokoll " + protRow[0] + ": ist ueberzaehlig\n") | |||
|             p += 1 | |||
|         elif protRow is not None and resRow is not None and protRow[0] == resRow[0]: | |||
|             if protRow[1] != resRow[1]: | |||
|                 error = True | |||
|                 logfile.write("ERROR "+protRow[0]+": md5Hash unterscheiden sich (" + protRow[1] + "!=" + resRow[1].strip() + ")\n") | |||
|             r += 1 | |||
|             p += 1 | |||
|     if error: | |||
|         logfile.write("\n+--------------------------------------------------------+\n") | |||
|         logfile.write("| Fehler aufgetreten, die Dateien unterscheiden sich     |\n") | |||
|         logfile.write("+--------------------------------------------------------+\n") | |||
|     else: | |||
|         logfile.write("\nDateien unterscheiden sich nicht\n") | |||
| 
 | |||
| 
 | |||
| def readParameter(): | |||
|     """ | |||
|     --dir  das zu durchsuchende Verzeichnis | |||
|     --name Namenszusatz fuer das zu untersuchende Programmpaket | |||
|     --work Arbeitserzeichnis mit: | |||
|      <name>_md5result.txt         erstellte Ergebnisdatei | |||
|      <name>_md5protokoll.txt      mitgelieferte Vergleichsdatei | |||
|      <name>_JJJJMMTT_hhmmss.txt   Protokolldatei | |||
|     """ | |||
|     parser = argparse.ArgumentParser() | |||
|     parser.add_argument('-p', '--path', required=True, action='store') | |||
|     parser.add_argument('-d', '--dir', required=True, action='store') | |||
|     parser.add_argument('-n', '--name', required=True, action='store') | |||
|     parser.add_argument('-w', '--work', required=True, action='store') | |||
|     args = parser.parse_args() | |||
|     return args | |||
| 
 | |||
| if __name__ == '__main__': | |||
|     args = readParameter() | |||
|     logfile = openLog(args) | |||
|     logfile.write("\n") | |||
|     resultfile = openResult(args, "w", "md5result") | |||
|     path = os.path.join(getattr(args, "path")) | |||
|     traverseDir(logfile, resultfile, path, path) | |||
|     resultfile.close() | |||
|     logfile.write("\n") | |||
|     compareLists(logfile, args) | |||
|     logfile.close() | |||
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| @ -0,0 +1,246 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.program | |||
| import basic.toolHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import model.constants as M | |||
| import tools.data_const as D | |||
| import tools.path_const as P | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| import tools.file_type | |||
| 
 | |||
| TABLE_NAMES = ["application", "ap_project", "ap_component"] | |||
| DEFAULT_SYNC = M.SYNC_FULL_GIT2DB | |||
| 
 | |||
| TABLE_NAME = B.SUBJECT_APP | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "apid" | |||
| 
 | |||
| 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 """ | |||
| 
 | |||
| def searchProjects(job, appl): | |||
|     """ | |||
|     search all relevant projects from server-configuration | |||
|     filtered by parameter --application , --project | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     projects = {} | |||
|     if B.SUBJECT_PROJECTS in job.conf: | |||
|         for k in job.conf[B.SUBJECT_PROJECTS]: | |||
|             if k in B.LIST_SUBJECTS: | |||
|                 continue | |||
|             if hasattr(job.par, B.PAR_PROJ) and k != getattr(job.par, B.PAR_PROJ): | |||
|                 continue | |||
|             if hasattr(job.par, B.PAR_APP) \ | |||
|             and k not in appl[B.SUBJECT_APPS][getattr(job.par, B.PAR_APP)][B.SUBJECT_PROJECTS]: | |||
|                 continue | |||
|             projects[k] = appl[B.SUBJECT_PROJECTS][k] | |||
|             projects[k][B.SUBJECT_ENVIRONMENT] = [] | |||
|     else: | |||
|         job.conf[B.SUBJECT_PROJECTS] = appl[B.SUBJECT_PROJECTS] | |||
|     return projects | |||
| 
 | |||
| def select_applications(job, projectList): | |||
|     """ | |||
|     get all project which are configured for the workspace | |||
|     with all environments where the application of the project are installed | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     appl = tools.config_tool.getConfig(job, P.KEY_BASIC, B.SUBJECT_APPS) | |||
|     return searchApplications(job, projectList, appl) | |||
| 
 | |||
| def searchApplications(job, projectList, appl): | |||
|     appList = {} | |||
|     for proj in projectList: | |||
|         if hasattr(job, "par") and hasattr(job.par, B.PAR_PROJ) and proj != getattr(job.par, B.PAR_PROJ): | |||
|             continue | |||
|         for app in appl[B.SUBJECT_APPS]: | |||
|             if B.SUBJECT_PROJECT in appl[B.SUBJECT_APPS][app] and proj != appl[B.SUBJECT_APPS][app][B.SUBJECT_PROJECT]: | |||
|                 continue | |||
|             appList[app] = appl[B.SUBJECT_APPS][app] | |||
|     return appList | |||
| 
 | |||
| 
 | |||
| import model.entity | |||
| def syncEnitities(job): | |||
|     """ | |||
|     synchronize the configuration with the database | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     syncMethod = DEFAULT_SYNC | |||
|     if syncMethod.count("-") < 2: | |||
|         return | |||
|     fileTime = model.entity.VAL_ZERO_TIME | |||
|     dbTime = model.entity.VAL_ZERO_TIME | |||
|     # get git-commit | |||
|     if "git" in syncMethod: | |||
|         apppath = tools.config_tool.select_config_path(job, P.KEY_BASIC, B.SUBJECT_APPS, "") | |||
|         repopath = apppath[len(job.conf[B.TOPIC_PATH][B.ATTR_PATH_COMPS]) + 1:] | |||
|         gitresult = tools.git_tool.gitLog(job, B.ATTR_PATH_COMPS, repopath, 1) | |||
|         fileTime = gitresult[0]["date"] | |||
|         print(str(gitresult)) | |||
|     if "db" in syncMethod: | |||
|         if B.TOPIC_NODE_DB in job.conf: | |||
|             dbi = basic.toolHandling.getDbTool(job, job.testserver, job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) | |||
|         else: | |||
|             return "No DB in job-config" | |||
|         data = dbi.selectRows(TABLE_NAMES[0], job) | |||
|         print(str(data[B.DATA_NODE_DATA])) | |||
|         if len(data[B.DATA_NODE_DATA]) > 0: | |||
|             dbTime = data[B.DATA_NODE_DATA][0]["updtime"] | |||
| 
 | |||
|     if fileTime == dbTime: | |||
|         print("gleich") | |||
|     elif fileTime < dbTime: | |||
|         print("db vorne") | |||
|         (appObjects, appDict) = selectEntities(job, dbi) | |||
|         print(str(appDict)) | |||
|         applPath = tools.config_tool.select_config_path(job, P.KEY_BASIC, B.SUBJECT_APPS) | |||
|         tools.file_tool.write_file_dict(job.m, job, applPath, appDict) | |||
|         # | |||
|     elif fileTime > dbTime: | |||
|         print("git vorne") | |||
|         applData = tools.config_tool.getConfig(job, P.KEY_BASIC, B.SUBJECT_APPS) | |||
|         insertEntities(job, applData, dbTime, dbi) | |||
| 
 | |||
| def selectEntities(job, dbi): | |||
|     appObjects = [] | |||
|     appDict = {} | |||
|     appDict[B.SUBJECT_PROJECTS] = {} | |||
|     appDict[B.SUBJECT_APPS] = {} | |||
|     appData = dbi.selectRows(TABLE_NAMES[0], job) | |||
|     projData = dbi.selectRows(TABLE_NAMES[1], job) | |||
|     compData = dbi.selectRows(TABLE_NAMES[2], job) | |||
|     for row in appData[B.DATA_NODE_DATA]: | |||
|         ao = Application(job) | |||
|         ao.setAppRow(row, "") | |||
|         appDict[B.SUBJECT_APPS][ao.name] = {} | |||
|         for f in job.testserver.conf[B.DATA_NODE_DDL][TABLE_NAMES[0]][B.DATA_NODE_HEADER]: | |||
|             if f in model.entity.ENTITY_FIELDS: | |||
|                 continue | |||
|             appDict[B.SUBJECT_APPS][ao.name][f] = getattr(ao, f) | |||
|         apid = ao.apid | |||
|         rows = [row for row in projData[B.DATA_NODE_DATA] if row["apid"] == apid] | |||
|         ao.setProjRow(rows) | |||
|         appDict[B.SUBJECT_APPS][ao.name][B.SUBJECT_PROJECTS] = [] | |||
|         for proj in getattr(ao, B.PAR_PROJ): | |||
|             appDict[B.SUBJECT_APPS][ao.name][B.SUBJECT_PROJECTS].append(proj) | |||
|             if proj in appDict[B.SUBJECT_PROJECTS]: | |||
|                 appDict[B.SUBJECT_PROJECTS][proj][B.SUBJECT_APPS].append(ao.name) | |||
|                 continue | |||
|             appDict[B.SUBJECT_PROJECTS][proj] = {} | |||
|             appDict[B.SUBJECT_PROJECTS][proj][B.SUBJECT_APPS] = [] | |||
|             appDict[B.SUBJECT_PROJECTS][proj][B.SUBJECT_APPS].append(ao.name) | |||
|             aoproj = getattr(ao, "project")[proj] | |||
|             for f in job.testserver.conf[B.DATA_NODE_DDL][TABLE_NAMES[1]][B.DATA_NODE_HEADER]: | |||
|                 if f in model.entity.ENTITY_FIELDS + ["approid", "apid"]: | |||
|                     continue | |||
|                 appDict[B.SUBJECT_PROJECTS][proj][f] = aoproj[f] | |||
|         rows = [row for row in compData[B.DATA_NODE_DATA] if row["apid"] == apid] | |||
|         ao.setCompRow(rows) | |||
|         appDict[B.SUBJECT_APPS][ao.name][B.SUBJECT_COMPS] = [] | |||
|         for comp in getattr(ao, B.PAR_COMP): | |||
|             appDict[B.SUBJECT_APPS][ao.name][B.SUBJECT_COMPS].append(comp) | |||
|         appObjects.append(ao) | |||
|     return appObjects, appDict | |||
| 
 | |||
| def insertEntities(job,applData, dbTime, dbi): | |||
|         # insertRows | |||
|         # get list of application | |||
|         if dbTime != model.entity.VAL_ZERO_TIME: | |||
|             for t in TABLE_NAMES: | |||
|                 dbi.deleteRows(job, t) | |||
|         for app in applData[B.SUBJECT_APPS]: | |||
|             ao = Application(job) | |||
|             ao.read_entity(job, app) | |||
|             ao.insertEntity(dbi) | |||
| 
 | |||
| 
 | |||
| 
 | |||
| class Application(model.entity.Entity): | |||
|     """    table = "application" | |||
|     job = None | |||
|     name = "" | |||
|     description = "" | |||
|     reference = "" | |||
|     components = {} | |||
|     project = {} | |||
|     """ | |||
|     FIELD_ID = "apid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = [B.SUBJECT_APPS, B.SUBJECT_COMPS, B.SUBJECT_USECASES, B.SUBJECT_VARIANTS] | |||
|     PREFIX_SUBTABLE = "ap" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_APPS, | |||
|                                 tools.config_tool.get_plain_filename(job, ""), ttype=B.SUBJECT_APP) | |||
|         conf = list(config[B.SUBJECT_APPS].keys()) | |||
|         outList = [] | |||
|         for k in conf: | |||
|             if k[:1] != "_": | |||
|                 outList.append(k) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_APPS, | |||
|                                 tools.config_tool.get_plain_filename(job, name), ttype=B.SUBJECT_APP) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     def check_data(self, job, data: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [B.SUBJECT_COMPS] | |||
|         checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_KEYS] | |||
|         checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_APPS, B.SUBJECT_VARIANTS, B.SUBJECT_USECASES] | |||
|         for conf in data: | |||
|             tools.file_type.check_nodes(job, data[conf], checkNodes) | |||
|         return data | |||
| 
 | |||
| 
 | 
| @ -0,0 +1,46 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.toolHandling | |||
| import tools.data_const as D | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.config_tool | |||
| 
 | |||
| FIELD_ID = "arid" | |||
| LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, | |||
|                B.SUBJECT_PROJECT, B.SUBJECT_COMP, B.SUBJECT_TESTCASE] | |||
| """ list of object-attributes """ | |||
| LIST_NODES = [B.NODE_ATTRIBUTES] | |||
| 
 | |||
| LIST_SUBTABLES = [] | |||
| 
 | |||
| 
 | |||
| class Artifact(model.entity.Entity): | |||
|     FIELD_ID = "arid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, "artype", B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, | |||
|                    B.SUBJECT_PROJECT, B.SUBJECT_COMP, B.SUBJECT_TESTCASE] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
| 
 | |||
|     LIST_SUBTABLES = [] | |||
|     name = "" | |||
|     description = "" | |||
|     prelease = "" | |||
|     testsuites = {} | |||
|     steps = [] | |||
| 
 | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = {} | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
| @ -0,0 +1,117 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.program | |||
| import basic.constants as B | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.path_tool | |||
| import tools.file_tool | |||
| # import tools.tdata_tool | |||
| 
 | |||
| EXP_KEY_MISSING = "key is missing {}" | |||
| EXP_KEY_DOESNT_EXIST = "key doesnt exist in domain {}" | |||
| 
 | |||
| class Catalog: | |||
|     __instance = None | |||
|     """ | |||
|     in this class there should be managed each defined key-value-pairs | |||
|     the pairs ara loaded from the path testdata/catalog: | |||
|     * initially the csv-file catalog.csv | |||
|     * on demand other csv-files in the path | |||
|     """ | |||
| 
 | |||
|     def __init__(self): | |||
|         self.catalog = {} | |||
|         Catalog.__instance = self | |||
|         pass | |||
| 
 | |||
| 
 | |||
|     @staticmethod | |||
|     def getInstance(): | |||
|         if Catalog.__instance == None: | |||
|             return Catalog() | |||
|         return Catalog.__instance | |||
| 
 | |||
| 
 | |||
|     def getValue(self, job, domain, key, subkey=""): | |||
|         """ | |||
|         this function gets the value of the domain an key | |||
|         :param domain: | |||
|         :param key: | |||
|         :return: | |||
|         """ | |||
|         if not (isinstance(domain, str) or len(domain) < 1): | |||
|             raise Exception(EXP_KEY_MISSING, (domain, key)) | |||
|         if not (isinstance(key, str) or len(key) < 1): | |||
|             job.m.setError(EXP_KEY_MISSING+" ("+domain+", "+key+")") | |||
|             return "" | |||
| 
 | |||
|         if domain not in self.catalog: | |||
|             self.readDomain(domain, job) | |||
|         if key not in self.catalog[domain]: | |||
|             job.m.setError(EXP_KEY_DOESNT_EXIST+" ("+domain+", "+key+")") | |||
|             return "" | |||
|         if len(subkey) > 0: | |||
|             if subkey not in self.catalog[domain][key]: | |||
|                 job.m.setError(EXP_KEY_DOESNT_EXIST + " (" + domain + ", " + key + ", " + subkey + ")") | |||
|                 return "" | |||
|             return self.catalog[domain][key][subkey].strip() | |||
|         return self.catalog[domain][key] | |||
| 
 | |||
| 
 | |||
|     def getKeys(self, domain, job): | |||
|         """ | |||
|         this function gets the value of the domain an key | |||
|         :param domain: | |||
|         :param key: | |||
|         :return: | |||
|         """ | |||
|         if not (isinstance(domain, str) or len(domain) < 1): | |||
|             raise Exception(EXP_KEY_MISSING, (domain)) | |||
| 
 | |||
|         if domain not in self.catalog: | |||
|             self.readDomain(domain, job) | |||
|         if domain not in self.catalog: | |||
|             return [] | |||
|         out = [] | |||
|         for x in self.catalog[domain].keys(): | |||
|             out.append(x) | |||
|         return out | |||
| 
 | |||
| 
 | |||
|     def readDomain(self, domain, job): | |||
|         """ | |||
|         this function reads the domain-entries | |||
|         :param domain: | |||
|         :return: | |||
|         """ | |||
|         if not (isinstance(domain, str) or len(domain) < 1): | |||
|             raise Exception(EXP_KEY_MISSING, (domain)) | |||
|         if domain in self.catalog: | |||
|             return self.catalog[domain] | |||
|         pathname = tools.config_tool.select_config_path(job, P.KEY_CATALOG, domain) | |||
|         if pathname is None: | |||
|             raise Exception(EXP_KEY_MISSING, (domain)) | |||
|         if hasattr(job, "m"): | |||
|             msg = job.m | |||
|         else: | |||
|             msg = None | |||
|         data = tools.file_tool.read_file_dict(job, pathname, msg, D.CSV_SPECTYPE_CTLG) | |||
|         if hasattr(job, "m"): | |||
|             job.m.debug(12, "domain " + domain + " readed from " + pathname) | |||
|         self.catalog[domain] = data[B.DATA_NODE_KEYS] | |||
|         return data | |||
| 
 | |||
| 
 | |||
|     def exportXSD(self, domain): | |||
|         """ | |||
|         this function exports the domain into xsd-declaration of simple types | |||
|         :return: | |||
|         """ | |||
|         pass | |||
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| @ -0,0 +1,146 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.toolHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import model.factory | |||
| import tools.data_const as D | |||
| import tools.path_const as P | |||
| import tools.config_tool as config_tool | |||
| import tools.file_tool as file_tool | |||
| import tools.git_tool | |||
| import tools.file_type | |||
| 
 | |||
| TABLE_NAMES = ["component", "co_step", "co_table", "co_artifact", "co_comps"] | |||
| DEFAULT_SYNC = model.entity.SYNC_FULL_GIT2DB | |||
| 
 | |||
| TABLE_NAME = "component" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "coid" | |||
| 
 | |||
| CP_SUBJECT_COMPS = "components" | |||
| CP_SUBJECT_STEPS = "steps" | |||
| CP_SUBJECT_TABLES = "tables" | |||
| CP_SUBJECT_ARTS = B.SUBJECT_ARTIFACTS | |||
| LIST_CP_SUBJECTS = [CP_SUBJECT_COMPS, CP_SUBJECT_STEPS, CP_SUBJECT_TABLES, CP_SUBJECT_ARTS] | |||
| 
 | |||
| REL_ATTR_TYPE = "relationtyp" | |||
| REL_ATTR_FILE = "conffile" | |||
| REL_ATTR_FTYPE = "filetyp" | |||
| REL_ATTR_IP_PATTERN = "ippattern" | |||
| REL_ATTR_HOST_PATTERN = "hostpattern" | |||
| REL_ATTR_PORT_PATTERN = "portpattern" | |||
| REL_ATTR_URL_PATTERN = "urlpattern" | |||
| LIST_REL_ATTR = [REL_ATTR_TYPE, REL_ATTR_FILE, REL_ATTR_FTYPE, | |||
|                  REL_ATTR_IP_PATTERN, REL_ATTR_HOST_PATTERN, REL_ATTR_PORT_PATTERN, REL_ATTR_URL_PATTERN] | |||
| 
 | |||
| 
 | |||
| def select_components(job, project, application): | |||
|     """ | |||
|     get all project which are configured for the workspace | |||
|     with all environments where the application of the project are installed | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     outList = [] | |||
|     appl = tools.config_tool.getConfig(job, P.KEY_BASIC, B.SUBJECT_APPS) | |||
|     path = job.conf[B.TOPIC_PATH][B.ATTR_PATH_COMPS] | |||
|     for p in os.listdir(path): | |||
|         if p in ["catalog", "config", "test", "tools"]: | |||
|             continue | |||
|         if p[0:1] in [".", "_"]: | |||
|             continue | |||
|         if not os.path.isdir(os.path.join(path, p)): | |||
|             continue | |||
|         outList.append(p) | |||
|     return outList | |||
| 
 | |||
| class Component(model.entity.Entity): | |||
|     FIELD_ID = "coid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES, B.DATA_NODE_TOPICS] | |||
|     LIST_SUBTABLES = [B.SUBJECT_ARTIFACTS, B.SUBJECT_COMPS, B.SUBJECT_STEPS, B.SUBJECT_DATATABLES] | |||
|     PREFIX_SUBTABLE = "co" | |||
|     coid = 0 | |||
|     name = "" | |||
|     description = "" | |||
|     reference = "" | |||
|     project = "" | |||
|     application = "" | |||
|     attributes = "" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         # suche weiterleiten | |||
|         if application != "": | |||
|             app = model.factory.getApplication() | |||
|             return list(app.components.keys()) | |||
|         path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_COMPS]) | |||
|         outList = self.getDirlist(job, path, "csv") | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_COMP, tools.config_tool.get_plain_filename(job, name), "", ttype=B.SUBJECT_COMP) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     def check_data(self, job, data: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [B.SUBJECT_COMPS] | |||
|         checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_KEYS] | |||
|         checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_APPS, B.SUBJECT_VARIANTS, B.SUBJECT_USECASES] | |||
|         for conf in data: | |||
|             tools.file_type.check_nodes(job, data[conf], checkNodes) | |||
|         return data | |||
| 
 | |||
| 
 | |||
|     def write_entity(self, job, name): | |||
|         return | |||
| 
 | |||
|     def remove_entity(self, job, name): | |||
|         return | |||
|     def select_entity(self, job, name): | |||
|         return | |||
| 
 | |||
|     def update_entity(self, job, name): | |||
|         return | |||
| 
 | |||
|     def delete_entity(self, job, name): | |||
|         return | |||
| 
 | |||
| @ -0,0 +1,11 @@ | |||
| import basic.constants as B | |||
| SYNC_FULL_GIT2DB = "full-git-db" | |||
| SYNC_HEAD_GIT2DB = "head-git-db" | |||
| SYNC_COPY_FILE2DB = "copy-file-db" | |||
| SYNC_ONLY_GIT = "only-git" | |||
| SYNC_ONLY_DB = "only-db" | |||
| 
 | |||
| STORAGE_DB = B.TOPIC_NODE_DB | |||
| STORAGE_FILE = B.TOPIC_NODE_FILE | |||
| 
 | |||
| LIST_ENTITY_SYNC = [SYNC_ONLY_GIT, SYNC_FULL_GIT2DB, SYNC_HEAD_GIT2DB, SYNC_COPY_FILE2DB, SYNC_ONLY_DB] | |||
| 
 | 
| @ -0,0 +1,58 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| 
 | |||
| FIELD_ID = "dtid" | |||
| FIELD_NAME = "name" | |||
| FIELD_DESCRIPTION = B.SUBJECT_DESCRIPTION | |||
| FIELD_REFERENCE = B.SUBJECT_REFERENCE | |||
| FIELD_COMPONENT = B.SUBJECT_COMP | |||
| FIELD_ATTRIBUTES = B.NODE_ATTRIBUTES | |||
| FIELD_HEADER = "" | |||
| LIST_FIELDS = [FIELD_ID, FIELD_NAME, FIELD_DESCRIPTION, FIELD_REFERENCE, FIELD_COMPONENT] | |||
| LIST_NODES = [B.DATA_NODE_HEADER, B.DATA_NODE_DATA, B.DATA_NODE_FIELDS] | |||
| 
 | |||
| LIST_SUBTABLES = {} | |||
| 
 | |||
| class Datatable(model.entity.Entity): | |||
|     FIELD_ID = "dtid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, "dtdatabase", "dtschema", | |||
|                    B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_COMP] | |||
|     LIST_NODES = [B.DATA_NODE_HEADER, B.DATA_NODE_DATA, B.DATA_NODE_FIELDS, B.NODE_ATTRIBUTES, "fieldnames"] | |||
| 
 | |||
|     LIST_SUBTABLES = [] | |||
|     dcid = 0 | |||
|     document = "" | |||
|     description = "" | |||
|     project = "" | |||
|     reference = "" | |||
| 
 | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_COMPS], P.KEY_CATALOG, P.VAL_TABLES) | |||
|         outList = self.getDirlist(job, path, "csv") | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         config = self.getConfig(job, P.KEY_CATALOG, name, tools.config_tool.get_plain_filename(job, name)) | |||
|         return self.setAttributes(job, config, name, LIST_FIELDS, LIST_NODES, LIST_SUBTABLES) | |||
| 
 | |||
| 
 | |||
| 
 | 
| 
 | 
| @ -0,0 +1,643 @@ | |||
| import getpass | |||
| import os | |||
| import re | |||
| import basic.toolHandling | |||
| #import model.factory | |||
| # import model.entity | |||
| import tools.data_const as D | |||
| import tools.path_const as P | |||
| import basic.constants as B | |||
| import tools.config_tool | |||
| import tools.data_tool | |||
| import tools.date_tool | |||
| import tools.file_tool | |||
| 
 | |||
| ENTITY_NAME = "name" | |||
| ENTITY_ATTRIBUTES = B.NODE_ATTRIBUTES | |||
| ENTITY_INS_COMMIT = "inscommit" | |||
| ENTITY_INS_AUTHOR = "insauthor" | |||
| ENTITY_INS_TIME = "instime" | |||
| ENTITY_UPD_COMMIT = "updcommit" | |||
| ENTITY_UPD_AUTHOR = "updauthor" | |||
| ENTITY_UPD_TIME = "updtime" | |||
| ENTITY_ACTUAL = "actual" | |||
| VAL_ACTUAL = 1 | |||
| VAL_ZERO_TIME = "2000-01-01_00-00-00" | |||
| ENTITY_FIELDS = [ENTITY_INS_COMMIT, ENTITY_INS_AUTHOR, ENTITY_INS_TIME, | |||
|                  ENTITY_UPD_COMMIT, ENTITY_UPD_AUTHOR, ENTITY_UPD_TIME, ENTITY_ACTUAL] | |||
| SYNC_FULL_GIT2DB = "full-git-db" | |||
| SYNC_HEAD_GIT2DB = "head-git-db" | |||
| SYNC_COPY_FILE2DB = "copy-file-db" | |||
| SYNC_ONLY_GIT = "only-git" | |||
| SYNC_ONLY_DB = "only-db" | |||
| 
 | |||
| STORAGE_DB = B.TOPIC_NODE_DB | |||
| STORAGE_FILE = B.TOPIC_NODE_FILE | |||
| 
 | |||
| LIST_ENTITY_SYNC = [SYNC_ONLY_GIT, SYNC_FULL_GIT2DB, SYNC_HEAD_GIT2DB, SYNC_COPY_FILE2DB, SYNC_ONLY_DB] | |||
| 
 | |||
| print("is importing module.entity") | |||
| def getEntityValue(job, field, gitcommit): | |||
|     if field == ENTITY_INS_COMMIT: | |||
|         return "" | |||
|     if field == ENTITY_INS_AUTHOR: | |||
|         return getpass.getuser() | |||
|     if field == ENTITY_INS_TIME: | |||
|         return tools.date_tool.getActdate(tools.date_tool.F_DIR) | |||
|     if field == ENTITY_UPD_COMMIT: | |||
|         return gitcommit["commit"] | |||
|     if field == ENTITY_UPD_AUTHOR: | |||
|         return gitcommit["author"] | |||
|     if field == ENTITY_UPD_TIME: | |||
|         return gitcommit["date"] | |||
|     if field == ENTITY_ACTUAL: | |||
|         return VAL_ACTUAL | |||
| 
 | |||
| 
 | |||
| class Entity: | |||
|     """ system-name for this entity """ | |||
|     FIELD_ID = "" | |||
|     LIST_FIELDS = [] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [] | |||
|     LIST_SUBTABLES = [] | |||
|     PREFIX_SUBTABLE = "" | |||
| 
 | |||
|     def __init__(self, job, entityname: str = "", name: str = "", args: dict = {}): | |||
|         import model.table | |||
|         self.job = job | |||
|         if entityname == "": | |||
|             classname = str(self) | |||
|             a = classname.split(".") | |||
|             entityname = a[1] | |||
|         entityname = tools.data_tool.getSingularKeyword(entityname) | |||
|         self.entityname = entityname | |||
|         if entityname not in ["", "table"]: | |||
|             self.setDdlAttributes(job, entityname) | |||
|             for f in self.ddls[entityname][model.table.LISTNAME_SUBTABLE]: | |||
|                 self.setDdlAttributes(job, self.PREFIX_SUBTABLE + "_" + tools.data_tool.getSingularKeyword(f)) | |||
|         if len(name) > 1: | |||
|             self.getEntity(job, name, args) | |||
| 
 | |||
| 
 | |||
|     def setDdlAttributes(self, job, entityname: str=""): | |||
|         """ | |||
| 
 | |||
|         :param job: | |||
|         :return: | |||
|         """ | |||
|         import model.table | |||
|         self.ddls = {} | |||
|         ddlargs = {model.table.TYPE_CONTEXT: B.ATTR_INST_TESTSERVER} | |||
|         if entityname not in ["", B.SUBJECT_DATATABLES]: | |||
|             table = model.table.Table(job) | |||
|             table = table.read_entity(job, self.entityname, args=ddlargs) | |||
|             self.ddls[entityname] = {} | |||
|             self.ddls[entityname][model.table.LISTNAME_DDLNAMES] = getattr(table, model.table.LISTNAME_DDLNAMES) | |||
|             self.ddls[entityname][model.table.LISTNAME_DDLFIELDS] = getattr(table, model.table.LISTNAME_DDLFIELDS) | |||
|         listFields = [] | |||
|         listNodes = [] | |||
|         listSubtables = [] | |||
|         for f in self.ddls[entityname][model.table.LISTNAME_DDLNAMES]: | |||
|             if self.ddls[entityname][model.table.LISTNAME_DDLFIELDS][f][D.DDL_FIELD] in B.LIST_SUBJECTS: | |||
|                 listSubtables.append(f) | |||
|             elif self.ddls[entityname][model.table.LISTNAME_DDLFIELDS][f][D.DDL_FORMAT] in ["jlob"]: | |||
|                 listNodes.append(f) | |||
|             elif self.ddls[entityname][model.table.LISTNAME_DDLFIELDS][f][D.DDL_FIELD] in table.LIST_ADMINFIELDS: | |||
|                 pass | |||
|             else: | |||
|                 listFields.append(f) | |||
|         self.ddls[entityname][model.table.LISTNAME_FIELDS] = listFields | |||
|         self.ddls[entityname][model.table.LISTNAME_NODES] = listNodes | |||
|         self.ddls[entityname][model.table.LISTNAME_SUBTABLE] = listSubtables | |||
|         # check LISTEN ... hard coded vs. configuered | |||
|         # TODO why hard coded const ?? | |||
|         for f in listFields: | |||
|             if f not in self.LIST_FIELDS: | |||
|                 raise Exception(entityname + " " + str(self) + " a check list <-> LIST_FIELDS " + f) | |||
|         for f in listNodes: | |||
|             if f not in self.LIST_NODES: | |||
|                 raise Exception(entityname + " " + str(self)  + " a check list <-> LIST_NODES " + f) | |||
|         for f in listSubtables: | |||
|             if f not in self.LIST_SUBTABLES: | |||
|                 raise Exception(entityname + " " + str(self)  + " a check list <-> LIST_SUBTABLES " + f) | |||
|         for f in self.LIST_FIELDS: | |||
|             if f not in listFields: | |||
|                 raise Exception(entityname + " " + str(self)  + " b check list <-> LIST_FIELDS " + f) | |||
|         for f in self.LIST_NODES: | |||
|             if f in B.LIST_DATA_NODE or f[:1] == "_": | |||
|                 continue | |||
|             if f not in listNodes: | |||
|                 raise Exception(entityname + " " + str(self) + " b check list <-> LIST_NODES " + f) | |||
|         for f in self.LIST_SUBTABLES: | |||
|             if f not in listSubtables: | |||
|                 raise Exception(entityname + " " + str(self) + " b check list <-> LIST_SUBTABLES " + f) | |||
| 
 | |||
| 
 | |||
|     def get_unique_names(self, job, storage = "", project = "", application = "", gran = "", | |||
|                          ttype: str = "", args: dict = {}) -> list: | |||
|         """ | |||
|         gets the entity-names from the defined storage - the field name must be an unique identifier | |||
|         :param job: | |||
|         :param storage:  opt. values db / files - default files | |||
|         :param project: opt. select-criteria if used and defined | |||
|         :param application: opt. select-criteria if used and defined | |||
|         :param gran: opt. granularity values testcase / testsuite / testplan | |||
|         :param ttype: opt. ddd | |||
|         :param args: opt. additional args | |||
|         :return: list of entity-names | |||
|         """ | |||
|         entityNames = [] | |||
|         if storage == STORAGE_DB: | |||
|             entityNames = self.select_unique_names(job, project, application, gran, args) | |||
|         elif storage == STORAGE_FILE: | |||
|             entityNames = self.read_unique_names(job, project, application, gran, args) | |||
|         else: | |||
|             entityNames = self.read_unique_names(job, project, application, gran, args) | |||
|         return [item for item in entityNames if item not in B.LIST_DATA_NODE] | |||
| 
 | |||
|     def select_unique_names(self, job, project, application, gran, args): | |||
|         """ | |||
|         reads the entity-names from file-storage | |||
|         :param job: | |||
|         :param project: opt. select-criteria if used and defined | |||
|         :param application: opt. select-criteria if used and defined | |||
|         :param gran: opt. granularity values testcase / testsuite / testplan | |||
|         :param args: opt. additional args | |||
|         :return: list of entity-names | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def get_entities(self, job, storage="", project="", application="", gran="", ttype="", args={}): | |||
|         """ | |||
|         gets the entity-names from the defined storage | |||
|         :param job: | |||
|         :param storage: opt. values db / files - default files | |||
|         :param project: opt. select-criteria if used and defined | |||
|         :param application: opt. select-criteria if used and defined | |||
|         :param gran: opt. granularity values testcase / testsuite / testplan | |||
|         :param args: opt. additional args | |||
|         :return: list of entity-names | |||
|         """ | |||
|         entities = [] | |||
|         entityNames = self.get_unique_names(job, storage=storage, project=project, application=application, | |||
|                                             gran=gran, args=args, ttype=ttype) | |||
|         for k in entityNames: | |||
|             if storage == STORAGE_DB: | |||
|                 entity = self.select_entity(job, k) | |||
|             elif storage == STORAGE_FILE: | |||
|                 print(" entity.read_e "+ k) | |||
|                 entity = self.read_entity(job, k) | |||
|             else: | |||
|                 entity = self.read_entity(job, k) | |||
|             entities.append(entity) | |||
|         return entities | |||
| 
 | |||
|     def read_unique_names(self, job, project, application, gran, args, ttype: str=""): | |||
|         """ | |||
|         reads the entity-names from file-storage | |||
|         :param job: | |||
|         :param project: select-criteria if used and defined | |||
|         :param application: select-criteria if used and defined | |||
|         :param gran: granularity values testcase / testsuite / testplan | |||
|         :param args additional args | |||
|         :return: list of entity-names | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def setDbAttributes(self, job, tables): | |||
|         """ | |||
|         set the db-attributes like connection and ddl | |||
|         :param job: | |||
|         :param tables: list of table-names | |||
|         :return: | |||
|         """ | |||
|         setattr(self, "m", job.m) | |||
|         config = {} | |||
|         config[B.TOPIC_CONN] = job.conf[B.TOPIC_NODE_DB] | |||
|         config[B.DATA_NODE_DDL] = {} | |||
|         for t in tables: | |||
|             ddl = tools.db_abstract.get_ddl(job, B.ATTR_INST_TESTSERVER, t) | |||
|             config[B.DATA_NODE_DDL][t] = ddl | |||
|         setattr(self, "conf", config) | |||
| 
 | |||
|     def getEntity(self, job, name: str, args: dict={}): | |||
|         if len(args) > 0: | |||
|             self.set_entity(job, name, args) | |||
|         elif B.TOPIC_NODE_DB in job.conf: | |||
|             self.select_entity(job, name) | |||
|             #self.read_entity(job, name) | |||
|         else: | |||
|             self.read_entity(job, name) | |||
| 
 | |||
|     def set_entity(self, job, name: str, args: dict): | |||
|         setattr(self, D.FIELD_NAME, name) | |||
|         for k in self.LIST_FIELDS: | |||
|             if k in args: | |||
|                 setattr(self, k, args[k]) | |||
|         for k in self.LIST_SUBTABLES: | |||
|             if k in args: | |||
|                 setattr(self, k, args[k]) | |||
|         for k in self.LIST_NODES: | |||
|             if k in args: | |||
|                 setattr(self, k, args[k]) | |||
| 
 | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     @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: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def check_data(self, job, tdata: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         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 write_entity(self, job, name): | |||
|         """ | |||
|         writes the entity into the file-system | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def insert_entity(self, job, name): | |||
|         """ | |||
|         inserts the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def update_entity(self, job, name): | |||
|         """ | |||
|         writes the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def remove_entity(self, job, name): | |||
|         """ | |||
|         removes the entity from the file-system | |||
|         it similar to delete_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def removeEntity(self, job, name, storagepath, ext): | |||
|         """ | |||
|         removes the entity from the file-system | |||
|         it similar to delete_entity | |||
|         :param job: | |||
|         :param name: single substring or list of name or dict of names with the keys as | |||
|         :return: | |||
|         """ | |||
|         nameList = [] | |||
|         if isinstance(name, dict): | |||
|             nameList = name.keys() | |||
|         elif isinstance(name, list): | |||
|             nameList = name | |||
|         else: | |||
|             nameList.append(name) | |||
|         for name in nameList: | |||
|             pathname = os.path.join(storagepath, name + "." + ext) | |||
|             os.remove(pathname) | |||
| 
 | |||
|     def delete_entity(self, job, name, table): | |||
|         """ | |||
|         deletes the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     """ 2023-05 """ | |||
|     @staticmethod | |||
|     def getConfig(job, module: str, subject: str, name: str, ttype: str = D.CSV_SPECTYPE_DDL) -> dict: | |||
|         """ | |||
|         reads the entity from the database | |||
|         it should get the same result like read_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = tools.config_tool.getConfig(job, module, subject, ttype=ttype) | |||
|         oldConfig = config | |||
|         if config is not None: | |||
|             if subject not in config: | |||
|                 newConfig = {} | |||
|                 newConfig[subject] = {} | |||
|                 for k in config: | |||
|                     newConfig[subject][k] = config[k] | |||
|                 config = newConfig | |||
|             pass | |||
|             if len(name) == 0: | |||
|                 return config | |||
|             elif name in config[subject]: | |||
|                 outConfig = {} | |||
|                 outConfig[name] = config[subject][name] | |||
|                 return outConfig | |||
|             elif B.DATA_NODE_KEYS in config[subject] \ | |||
|             and name in config[subject][B.DATA_NODE_KEYS]: | |||
|                 # if csv-data is a catalog | |||
|                 outConfig = {} | |||
|                 outConfig[name] = config[subject][B.DATA_NODE_KEYS][name] | |||
|                 return outConfig | |||
|             elif name == subject: | |||
|                 return config | |||
|         raise Exception("keine Config zu "+name) | |||
| 
 | |||
|     @staticmethod | |||
|     def set_subtables(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: | |||
|         """ | |||
|         raise Exception("not implemented ") | |||
| 
 | |||
| 
 | |||
|     @staticmethod | |||
|     def getDirlist(job, path, ext) -> list: | |||
|         outList = [] | |||
|         for k in os.listdir(path): | |||
|             if k[:1] in [".", "_"]: | |||
|                 continue | |||
|             if k in [P.KEY_CATALOG, P.KEY_TOOL, P.VAL_CONFIG, P.VAL_TEST, P.VAL_TOOLS]: | |||
|                 continue | |||
|             if ext == "": | |||
|                 if not os.path.isdir(os.path.join(path, k)): | |||
|                     continue | |||
|                 outList.append(k) | |||
|                 continue | |||
|             else: | |||
|                 if not os.path.isfile(os.path.join(path, k)): | |||
|                     continue | |||
|                 if len(k) < len(ext): | |||
|                     continue | |||
|                 xx = k[-len(ext):] | |||
|                 if ext != k[-len(ext):]: | |||
|                     continue | |||
|             outList.append(k[:-len(ext)-1]) | |||
|         return outList | |||
| 
 | |||
|     def setAttributes(self, job, config, rootname, fields, nodes, subjects): | |||
|         """ | |||
|         it sets the attributes of config into the entity-object | |||
|         :param job: | |||
|         :param config:    dictionary of readed specification resp. configuration | |||
|         :param rootname:  rootname of config | |||
|         :param fields:    list of field-names, the model-const LIST_FIELDS | |||
|         :param nodes:     list of node-names, the model-const LIST_NODES | |||
|         :param subjects:  list of subtables-names, the model-const LIST_SUBTABLES | |||
|         :return: | |||
|         """ | |||
|         """ 2023-05 """ | |||
|         import model.factory | |||
|         verify = False | |||
|         if not job is None: | |||
|             self.job = job | |||
|         if rootname not in config: | |||
|             return self | |||
|         for k in fields + nodes: | |||
|             key = tools.data_tool.getExistKeyword(k, config[rootname]) | |||
|             if verify: print("setFields " + k + " / " + key) | |||
|             if key in ["", D.FIELD_PROJECT]: | |||
|                 continue | |||
|             if verify: print("setFields " + str(k) + " = " + str(config[rootname][key])) | |||
|             if k in fields: | |||
|                 setattr(self, tools.data_tool.getSingularKeyword(k), tools.data_tool.getValueStr(config[rootname][key])) | |||
|             elif k == "fieldnames": | |||
|                 setattr(self, tools.data_tool.getPluralKeyword(k), config[rootname][key]) | |||
|             else: | |||
|                 setattr(self, tools.data_tool.getSingularKeyword(k), config[rootname][key]) | |||
|         setattr(self, D.FIELD_NAME, rootname) | |||
|         for k in subjects: | |||
|             # tables: { person: { _header: [] , _data: {} } } | |||
|             # | |||
|             if k in [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_ROW]: | |||
|                 continue | |||
|             objects = {} | |||
|             key = tools.data_tool.getExistKeyword(k, config[rootname]) | |||
|             if key == "": | |||
|                 continue | |||
|             if not isinstance(config[rootname][key], dict): | |||
|                 continue | |||
|             for o in config[rootname][key]: | |||
|                 if o in [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_ROW, B.DATA_NODE_PATH]: | |||
|                     continue | |||
|                 args = {} | |||
|                 print("### " + k + " " + o + " " + str(config[rootname][key][o])) | |||
|                 if not isinstance(config[rootname][key][o], dict): | |||
|                     objects[k] = o | |||
|                     continue | |||
|                 for x in config[rootname][key][o]: | |||
|                     args[x] = config[rootname][key][o][x] | |||
|                 # args[k] = config[rootname][key][o] | |||
|                 if verify: print("setSubObject " + o + " = " + str(args[k])) | |||
|                 object = model.factory.get_entity_object(self.job, entityname=k, name=o, args=args) | |||
|                 objects[object.getIDName()] = object | |||
|             if verify: print("setSubtables " + k + " = " + str(objects)) | |||
|             setattr(self, k, objects) | |||
|         topics = {} | |||
|         key = tools.data_tool.getExistKeyword(B.DATA_NODE_TOPICS, config[rootname]) | |||
|         if key != "": | |||
|             for k in B.LIST_TOPIC_NODES: | |||
|                 if k in config[rootname][key]: | |||
|                     topics[k] = config[rootname][key][k] | |||
|             setattr(self, tools.data_tool.getPluralKeyword(B.DATA_NODE_TOPICS), topics) | |||
|         return self | |||
| 
 | |||
|     def getFieldList(self) -> list: | |||
|         """ | |||
|         returns a list of scalar attributes | |||
|         :return: LIST_FIELDS | |||
|         """ | |||
|         return self.LIST_FIELDS | |||
| 
 | |||
|     def getNodeList(self) -> list: | |||
|         """ | |||
|         returns a list of sub-nodes - which can be persisted in a clob-field | |||
|         :return: LIST_NODES | |||
|         """ | |||
|         return self.LIST_NODES | |||
| 
 | |||
|     def getSubtableList(self) -> list: | |||
|         """ | |||
|         returns a list of sub-tables | |||
|         :return: LIST_SUBTABLES | |||
|         """ | |||
|         return self.LIST_SUBTABLES | |||
| 
 | |||
|     def getPrefixSubtable(self) -> str: | |||
|         """ | |||
|         returns a list of sub-tables | |||
|         :return: LIST_SUBTABLES | |||
|         """ | |||
|         return self.PREFIX_SUBTABLE | |||
| 
 | |||
|     def getSubtableNames(self) -> list: | |||
|         """ | |||
|         returns a list of sub-tables | |||
|         :return: LIST_SUBTABLES | |||
|         """ | |||
|         out = [] | |||
|         for t in self.LIST_SUBTABLES: | |||
|             out.append(self.PREFIX_SUBTABLE+"_"+t) | |||
|         return out | |||
| 
 | |||
|     def getName(self) -> str: | |||
|         """ | |||
|         returns the name - maybe build from other attributes | |||
|         :return: | |||
|         """ | |||
|         return self.name | |||
| 
 | |||
|     def getIDName(self) -> str: | |||
|         """ | |||
|         it returns the name as unique-id - maybe build from few attributes | |||
|         :return: | |||
|         """ | |||
|         return self.name | |||
| 
 | |||
|     def setSubtable(self, job, subtable, sublist): | |||
|         outDict = {} | |||
|         for k in sublist: | |||
|             pass | |||
| 
 | |||
|     def getDbAttr(self, job): | |||
|         out = {} | |||
|         for attr in [B.ATTR_DB_HOST, B.ATTR_DB_USER, B.ATTR_DB_DATABASE, B.ATTR_DB_PASSWD]: | |||
|             out[attr] = job.conf[B.TOPIC_NODE_DB][attr] | |||
|         return out | |||
| 
 | |||
|     def getDdl(self, job, ddl): | |||
|         out = {} | |||
|         for t in ddl: | |||
|             out[t] = {} | |||
|             for f in ddl[t]: | |||
|                 out[t][f] = {} | |||
|                 for a in ddl[t][f]: | |||
|                     print("entity-23 "+f+", "+a+" "+str(ddl)) | |||
|                     out[t][f][a] = ddl[t][f][a] | |||
|                 out[t][f][D.DDL_FIELD] = f | |||
|             out[t][B.DATA_NODE_HEADER] = list(ddl[t].keys()) | |||
|         return out | |||
| 
 | |||
|     def createSchema(self, testserver): | |||
|         if B.TOPIC_NODE_DB in self.job.conf: | |||
|             dbi = basic.toolHandling.getDbTool(self.job, testserver, self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) | |||
|         else: | |||
|             return "No DB in job-config" | |||
|         sql = self.get_schema() | |||
|         print(sql) | |||
|         for s in sql.split(";\n"): | |||
|             if len(s) < 3: continue | |||
|             try: | |||
|                 # dbi.execStatement(s+";", self.job.conf[B.TOPIC_NODE_DB]) | |||
|                 print("SQL executed: "+s) | |||
|             except Exception as e: | |||
|                 raise Exception("Fehler bei createSchema "+s) | |||
| 
 | |||
| 
 | |||
|     def getHistoryFields(self): | |||
|         dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] | |||
|         dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) | |||
|         sql = dbi.getSchemaAttribut("inscommit", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("insauthor", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("instime", D.TYPE_TIME)+"," | |||
|         sql += dbi.getSchemaAttribut("updcommit", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("updauthor", D.TYPE_STR)+"," | |||
|         sql += dbi.getSchemaAttribut("updtime", D.TYPE_TIME)+"," | |||
|         sql += dbi.getSchemaAttribut("actual", D.TYPE_INT) | |||
|         return sql | |||
| 
 | |||
|     def selectHistoryFields(self): | |||
|         if B.TOPIC_NODE_DB in self.job.conf: | |||
|             dbi = basic.toolHandling.getDbTool(self.job, self.testserver, self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) | |||
|         else: | |||
|             return "No DB in job-config" | |||
|         dbi.selectRows | |||
| 
 | |||
|     def getHistoryIndex(self, table) -> str: | |||
|         dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] | |||
|         dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) | |||
|         sql = dbi.getSchemaIndex(table, "actual") + "\n" | |||
|         return sql | |||
| 
 | |||
|     def get_schema(self, tableName, tableObject): | |||
|         pass | |||
| 
 | |||
|     def insert_entity(self, job): | |||
|         """ | |||
|         inserts the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         pass | |||
| 
 | |||
| def read_spec(job, testentity, testgran, specpath): | |||
|     if not os.path.isfile(specpath): | |||
|         return | |||
|     text = tools.file_tool.read_file_text(job, specpath, job.m) | |||
|     if re.match(r".*?depricated;[jJyY]", text): | |||
|         return None | |||
|     spec = {} | |||
|     regex = re.compile(r".*\nhead:(.*?);(.+)") | |||
|     for res in regex.finditer(text): | |||
|         #res = re.search(r".*head:(.*?);(.+)\n", text) | |||
|         key = res.group(1) | |||
|         if key == B.SUBJECT_DESCRIPTION: | |||
|             spec[B.SUBJECT_DESCRIPTION] = res.group(2).replace(";", "") | |||
|         elif key in [B.SUBJECT_APPS, B.PAR_APP]: | |||
|             apps = res.group(2).replace(";", ",").split(",") | |||
|             spec[B.SUBJECT_APPS] = apps | |||
|         else: | |||
|             val = res.group(2).replace(";", "") | |||
|             spec[key] = val | |||
|     return spec | |||
| 
 | |||
| 
 | |||
| 
 | 
| @ -0,0 +1,122 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| import tools.data_const as D | |||
| import tools.file_type | |||
| 
 | |||
| TABLE_NAME = "environment" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "enid" | |||
| 
 | |||
| 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 """ | |||
| 
 | |||
| TABLE_NAMES = ["environment", "en_project", "en_component"] | |||
| DEFAULT_SYNC = model.entity.SYNC_FULL_GIT2DB | |||
| 
 | |||
| def select_environments(job, projectList): | |||
|     """ | |||
|     searches and gets environments in which the applications of the project are declared that these are installed | |||
|     filtered by parameter --environment | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     environments = {} | |||
|     path = job.conf[B.TOPIC_PATH][B.ATTR_PATH_ENV] | |||
|     if not os.path.exists(path): | |||
|         raise Exception("Umgebungsverzeichnis existiert nicht "+path) | |||
|     for envdir in os.listdir(path): | |||
|         if not os.path.isdir(os.path.join(path, envdir)): | |||
|             continue | |||
|         if envdir[0:1] == "_": | |||
|             continue | |||
|         try: | |||
|             pathname = tools.config_tool.select_config_path(job, P.KEY_TOOL, "conn", envdir) | |||
|             doc = tools.file_tool.read_file_dict(job, pathname, job.m) | |||
|             for proj in doc[B.SUBJECT_ENVIRONMENT][B.CONF_NODE_GENERAL][B.SUBJECT_PROJECTS]: | |||
|                 if proj in projectList: | |||
|                     environments[envdir] = doc[B.SUBJECT_ENVIRONMENT][B.CONF_NODE_GENERAL] | |||
|                 elif len(projectList) == 1 and projectList[0] == "ALL": | |||
|                     environments[envdir] = doc[B.SUBJECT_ENVIRONMENT][B.CONF_NODE_GENERAL] | |||
|         except: | |||
|             continue | |||
|     return environments | |||
| 
 | |||
| 
 | |||
| class Environment(model.entity.Entity): | |||
|     FIELD_ID = "enid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE] | |||
|     """ list of object-attributes """ | |||
|     LIST_SUBTABLES = [B.SUBJECT_COMPS, B.SUBJECT_PROJECTS] | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     PREFIX_SUBTABLE = "en" | |||
| 
 | |||
|     name = "" | |||
|     description = "" | |||
|     reference = "" | |||
|     attributes = "" | |||
|     project = "" | |||
|     component = "" | |||
| 
 | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_ENV]) | |||
|         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: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_ENV, name, | |||
|                                 tools.config_tool.get_plain_filename(job, name), ttype=B.SUBJECT_ENVIRONMENT) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     def check_data(self, job, data: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [B.SUBJECT_COMPS] | |||
|         checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_KEYS] | |||
|         checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_PROJECTS] | |||
|         return tools.file_type.check_nodes(job, data, checkNodes) | |||
| @ -0,0 +1,128 @@ | |||
| import model.entity | |||
| import basic.constants as B | |||
| import basic.Testserver | |||
| 
 | |||
| class Magazin(): | |||
|     __instance = None | |||
|     __entities = {} | |||
|     @staticmethod | |||
|     def getInstance(): | |||
|         if Magazin.__instance == None: | |||
|             return Magazin() | |||
| 
 | |||
|     @staticmethod | |||
|     def setEntity(name, object): | |||
|         if name not in Magazin.__entities: | |||
|             Magazin.__entities[name] = object | |||
|         return Magazin.__entities[name] | |||
| 
 | |||
|     @staticmethod | |||
|     def getEntity(name): | |||
|         if name in Magazin.__entities: | |||
|             return Magazin.__entities[name] | |||
| 
 | |||
|     @staticmethod | |||
|     def hasEntity(name): | |||
|         if name in Magazin.__entities: | |||
|             return True | |||
|         return False | |||
| 
 | |||
| def get_entity_object(job, entityname: str, name: str="", args: dict={}): | |||
|     if name == "" and len(args) == 0 and Magazin.hasEntity(entityname): | |||
|         return Magazin.getEntity(entityname) | |||
|     if entityname in [B.SUBJECT_STEPS, B.SUBJECT_STEP]: | |||
|         entity = getStep(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_STORIES, B.SUBJECT_STORY, "storys"]: | |||
|         entity = getStory(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_VARIANTS, B.SUBJECT_VARIANT]: | |||
|         entity = getVariant(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_DATATABLES, B.SUBJECT_DATATABLE]: | |||
|         entity = getDatatable(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_USECASES, B.SUBJECT_USECASE]: | |||
|         entity = getUsecase(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_PROJECTS, B.SUBJECT_PROJECT]: | |||
|         entity = getProject(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_APPS, B.SUBJECT_APP]: | |||
|         entity = getApplication(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_COMPS, B.SUBJECT_COMP]: | |||
|         entity = getComponent(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_ARTIFACTS, B.SUBJECT_ARTIFACT]: | |||
|         entity = getArtifact(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_TESTCASES, B.SUBJECT_TESTCASE]: | |||
|         entity = getTestcase(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_TESTSUITES, B.SUBJECT_TESTSUITE]: | |||
|         entity = getTestsuite(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_TESTPLANS, B.SUBJECT_TESTPLAN]: | |||
|         entity = getTestplan(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_USERS, B.SUBJECT_USER]: | |||
|         entity = getUser(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_REL, B.SUBJECT_RELS]: | |||
|         entity = getRelease(job, entityname, name, args) | |||
|     elif entityname in [B.SUBJECT_ENVIRONMENT, B.SUBJECT_ENVIRONMENTS]: | |||
|         entity = getEnvironment(job, entityname, name, args) | |||
|     else: | |||
|         return None | |||
|     if name == "" and len(args) == 0 and not Magazin.hasEntity(entityname): | |||
|         return Magazin.setEntity(entityname, entity) | |||
|     return entity | |||
| 
 | |||
| def getRelease(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.prelease | |||
|     return model.prelease.Release(job, entityname, name, args) | |||
| 
 | |||
| def getEnvironment(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.environment | |||
|     return model.environment.Environment(job, entityname, name, args) | |||
| 
 | |||
| def getArtifact(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.artifact | |||
|     return model.artifact.Artifact(job, entityname, name, args) | |||
| 
 | |||
| def getApplication(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.application | |||
|     return model.application.Application(job, entityname, name, args) | |||
| 
 | |||
| def getProject(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.project | |||
|     return model.project.Project(job, entityname, name, args) | |||
| 
 | |||
| def getComponent(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.component | |||
|     return model.component.Component(job, entityname, name, args) | |||
| 
 | |||
| def getTestplan(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.testplan | |||
|     return model.testplan.Testplan(job, entityname, name, args) | |||
| 
 | |||
| def getTestsuite(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.testsuite | |||
|     return model.testsuite.Testsuite(job, entityname, name, args) | |||
| 
 | |||
| def getTestcase(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.testcase | |||
|     return model.testcase.Testcase(job, entityname, name, args) | |||
| 
 | |||
| def getStep(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.step | |||
|     return model.step.Step(job, entityname, name, args) | |||
| 
 | |||
| def getStory(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.story | |||
|     return model.story.Story(job, entityname, name, args) | |||
| 
 | |||
| def getUsecase(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.usecase | |||
|     return model.usecase.Usecase(job, entityname, name, args) | |||
| 
 | |||
| def getUser(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.user | |||
|     return model.user.User(job, entityname, name, args) | |||
| 
 | |||
| def getVariant(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.variant | |||
|     return model.variant.Variant(job, entityname, name, args) | |||
| 
 | |||
| def getDatatable(job=None, entityname: str="" , name: str="", args: dict={}): | |||
|     import model.datatable | |||
|     return model.datatable.Datatable(job, entityname, name, args) | |||
| 
 | |||
| 
 | 
| 
 | 
| @ -0,0 +1,121 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.toolHandling | |||
| import basic.componentHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| import tools.file_type | |||
| 
 | |||
| TABLE_NAME = "prelease" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "rlid" | |||
| FIELD_PRELEASE = "prelease" | |||
| """ project-release""" | |||
| FIELD_APPRELEASE = "apprelease" | |||
| FILE_EXTENSION = D.DFILE_TYPE_CSV | |||
| UNIQUE_FIELDS = [D.FIELD_NAME] | |||
| """ unique business field as human identifer """ | |||
| IDENTIFYER_FIELDS = [FIELD_ID] | |||
| """ unique technical field as technical identifer """ | |||
| 
 | |||
| class Release(model.entity.Entity): | |||
|     FIELD_ID = "rlid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = [B.SUBJECT_APPS, B.SUBJECT_STORIES] | |||
|     PREFIX_SUBTABLE = "rl" | |||
| 
 | |||
| 
 | |||
|     rlid = 0 | |||
|     name = "" | |||
|     project = "" | |||
|     application = "" | |||
|     description = "" | |||
|     attributes = "" | |||
|     reference = "" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_CATALOG, B.SUBJECT_RELS, tools.config_tool.get_plain_filename(job, ""), D.CSV_SPECTYPE_CTLG) | |||
|         outList = list(config[B.SUBJECT_RELS][B.DATA_NODE_KEYS].keys()) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_CATALOG, B.SUBJECT_RELS, | |||
|                                 tools.config_tool.get_plain_filename(job, name), ttype=B.SUBJECT_REL) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
|     def rebuild_data(self, 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.popTablesNode(job, data) | |||
|         data = tools.file_type.popSubjectsNode(job, data) | |||
|         data = self.rebuildReleases(job, data) | |||
|         return data | |||
| 
 | |||
|     def rebuildReleases(self, job, data: dict) -> dict: | |||
|         outdata = {} | |||
|         for row in data[B.DATA_NODE_DATA]: | |||
|             if FIELD_PRELEASE not in row: | |||
|                 continue | |||
|             if row[FIELD_PRELEASE] in outdata: | |||
|                 general = outdata[row[FIELD_PRELEASE]] | |||
|             else: | |||
|                 general = {} | |||
|                 general[B.SUBJECT_APPS] = {} | |||
|             if ( FIELD_APPRELEASE not in row | |||
|                 or len(FIELD_APPRELEASE) == 0 | |||
|                 or row[FIELD_APPRELEASE] == row[FIELD_PRELEASE]): | |||
|                 for f in self.LIST_FIELDS: | |||
|                     if f in row: | |||
|                         general[f] = row[f] | |||
|             if B.SUBJECT_APPS in row and len(row[B.SUBJECT_APPS]) > 0: | |||
|                 a = str(row[B.SUBJECT_APPS]).split(",") | |||
|                 for app in a: | |||
|                     o = {} | |||
|                     o["appname"] = app | |||
|                     o["apprelease"] = row[FIELD_APPRELEASE] | |||
|                     o["prelease"] = row[FIELD_PRELEASE] | |||
|                     general[B.SUBJECT_APPS][app] = o | |||
|             outdata[row[FIELD_PRELEASE]] = general | |||
|         return outdata | |||
| 
 | |||
|     def check_data(self, job, data: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [] #[B.SUBJECT_APPS] | |||
|         checkNodes[tools.file_type.MUSTNT_NODES] = [] # [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_KEYS] | |||
|         checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_PROJECTS] | |||
|         return tools.file_type.check_nodes(job, data, checkNodes) | |||
| 
 | 
| @ -0,0 +1,272 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.toolHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.db_abstract | |||
| import tools.git_tool | |||
| import tools.file_type | |||
| 
 | |||
| TABLE_NAME = "project" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "prid" | |||
| FIELD_NAME = "name" | |||
| FIELD_DESCRIPTION = B.SUBJECT_DESCRIPTION | |||
| FIELD_REFERENCE = B.SUBJECT_REFERENCE | |||
| LIST_FIELDS = [FIELD_ID, FIELD_NAME, FIELD_DESCRIPTION, FIELD_REFERENCE] | |||
| """ list of object-attributes """ | |||
| LIST_NODES = [] | |||
| LIST_SUBTABLES = {} | |||
| 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 Project(model.entity.Entity): | |||
|     FIELD_ID = "prid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [] | |||
|     LIST_SUBTABLES = [] | |||
|     prid = 0 | |||
|     name = "" | |||
|     description = "" | |||
|     reference = "" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, B.SUBJECT_PROJECTS, "") | |||
|         if B.SUBJECT_PROJECTS in config: | |||
|             conf = list(config[B.SUBJECT_PROJECTS].keys()) | |||
|         else: | |||
|             conf = config.keys() | |||
|         outList = [] | |||
|         for k in conf: | |||
|             if k[:1] != "_": | |||
|                 outList.append(k) | |||
|         return outList | |||
| 
 | |||
|     def select_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 | |||
|         """ | |||
|         outList = [] | |||
|         self.setDbAttributes(job, [TABLE_NAME]) | |||
|         dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|         data = dbi.selectRows(TABLE_NAME, job) | |||
|         checkList = {} | |||
|         for row in data[B.DATA_NODE_DATA]: | |||
|             key = "" | |||
|             for f in UNIQUE_FIELDS: | |||
|                 key += "_" + row[f] | |||
|             if key in checkList: | |||
|                 continue | |||
|             else: | |||
|                 checkList[key] = key | |||
|             fields = [] | |||
|             for f in UNIQUE_FIELDS: | |||
|                 fields.append(row[f]) | |||
|             outList.append(fields) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         print("name "+name) | |||
|         config = self.getConfig(job, B.SUBJECT_PROJECTS, tools.config_tool.get_plain_filename(job, name)) | |||
|         for k in LIST_FIELDS: | |||
|             if k not in config: | |||
|                 continue | |||
|             setattr(self, k, config[k]) | |||
|         return self | |||
| 
 | |||
| 
 | |||
|     def select_entity(self, job, name, row={}): | |||
|         """ | |||
|         reads the entity from the database | |||
|         it should get the same result like read_entity | |||
|         :param job: | |||
|         :param name: unique field as string, unique fields as list | |||
|             the unique-fields are defined in the class | |||
|         :return: itself with filled object-attributes | |||
|         """ | |||
|         if row is None or len(row) == 0: | |||
|             self.setDbAttributes(job, [TABLE_NAME]) | |||
|             dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|             if type(name) is list: | |||
|                 names = name | |||
|             elif type(name) is str: | |||
|                 names = [name] | |||
|             condition = "where " | |||
|             for v in names: | |||
|                 condition += " and " + "" | |||
|             data = dbi.selectRows(TABLE_NAME, job, "where username = \'" + names[0] + "\'") | |||
|             if len(data[B.DATA_NODE_DATA]) > 1: | |||
|                 raise Exception("single selection with more than one result: "+names[0]) | |||
|             elif len(data[B.DATA_NODE_DATA]) == 1: | |||
|                 row = data[B.DATA_NODE_DATA][0] | |||
|             else: | |||
|                 raise Exception("no result for: "+names[0]) | |||
|         for k in LIST_FIELDS: | |||
|             if k not in row: | |||
|                 continue | |||
|             setattr(self, k, row[k]) | |||
|         return self | |||
| 
 | |||
|     def write_entity(self, job, name): | |||
|         """ | |||
|         writes the entity into the file-system | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = {} | |||
|         config[model.project.TABLE_NAME] = {} | |||
|         pathname = os.path.join(job.conf[B.TOPIC_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, | |||
|                                 P.VAL_USER, name + ".yml") | |||
|         for k in LIST_FIELDS: | |||
|             if getattr(self, k, "") == "" \ | |||
|             or k == FIELD_ID: | |||
|                 continue | |||
|             config[model.project.TABLE_NAME][k] = getattr(self, k, "") | |||
|         tools.file_tool.write_file_dict(job.m, job, pathname, config) | |||
|         return self | |||
| 
 | |||
|     def insert_entity(self, job, name="", table="", rows={}): | |||
|         """ | |||
|         inserts the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         if table == "": | |||
|             table = self.entityname | |||
|             if len(self.ddls) == 0: | |||
|                 self.insert_entity(job, name=name, table=self.entityname, rows=rows) | |||
|         # self.setDbAttributes(job, [TABLE_NAME]) | |||
|         dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|         condition = "where" | |||
|         for f in UNIQUE_FIELDS: | |||
|             # TODO other db-formats than string has to be implemented | |||
|             condition += " and " + f + " = \'" + getattr(self, f, "") + "\'" | |||
|         condition = condition.replace("where and", "where ") | |||
|         data = dbi.selectRows(TABLE_NAME, job, condition) | |||
|         if len(data[B.DATA_NODE_DATA]) > 0: | |||
|             print("update statt insert") | |||
|             return | |||
|         if rows is None or len(rows) == 0: | |||
|             rows = [] | |||
|             row = {} | |||
|             for f in self.ddls[table]: | |||
|                 row[f] = getattr(self, f, "") | |||
|             rows.append(row) | |||
|         dbi.insertRows(job, table, rows) | |||
| 
 | |||
|     def update_entity(self, job, name): | |||
|         """ | |||
|         writes the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def remove_entity(self, job, name): | |||
|         """ | |||
|         removes the entity from the file-system | |||
|         it similar to delete_entity | |||
|         :param job: | |||
|         :param name: single substring or list of name or dict of names with the keys as | |||
|         :return: | |||
|         """ | |||
|         self.removeEntity(job, name, os.path.join(job.conf[B.TOPIC_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, P.VAL_USER), "yml") | |||
| 
 | |||
|     def delete_entity(self, job, name, table): | |||
|         """ | |||
|         deletes the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         self.setDbAttributes(job, [TABLE_NAME]) | |||
|         dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|         condition = "where" | |||
|         for f in IDENTIFYER_FIELDS: | |||
|             # TODO other db-formats than string has to be implemented | |||
|             val = dbi.getDbValue(self.conf[B.DATA_NODE_DDL][table][f], getattr(self, f, "")) | |||
|             condition += " and " + f + " = " + val + "" | |||
|         condition = condition.replace("where and", "where ") | |||
|         dbi.deleteRows(job, table, condition) | |||
| 
 | |||
|     @staticmethod | |||
|     def getConfig(job, subject, name): | |||
|         """ | |||
|         reads the entity from the database | |||
|         it should get the same result like read_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = tools.config_tool.getConfig(job, P.KEY_BASIC, subject, ttype=B.SUBJECT_PROJECT) | |||
|         if config is not None: | |||
|             if len(name) == 0: | |||
|                 return config | |||
|             elif subject in config and name in config[subject]: | |||
|                 return config[subject][name] | |||
|             elif name in config: | |||
|                 return config[name] | |||
|         raise Exception("keine Config zu "+name) | |||
| 
 | |||
|     @staticmethod | |||
|     def getCurrentUser(job): | |||
|         return os.environ.get("USERNAME") | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     @staticmethod | |||
|     def check_data(job, data: dict) -> dict: | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [] | |||
|         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_PROJECTS, B.NODE_ATTRIBUTES] | |||
|         return tools.file_type.check_nodes(job, data, checkNodes) | |||
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| @ -0,0 +1,123 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.toolHandling | |||
| import basic.componentHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| 
 | |||
| TABLE_NAME = "step" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "spid" | |||
| FIELD_NAME = "name" | |||
| FIELD_VARIANT = B.SUBJECT_VARIANT   # variant | |||
| FIELD_COMPONENT = B.SUBJECT_COMP    # variant | |||
| FIELD_SORTNR = "sortnr"             #   testcase | |||
| FIELD_STEPNR = "stepnr"             #   testcase | |||
| FIELD_DATAREF = "dataref"           #   testcase | |||
| FIELD_ATTRIBUTES = B.NODE_ATTRIBUTES | |||
| LIST_FIELDS = [FIELD_ID, FIELD_NAME, FIELD_VARIANT, FIELD_COMPONENT, FIELD_SORTNR, FIELD_STEPNR, FIELD_DATAREF] | |||
| """ list of object-attributes """ | |||
| LIST_NODES = [B.NODE_ATTRIBUTES, B.DATA_NODE_TOPICS] | |||
| LIST_SUBTABLES = [] | |||
| PREFIX_SUBTABLE = "" | |||
| 
 | |||
| 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 Step(model.entity.Entity): | |||
|     """ | |||
|     this class describes execution steps in a formal language = fields, | |||
|     in testcase-specification it describe the start-point of an action, here the business information are specified like | |||
|     * variant | |||
|     * reference of program-step, sorting-nr, reference to testdata which are specified above | |||
|     * entity which implements the action | |||
|     * further business-arguments as json-string | |||
|     the detailed steps (build the request, send the request, get the response, ..) are configured in the component | |||
|     in sub-steps of the specified step, here the technical information are configured like | |||
|     * topic and type which implements the detail-step | |||
|     * further arguments inside the dict | |||
|     """ | |||
|     FIELD_ID = "spid" | |||
|     FIELD_SORTNR = "sortnr"  # testcase | |||
|     FIELD_STEPNR = "stepnr"  # testcase | |||
|     FIELD_DATAREF = "dataref"  # testcase | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_VARIANT, B.SUBJECT_COMP, FIELD_SORTNR, FIELD_STEPNR, FIELD_DATAREF, | |||
|                    B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES, B.DATA_NODE_TOPICS] | |||
|     LIST_SUBTABLES = [] | |||
|     name = "" # variant | |||
|     variant = "" | |||
|     sortnr = 0 | |||
|     """ sorting, alternative step may have the same sortnr, then the correct step is selected by program-variant """ | |||
|     stepnr = 0 | |||
|     """ in order to filter the steps for specific program-executions """ | |||
|     dataref = "" | |||
|     component = "" # the name of the component or of the parameter "testcases" | |||
|     attributes = {} | |||
|     topics = "" # is set by component-configuration | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_VARIANTS, | |||
|                                 tools.config_tool.get_plain_filename(job, ""), B.SUBJECT_STEP) | |||
|         outList = list(config[B.SUBJECT_VARIANTS].keys()) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_VARIANTS, | |||
|                                 tools.config_tool.get_plain_filename(job, name), B.SUBJECT_STEP) | |||
|         return self.setAttributes(job, config, name, LIST_FIELDS, LIST_NODES, LIST_SUBTABLES) | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     @staticmethod | |||
|     def check_data(job, data: dict) -> dict: | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [] | |||
|         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_COMP, B.NODE_ATTRIBUTES] | |||
|         return tools.file_type.check_nodes(job, data, checkNodes) | |||
| 
 | |||
|     def getIDName(self): | |||
|         """ | |||
|         it returns the name as unique-id - maybe build from few attributes | |||
|         :return: | |||
|         """ | |||
|         return "{:02d}_{}".format(int(self.sortnr), self.variant) | |||
| 
 | 
| @ -0,0 +1,63 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| 
 | |||
| TABLE_NAME = "story" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "stid" | |||
| """ list of object-attributes """ | |||
| 
 | |||
| FILE_EXTENSION = D.DFILE_TYPE_CSV | |||
| UNIQUE_FIELDS = [D.FIELD_NAME] | |||
| """ unique business field as human identifer """ | |||
| IDENTIFYER_FIELDS = [FIELD_ID] | |||
| """ unique technical field as technical identifer """ | |||
| 
 | |||
| class Story(model.entity.Entity): | |||
|     FIELD_ID = "stid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = [B.SUBJECT_RELS] | |||
|     PREFIX_SUBTABLE = "st" | |||
| 
 | |||
|     stid = 0 | |||
|     story = "" | |||
|     project = "" | |||
|     description = "" | |||
|     reference = "" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_CATALOG, B.SUBJECT_STORIES, | |||
|                                 tools.config_tool.get_plain_filename(job, ""), ttype=D.CSV_SPECTYPE_CTLG) | |||
|         outList = list(config[B.SUBJECT_STORIES][B.DATA_NODE_KEYS].keys()) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_CATALOG, B.SUBJECT_STORIES, | |||
|                                 tools.config_tool.get_plain_filename(job, name), ttype=D.CSV_SPECTYPE_CTLG) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
| 
 | 
| @ -0,0 +1,346 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.toolHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| 
 | |||
| TYPE_ADMIN = "admin" | |||
| TYPE_CTLG = "catalog" | |||
| TYPE_CONTEXT = "context" | |||
| 
 | |||
| LISTNAME_DDLNAMES = "fieldnames" | |||
| LISTNAME_DDLFIELDS = "fielddef" | |||
| LISTNAME_FIELDS = "fieldlist" | |||
| LISTNAME_NODES = "nodelist" | |||
| LISTNAME_SUBTABLE = "subtables" | |||
| 
 | |||
| TABLE_NAME = "table" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "tbid" | |||
| 
 | |||
| DEFAULT_FIELD = "" | |||
| DEFAULT_TYPE = "string" | |||
| DEFAULT_FORMAT = "vchar(256)" | |||
| DEFAULT_INDEX = "N" | |||
| DEFAULT_CONSTRAINT = "nullable" | |||
| DEFAULT_AGGREGAT = "" | |||
| DEFAULT_GENERIC = "" | |||
| DEFAULT_KEY = "" | |||
| DEFAULT_ACCEPTANCE = "" | |||
| DEFAULT_ALIAS = "" | |||
| DEFAULT_DESCRIPTION = "" | |||
| DEFAULTS = { | |||
|     D.DDL_FIELD : DEFAULT_FIELD, | |||
|     D.DDL_TYPE : DEFAULT_TYPE, | |||
|     D.DDL_FORMAT : DEFAULT_FORMAT, | |||
|     D.DDL_INDEX : DEFAULT_INDEX, | |||
|     D.DDL_CONSTRAINT : DEFAULT_CONSTRAINT, | |||
|     D.DDL_AGGREGAT : DEFAULT_AGGREGAT, | |||
|     D.DDL_GENERIC : DEFAULT_GENERIC, | |||
|     D.DDL_KEY : DEFAULT_KEY, | |||
|     D.DDL_ACCEPTANCE : DEFAULT_ACCEPTANCE, | |||
|     D.DDL_ALIAS : DEFAULT_ALIAS, | |||
|     D.DDL_DESCRIPTION : DEFAULT_DESCRIPTION | |||
| } | |||
| def select_tables(job, project="", application="", component=""): | |||
|     outList = [] | |||
|     appl = tools.config_tool.getConfig(job, P.KEY_BASIC, B.SUBJECT_APPS) | |||
|     path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_COMPS], "catalog", "tables") | |||
|     for p in os.listdir(path): | |||
|         if p[-4:] not in [".csv", ".yml", ".xml", "json"]: | |||
|             continue | |||
|         table = p[:-4] | |||
|         outList.append(table) | |||
|     return outList | |||
| 
 | |||
| class Table(model.entity.Entity): | |||
|     """ | |||
|     table-object as part of a database | |||
|     in different of datatable it is neither a concrete table in the automation-model | |||
|     nor a concrete table in the system-model | |||
|     it is an abstract super-class in order to relation to the database-management-system | |||
|     """ | |||
|     FIELD_ID = "tbid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES, "fielddef", "fieldnames"] | |||
| 
 | |||
|     LIST_SUBTABLES = [] | |||
|     LIST_ADMINFIELDS = { | |||
|         "insauthor": { | |||
|             "_field": "insauthor", | |||
|             "type": "str", | |||
|             "format": "varchar(128)", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "inscommit": { | |||
|             "_field": "inscommit", | |||
|             "type": "str", | |||
|             "format": "varchar(1024)", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "instime": { | |||
|             "_field": "instime", | |||
|             "type": "time", | |||
|             "format": "time", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "updauthor": { | |||
|             "_field": "updauthor", | |||
|             "type": "str", | |||
|             "format": "varchar(128)", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "updcommit": { | |||
|             "_field": "updcommit", | |||
|             "type": "str", | |||
|             "format": "varchar(1024)", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "updtime": { | |||
|             "_field": "updtime", | |||
|             "type": "time", | |||
|             "format": "time", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "actual": { | |||
|             "_field": "actual", | |||
|             "type": "int", | |||
|             "format": "int", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         } | |||
|     } | |||
|     # project | |||
|     # testcase | |||
|     # artefact : | |||
|     # | |||
|     LIST_CATALOGFIELDS = { | |||
|         "project": { | |||
|             "_field": "project", | |||
|             "type": "str", | |||
|             "format": "varchar(128)", | |||
|             "index": "I", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "application": { | |||
|             "_field": "application", | |||
|             "type": "str", | |||
|             "format": "varchar(128)", | |||
|             "index": "I", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "testcase": { | |||
|             "_field": "testcase", | |||
|             "type": "str", | |||
|             "format": "varchar(128)", | |||
|             "index": "I", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         }, | |||
|         "artifact": { | |||
|             "_field": "artifact", | |||
|             "type": "str", | |||
|             "format": "varchar(128)", | |||
|             "index": "I", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "result " | |||
|         }, | |||
|         "refdate": { | |||
|             "_field": "refdate", | |||
|             "type": "time", | |||
|             "format": "time", | |||
|             "index": "N", | |||
|             "generic": "", | |||
|             "aggregat": "", | |||
|             "key": "", | |||
|             "acceptance": "", | |||
|             "alias": "", | |||
|             "description": "" | |||
|         } | |||
|     } | |||
|     tbid = 0 | |||
|     name = "" | |||
|     project = "" | |||
|     fieldnames = [] | |||
|     fielddef = {} | |||
| 
 | |||
|     def set_object(self, project, name): | |||
|         self.project = project | |||
|         self.name = name | |||
| 
 | |||
|     def get_schema(self, tableName="", tableType=""): | |||
|         """ | |||
|         gets schema/ddl-informations in order to create the database | |||
|         """ | |||
|         sql = "" | |||
|         sqlTable = "" | |||
|         sqlSub = "" | |||
|         dbi = basic.toolHandling.getDbTool(self.job, None, self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) | |||
|         sqlTable += dbi.getCreateTable(tableName) | |||
|         tableId = "" | |||
|         if tableType in [TYPE_CTLG]: | |||
|             for f in self.LIST_CATALOGFIELDS.keys(): | |||
|                 if f not in self.fieldnames: | |||
|                     self.fieldnames.append(f) | |||
|                 self.fielddef[f] = self.LIST_CATALOGFIELDS[f] | |||
|         if tableType in [TYPE_ADMIN, TYPE_CTLG]: | |||
|             for f in self.LIST_ADMINFIELDS.keys(): | |||
|                 if f not in self.fieldnames: | |||
|                     self.fieldnames.append(f) | |||
|                 self.fielddef[f] = self.LIST_ADMINFIELDS[f] | |||
|         for f in self.fieldnames: | |||
|             if f[0:1] == "_": | |||
|                 continue | |||
|             fo = self.fielddef[f] | |||
|             if D.DDL_INDEX in fo and len(fo[D.DDL_INDEX]) > 0: | |||
|                 a = fo[D.DDL_INDEX].split(":") | |||
|                 if a[0] == "I": | |||
|                     sqlSub += dbi.getSchemaIndex(tableName, fo[D.DDL_FIELD]) + "\n" | |||
|                 elif a[0] == "S": | |||
|                     attrList = [] | |||
|                     attr = {"attr":fo[D.DDL_FIELD], "atype": fo[D.DDL_TYPE]} | |||
|                     attrList.append(attr) | |||
|                     for i in range(2, len(a)): | |||
|                         if i % 2 == 1: | |||
|                             continue | |||
|                         if a[i] == "attr": | |||
|                             attr = {"attr":B.NODE_ATTRIBUTES, "atype": D.TYPE_TEXT} | |||
|                         elif i+1 < len(a): | |||
|                             attr = {"attr": a[i], "atype": a[i+1]} | |||
|                         attrList.append(attr) | |||
|                     sqlSub += dbi.getSchemaSubtable(a[1], attrList) + "\n" | |||
|                     sqlSub += dbi.getSchemaIndex(dbi.getSubtableName(a[1], fo[D.DDL_FIELD]), tableId) + "\n" | |||
|                     continue | |||
|             if fo[D.DDL_TYPE] not in ["subtable"]: | |||
|                 sqlTable += dbi.getSchemaAttribut(fo[D.DDL_FIELD], fo[D.DDL_TYPE]) + "," | |||
|             if fo[D.DDL_TYPE] == D.TYPE_PK: | |||
|                 tableId = fo[D.DDL_FIELD] | |||
|         sql = sqlTable[0:-1]+");\n"+sqlSub | |||
|         """ | |||
|         # print(sql) | |||
|         """ | |||
|         return sql | |||
| 
 | |||
|     def read_unique_names(self, job, project="", application="", gran= "", args={}, ttype: str="") -> list: | |||
|         return [] | |||
|     # table is not an real entity | |||
| 
 | |||
|     def read_entity(self, job, name: str, args: dict={}): | |||
|         return self.read_ddl(job, name, args=args) | |||
|     # table is not an real entity | |||
| 
 | |||
|     def read_ddl(self, job: any, name: str, args: dict = {}): | |||
|         """ | |||
|         reads the ddl of the table depending on context | |||
|         a) component: the ddl is read from specific or general component-folder | |||
|         b) testcase: the ddl is read from general component-folder | |||
|         c) testserver: the ddl is read from model-folder | |||
|         :param job: | |||
|         :param name: | |||
|         :param args: | |||
|         :return: | |||
|         """ | |||
|         config = {} | |||
|         if "context" in args: | |||
|             if args["context"] == "component": | |||
|                 ddl = tools.config_tool.getConfig(job, D.DDL_FILENAME, self.component.name, name, ttype=D.CSV_SPECTYPE_DDL) | |||
|             elif args["context"] == "testdata": | |||
|                 ddl = tools.config_tool.getConfig(job, D.DDL_FILENAME, args["context"], name, ttype=D.CSV_SPECTYPE_DDL) | |||
|             elif args["context"] == B.ATTR_INST_TESTSERVER: | |||
|                 ddl = tools.config_tool.getConfig(job, D.DDL_FILENAME, B.ATTR_INST_TESTSERVER, name, ttype=D.CSV_SPECTYPE_DDL) | |||
|             if "_name" in ddl: | |||
|                 config[ddl["_name"]] = ddl | |||
|             else: | |||
|                 config = ddl | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
|     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: | |||
|         """ | |||
|         self.read_entity(job, name) | |||
|         # raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     # def write_entity(self, job, name): | |||
|     # table is not an real entity | |||
| 
 | |||
|     # def update_entity(self, job, name): | |||
|     # table is not an real entity | |||
| 
 | |||
|     # def remove_entity(self, job, name): | |||
|     # table is not an real entity | |||
| 
 | |||
|     # def delete_entity(self, job, name): | |||
|     # table is not an real entity | |||
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| @ -0,0 +1,268 @@ | |||
| #!/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] | |||
|     PREFIX_SUBTABLE = "tc" | |||
| 
 | |||
|     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 == B.DATA_NODE_TABLES and B.SUBJECT_DATATABLES in subtables): | |||
|                     outdata[tools.data_tool.getPluralKeyword(B.SUBJECT_DATATABLES)] = data[k] | |||
|                 elif k in B.LIST_DATA_NODE and tools.data_tool.getPluralKeyword(k) in subtables: | |||
|                     outdata[tools.data_tool.getPluralKeyword(k)] = data[k] | |||
|                 elif k[:1] == "_": | |||
|                     a = k.split("-") | |||
|                     val = data[k] | |||
|                     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) | |||
|                 else: | |||
|                     outdata[k] = data[k] | |||
|             if B.DATA_NODE_OPTION in outdata and len(outdata[B.DATA_NODE_OPTION]) == 0: | |||
|                 outdata.pop(B.DATA_NODE_OPTION) | |||
|             if B.DATA_NODE_HEAD in outdata and 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 | |||
| 
 | 
| @ -0,0 +1,77 @@ | |||
| #!/usr/bin/python | |||
| # -*- coding: utf-8 -*- | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.toolHandling | |||
| import tools.data_const as D | |||
| import basic.constants as B | |||
| import tools.path_const as P | |||
| import model.entity | |||
| import tools.config_tool | |||
| 
 | |||
| FIELD_ID = "tpid" | |||
| FIELD_NAME = D.FIELD_NAME | |||
| FIELD_DESCRIPTION = B.SUBJECT_DESCRIPTION | |||
| FIELD_REFERENCE = B.SUBJECT_REFERENCE | |||
| FIELD_PROJECT = B.SUBJECT_PROJECT | |||
| FIELD_RELEASE = B.SUBJECT_REL | |||
| 
 | |||
| class Testplan(model.entity.Entity): | |||
|     LIST_FIELDS = [FIELD_ID, FIELD_NAME, FIELD_DESCRIPTION, FIELD_REFERENCE, FIELD_PROJECT, FIELD_RELEASE] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
| 
 | |||
|     LIST_SUBTABLES = [B.SUBJECT_STEPS, B.SUBJECT_TESTSUITES, B.SUBJECT_APPS] | |||
|     PREFIX_SUBTABLE = "tp" | |||
|     name = "" | |||
|     description = "" | |||
|     prelease = "" | |||
|     testsuites = {} | |||
|     steps = [] | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_VARIANTS, tools.config_tool.get_plain_filename(job, name)) | |||
|         return self.setAttributes(job, config, name, LIST_FIELDS, LIST_NODES, LIST_SUBTABLES) | |||
| 
 | |||
|     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 | |||
| 
 | 
| 
 | 
| @ -0,0 +1,186 @@ | |||
| #!/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 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 | |||
| 
 | |||
| FIELD_ID = "tsid" | |||
| FIELD_NAME = D.FIELD_NAME | |||
| FIELD_DESCRIPTION = B.SUBJECT_DESCRIPTION | |||
| FIELD_REFERENCE = B.SUBJECT_REFERENCE | |||
| FIELD_PROJECT = B.SUBJECT_PROJECT | |||
| 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_TESTCASES = B.SUBJECT_TESTCASES | |||
| SUB_STEPS = "steps" | |||
| LIST_SUBTABLES = [SUB_USECASE, SUB_STEPS, SUB_TESTCASES] | |||
| LIST_SUB_DESCRIPT = [D.DATA_ATTR_USECASE_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 Testsuite(model.entity.Entity): | |||
|     FIELD_ID = "tsid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT, B.SUBJECT_APP] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = [B.SUBJECT_USECASES, B.SUBJECT_STEPS, B.SUBJECT_TESTCASES] | |||
|     PREFIX_SUBTABLE = "ts" | |||
|     name = "" | |||
|     description = "" | |||
|     application = "" | |||
|     usecase = [] | |||
|     testcases = {} | |||
|     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 | |||
|         """ | |||
|         path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_TDATA], getattr(job.par, B.SUBJECT_PROJECT), | |||
|                             B.SUBJECT_TESTSUITES) | |||
|         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: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_TESTSUITE, tools.config_tool.get_plain_filename(job, name), "", ttype=B.SUBJECT_TESTSUITE) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     def check_data(self, job, data: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [B.SUBJECT_TESTCASES] | |||
|         checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_KEYS] | |||
|         checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_APPS, B.SUBJECT_USECASES] | |||
|         tools.file_type.check_nodes(job, data, checkNodes) | |||
|         return data | |||
| 
 | |||
| 
 | |||
|     def old_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") | |||
|         setattr(self, FIELD_NAME, name) | |||
|         config = self.getConfig(job, P.KEY_TESTSUITE, name, tools.config_tool.get_plain_filename(job, name)) | |||
|         #self.setAttributes(config, name, LIST_FIELDS, LIST_SUBTABLES) | |||
|         for k in LIST_SUBTABLES: | |||
|             if not hasattr(self, k): | |||
|                 continue | |||
|             if "_"+k in config[name] and "_"+k+"-description" in LIST_SUB_DESCRIPT: | |||
|                 values = {} | |||
|                 if "_"+k+"-description" in config[name]: | |||
|                     for l in config[name]["_"+k]: | |||
|                         if l in config[name]["_"+k+"-description"]: | |||
|                             values[config[name]["_"+k][l]] = config[name]["_" + k + "-description"][l] | |||
|                         else: | |||
|                             values[config[name]["_"+k][l]] = "" | |||
|                 else: | |||
|                     for l in config[name]["_"+k]: | |||
|                         values[config[name]["_" + k][l]] = "" | |||
|                 setattr(self, k, values) | |||
|         return self | |||
| 
 | |||
| 
 | |||
| def select_testsuite(job, project, testsuite): | |||
|     jobProj = None | |||
|     print("testsuite select: "+str(project)+" "+str(testsuite)) | |||
|     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, testsuite, D.DFILE_TESTSUITE_NAME + ".csv") | |||
|     spec = model.entity.read_spec(job, testsuite, J.GRAN_TS, specpath) | |||
|     if jobProj is None: | |||
|         delattr(job.par, B.PAR_PROJ) | |||
|     else: | |||
|         setattr(job.par, B.PAR_PROJ, jobProj) | |||
|     return spec | |||
| 
 | |||
| def select_testsuites(job, projList, appList): | |||
|     out = {} | |||
|     jobProj = None | |||
|     print("testsuite select: "+str(projList)+" "+str(appList)) | |||
|     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 | |||
|                 print(d) | |||
|                 specpath = os.path.join(path, d, D.DFILE_TESTSUITE_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 | |||
| @ -0,0 +1,98 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| """ | |||
| spontanes Fliegengewicht, das aus einer der folgenden Contexte gebodlet wird. | |||
| step: | |||
|     hier als umzusetzende Technik | |||
| artefact: | |||
|     hier als umzusetzende Technik bei init oder collect | |||
| component: | |||
|     als Superklasse zwecks Ererben fehlernder Attribute | |||
| environment: | |||
|     als Superklasse zwecks Ererben fehlernder Attribute | |||
| in den jeweiligen technischen Elternklassenv werden die Attribute gesammelt und bei der Ausfuehrung komprimmiert. | |||
| Die so zusammen gesammelten Konfigurationen werden der jeweilgen Funktionsklasse uebergeben. | |||
| """ | |||
| import os | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_tool | |||
| import tools.data_const as D | |||
| 
 | |||
| TABLE_NAME = tools.data_tool.getSingularKeyword(B.DATA_NODE_TOPICS) | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "toid" | |||
| FIELD_NAME = D.FIELD_NAME | |||
| LIST_FIELDS = [FIELD_ID, FIELD_NAME] | |||
| """ list of object-attributes """ | |||
| LIST_NODES = [] | |||
| LIST_SUBTABLES = {} | |||
| 
 | |||
| component = "" | |||
| environment = "" | |||
| topic = "" # | |||
| """ one of B.LIST_TOPIC_NODES """ | |||
| type = ""  # | |||
| """ one of the implemented Tools """ | |||
| 
 | |||
| class Topic(model.entity.Entity): | |||
|     name = "" | |||
|     type = "" | |||
|     attributes = "" | |||
|     environment = "" | |||
|     component = "" | |||
| 
 | |||
|     def __init__(self, job, environment, component, name=""): | |||
|         """ | |||
|         to be initialized by readSpec | |||
|         """ | |||
|         self.job = job | |||
|         self.environment = environment | |||
|         self.component = component | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_VARIANTS, "") | |||
| 
 | |||
|     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 | |||
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| 
 | 
| @ -0,0 +1,63 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| import tools.file_type | |||
| 
 | |||
| TABLE_NAME = "uscase" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "ucid" | |||
| 
 | |||
| FILE_EXTENSION = D.DFILE_TYPE_CSV | |||
| UNIQUE_FIELDS = [D.FIELD_NAME] | |||
| """ unique business field as human identifer """ | |||
| IDENTIFYER_FIELDS = [FIELD_ID] | |||
| """ unique technical field as technical identifer """ | |||
| 
 | |||
| class Usecase(model.entity.Entity): | |||
|     FIELD_ID = "ucid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT, B.SUBJECT_APP] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = [] | |||
|     ucid = 0 | |||
|     usecase = "" | |||
|     project = "" | |||
|     application = "" | |||
|     description = "" | |||
|     reference = "" | |||
|     attributes = "" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_CATALOG, B.SUBJECT_USECASES, | |||
|                                 tools.config_tool.get_plain_filename(job, ""), ttype=D.CSV_SPECTYPE_CTLG) | |||
|         outList = list(config[B.SUBJECT_USECASES][B.DATA_NODE_KEYS].keys()) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_CATALOG, B.SUBJECT_USECASES, | |||
|                                 tools.config_tool.get_plain_filename(job, name), ttype=D.CSV_SPECTYPE_CTLG) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
| 
 | 
| @ -0,0 +1,297 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.toolHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.db_abstract | |||
| import tools.git_tool | |||
| 
 | |||
| TABLE_NAME = "user" | |||
| """ system-name for this entity """ | |||
| 
 | |||
| FIELD_ID = "id" | |||
| FIELD_USERNAME = "username" | |||
| FILE_EXTENSION = D.DFILE_TYPE_YML | |||
| UNIQUE_FIELDS = [FIELD_USERNAME] | |||
| """ unique business field as human identifer """ | |||
| IDENTIFYER_FIELDS = [FIELD_ID] | |||
| """ unique technical field as technical identifer """ | |||
| 
 | |||
| class User(model.entity.Entity): | |||
|     FIELD_ID = "id" | |||
|     FIELD_USERNAME = "username" | |||
|     FIELD_NAME = "name" | |||
|     FIELD_FAMNAME = "famname" | |||
|     FIELD_EMAIL = "email" | |||
|     FIELD_PASSWORD = "password" | |||
|     FIELD_PROJECT = B.SUBJECT_PROJECT | |||
|     FIELD_ROLE = "role" | |||
|     LIST_FIELDS = [FIELD_ID, FIELD_ROLE, FIELD_PROJECT, FIELD_PASSWORD, FIELD_EMAIL, FIELD_FAMNAME, FIELD_NAME, | |||
|                    FIELD_USERNAME] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = {} | |||
|     UNIQUE_FIELDS = [FIELD_USERNAME] | |||
|     id = 0 | |||
|     username = "" | |||
|     name = "" | |||
|     famname = "" | |||
|     email = "" | |||
|     password = "" | |||
|     project = "" | |||
|     role = "" | |||
|     attributes = "" | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         outList = [] | |||
|         path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_HOME], P.VAL_CONFIG, "user") | |||
|         for k in os.listdir(path): | |||
|             filename = tools.config_tool.get_plain_filename(job, k) | |||
|             if "default" == filename: | |||
|                 continue | |||
|             outList.append(filename) | |||
|         return outList | |||
| 
 | |||
|     def select_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 | |||
|         """ | |||
|         outList = [] | |||
|         self.setDbAttributes(job, [TABLE_NAME]) | |||
|         dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|         data = dbi.selectRows(TABLE_NAME, job) | |||
|         checkList = {} | |||
|         for row in data[B.DATA_NODE_DATA]: | |||
|             key = "" | |||
|             for f in UNIQUE_FIELDS: | |||
|                 key += "_" + row[f] | |||
|             if key in checkList: | |||
|                 continue | |||
|             else: | |||
|                 checkList[key] = key | |||
|             fields = [] | |||
|             for f in UNIQUE_FIELDS: | |||
|                 fields.append(row[f]) | |||
|             outList.append(fields) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         print("name "+name) | |||
|         config = model.user.User.getUserConfig(job, tools.config_tool.get_plain_filename(job, name)) | |||
|         for k in self.LIST_FIELDS: | |||
|             if k not in config: | |||
|                 continue | |||
|             setattr(self, k, config[k]) | |||
|         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) | |||
|         outdata = {} | |||
|         for k in data: | |||
|             if k == "sysuser": | |||
|                 sysuser = User.getCurrentUser(job) | |||
|                 outdata[sysuser] = data[k] | |||
|                 outdata[sysuser][FIELD_USERNAME] = sysuser | |||
|             else: | |||
|                 outdata[k] = data[k] | |||
|         return outdata | |||
| 
 | |||
|     def check_data(self, job, data: dict) -> dict: | |||
|         """ | |||
|         it checks the data for the specific form | |||
|         :param job: | |||
|         :param tdata: | |||
|         :param ttype: | |||
|         :return: | |||
|         """ | |||
|         import tools.file_type | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [] | |||
|         checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_DATA, B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_KEYS] + B.LIST_SUBJECTS | |||
|         checkNodes[tools.file_type.OPT_NODES] = [] | |||
|         return tools.file_type.check_nodes(job, data, checkNodes) | |||
| 
 | |||
| 
 | |||
|     def select_entity(self, job, name, row={}): | |||
|         """ | |||
|         reads the entity from the database | |||
|         it should get the same result like read_entity | |||
|         :param job: | |||
|         :param name: unique field as string, unique fields as list | |||
|             the unique-fields are defined in the class | |||
|         :return: itself with filled object-attributes | |||
|         """ | |||
|         if row is None or len(row) == 0: | |||
|             self.setDbAttributes(job, [TABLE_NAME]) | |||
|             dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|             if type(name) is list: | |||
|                 names = name | |||
|             elif type(name) is str: | |||
|                 names = [name] | |||
|             condition = "where " | |||
|             for v in names: | |||
|                 condition += " and " + "" | |||
|             data = dbi.selectRows(TABLE_NAME, job, "where username = \'" + names[0] + "\'") | |||
|             if len(data[B.DATA_NODE_DATA]) > 1: | |||
|                 raise Exception("single selection with more than one result: "+names[0]) | |||
|             elif len(data[B.DATA_NODE_DATA]) == 1: | |||
|                 row = data[B.DATA_NODE_DATA][0] | |||
|             else: | |||
|                 raise Exception("no result for: "+names[0]) | |||
|         for k in self.LIST_FIELDS: | |||
|             if k not in row: | |||
|                 continue | |||
|             setattr(self, k, row[k]) | |||
|         return self | |||
| 
 | |||
|     def write_entity(self, job, name): | |||
|         """ | |||
|         writes the entity into the file-system | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = {} | |||
|         config[model.user.TABLE_NAME] = {} | |||
|         pathname = os.path.join(job.conf[B.TOPIC_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, | |||
|                                 P.VAL_USER, name + ".yml") | |||
|         for k in self.LIST_FIELDS: | |||
|             if getattr(self, k, "") == "" \ | |||
|             or k == FIELD_ID: | |||
|                 continue | |||
|             config[model.user.TABLE_NAME][k] = getattr(self, k, "") | |||
|         tools.file_tool.write_file_dict(job.m, job, pathname, config) | |||
|         return self | |||
| 
 | |||
|     def insert_entity(self, job, name, table="", rows={}): | |||
|         """ | |||
|         inserts the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         self.setDbAttributes(job, [TABLE_NAME]) | |||
|         dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|         condition = "where" | |||
|         for f in UNIQUE_FIELDS: | |||
|             # TODO other db-formats than string has to be implemented | |||
|             condition += " and " + f + " = \'" + getattr(self, f, "") + "\'" | |||
|         condition = condition.replace("where and", "where ") | |||
|         data = dbi.selectRows(TABLE_NAME, job, condition) | |||
|         if len(data[B.DATA_NODE_DATA]) > 0: | |||
|             print("update statt insert") | |||
|             return | |||
|         if rows is None or len(rows) == 0: | |||
|             insheader = dbi.getInsertFields(self.conf[B.DATA_NODE_DDL][table]) | |||
|             rows = [] | |||
|             row = {} | |||
|             for f in insheader: | |||
|                 row[f] = getattr(self, f) | |||
|             rows.append(row) | |||
|         dbi.insertRows(job, table, rows) | |||
| 
 | |||
|     def update_entity(self, job, name): | |||
|         """ | |||
|         writes the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         raise Exception(B.EXCEPT_NOT_IMPLEMENT) | |||
| 
 | |||
|     def remove_entity(self, job, name): | |||
|         """ | |||
|         removes the entity from the file-system | |||
|         it similar to delete_entity | |||
|         :param job: | |||
|         :param name: single substring or list of name or dict of names with the keys as | |||
|         :return: | |||
|         """ | |||
|         self.removeEntity(job, name, os.path.join(job.conf[B.TOPIC_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, P.VAL_USER), "yml") | |||
| 
 | |||
|     def delete_entity(self, job, name, table): | |||
|         """ | |||
|         deletes the entity into the database | |||
|         it similar to update_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         self.setDbAttributes(job, [TABLE_NAME]) | |||
|         dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) | |||
|         condition = "where" | |||
|         if B.DATA_NODE_DDLKEYS in self.conf[B.DATA_NODE_DDL][table]: | |||
|             keys = self.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_DDLKEYS] | |||
|         else: | |||
|             keys = self.conf[B.DATA_NODE_DDL][table] | |||
|         for f in IDENTIFYER_FIELDS: | |||
|             # TODO other db-formats than string has to be implemented | |||
|             val = dbi.getDbValue(keys[f], getattr(self, f, "")) | |||
|             condition += " and " + f + " = " + val + "" | |||
|         condition = condition.replace("where and", "where ") | |||
|         dbi.deleteRows(job, table, condition) | |||
| 
 | |||
|     @staticmethod | |||
|     def getUserConfig(job, name): | |||
|         """ | |||
|         reads the entity from the database | |||
|         it should get the same result like read_entity | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = tools.config_tool.getConfig(job, P.KEY_USER, name, ttype=B.SUBJECT_USER) | |||
|         if config is not None: | |||
|             return config | |||
|         if name == model.user.User.getCurrentUser(job): | |||
|             config = tools.config_tool.getConfig(job, P.KEY_USER, "default", ttype=B.SUBJECT_USER) | |||
|             if "user" in config: | |||
|                 config = config["user"] | |||
|             if config is not None: | |||
|                 config["username"] = name | |||
|                 return config | |||
|         raise Exception("keine Config zu "+name) | |||
| 
 | |||
|     @staticmethod | |||
|     def getCurrentUser(job): | |||
|         return os.environ.get("USERNAME") | |||
| 
 | |||
| 
 | 
| @ -0,0 +1,88 @@ | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| # Author : Ulrich Carmesin | |||
| # Source : gitea.ucarmesin.de | |||
| # --------------------------------------------------------------------------------------------------------- | |||
| import os | |||
| import basic.toolHandling | |||
| import basic.componentHandling | |||
| import basic.constants as B | |||
| import model.entity | |||
| import tools.path_const as P | |||
| import tools.data_const as D | |||
| import tools.config_tool | |||
| import tools.file_tool | |||
| import tools.git_tool | |||
| 
 | |||
| TABLE_NAME = "variant" | |||
| """ system-name for this entity """ | |||
| FIELD_ID = "vrid" | |||
| 
 | |||
| 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 Variant(model.entity.Entity): | |||
|     FIELD_ID = "vrid" | |||
|     LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT, B.SUBJECT_COMP] | |||
|     """ list of object-attributes """ | |||
|     LIST_NODES = [B.NODE_ATTRIBUTES] | |||
|     LIST_SUBTABLES = [] | |||
|     """ list of object-attributes """ | |||
|     name = "" | |||
|     description = "" | |||
|     reference = "" | |||
|     attributes = "" | |||
|     project = "" | |||
|     component = "" | |||
| 
 | |||
| 
 | |||
|     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 | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_VARIANTS, | |||
|                                 tools.config_tool.get_plain_filename(job, ""), B.SUBJECT_VARIANT) | |||
|         outList = list(config[B.SUBJECT_VARIANTS].keys()) | |||
|         return outList | |||
| 
 | |||
|     def read_entity(self, job, name): | |||
|         """ | |||
|         reads the entity from the file-system | |||
|         :param job: | |||
|         :param name: | |||
|         :return: | |||
|         """ | |||
|         config = self.getConfig(job, P.KEY_BASIC, B.SUBJECT_VARIANTS, | |||
|                                 tools.config_tool.get_plain_filename(job, name), B.SUBJECT_VARIANT) | |||
|         return self.setAttributes(job, config, name, self.LIST_FIELDS, self.LIST_NODES, self.LIST_SUBTABLES) | |||
| 
 | |||
| 
 | |||
|     @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) | |||
|         return data | |||
| 
 | |||
|     @staticmethod | |||
|     def check_data(job, data: dict) -> dict: | |||
|         checkNodes = {} | |||
|         checkNodes[tools.file_type.MUST_NODES] = [] | |||
|         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_PROJECTS, B.NODE_ATTRIBUTES] | |||
|         return tools.file_type.check_nodes(job, data, checkNodes) | |||
| 
 | |||
| @ -1,153 +1,232 @@ | |||
| #!/usr/bin/python | |||
| # program to execute programs for a testcases or for a testsuite | |||
| # PARAM from INPUT:  --granularity --application --environment --testcase/testsuite | |||
| # main functions | |||
| #  + input_param()  : cache-actjob --> user-input -->  local-param | |||
| #  + start_job()    : local-param --> cache-actjob --> start-param | |||
| # --------------------------------------------------- | |||
| 
 | |||
|     # | |||
| # | |||
| # ---------------------------------------------------------- | |||
| """ | |||
| 
 | |||
| This program is created for the business-test on the level of unit testing. | |||
| On this level there is an intensive test-set up to a carthesian product possible. | |||
| The test-specification is written in a yaml-config in the data-directory. | |||
| workflow: | |||
| 1. generate test-cases with all inputs into a csv-file of the spec-yaml | |||
| 2. run the csv-file and collect all results into a new result-csv-file with all inputs and outputs | |||
| 3. check the result-csv-file and declare it as a target-results | |||
| OR instead 2 and 3 on test-first-strategy: | |||
| 3. create manually the target-result with your inputs and the target system-outputs | |||
| 4. run and compare the actual-result with the target-result | |||
| 5. at the end you get an xls-sheet like your result-csv-file | |||
| but additionally with comparsion-result as detailed result and the only counts of passed and failed tests | |||
|  as minimum-result which can be inserted into management-tools | |||
| """ | |||
| import os.path | |||
| import json | |||
| # Press the green button in the gutter to run the script. | |||
| import importlib | |||
| import os, glob | |||
| import io | |||
| import sys | |||
| import basic.program | |||
| import basic.constants as B | |||
| import utils.file_tool | |||
| tempJob = {} | |||
| 
 | |||
| PROGRAM_NAME = "unit" | |||
| JSON_FILE = "actualJob.json" | |||
| JOB_NR = { | |||
|     "init_testsuite": { | |||
|         "jobnr": "0" }, | |||
|     "execute_testsuite": { | |||
|         "jobnr": "1"}, | |||
|     "collect_testsuite": { | |||
|         "jobnr": "2"}, | |||
|     "compare_testsuite": { | |||
|         "jobnr": "3"}, | |||
|     "finish_testsuite": { | |||
|         "jobnr": "4"}, | |||
|     "init_testcase": { | |||
|         "jobnr": "5" }, | |||
|     "execute_testcase": { | |||
|         "jobnr": "6" }, | |||
|     "collect_testcase": { | |||
|         "jobnr": "7" }, | |||
|     "compare_testcase": { | |||
|         "jobnr": "8" }, | |||
|     "check_environment": { | |||
|         "jobnr": "9" }, | |||
|     "test_executer": { | |||
|         "jobnr": "10"}, | |||
| } | |||
| JOB_LIST = [ | |||
|     "init_testsuite", | |||
|     "execute_testsuite", | |||
|     "collect_testsuite", | |||
|     "compare_testsuite", | |||
|     "finish_testsuite", | |||
|     "init_testcase", | |||
|     "execute_testcase", | |||
|     "collect_testcase", | |||
|     "compare_testcase", | |||
|     "check_environment", | |||
|     "test_executer" | |||
| ] | |||
| 
 | |||
| appList = [] | |||
| envList = ["ENV01"] | |||
| testList = {"TEST": [ | |||
|     "TC0001", "TST001" | |||
| ]} | |||
| 
 | |||
| def readContext(job): | |||
|     for k in job.conf.confs["applications"]: | |||
|         appList.append(k) | |||
| import tools.job_tool as job_tool | |||
| import model.catalog | |||
| import tools.job_const as J | |||
| import tools.step_tool | |||
| 
 | |||
| PROGRAM_NAME = "start_dialog" | |||
| JOB_PROC = "proc" | |||
| verbose = False | |||
| def startPyJob(job): | |||
|     # for debugging write | |||
|     setattr(job.par, "tool", "job_tool") | |||
|     # check if an actual job is stored | |||
|     childArgs = job_tool.read_child_args(job) | |||
|     if childArgs is None: | |||
|         childArgs = initDialog(job) | |||
|     else: | |||
|         childDialog(job) | |||
|     pass | |||
| 
 | |||
| def restartActualProcess(job): | |||
| def getChoice(job, choiselist, description): | |||
|     """ | |||
|     check if an actual process is open | |||
|     to choise one of the list or exit the program | |||
|     :param job: | |||
|     :param choiselist: | |||
|     :param description: | |||
|     :return: | |||
|     """ | |||
|     path = os.path.join(job.conf.confs[B.SUBJECT_PATH][B.ATTR_PATH_DEBUG], JSON_FILE) | |||
|     if os.path.exists(path): | |||
|         actProc = utils.file_tool.readFileDict(job, path) | |||
|         jobNr = int(JOB_NR[actProc["job"]]["jobnr"]) | |||
|         question = "Prozess " | |||
|         choiceList = "" | |||
|         if jobNr < 8 and jobNr != 4: | |||
|             question += "F_ortsetzen | " | |||
|             choiceList += "f | " | |||
|         question += "W_iederholen | N_euen Prozess | X_exit" | |||
|         choiceList = "w | n | x ?" | |||
|         print("+-----------------------------------------------") | |||
|         for k in actProc: | |||
|             print('| {:6s} : {:60s}'.format(k, actProc[k])) | |||
|         print("+-----------------------------------------------") | |||
|         print(question) | |||
|         choice = input("Auswahl "+choiceList) | |||
|         choiceList.replace(" | ","") | |||
|         if choice.lower() not in choiceList[:-1]: | |||
|             print("FEHLER : falsche Auswahl") | |||
|         elif choice.lower() == "x": | |||
|             job.stopJob(0) | |||
|         elif choice.lower() == "w": | |||
|             startProcess(job, actProc) | |||
|         elif choice.lower() == "f": | |||
|             actProc["job"] = JOB_NR[int(jobNr)+1] | |||
|             startProcess(job, actProc) | |||
|         elif choice.lower() == "n": | |||
|             createProcess(job) | |||
|         else: | |||
|             print("unbekannte Situation") | |||
|     else: | |||
|         createProcess(job) | |||
| 
 | |||
| 
 | |||
| def createProcess(job): | |||
|     process = {} | |||
|     index = 0 | |||
|     print("create new process") | |||
|     process["app"] = getChoice(job, appList, "Anwendung") | |||
|     # | |||
|     if len(envList) == 1: | |||
|         process["env"] = envList[0] | |||
|     else: | |||
|         process["env"] = getChoice(job, envList, "Umgebung") | |||
|     # | |||
|     process["tc"] = getChoice(job, testList[process["app"]], "Testfall") | |||
|     print(str(process)) | |||
| 
 | |||
| 
 | |||
| def getChoice(job, choiselist, description): | |||
|     index = 0 | |||
|     if isinstance(choiselist, dict): | |||
|         choiselist = list(choiselist.keys()) | |||
|     if len(choiselist) == 0: | |||
|         raise Exception("Keine Auswahl zu: "+description) | |||
|     if len(choiselist) == 1: | |||
|         return choiselist[0] | |||
|     print("+------------- "+description+" ----------") | |||
|     print('| {:2d} : {:60s}'.format(0, "exit")) | |||
|     print('| | {:2d} : {:60s}'.format(0, "exit")) | |||
|     for k in choiselist: | |||
|         index += 1 | |||
|         print('| {:2d} : {:60s}'.format(index, k)) | |||
|         print('| | {:2d} : {:60s}'.format(index, k)) | |||
|     print("+-----------------------------------------------") | |||
|     choice = input("Auswahl 1-" + str(index) + ": ") | |||
|     if verbose: print("auswahl "+str(choice)) | |||
|     if not choice.isnumeric(): | |||
|         print("FEHLER Fehleingabe "+choice) | |||
|         getChoice(job, choiselist, description) | |||
|     elif int(choice) < 1: | |||
|         job.stopJob(0) | |||
|         exit(0) | |||
|     elif int(choice) > index: | |||
|         print("FEHLER Fehleingabe "+choice) | |||
|         getChoice(job, choiselist, description) | |||
|     else: | |||
|         if verbose: print("treffer "+str(choiselist)) | |||
|         return choiselist[int(choice) - 1] | |||
| 
 | |||
| def initDialog(job): | |||
|     """ | |||
|     dialog to initialize a child-process | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     # which process | |||
|     args = {} | |||
|     verify = job.getDebugLevel("job_tool") | |||
|     if JOB_PROC not in args: | |||
|         args[JOB_PROC] = getChoice(job, J.LIST_PROC, "Welchen Prozess starten") | |||
|     args[B.PAR_GRAN] = "" | |||
|     args[B.PAR_USER] = job_tool.getUser() | |||
|     args[B.PAR_PROJ] = job_tool.getUserProject() | |||
|     args[B.PAR_STEP] = "" | |||
|     job.m.logTrace(verify, args[JOB_PROC]) | |||
|     # """ | |||
|     print("JOB_PROC "+args[JOB_PROC]) | |||
|     if args[JOB_PROC] == J.PROC_TP_EXECUTION: | |||
|         args[B.PAR_GRAN] = B.PAR_TESTPLAN | |||
|         args[B.PAR_STEP] = tools.step_tool.getNextStepID(job, 0, "", args[B.PAR_GRAN]) | |||
|         args[B.PAR_PROGRAM] = J.PROG_TEST_EXECUTER | |||
|     elif args[JOB_PROC] in [J.PROC_TS_STEPWISE, J.PROC_TS_EXECUTION]: | |||
|         args[B.PAR_GRAN] = B.PAR_TESTSUITE | |||
|         args[B.PAR_STEP] = tools.step_tool.getNextStepID(job, 0, "", args[B.PAR_GRAN]) | |||
|         if args[JOB_PROC] == J.PROC_TS_EXECUTION: | |||
|             args[B.PAR_PROGRAM] = J.PROG_TEST_EXECUTER | |||
|         else: | |||
|             args[B.PAR_PROGRAM] = J.PROG_TS_INIT | |||
|     # elif args[JOB_PROC] in [J.PROC_TC_STEPWISE, J.PROC_TC_EXECUTION]: | |||
|     elif args[JOB_PROC] == J.PROC_TC_EXECUTION: | |||
|         print("JOB_PROC - 111 " + args[JOB_PROC]) | |||
|         args[B.PAR_GRAN] = B.PAR_TESTCASE | |||
|         args[B.PAR_STEP] = tools.step_tool.getNextStepID(job, 0, "", args[B.PAR_GRAN]) | |||
|         args[B.PAR_PROGRAM] = J.PROG_TEST_EXECUTER | |||
|     elif args[JOB_PROC] == J.PROC_TC_STEPWISE: | |||
|         print("JOB_PROC - 116 " + args[JOB_PROC]) | |||
|         args[B.PAR_GRAN] = B.PAR_TESTCASE | |||
|         args[B.PAR_STEP] = tools.step_tool.getNextStepID(job, 0, "", args[B.PAR_GRAN]) | |||
|         args[B.PAR_PROGRAM] = J.PROG_TC_INIT | |||
|     elif args[JOB_PROC] == J.PROC_REDO_EXECUTION: | |||
|         args[B.PAR_PROGRAM] = getChoice(job, J.LIST_TS_PROGS + J.LIST_TC_PROGS, | |||
|                                         "Welches Programm starten") | |||
|     elif args[JOB_PROC] == J.PROC_SINGLE_JOB: | |||
|         args[B.PAR_PROGRAM] = getChoice(job, J.LIST_SERVICE_PROG, "Welches Programm starten") | |||
|     else: | |||
|         args[B.PAR_GRAN] = "" | |||
|     # args[B.PAR_GRAN] = "" | |||
|     # """2 | |||
|     catalog = model.catalog.Catalog.getInstance() | |||
|     setattr(job.par, B.SUBJECT_PROJECT, "TESTPROJ") | |||
|     programDef = catalog.getValue(job, basic.program.CTLG_NAME, args[B.PAR_PROGRAM], "") | |||
|     job.m.logTrace(verify, "programdefinition "+str(programDef)) | |||
|     print("programdefinition "+str(programDef)) | |||
|     if verbose: print("programdefinition "+args[B.PAR_PROGRAM]+"  "+str(programDef)) | |||
|     #for p in programDef[basic.program.CTLG_PARDEF]: | |||
|     print(str(args)) | |||
|     for p in [B.PAR_PROJ, B.PAR_GRAN, B.PAR_APP, J.ARG_TESTELEM, B.PAR_COMP, B.PAR_ENV, | |||
|               B.PAR_TESTPLAN, B.PAR_TESTSUITE, B.PAR_TESTCASE, | |||
|               B.PAR_TSTIME, B.PAR_TCTIME, B.PAR_TPTIME, B.PAR_VAR]: | |||
|         if p in args and len(args[p]) > 0: | |||
|             continue | |||
|         if p not in programDef[basic.program.CTLG_PARDEF]: | |||
|             continue | |||
|         if programDef[basic.program.CTLG_PARDEF][p] != "args": | |||
|             args[p] = programDef[basic.program.CTLG_PARDEF][p] | |||
|             continue | |||
|         print("+ bearbeite "+p) | |||
|         if programDef[basic.program.CTLG_PARDEF][p] == "args": | |||
|             description = "" | |||
|             job.m.logDebug(verify, "to select "+p) | |||
|             if p == B.PAR_GRAN: | |||
|                 description = J.CHOICE_GRAN | |||
|                 choiceList = J.LIST_GRAN | |||
|             elif p == B.PAR_APP: | |||
|                 description = J.CHOICE_APP | |||
|                 choiceList = job_tool.select_application(job, programDef, args[B.PAR_PROJ]) | |||
|             elif p == B.PAR_TESTPLAN or p == J.ARG_TESTELEM and args[B.PAR_GRAN] in [J.GRAN_TP, B.PAR_TESTPLAN]: | |||
|                 description = J.CHOICE_TP | |||
|                 choiceList = job_tool.select_testplan(job, programDef, args) | |||
|                 p = B.PAR_TESTPLAN | |||
|                 if J.ARG_TESTELEM in programDef[basic.program.CTLG_PARDEF]: args[J.ARG_TESTELEM] = p | |||
|             elif p == B.PAR_TESTSUITE or p == J.ARG_TESTELEM and args[B.PAR_GRAN] in [J.GRAN_TS, B.PAR_TESTSUITE]: | |||
|                 description = J.CHOICE_TS | |||
|                 choiceList = job_tool.select_testsuite(job, programDef, args) | |||
|                 p = B.PAR_TESTSUITE | |||
|                 if J.ARG_TESTELEM in programDef[basic.program.CTLG_PARDEF]: args[J.ARG_TESTELEM] = p | |||
|             elif p == B.PAR_TESTCASE or p == J.ARG_TESTELEM and args[B.PAR_GRAN] in [J.GRAN_TC, B.PAR_TESTCASE]: | |||
|                 description = J.CHOICE_TC | |||
|                 choiceList = job_tool.select_testcase(job, programDef, args) | |||
|                 p = B.PAR_TESTCASE | |||
|                 if J.ARG_TESTELEM in programDef[basic.program.CTLG_PARDEF]: args[J.ARG_TESTELEM] = p | |||
|             elif p == B.PAR_COMP: | |||
|                 description = J.CHOICE_ENV | |||
|                 choiceList = job_tool.select_components(job, programDef, args[B.PAR_PROJ], args[B.PAR_APP]) | |||
|                 choiceAll = ",".join(choiceList) | |||
|                 choiceList.append(choiceAll) | |||
|             elif p == B.PAR_ENV: | |||
|                 description = J.CHOICE_ENV | |||
|                 choiceList = job_tool.select_environment(job, programDef, args[B.PAR_PROJ]) | |||
|             elif p in [B.PAR_TESTPLAN, B.PAR_TESTSUITE, B.PAR_TESTCASE]: | |||
|                 if args[JOB_PROC] == J.PROC_REDO_EXECUTION: | |||
|                     description = J.CHOICE_ARCHIV | |||
|                     choiceList = job_tool.select_archiv(job, programDef, args[B.PAR_GRAN], args[B.PAR_APP]) | |||
|                 else: | |||
|                     args[B.PAR_STEP] = "1" | |||
|                     description = J.CHOICE_SPEC | |||
|                     choiceList = job_tool.select_spec(job, programDef, args[B.PAR_GRAN], args) | |||
|             elif p in [B.PAR_TSTIME, B.PAR_TCTIME] and args[JOB_PROC] in [J.PROC_REDO_EXECUTION]: | |||
|                 description = J.CHOICE_TIME | |||
|                 choiceList = job_tool.select_testtime(job, programDef, args[B.PAR_GRAN], args) | |||
|             elif p == B.PAR_VAR: | |||
|                 description = J.CHOICE_VARIANT | |||
|                 choiceList = job_tool.select_variant(job, programDef, args[B.PAR_GRAN], args) | |||
|             else: | |||
|                 continue | |||
|             if choiceList is None: | |||
|                 job.m.logError(verify, "choiceList in None "+p) | |||
|             args[p] = getChoice(job, choiceList, description) | |||
|     job.m.logDebug(verify, args) | |||
|     job_tool.write_child_args(job, args) | |||
|     job_tool.start_child_process(job, args) | |||
|     childDialog(job) | |||
| 
 | |||
| def startProcess(job, process): | |||
|     print(str(process)) | |||
| 
 | |||
| def childDialog(job): | |||
|     """ | |||
|     dialog to manage the child-process | |||
|     :param job: | |||
|     :return: | |||
|     """ | |||
|     args = job_tool.read_child_args(job) | |||
|     print("+-----------------------------------------------") | |||
|     for p in args: | |||
|         if p in [JOB_PROC]: | |||
|             continue | |||
|         if len(args[p]) < 1: | |||
|             continue | |||
|         print('+ {:12s} : {:60s}'.format(p, str(args[p]))) | |||
|     print("+-----------------------------------------------") | |||
|     initDialog(job) | |||
| 
 | |||
| if __name__ == '__main__': | |||
|     job = basic.program.Job(PROGRAM_NAME) | |||
|     readContext(job) | |||
|     restartActualProcess(job) | |||
|     # TODO to move to job_tool | |||
|     args = {} | |||
|     if isinstance(job.programDef[basic.program.CTLG_PARDEF], dict): | |||
|         for p in job.programDef[basic.program.CTLG_PARDEF]: | |||
|             args[p] = job.programDef[basic.program.CTLG_PARDEF][p] | |||
|     job.setParameter(args) | |||
|     job.startJob() | |||
|     startPyJob(job) | |||
|     job.stopJob(0) | |||
|  | |||
Some files were not shown because too many files changed in this diff
					Loading…
					
					
				
		Reference in new issue