From 9fbd75e5a14996e6606d0c7b349d747d39457e8b Mon Sep 17 00:00:00 2001 From: Ulrich Date: Fri, 2 Jun 2023 20:50:53 +0200 Subject: [PATCH] testcase reading --- basic/constants.py | 4 ++- model/factory.py | 12 +++---- model/testcase.py | 2 +- test/test_05data.py | 30 ++++++++++------ test/test_31filecsv.py | 30 ++++++++++++++-- tools/data_tool.py | 38 ++++++++++++++++++++ tools/filecsv_fcts.py | 78 ++++++++++++++++++++++++++++++++---------- 7 files changed, 154 insertions(+), 40 deletions(-) diff --git a/basic/constants.py b/basic/constants.py index 1c1db35..7c0fc7d 100644 --- a/basic/constants.py +++ b/basic/constants.py @@ -193,6 +193,8 @@ SUBJECT_STORIES = "stories" SUBJECT_DESCRIPTION = "description" # --> MAIN-ATTR SUBJECT_REFERENCE = "reference" # --> MAIN-ATTR LIST_SUBJECTS = [SUBJECT_APPS, SUBJECT_ARTIFACT, SUBJECT_COMPS, SUBJECT_PROJECTS] +SUBJECT_STEP = "step" +SUBJECT_STEPS = "steps" # --Topic ----------------------------------------------------- # _____ _ @@ -315,7 +317,7 @@ DATA_NODE_FIELDS = "_fields" """ it defines a subnode of a table for the data as key-value-pair, keys from header """ DATA_NODE_DATA = "_data" """ it defines the main node in the testdata for the steps to execute """ -DATA_NODE_STEPS = "_step" ## ?? SUBJECT +DATA_NODE_STEPS = SUBJECT_STEPS # "_step" ## ?? SUBJECT """ it defines main node in the testdata for testcase specific parameters """ DATA_NODE_OPTION = "_option" ## ?? SUBJECT DATA_NODE_HEAD = "_head" ## ?? diff --git a/model/factory.py b/model/factory.py index 9f1e5de..46809ae 100644 --- a/model/factory.py +++ b/model/factory.py @@ -5,22 +5,22 @@ def getEnvironment(job=None): import model.environment return model.environment.Environment(job) -def getApplication(job=None): +def getApplication(job=None, name=""): import model.application return model.application.Application() -def getComponent(job=None): +def getComponent(job=None, name=""): import model.component return model.component.Component(job) -def getTestplam(job=None, project="", application=""): +def getTestplan(job=None, project="", application="", name=""): import model.testplan return model.testplan.Testplan(job, project) -def getTestsuite(job=None, project="", application=""): +def getTestsuite(job=None, project="", application="", name=""): import model.testsuite return model.testsuite.Testsuite(job, project) -def getTestcase(job=None, project="", application=""): +def getTestcase(job=None, project="", application="", name=""): import model.testcase - return model.testcase.Testcase(job, project) + return model.testcase.Testcase(job, project, name=name) diff --git a/model/testcase.py b/model/testcase.py index 7a0d851..3c42e1c 100644 --- a/model/testcase.py +++ b/model/testcase.py @@ -92,7 +92,7 @@ class Testcase(model.entity.Entity): self.project = project if len(name) > 1: self.name = name - # self.getEntity(job, name) + self.read_entity(job, name) def read_unique_names(self, job, project, application, gran, args): """ diff --git a/test/test_05data.py b/test/test_05data.py index 855eb6b..a852bca 100644 --- a/test/test_05data.py +++ b/test/test_05data.py @@ -13,19 +13,11 @@ 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"] +TEST_FUNCTIONS = ["test_01getKeyword", "test_02getStrDict"] PROGRAM_NAME = "clean_workspace" # with this variable you can switch prints on and off @@ -46,6 +38,24 @@ class MyTestCase(unittest.TestCase): res = tools.data_tool.getPurKeyword(x) self.assertEqual(res, "variant") + def test_02getStrDict(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) + res = tools.data_tool.getStrDict("val1") + self.assertEqual(len(res), 0) + res = tools.data_tool.getStrDict("val1,val2") + self.assertEqual(len(res), 0) + res = tools.data_tool.getStrDict("key1:val1") + self.assertEqual(len(res), 1) + res = tools.data_tool.getStrDict("key1:val1,key2:val2") + self.assertEqual(len(res), 2) + res = tools.data_tool.getStrDict('"key1":"val1","key2":"val2"') + self.assertEqual(len(res), 2) + def test_zzz(self): print(MyTestCase.mymsg) diff --git a/test/test_31filecsv.py b/test/test_31filecsv.py index 71e68e2..43c3509 100644 --- a/test/test_31filecsv.py +++ b/test/test_31filecsv.py @@ -33,7 +33,8 @@ 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_02isBlock"] +TEST_FUNCTIONS = ["test_16getCsvSpec_data"] +# TEST_FUNCTIONS = ["test_02isBlock"] PROGRAM_NAME = "clean_workspace" # with this variable you can switch prints on and off @@ -197,7 +198,10 @@ class MyTestCase(unittest.TestCase): self.assertEqual(True, res) res = f.isBlock(job.m, job, "table:name", D.CSV_BLOCK_OPTION, "option") self.assertEqual(False, res) - + res = f.isBlock(job.m, job, "steps", D.CSV_BLOCK_STEP, "status") + self.assertEqual(True, res) + res = f.isBlock(job.m, job, "steps", D.CSV_BLOCK_SUBTABLES, "status") + self.assertEqual(False, res) def test_16getCsvSpec_data(self): global mymsg @@ -260,9 +264,29 @@ class MyTestCase(unittest.TestCase): "#;;;;;;" ] tdata = f.parseCsv(job.m, job, specLines, D.CSV_SPECTYPE_DATA) + print(tdata) self.assertEqual(2, len(tdata)) + self.assertIn(B.SUBJECT_STORIES, tdata) + cnttest += 2 + specLines = [ + "steps;variant;sortnr;stepnr;datanr;args;;", + ";xml-rest;1;2;1;one:1,two:2;;;", + "#;;;;;;" + ] + tdata = f.parseCsv(job.m, job, specLines, D.CSV_SPECTYPE_DATA) print(tdata) - self.assertIn(D.CSV_BLOCK_OPTION, tdata) + self.assertIn(B.SUBJECT_STEPS, tdata) + self.assertEqual(2, len(tdata[B.SUBJECT_STEPS])) + specLines = [ + "steps;variant;sortnr;stepnr;datanr;args;;", + ";xml-rest;1;2;1;one:1,two:2;;;", + ";json-rest;1;2;3;jone:1,jtwo:2;;;", + "#;;;;;;" + ] + tdata = f.parseCsv(job.m, job, specLines, D.CSV_SPECTYPE_DATA) + print(tdata) + self.assertIn(B.SUBJECT_STEPS, tdata) + self.assertEqual(3, len(tdata[B.SUBJECT_STEPS])) cnttest += 2 if D.CSV_BLOCK_OPTION in tests: specLines = [ diff --git a/tools/data_tool.py b/tools/data_tool.py index 2add61b..08a1c5d 100644 --- a/tools/data_tool.py +++ b/tools/data_tool.py @@ -1,4 +1,5 @@ + def getPurKeyword(inkey): """ each key is case-insensitve in lower case. @@ -19,3 +20,40 @@ def getPurKeyword(inkey): if keyPur[-1:] == "s": keyPur = keyPur[:-1] return keyPur + +def getPluralKeyword(inkey): + return getPurKeyword(inkey)+"s" + +def getSingularKeyword(inkey): + return getPurKeyword(inkey) + +def getPluralAttribut(inkey): + return "_"+getPurKeyword(inkey)+"s" + +def getSingularAttribut(inkey): + return "_"+getPurKeyword(inkey) + +def isStrDict(invalue): + if isinstance(invalue, dict): + return True + if invalue.count(":") == invalue.count(",") + 1: + return True + return False + +def getStrDict(invalue): + """ + returns a dict of the input-value. + If it is a string like json (delimited for key-value-pairs by comma and delimted the key-values by colon) then + it is transformed into a dictionary + :param invalue: + :return: + """ + if isinstance(invalue, dict): + return invalue + outDict = {} + if isStrDict(invalue): + keyvalues = invalue.split(",") + for x in keyvalues: + kv = x.split(":") + outDict[kv[0].replace("\"", "")] = kv[1].replace("\"", "") + return outDict diff --git a/tools/filecsv_fcts.py b/tools/filecsv_fcts.py index eac8139..b78e753 100644 --- a/tools/filecsv_fcts.py +++ b/tools/filecsv_fcts.py @@ -64,14 +64,14 @@ class FileFcts(tools.file_abstract.FileFcts): keyPur = keyPur[keyPur.find("-")+1:] if verify: 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: + and block == D.CSV_BLOCK_SUBTABLES and keyPur != B.SUBJECT_STEP: 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 status not in [D.CSV_BLOCK_OPTION, D.CSV_BLOCK_HEAD, 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: + and block == D.CSV_BLOCK_SUBTABLES and keyPur != B.SUBJECT_STEP: return True elif "_"+a[0] == block or a[0] == block or "_"+a[0] == block: return True @@ -101,12 +101,14 @@ class FileFcts(tools.file_abstract.FileFcts): g) data-table: array: field - values # spec.data, comp.artifacts :return: """ + verify = True tdata = {} status = "start" verbose = False tableAttr = {} # table tableDict = {} # table subtable = {} + steps = {} # Zeilen parsen for l in lines: fields = splitFields(l, D.CSV_DELIMITER, job) @@ -115,11 +117,13 @@ class FileFcts(tools.file_abstract.FileFcts): # keywords option, step, table # subtable-Block if self.isBlock(msg, job, fields[0], D.CSV_BLOCK_SUBTABLES, status): # a[0].lower() in D.LIST_DATA_ATTR: + if verify: print("block "+D.CSV_BLOCK_SUBTABLES+" :: "+l) 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: + if verify: print("block "+D.CSV_BLOCK_ATTR+" :: "+l) tableAttr = setTableAttribute(job, tableAttr, a[0], fields) if ttype == "" and D.DATA_ATTR_TYPE in tableAttr: ttype = tableAttr[D.DATA_ATTR_TYPE] @@ -129,26 +133,31 @@ class FileFcts(tools.file_abstract.FileFcts): continue # head-Block elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_HEAD, status): + if verify: print("block "+D.CSV_BLOCK_HEAD+" :: "+l) 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): + if verify: print("block "+D.CSV_BLOCK_OPTION+" :: "+l) 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 = [] - h.append(B.DATA_NODE_STEPS) + if verify: print("block "+D.CSV_BLOCK_STEP+" :: "+l) + #h = [] + steps = setStepAttribute(job, steps, "", fields) + #h.append(B.DATA_NODE_STEPS) if verbose: print(">> step "+l) - tableDict = getTdataContent(msg, tdata, h) - setTableHeader(tableDict, tableAttr, fields, ttype, job) + #tableDict = getTdataContent(msg, tdata, h) + #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 verify: print("block "+D.CSV_BLOCK_TABLES+" :: "+l) if verbose: print(">> tables " + l) h = a h[0] = B.DATA_NODE_TABLES @@ -159,21 +168,26 @@ class FileFcts(tools.file_abstract.FileFcts): status = D.CSV_SPECTYPE_DATA # table-data-Block elif (status == D.CSV_SPECTYPE_DATA): + if verify: print("block "+D.CSV_SPECTYPE_DATA+" :: "+l) 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): + if verify: print("block "+D.CSV_BLOCK_STEP+"2 :: "+l) print("step-line "+status+": "+l) - h = [] - h.append(B.DATA_NODE_STEPS) - tableDict = getTdataContent(msg, tdata, h) - if verbose: print(">> setTableData " + str(h) + " " + str(tableDict)) - setTableData(tableDict, fields, ttype, job) + #h = [] + steps = setStepAttribute(job, steps, fields[1], fields) + tdata[B.SUBJECT_STEPS] = steps + #h.append(B.DATA_NODE_STEPS) + #tableDict = getTdataContent(msg, tdata, h) + #if verbose: print(">> setTableData " + str(h) + " " + str(tableDict)) + #setTableData(tableDict, fields, ttype, job) #tableDict = getTdataContent(msg, tdata, h) #if verbose: print(">> setTableData " + str(h) + " " + str(tableDict)) #setTableData(tableDict, fields, ttype, job) else: + if verify: print("block else :: "+l) print("unbekannter Block "+status+": "+l) if D.DATA_ATTR_TYPE not in tableAttr: @@ -385,32 +399,58 @@ def setSubTable(job, subtable, key, val): # stories => new subtable # stories-descriptiom => attribute of actual subtable # descriptiom => attribute of actual subtable - key = key.lower() + key = key.lower() # tools.data_tool.getPluralKeyword(key) subkey = "" newSubtable = False 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: + keyword = tools.data_tool.getPluralKeyword(key) + if subkey == "" and keyword not in subtable: newSubtable = True - subtable[key] = {} - subtable["actTable"] = key + subtable[keyword] = {} + subtable["actTable"] = keyword actTable = subtable["actTable"] purKey = tools.data_tool.getPurKeyword(key) print("setSubtable "+key+" =? "+actTable+ " + "+ purKey +" , "+str(val)) actKeys = list(subtable[actTable].keys()) for i in range(1, len(val)): - if newSubtable and val[i] not in subtable[key]: + if newSubtable and val[i] not in subtable[actTable]: if val[i] == "": break subtable[actTable][val[i]] = {} subtable[actTable][val[i]]["name"] = val[i] else: - if i >= len(actKeys): + if i > len(actKeys): break - subtable[actTable][actKeys[i]][purKey] = val[i] + subtable[actTable][actKeys[i-1]][purKey] = val[i] return subtable +def setStepAttribute(job, stepAttr, key, val): + if key == "": + stepAttr[B.DATA_NODE_HEADER] = [] + for i in range(1, len(val)): + if len(val[i]) < 1: + continue + stepAttr[B.DATA_NODE_HEADER].append(val[i]) + else: + if B.DATA_NODE_HEADER not in stepAttr: + print("Error: header is missing ") + i = 1 + step = {} + for h in stepAttr[B.DATA_NODE_HEADER]: + if len(h) < 1: + continue + if tools.data_tool.isStrDict(val[i]): + step[h] = tools.data_tool.getStrDict(val[i]) + else: + step[h] = val[i] + i += 1 + key = "{:0>2d}_{}".format(int(step["sortnr"]), step["variant"]) + step["name"] = step["variant"] + stepAttr[key] = step + return stepAttr + def setTableAttribute(job, tableAttr, key, val): key = key.lower() if key in D.LIST_DATA_ATTR: