diff --git a/check_configuration.py b/check_configuration.py index 854a0ca..b8f868b 100644 --- a/check_configuration.py +++ b/check_configuration.py @@ -9,8 +9,9 @@ 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.component -import model.table +import model.entity +import model.factory +#import model.table PROGRAM_NAME = "check_configuration" @@ -37,6 +38,7 @@ def checkComponent(job, componentName): :param componentName: :return: """ + import model.component configPath = config_tool.getExistingPath(job, [os.path.join(job.conf[B.SUBJECT_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: diff --git a/model/application.py b/model/application.py index 2f0cc1d..ae13ee5 100644 --- a/model/application.py +++ b/model/application.py @@ -240,7 +240,7 @@ class Application(model.entity.Entity): components = {} project = {} - def __int__(self, job): + def __int__(self, job, project=""): self.job = job def read_unique_names(self, job, project, application, gran, args): diff --git a/model/constants.py b/model/constants.py index e69de29..31134a0 100644 --- a/model/constants.py +++ b/model/constants.py @@ -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] diff --git a/model/factory.py b/model/factory.py index 85711d0..9f1e5de 100644 --- a/model/factory.py +++ b/model/factory.py @@ -13,6 +13,10 @@ def getComponent(job=None): import model.component return model.component.Component(job) +def getTestplam(job=None, project="", application=""): + import model.testplan + return model.testplan.Testplan(job, project) + def getTestsuite(job=None, project="", application=""): import model.testsuite return model.testsuite.Testsuite(job, project) diff --git a/model/testcase.py b/model/testcase.py index e8ad45b..71e0b72 100644 --- a/model/testcase.py +++ b/model/testcase.py @@ -37,9 +37,18 @@ LIST_FIELDS = [FIELD_ID, FIELD_NAME, FIELD_DESCRIPTION, FIELD_REFERENCE, FIELD_P SUB_USECASE = B.SUBJECT_USECASES SUB_STORIES = B.SUBJECT_STORIES +SUB_VARIANTS = B.SUBJECT_VARIANTS +SUB_APPLICATIONS = B.SUBJECT_APPS SUB_STEPS = "steps" SUB_TABLES = "tables" -LIST_SUBTABLES = [SUB_TABLES, SUB_STEPS, SUB_USECASE, SUB_STORIES] +LIST_SUBTABLES = { + SUB_TABLES: [D.DATA_ATTR_DATE], + SUB_STEPS: [], + SUB_USECASE: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE], + SUB_STORIES: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE], + SUB_APPLICATIONS: [], + SUB_VARIANTS: [] +} LIST_SUB_DESCRIPT = [D.DATA_ATTR_USECASE_DESCR, D.DATA_ATTR_STORY_DESCR] FILE_EXTENSION = D.DFILE_TYPE_YML @@ -64,13 +73,14 @@ class Testcase(model.entity.Entity): name = "" description = "" project = "" - application = "" reference = "" attributes = "" - story = [] + stories = {} docs = [] tables = {} - steps = [] + steps = {} + applications = {} + variants = {} def __init__(self, job, project, name=""): """ @@ -94,7 +104,9 @@ class Testcase(model.entity.Entity): :param opt. args additional args :return: list of entity-names """ - path = os.path.join(job.conf[B.SUBJECT_PATH][B.ATTR_PATH_TDATA], getattr(job.par, B.SUBJECT_PROJECT), + if project == "": + project = getattr(job.par, B.SUBJECT_PROJECT) + path = os.path.join(job.conf[B.SUBJECT_PATH][B.ATTR_PATH_TDATA], project, B.SUBJECT_TESTCASES) outList = self.getDirlist(job, path, "") return outList @@ -109,9 +121,10 @@ class Testcase(model.entity.Entity): # r = tools.config_tool.select_config_path(job, P.KEY_TESTCASE, "TC0001") config = self.getConfig(job, P.KEY_TESTCASE, name, tools.config_tool.get_plain_filename(job, name)) self.setAttributes(config, name, LIST_FIELDS, LIST_SUBTABLES) - for k in LIST_SUBTABLES: + for k in LIST_SUBTABLES.keys(): if not hasattr(self, k): continue + pass if "_"+k in config[name] and "_"+k+"-description" in LIST_SUB_DESCRIPT: values = {} if "_"+k+"-description" in config[name]: diff --git a/model/testplan.py b/model/testplan.py index 079087f..ad54fa4 100644 --- a/model/testplan.py +++ b/model/testplan.py @@ -5,7 +5,7 @@ # Source : gitea.ucarmesin.de # --------------------------------------------------------------------------------------------------------- import basic.toolHandling -import utils.data_const as D +import tools.data_const as D import basic.constants as B import model.entity @@ -16,32 +16,10 @@ class Testplan(model.entity.Entity): testsuites = {} steps = [] - def __init__(self, job): + def __init__(self, job, project=""): """ to be initialized by readSpec :param job: """ self.job = job - def get_schema(self, tableName="", tableObject=None): - dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] - dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) - sql = dbi.getCreateTable("testplan") - sql += dbi.getSchemaAttribut("tpid", "id")+"," - sql += dbi.getSchemaAttribut("name", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("description", D.TYPE_TEXT)+"," - sql += dbi.getSchemaAttribut("project", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("prelease", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("attributes", D.TYPE_TEXT)+"," - sql += self.getHistoryFields() - sql += ");\n" - sql += self.getHistoryIndex("testplan") - for attr in ["testsuite"]: - sql += dbi.getSchemaSubtable("tp", [{"attr":attr, "atype": D.TYPE_STR}])+"\n" - sql += dbi.getSchemaIndex(dbi.getIndexName("tp", attr), - dbi.getSubTableId(dbi.getSubTableName("tp", attr), attr))+"\n" - for attr in ["step"]: - sql += dbi.getSchemaSubtable("tp", [{"attr":attr, "atype": D.TYPE_STR}, {"attr":"attributes", "atype": D.TYPE_TEXT}])+"\n" - sql += dbi.getSchemaIndex(dbi.getSubTableName("tp", attr), - dbi.getSubTableId(dbi.getSubTableName("tp", attr), attr))+"\n" - return sql \ No newline at end of file diff --git a/start_dialog.py b/start_dialog.py index 9f1449b..88fd55d 100644 --- a/start_dialog.py +++ b/start_dialog.py @@ -28,6 +28,7 @@ import model.catalog import tools.job_const as J PROGRAM_NAME = "start_dialog" +JOB_PROC = "proc" verbose = False def startPyJob(job): # for debugging write @@ -76,7 +77,6 @@ def getChoice(job, choiselist, description): if verbose: print("treffer "+str(choiselist)) return choiselist[int(choice) - 1] - def initDialog(job, args={}): """ dialog to initialize a child-process @@ -85,36 +85,36 @@ def initDialog(job, args={}): """ # which process verify = job.getDebugLevel("job_tool") - if "proc" not in args: - args["proc"] = getChoice(job, J.LIST_PROC, "Welchen Prozess starten") + if JOB_PROC not in args: + args[JOB_PROC] = getChoice(job, J.LIST_PROC, "Welchen Prozess starten") args[J.MODEL_GRAN] = "" args[B.PAR_USER] = job_tool.getUser() args[B.PAR_PROJ] = job_tool.getUserProject() args[B.PAR_STEP] = "" - job.m.logTrace(verify, args["proc"]) + job.m.logTrace(verify, args[JOB_PROC]) # """ - if args["proc"] == J.PROC_TP_EXECUTION: + if args[JOB_PROC] == J.PROC_TP_EXECUTION: #args[J.MODEL_GRAN] = B.PAR_TESTPLAN args[B.PAR_STEP] = "1" args[B.PAR_PROGRAM] = J.PROG_TEST_EXECUTER - elif args["proc"] in [J.PROC_TS_STEPWISE, J.PROC_TS_EXECUTION]: + elif args[JOB_PROC] in [J.PROC_TS_STEPWISE, J.PROC_TS_EXECUTION]: #args[J.MODEL_GRAN] = B.PAR_TESTSUITE args[B.PAR_STEP] = "1" - if args["proc"] == J.PROC_TS_EXECUTION: + 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["proc"] in [J.PROC_TC_STEPWISE, J.PROC_TC_EXECUTION]: + elif args[JOB_PROC] in [J.PROC_TC_STEPWISE, J.PROC_TC_EXECUTION]: #args[J.MODEL_GRAN] = B.PAR_TESTCASE args[B.PAR_STEP] = "1" - if args["proc"] == J.PROC_TC_EXECUTION: + if args[JOB_PROC] == J.PROC_TC_EXECUTION: args[B.PAR_PROGRAM] = J.PROG_TEST_EXECUTER else: args[B.PAR_PROGRAM] = J.PROG_TC_INIT - elif args["proc"] == J.PROC_REDO_EXECUTION: + 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["proc"] == J.PROC_SINGLE_JOB: + elif args[JOB_PROC] == J.PROC_SINGLE_JOB: args[B.PAR_PROGRAM] = getChoice(job, J.LIST_SERVICE_PROG, "Welches Programm starten") else: args[J.MODEL_GRAN] = "" @@ -165,14 +165,14 @@ def initDialog(job, args={}): 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["proc"] == J.PROC_REDO_EXECUTION: + if args[JOB_PROC] == J.PROC_REDO_EXECUTION: description = J.CHOICE_ARCHIV choiceList = job_tool.select_archiv(job, programDef, args[J.MODEL_GRAN], args[B.PAR_APP]) else: args[B.PAR_STEP] = "1" description = J.CHOICE_SPEC choiceList = job_tool.select_spec(job, programDef, args[J.MODEL_GRAN], args) - elif p in [B.PAR_TSTIME, B.PAR_TCTIME] and args["proc"] in [J.PROC_REDO_EXECUTION]: + 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[J.MODEL_GRAN], args) elif p == B.PAR_VAR: @@ -201,11 +201,11 @@ def childDialog(job): args = job_tool.read_child_args(job) print("+-----------------------------------------------") for p in args: - if p in ["proc"]: + if p in [JOB_PROC]: continue if len(args[p]) < 1: continue - print('+ {:12s} : {:60s}'.format(p, args[p])) + print('+ {:12s} : {:60s}'.format(p, str(args[p]))) print("+-----------------------------------------------") initDialog(job) diff --git a/test/test_05data.py b/test/test_05data.py new file mode 100644 index 0000000..855eb6b --- /dev/null +++ b/test/test_05data.py @@ -0,0 +1,53 @@ +import unittest +import inspect +import basic.constants as B +import basic.toolHandling as toolHandling +import tools.data_const as D +import test.testtools +import test.constants +import basic.program +import os + +import tools.data_tool + +HOME_PATH = test.constants.HOME_PATH +DATA_PATH = test.constants.DATA_PATH +OS_SYSTEM = test.constants.OS_SYSTEM +""" + a) catalog: key(s) - values # meta-spec, meta-auto + b) head: key - value # spec-info + c) option: key - value # spec -> job.par + d) step: key=function - values # spec (tp, ts) -> comp.function + e) step: key=usecase - values # spec (tc) -> comp.steps + f) ddl-table: key=field - vaulues=attributes # meta-spec, comp + g) data-table: array: field - values # spec.data, comp.artifacts +""" + +# the list of TEST_FUNCTIONS defines which function will be really tested. +# if you minimize the list you can check the specific test-function +TEST_FUNCTIONS = ["test_01getKeyword"] +PROGRAM_NAME = "clean_workspace" + +# with this variable you can switch prints on and off +verbose = False + +class MyTestCase(unittest.TestCase): + mymsg = "--------------------------------------------------------------" + + def test_01getKeyword(self): + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + # job = basic.program.SimpleJob(PROGRAM_NAME) + #job = test.testtools.getWorkspaceJob(PROGRAM_NAME) + for x in ["_variants", "_variant", "subtable:_variants", "subtable:variants"]: + res = tools.data_tool.getPurKeyword(x) + self.assertEqual(res, "variant") + + def test_zzz(self): + print(MyTestCase.mymsg) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_10job.py b/test/test_10job.py index fd154db..9156c0b 100644 --- a/test/test_10job.py +++ b/test/test_10job.py @@ -27,9 +27,10 @@ import tools.file_tool HOME_PATH = test.constants.HOME_PATH PYTHON_CMD = "python" TEST_FUNCTIONS = ["test_00init", - "test_11selectApplication", "test_12selectComponent", "test_13selectEnvironment" + "test_11selectApplication", "test_12selectComponent", "test_13selectEnvironment", + "test_16selectTestcase", "test_30startActJob"] -TEST_FUNCTIONS = ["test_11selectApplication", "test_12selectComponent", "test_13selectEnvironment"] +TEST_FUNCTIONS = ["test_16selectTestcase"] PROGRAM_NAME = "clean_workspace" @@ -105,9 +106,55 @@ class MyTestCase(unittest.TestCase): # simple job instantiate - without parameter and only simple messaging job = basic.program.Job(PROGRAM_NAME) #res = tools.job_tool.select_components(job, {}, "TESTPROJ", "") + res = model.factory.getEnvironment(job).read_unique_names(job, "TESTPROJ", "", "", {}) + self.assertIsInstance(res, list) + print(str(res)) + + def test_14selectTestplan(self): + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + # simple job instantiate - without parameter and only simple messaging + job = basic.program.Job(PROGRAM_NAME) + #res = tools.job_tool.select_components(job, {}, "TESTPROJ", "") + res = model.factory.getTestplan(job).read_unique_names(job, "TESTPROJ", "", "", {}) + self.assertIsInstance(res, list) + print(str(res)) + + def test_15selectTestsuite(self): + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + # simple job instantiate - without parameter and only simple messaging + job = basic.program.Job(PROGRAM_NAME) + # res = tools.job_tool.select_components(job, {}, "TESTPROJ", "") res = model.environment.Environment(job).read_unique_names(job, "TESTPROJ", "", "", {}) self.assertIsInstance(res, list) print(str(res)) + def test_16selectTestcase(self): + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + # simple job instantiate - without parameter and only simple messaging + args = {} + args[B.PAR_PROJ] = "TESTPROJ" + job = basic.program.Job(PROGRAM_NAME, args=args) + #setattr(job, "par", object) + #setattr(job.par, B.PAR_PROJ, "TESTPROJ") + import model.testcase + #outList = model.testcase.select_testcases(job, ["TESTPROJ"], ["TESTAPP"]) + outList = tools.job_tool.select_testcase() + outList = model.factory.getTestcase(job, "TESTPROJ").read_unique_names(job, "TESTPROJ", "TESTAPP", "", {}) + #self.assertIsInstance(res, list) + print(str(outList)) + + if __name__ == '__main__': unittest.main() diff --git a/test/test_12component.py b/test/test_12component.py index 2f0c12b..cc555f2 100644 --- a/test/test_12component.py +++ b/test/test_12component.py @@ -1,28 +1,70 @@ +import traceback import unittest import inspect import basic.program -import utils.path_tool +import tools.path_tool import basic.componentHandling import test.constants -import basic.component +import model.component import basic.constants as B -import utils.db_abstract +import tools.db_abstract import test.testtools -import utils.config_tool -import utils.conn_tool +import tools.config_tool +import tools.conn_tool HOME_PATH = test.constants.HOME_PATH DATA_PATH = test.constants.DATA_PATH conf = {} # here you can select single testfunction for developping the tests -TEST_FUNCTIONS = ["test_10actHandler", "test_21createInstance", "test_22createComponent", +TEST_FUNCTIONS = ["test_00entity", "test_01read_entity", + "test_10actHandler", "test_21createInstance", "test_22createComponent", "test_23getComponents", "test_24getComponent"] -TEST_FUNCTIONS = ["test_24getComponent"] +TEST_FUNCTIONS = ["test_00entity"] class MyTestCase(unittest.TestCase): mymsg = "--------------------------------------------------------------" + def test_00entity(self): + """ + test if the class with all interfaces are implemented + :return: + """ + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + comp = model.component.Component(job) + faults = 0 + functionList = ["read_entity", "write_entity", "remove_entity", + "select_entity", "update_entity", "delete_entity"] + try: + func = getattr(comp, "get_schema") + func() + except Exception as e: + print("get_schema: " + str(e)) + faults += 1 + for function in functionList: + try: + func = getattr(comp, function) + func(job, "testacnt") + except Exception as e: + print(function + ": " +str(e)) + faults += 1 + self.assertEqual(0, faults) + + def test_01read_entity(self): + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + comp = model.component.Component(job) + comp.read_entity(job, "testact") + def test_22createComponent(self): global mymsg @@ -58,10 +100,10 @@ class MyTestCase(unittest.TestCase): job = test.testtools.getJob() cm = basic.componentHandling.ComponentManager.getInstance(job, "J") componentName = "testcm" - confs = utils.config_tool.getConfig(job, "comp", componentName) - conns = utils.conn_tool.getConnections(job, componentName) + confs = tools.config_tool.getConfig(job, "comp", componentName) + conns = tools.conn_tool.getConnections(job, componentName) c = cm.createInstance(componentName, None, confs, conns, 1) - self.assertEqual(hasattr(c, "conf"), True, "cinfig-dict must be") + self.assertEqual(hasattr(c, "conf"), True, "config-dict must be") self.assertEqual(hasattr(c, "m"), True, "message-object must be") self.assertEqual(c.name, "testcm_01", "classname with number") # classname with number cnttest += 3 @@ -70,8 +112,8 @@ class MyTestCase(unittest.TestCase): self.assertEqual(c.conf[B.SUBJECT_INST][B.ATTR_INST_SGL], "n", "without conn-attribute the config-attribute keeps") cnttest += 1 # it keep componentName = "testprddb" - confs = utils.config_tool.getConfig(job, "comp", componentName) - conns = utils.conn_tool.getConnections(job, componentName) + confs = tools.config_tool.getConfig(job, "comp", componentName) + conns = tools.conn_tool.getConnections(job, componentName) c = cm.createInstance(componentName, None, confs, conns, 0) self.assertEqual(c.name, "testprddb") self.assertIn(B.ATTR_DB_TYPE, c.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB], "conn-attribute creates missing config-attribute") diff --git a/test/test_20application.py b/test/test_20application.py index ad59fd0..db38d2b 100644 --- a/test/test_20application.py +++ b/test/test_20application.py @@ -13,8 +13,8 @@ import model.application HOME_PATH = test.constants.HOME_PATH PYTHON_CMD = "python" -TEST_FUNCTIONS = ["test_10getEntityNames", "test_12getEntity", "test_10getApplications"] -#TEST_FUNCTIONS = ["test_12getEntity"] +TEST_FUNCTIONS = ["test_10getEntityNames", "test_12getEntity", "test_11getEntities", "test_10getApplications"] +TEST_FUNCTIONS = ["test_11getEntities"] PROGRAM_NAME = "clean_workspace" @@ -37,6 +37,20 @@ class MyTestCase(unittest.TestCase): #entityNames = component.select_unique_names(job, "", "", "", {}) #self.assertEquals(type(entityNames), list) + def test_11getEntities(self): + global mymsg + global jobObject + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + application = model.application.Application() + entityNames = application.get_entities(job, storage=model.entity.STORAGE_FILE) + self.assertEqual(type(entityNames), dict) + #entityNames = environment.get_entities(job, storage=model.entity.STORAGE_DB) + #self.assertEqual(type(entityNames), list) + def test_12getEntity(self): global mymsg global jobObject diff --git a/test/test_31filecsv.py b/test/test_31filecsv.py index 06cdfa2..86d6999 100644 --- a/test/test_31filecsv.py +++ b/test/test_31filecsv.py @@ -12,6 +12,7 @@ import basic.program import tools.path_tool import tools.file_tool import os +import test.testtools HOME_PATH = test.constants.HOME_PATH DATA_PATH = test.constants.DATA_PATH @@ -28,11 +29,11 @@ OS_SYSTEM = test.constants.OS_SYSTEM # the list of TEST_FUNCTIONS defines which function will be really tested. # if you minimize the list you can check the specific test-function -TEST_FUNCTIONS = ["test_11ddl", "test_12catalog", - "test_02getCsvSpec_data", "test_03getCsvSpec_tree", "test_14getCsvSpec_key", - "test_15getCsvSpec_conf", "test_06parseCsv"] -TEST_FUNCTIONS = ["test_11ddl", "test_12catalog", "test_14getCsvSpec_key", "test_15getCsvSpec_conf"] -TEST_FUNCTIONS = ["test_02getCsvSpec_data"] +TEST_FUNCTIONS = [ "test_02isBlock", "test_03setSubtable", "test_06parseCsv", + "test_11ddl", "test_12catalog", "test_13getCsvSpec_tree", "test_14getCsvSpec_key", + "test_15getCsvSpec_conf", "test_16getCsvSpec_data" + ] +TEST_FUNCTIONS = ["test_03setSubtable"] PROGRAM_NAME = "clean_workspace" # with this variable you can switch prints on and off @@ -41,6 +42,20 @@ verbose = False class MyTestCase(unittest.TestCase): mymsg = "--------------------------------------------------------------" + def test_03setSubtable(self): + global mymsg + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + # job = basic.program.SimpleJob(PROGRAM_NAME) + job = test.testtools.getWorkspaceJob(PROGRAM_NAME) + f = toolHandling.getFileTool(job, None, "csv") + subtable = {} + subtable = f.setSubTable(job, subtable, "_stories", ["_stories", "S1", "S2", "", "", "", ""]) + subtable = f.setSubTable(job, subtable, "_stories-description", ["_stories-description", "todo 1", "todo 2", "", "", "", ""]) + subtable = f.setSubTable(job, subtable, "reference", ["reference", "ext 1", "ext 2", "", "", "", ""]) + pass def test_11ddl(self): global mymsg @@ -161,12 +176,18 @@ class MyTestCase(unittest.TestCase): cnttest = 0 if actfunction not in TEST_FUNCTIONS: return - job = basic.program.SimpleJob(PROGRAM_NAME) + job = test.testtools.getWorkspaceJob(PROGRAM_NAME) f = toolHandling.getFileTool(job, None, "csv") - res = f.isBlock(job.m, job, "_type", D.CSV_BLOCK_ATTR, "status") + res = f.isBlock(job.m, job, "_variants", D.CSV_BLOCK_SUBTABLES, "status") self.assertEqual(True, res) - res = f.isBlock(job.m, job, "", D.CSV_BLOCK_ATTR, "status") + res = f.isBlock(job.m, job, "_description", D.CSV_BLOCK_SUBTABLES, B.DATA_NODE_SUBTABLES) self.assertEqual(True, res) + res = f.isBlock(job.m, job, "_type", D.CSV_BLOCK_ATTR, "status") + self.assertEqual(True, res) # with any attribute it is true - open for new attributes + res = f.isBlock(job.m, job, "", D.CSV_BLOCK_ATTR, "status") + self.assertEqual(False, res) # without any attribute it is False + res = f.isBlock(job.m, job, "_xyz", D.CSV_BLOCK_ATTR, "status") + self.assertEqual(True, res) # with any attribute it is true - open for new attributes res = f.isBlock(job.m, job, "head:name", D.CSV_BLOCK_OPTION, "status") self.assertEqual(False, res) res = f.isBlock(job.m, job, "option:name", D.CSV_BLOCK_OPTION, "status") @@ -177,7 +198,7 @@ class MyTestCase(unittest.TestCase): self.assertEqual(False, res) - def test_02getCsvSpec_data(self): + def test_16getCsvSpec_data(self): global mymsg actfunction = str(inspect.currentframe().f_code.co_name) cnttest = 0 @@ -191,13 +212,14 @@ class MyTestCase(unittest.TestCase): a_0 : { a_1 : { f_1 : v_1, .... } # option, step a_0 : { .. a_n : { _header : [ .. ], _data : [ rows... ] # table, node """ - tests = ["malformated", "comments", D.CSV_BLOCK_OPTION, D.CSV_BLOCK_STEP, B.DATA_NODE_TABLES] + tests = ["malformated", "comments", D.CSV_BLOCK_OPTION, D.CSV_BLOCK_STEP, B.DATA_NODE_TABLES, D.SUB_TABLES] + tests = [D.SUB_TABLES] + f = toolHandling.getFileTool(job, None, "csv") if "comments" in tests: specLines = [ ";;;;;;", "#;;;;;;" ] - f = toolHandling.getFileTool(job, None, "csv") tdata = f.parseCsv(job.m, job, specLines, D.CSV_SPECTYPE_DATA) self.assertEqual(1, len(tdata)) cnttest += 1 @@ -230,6 +252,17 @@ class MyTestCase(unittest.TestCase): "#option:nopar;arg;;;;;", "#;;;;;;" ] + if D.SUB_TABLES in tests: + specLines = [ + "_stories;something;;;;;", + "_stories-description;something-one;;;;;", + "#;;;;;;" + ] + tdata = f.parseCsv(job.m, job, specLines, D.CSV_SPECTYPE_DATA) + self.assertEqual(2, len(tdata)) + print(tdata) + self.assertIn(D.CSV_BLOCK_OPTION, tdata) + cnttest += 2 if D.CSV_BLOCK_OPTION in tests: specLines = [ "option:description;something;;;;;", @@ -323,7 +356,7 @@ class MyTestCase(unittest.TestCase): out = out[1:] return out - def test_03getCsvSpec_tree(self): + def test_13getCsvSpec_tree(self): # TODO : Baumstruktur fuer properties global mymsg actfunction = str(inspect.currentframe().f_code.co_name) diff --git a/tools/data_const.py b/tools/data_const.py index f2a1ebc..5449e88 100644 --- a/tools/data_const.py +++ b/tools/data_const.py @@ -81,18 +81,36 @@ DATA_ATTR_USECASES = "_"+B.SUBJECT_USECASES DATA_ATTR_USECASE_DESCR = DATA_ATTR_USECASES+"-description" DATA_ATTR_STORIES = "_"+B.SUBJECT_STORIES DATA_ATTR_STORY_DESCR = DATA_ATTR_STORIES+"-description" +DATA_ATTR_VARIANTS = "_"+B.SUBJECT_VARIANTS +DATA_ATTR_APPS = "_"+B.SUBJECT_APPS """ name of the table - it can be overwrite from the environment-attribut tablename """ LIST_DATA_ATTR = [DATA_ATTR_TYPE, DATA_ATTR_COUNT, DATA_ATTR_DATE, DATA_ATTR_CHAR, DATA_ATTR_COMP, DATA_ATTR_REF, DATA_ATTR_IDS, DATA_ATTR_ALIAS, DATA_ATTR_KEY, DATA_ATTR_TBL, DATA_ATTR_DLIM, - DATA_ATTR_NAME, DATA_ATTR_DESCRIPTION, DATA_ATTR_REFERENCE, DATA_ATTR_PROJECT, - DATA_ATTR_STORIES, DATA_ATTR_STORY_DESCR, DATA_ATTR_USECASES, DATA_ATTR_USECASE_DESCR] + DATA_ATTR_NAME, DATA_ATTR_DESCRIPTION, DATA_ATTR_REFERENCE, DATA_ATTR_PROJECT, DATA_ATTR_VARIANTS, + DATA_ATTR_STORIES, DATA_ATTR_STORY_DESCR, DATA_ATTR_USECASES, DATA_ATTR_USECASE_DESCR, DATA_ATTR_APPS] LIST_ATTR_CONST = ["DATA_ATTR_COUNT", "DATA_ATTR_DATE", "DATA_ATTR_CHAR", "DATA_ATTR_COMP", "DATA_ATTR_ALIAS", "DATA_ATTR_KEY"] -LIST_ATTR_MULTI = [DATA_ATTR_USECASES, DATA_ATTR_STORIES, DATA_ATTR_STORY_DESCR] +LIST_ATTR_MULTI = [DATA_ATTR_USECASES, DATA_ATTR_STORIES, DATA_ATTR_STORY_DESCR, DATA_ATTR_VARIANTS, DATA_ATTR_APPS] + +# subtables of testcase and other +SUB_USECASE = B.SUBJECT_USECASES +SUB_STORIES = B.SUBJECT_STORIES +SUB_VARIANTS = B.SUBJECT_VARIANTS +SUB_APPLICATIONS = B.SUBJECT_APPS +SUB_STEPS = "steps" +SUB_TABLES = "tables" +LIST_SUBTABLES = { + SUB_STEPS: [], + SUB_USECASE: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE], + SUB_STORIES: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE], + SUB_APPLICATIONS: [], + SUB_VARIANTS: [] +} +LIST_SUBTABLES_ATTR = [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE] # attributes in testcase-specification -HEAD_ATTR_DESCR = "decription" +HEAD_ATTR_DESCR = "description" HEAD_ATTR_TARGET = "target" HEAD_ATTR_USECASE = "usecase" HEAD_ATTR_UCID = "usecase-id" @@ -137,7 +155,8 @@ CSV_BLOCK_OPTION = B.DATA_NODE_OPTION CSV_BLOCK_STEP = B.DATA_NODE_STEPS CSV_BLOCK_TABLES = "_table" CSV_BLOCK_IMPORT = "_import" -LIST_CSV_BLOCKS = [CSV_BLOCK_ATTR, CSV_BLOCK_HEAD, CSV_BLOCK_OPTION, CSV_BLOCK_STEP, CSV_BLOCK_TABLES, CSV_BLOCK_IMPORT] +CSV_BLOCK_SUBTABLES = "_subtable" +LIST_CSV_BLOCKS = [CSV_BLOCK_ATTR, CSV_BLOCK_HEAD, CSV_BLOCK_OPTION, CSV_BLOCK_STEP, CSV_BLOCK_TABLES, CSV_BLOCK_IMPORT, CSV_BLOCK_SUBTABLES] LIST_BLOCK_CONST = ["CSV_BLOCK_HEAD", "CSV_BLOCK_OPTION", "CSV_BLOCK_STEP", "CSV_BLOCK_TABLES", "CSV_BLOCK_IMPORT"] STEP_COMP_I = 1 diff --git a/tools/data_tool.py b/tools/data_tool.py new file mode 100644 index 0000000..2add61b --- /dev/null +++ b/tools/data_tool.py @@ -0,0 +1,21 @@ + +def getPurKeyword(inkey): + """ + each key is case-insensitve in lower case. + A keyword can have a singular or plural form - so the plural-s at the end is optional. + A keyword can be assigned as keyword by the beginning digit underscore - so it is optional too. + A keyword in a csv-file can be characterized by the keyword delimited with the in-filed-delimiter colon. + a sub-keyword can be delimited + :param inkey: + :return: + """ + keyPur = inkey.lower() + if ":" in keyPur: + keyPur = keyPur.split(":").pop() + if "-" in keyPur: + keyPur = keyPur.split("-").pop() + if keyPur[0:1] == "_": + keyPur = keyPur[1:] + if keyPur[-1:] == "s": + keyPur = keyPur[:-1] + return keyPur diff --git a/tools/filecsv_fcts.py b/tools/filecsv_fcts.py index e01292f..5e307d5 100644 --- a/tools/filecsv_fcts.py +++ b/tools/filecsv_fcts.py @@ -40,6 +40,7 @@ class FileFcts(tools.file_abstract.FileFcts): return True return False + def isBlock(self, msg, job, field, block, status): """ detects the block either on keywords in the field which opens a block @@ -52,13 +53,29 @@ class FileFcts(tools.file_abstract.FileFcts): :return: """ try: - blockPur = block.replace("_", "") + print("isBlock "+field + " , " + block + " , " + status) + blockPur = self.getPurValue(block) a = field.split(":") - if a[0] == blockPur: + keyPur = self.getPurValue(a[0]) + statusPur = self.getPurValue(status) + if statusPur+"s-" in keyPur: + keyPur = keyPur[keyPur.find("-")+1:] + print("isBlock "+a[0] + "=" + keyPur +" , " + blockPur + " , " + status) + if (keyPur+"s" in D.LIST_SUBTABLES or keyPur in D.LIST_SUBTABLES) \ + and block == D.CSV_BLOCK_SUBTABLES: + return True + if block == D.CSV_BLOCK_SUBTABLES \ + and status not in [D.CSV_BLOCK_OPTION, D.CSV_BLOCK_HEAD, D.CSV_BLOCK_STEP, D.CSV_BLOCK_TABLES, "status"] \ + and keyPur in D.LIST_SUBTABLES_ATTR: + return True + if (keyPur + "s" in D.LIST_SUBTABLES or keyPur in D.LIST_SUBTABLES) \ + and block == D.CSV_BLOCK_SUBTABLES: + return True + elif "_"+a[0] == block or a[0] == block or "_"+a[0] == block: return True elif "_"+a[0] in [D.CSV_BLOCK_OPTION, D.CSV_BLOCK_HEAD, D.CSV_BLOCK_STEP, D.CSV_BLOCK_TABLES]: return False - if blockPur == status: + if blockPur == status or blockPur+"s" == status: return True if block == D.CSV_BLOCK_ATTR and len(a) == 1 and field[0:1] == "_": return True @@ -86,13 +103,20 @@ class FileFcts(tools.file_abstract.FileFcts): verbose = False tableAttr = {} # table tableDict = {} # table + subtable = {} # Zeilen parsen for l in lines: fields = splitFields(l, D.CSV_DELIMITER, job) if self.isEmptyLine(msg, job, l, fields): continue a = fields[0].lower().split(":") # keywords option, step, table - if self.isBlock(msg, job, fields[0], D.CSV_BLOCK_ATTR, status): # a[0].lower() in D.LIST_DATA_ATTR: + # subtable-Block + if self.isBlock(msg, job, fields[0], D.CSV_BLOCK_SUBTABLES, status): # a[0].lower() in D.LIST_DATA_ATTR: + subtable = setSubTable(job, subtable, a[0], fields) + tdata[subtable["actTable"]] = subtable[subtable["actTable"]] + status = subtable["actTable"] + # attribute-Block + elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_ATTR, status): # a[0].lower() in D.LIST_DATA_ATTR: tableAttr = setTableAttribute(job, tableAttr, a[0], fields) if ttype == "" and D.DATA_ATTR_TYPE in tableAttr: ttype = tableAttr[D.DATA_ATTR_TYPE] @@ -100,14 +124,17 @@ class FileFcts(tools.file_abstract.FileFcts): msg.logWarn("System-Type " + ttype + " be overwrite by file-Type " + tableAttr[D.DATA_ATTR_TYPE]) ttype = tableAttr[D.DATA_ATTR_TYPE] continue + # head-Block elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_HEAD, status): setTdataLine(tdata, fields, D.CSV_BLOCK_HEAD, job) status = "start" continue + # option-Block elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_OPTION, status): setTdataLine(tdata, fields, D.CSV_BLOCK_OPTION, job) status = "start" continue + # step-Block elif (status != D.CSV_BLOCK_STEP) \ and self.isBlock(msg, job, fields[0], D.CSV_BLOCK_STEP, status): h = [] @@ -117,6 +144,7 @@ class FileFcts(tools.file_abstract.FileFcts): setTableHeader(tableDict, tableAttr, fields, ttype, job) status = D.CSV_BLOCK_STEP continue + # table-Header Block elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_TABLES, status): if verbose: print(">> tables " + l) h = a @@ -126,10 +154,12 @@ class FileFcts(tools.file_abstract.FileFcts): tableDict = getTdataContent(msg, tdata, h) setTableHeader(tableDict, tableAttr, fields, ttype, job) status = D.CSV_SPECTYPE_DATA + # table-data-Block elif (status == D.CSV_SPECTYPE_DATA): tableDict = getTdataContent(msg, tdata, h) if verbose: print(">> setTableData " + str(h) + " " + str(tableDict)) setTableData(tableDict, fields, ttype, job) + # step-data-Block elif (status == D.CSV_BLOCK_STEP): print("step-line "+status+": "+l) h = [] @@ -140,6 +170,8 @@ class FileFcts(tools.file_abstract.FileFcts): #tableDict = getTdataContent(msg, tdata, h) #if verbose: print(">> setTableData " + str(h) + " " + str(tableDict)) #setTableData(tableDict, fields, ttype, job) + else: + print("unbekannter Block "+status+": "+l) if D.DATA_ATTR_TYPE not in tableAttr: tableAttr[D.DATA_ATTR_TYPE] = ttype @@ -338,6 +370,37 @@ def splitFields(line, delimiter, job): out.append(fields[i]) return out +def setSubTable(job, subtable, key, val): + """ + + :param job: + :param subtable: + :param key: + :param val: + :return: + """ + # stories => new subtable + # stories-descriptiom => attribute of actual subtable + # descriptiom => attribute of actual subtable + key = key.lower() + subkey = "" + print("setSubtable "+key+", "+str(val)) + if "actTable" in subtable and subtable["actTable"]+"-" in key: + subkey = key[key.find("-")+1:] + if subkey == "" and key not in subtable: + subtable[key] = {} + subtable["actTable"] = key + actTable = subtable["actTable"] + for i in range(1, len(val)): + if val[i] not in subtable[key]: + if val[i] == "": + break + subtable[key][val[i]] = {} + subtable[key][val[i]]["name"] = val[i] + else: + subtable[key][val[i]][key] = val[i] + return subtable + def setTableAttribute(job, tableAttr, key, val): key = key.lower() if key in D.LIST_DATA_ATTR: diff --git a/tools/job_tool.py b/tools/job_tool.py index de8ba23..4f5308a 100644 --- a/tools/job_tool.py +++ b/tools/job_tool.py @@ -46,12 +46,13 @@ import tools.path_tool import tools.file_tool import tools.date_tool as date_tool import components.tools.job_tool -import model.application -import model.environment -import model.testplan -import model.testsuite -import model.testcase -import model.component +#import model.application +# import model.environment +#import model.testplan +#import model.testsuite +#import model.testcase +#import model.component +import model.factory def hasModul(komp): #job = Job.getInstance() @@ -198,8 +199,9 @@ def select_application(job, programDef, project): job.debug(verify, "select_application "+project) # the application are configured in comp/applications.yml which are optionally stored in the database projList = [project] - apps = model.application.select_applications(job, projList) - return list(apps.keys()) + # apps = model.application.select_applications(job, projList) + apps = model.factory.getApplication(job).read_unique_names(job, project, "", "", {}) + return apps # list(apps.keys()) def select_components(job, programDef, project, application): """ @@ -218,8 +220,9 @@ def select_environment(job, programDef, project): :return: """ projList = [project] - envs = model.environment.select_environments(job, projList) - return list(envs.keys()) + envs = model.factory.getEnvironment().read_unique_names(job, project, "", "", "") + # model.environment.select_environments(job, projList) + return envs def select_spec(job, programDef, gran, args): """ @@ -236,8 +239,9 @@ def select_spec(job, programDef, gran, args): return list(out.keys()) elif gran in [B.PAR_TESTCASE, J.GRAN_TC]: print("select tc spec " + gran) - out = model.testcase.select_testcases(job, [args[B.PAR_PROJ]], [args[B.PAR_APP]]) - return list(out.keys()) + out = model.factory.getTestcase(job, args[B.PAR_PROJ], args[B.PAR_APP]).read_unique_names( + job, args[B.PAR_PROJ], args[B.PAR_APP], "", {}) + return out print("select no spec "+gran) def select_archiv(job, programDef, gran, project): @@ -272,7 +276,8 @@ def select_variant(job, programDef, gran, args): return list(out["variant"].keys()) elif gran in [B.PAR_TESTCASE, J.GRAN_TC]: print("select tc spec " + gran + " " + str(args)) - out = model.testcase.select_testcase(job, args[B.PAR_PROJ], args[B.PAR_TESTCASE]) + out = model.factory.getTestcase(job, args[B.PAR_PROJ]).read_entity(job, args[B.PAR_TESTCASE]) + print(str(out)) if "variant" not in out: return [""] return list(out["variant"].keys()) @@ -289,5 +294,8 @@ def select_testsuite(job, programDef, args): return outList def select_testcase(job, programDef, args): - outList = model.testcase.select_testcases(job, [args[B.PAR_PROJ]], [args[B.PAR_APP]]) + import model.testcase + print("testcase args "+str(args)) + # outList = model.testcase.select_testcases(job, [args[B.PAR_PROJ]], [args[B.PAR_APP]]) + outList = model.factory.getTestcase(job, args[B.PAR_PROJ]).get_unique_names(job, project=args[B.PAR_PROJ], application=args[B.PAR_APP]) return outList \ No newline at end of file