Data-Test-Executer Framework speziell zum Test von Datenverarbeitungen mit Datengenerierung, Systemvorbereitungen, Einspielungen, ganzheitlicher diversifizierender Vergleich
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

364 lines
13 KiB

#!/usr/bin/python
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------------------------------------
# Author : Ulrich Carmesin
# Source : gitea.ucarmesin.de
# ---------------------------------------------------------------------------------------------------------
import os
import basic.toolHandling
import tools.job_const as J
import tools.data_const as D
import basic.constants as B
import model.entity
import tools.config_tool
import tools.job_tool
import tools.path_tool
import tools.path_const as P
import model.entity
import model.story
import model.datatable
import model.step
import model.factory
import tools.file_type
TABLE_NAMES = ["application", "ap_project", "ap_component"]
STORAGES = [model.entity.STORAGE_FILE, model.entity.STORAGE_DB]
""" used storage in priority sortage, so: if file then read_fcts / if db then select-fcts """
DEFAULT_SYNC = model.entity.SYNC_FULL_GIT2DB
TABLE_NAME = B.SUBJECT_APP
""" system-name for this entity """
FIELD_ID = "tcid"
FIELD_NAME = D.FIELD_NAME
FIELD_DESCRIPTION = B.SUBJECT_DESCRIPTION
FIELD_REFERENCE = B.SUBJECT_REFERENCE
FIELD_PROJECT = B.SUBJECT_PROJECT
FIELD_APPLICATION = B.SUBJECT_APP
LIST_FIELDS = [FIELD_ID, FIELD_NAME,
FIELD_DESCRIPTION, FIELD_REFERENCE, FIELD_PROJECT]
""" list of object-attributes """
LIST_NODES = [B.NODE_ATTRIBUTES]
SUB_USECASE = B.SUBJECT_USECASES
SUB_STORIES = B.SUBJECT_STORIES
SUB_STEPS = "steps"
SUB_TABLES = "tables"
LIST_SUBTABLES = { # with additional attributes for the subtable
B.SUBJECT_APPS: [],
SUB_TABLES: [D.DATA_ATTR_DATE],
SUB_STEPS: [],
SUB_USECASE: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE],
SUB_STORIES: [B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE]
}
LIST_SUB_DESCRIPT = [D.DATA_ATTR_USECASE_DESCR, D.DATA_ATTR_STORY_DESCR]
FILE_EXTENSION = D.DFILE_TYPE_YML
UNIQUE_FIELDS = [FIELD_NAME]
""" unique business field as human identifer """
IDENTIFYER_FIELDS = [FIELD_ID]
""" unique technical field as technical identifer """
class Testcase(model.entity.Entity):
"""
Generally this object can be stored as a file with data or in a database.
references:
application ->
story -> story
variant -> comp.step
subtables
steps -> comp.step
tables -> comp.table
"""
FIELD_ID = "tcid"
LIST_FIELDS = [FIELD_ID, D.FIELD_NAME, B.SUBJECT_APPS,
B.SUBJECT_DESCRIPTION, B.SUBJECT_REFERENCE, B.SUBJECT_PROJECT]
LIST_NODES = [B.NODE_ATTRIBUTES]
tcid = ""
name = ""
description = ""
project = ""
reference = ""
attributes = ""
stories = {}
tables = {}
steps = {}
def __init__(self, job, project, name=""):
"""
to be initialized by readSpec
:param job:
"""
self.job = job
if len(project) > 1:
self.project = project
if len(name) > 1:
self.name = name
self.read_entity(job, name)
def read_unique_names(self, job, project, application, gran, args):
"""
reads the entity-names from file-storage
:param job:
:param opt. project: select-criteria if used and defined
:param opt. application: select-criteria if used and defined
:param opt. gran: granularity values testcase / testsuite / testplan
:param opt. args additional args
:return: list of entity-names
"""
if project == "":
project = getattr(job.par, B.SUBJECT_PROJECT)
path = os.path.join(job.conf[B.TOPIC_PATH][B.ATTR_PATH_TDATA], project,
B.SUBJECT_TESTCASES)
outList = self.getDirlist(job, path, "")
return outList
def read_entity(self, job, name):
"""
reads the entity from the file-system
:param job:
:param name:
:return:
"""
# r = tools.config_tool.select_config_path(job, P.KEY_TESTCASE, "TC0001")
# ttype=testcase => Aufteilung der Testspec in Bloecke und separater Aufruf zur Pruefung der Bloecke
config = self.getConfig(job, P.KEY_TESTCASE, name, tools.config_tool.get_plain_filename(job, name), B.SUBJECT_TESTCASE)
self.setAttributes(job, config, name, LIST_FIELDS, LIST_NODES, LIST_SUBTABLES)
return self
@staticmethod
def rebuild_data(job, tdata: dict) -> dict:
"""
gets the subtable-tag from filecsv and sets the subtables in order to workable entity-elements
:param job:
:param tdata:
:return:
"""
outData = {}
subtables = {}
arguments = {}
for k in tdata:
if k in [B.DATA_NODE_TABLES]:
outData[k[1:]] = tdata[k]
elif k in [B.DATA_NODE_OPTION, "_head"]:
outData[k[1:]] = {}
for e in tdata[k]:
ka = str(e).split("-")
if ka[0] in B.LIST_SUBJECTS:
# not necceassary, because here are single-names with fieldname
ka[0] = ka[0][:-1]
if len(ka) == 1:
# add reference name to potential subtable
ka.append("name")
if ka[0]+"s" in B.LIST_SUBJECTS:
# standard table form: step: { _header: [], _data: [{}, {}, ..] }
if ka[0] in subtables:
subject = subtables[ka[0]]
sublist = subject[B.DATA_NODE_DATA]
header = subject[B.DATA_NODE_HEADER]
else:
enty = model.factory.get_entity_object(job, ka[0], {})
header = enty.getFieldList() + enty.getNodeList()
sublist = []
subject = {}
subject[B.DATA_NODE_DATA] = sublist
subject[B.DATA_NODE_HEADER] = header
#subtables[ka[0]]
string = str(tdata[k][e])
values = str(tdata[k][e]).split(D.INTERNAL_DELIMITER)
i = 0
for v in values:
if len(v) < 1:
continue
if len(sublist) > i:
subtable = sublist[i]
else:
subtable = {}
sublist.append(subtable)
subtable[ka[1]] = v
sublist[i] = subtable
i += 1
subject[B.DATA_NODE_DATA] = sublist
subtables[ka[0]] = subject
else: # attributes
arguments[e] = tdata[k][e]
elif k in B.SUBJECT_STORY:
outData[B.SUBJECT_STORIES] = tdata[k]
elif k in B.LIST_SUBJECTS:
outData[k] = tdata[k]
elif k in B.LIST_DATA_NODE:
outData[k[1:]] = tdata[k]
elif k[1:] in Testcase.LIST_FIELDS:
outData[k[1:]] = tdata[k]
else:
raise Exception("unknown tag in csv-data: "+k)
for s in subtables:
outData[s] = subtables[s]
outData[B.NODE_ATTRIBUTES] = arguments
return outData
@staticmethod
def check_data(job, data: dict) -> dict:
checkNodes = {}
checkNodes[tools.file_type.MUST_NODES] = [B.SUBJECT_APP, B.SUBJECT_DATATABLES, B.SUBJECT_STEPS,
B.NODE_ATTRIBUTES]
checkNodes[tools.file_type.MUSTNT_NODES] = [B.DATA_NODE_OPTION, B.DATA_NODE_DATA, B.DATA_NODE_FIELDS, B.DATA_NODE_HEADER]
checkNodes[tools.file_type.OPT_NODES] = [B.SUBJECT_USECASES, B.SUBJECT_STORIES]
return tools.file_type.check_nodes(job, data, checkNodes)
def getFieldList(self):
"""
returns a list of scalar attributes
:return: LIST_FIELDS
"""
return LIST_FIELDS
def getNodeList(self):
"""
returns a list of sub-nodes - which can be persisted in a clob-field
:return: LIST_NODES
"""
return LIST_NODES
def getSubtableList(self):
"""
returns a list of sub-tables
:return: LIST_SUBTABLES
"""
return LIST_SUBTABLES
def getName(self):
"""
returns the name - maybe build from other attributes
:return:
"""
return self.name
def getIDName(self):
"""
it returns the name as unique-id - maybe build from few attributes
:return:
"""
return self.name
def xxread_entity(self, job, name):
"""
reads the entity from the file-system
:param job:
:param name:
:return:
"""
pathname = tools.config_tool.select_config_path(job, P.KEY_TESTCASE, name, "")
print(pathname)
(fname, ext) = os.path.splitext(pathname)
fi = basic.toolHandling.getFileTool(job, None, ext[1:])
tdata = fi.load_file(pathname, ttype=D.CSV_SPECTYPE_DATA)
stories = []
docs = []
attributes = {}
pass
if B.DATA_NODE_HEAD in tdata:
for h in D.LIST_HEAD_ATTR:
if h in tdata[B.DATA_NODE_HEAD]:
setattr(self, h, tdata[B.DATA_NODE_HEAD][h])
else:
job.m.logWarn("Keine Head-Daten in Testcase "+name)
if B.DATA_NODE_OPTION in tdata:
for o in tdata[B.DATA_NODE_OPTION]:
if o in [D.OPT_ATTR_UCID, D.OPT_ATTR_USECASE]:
pass
elif o in [D.OPT_ATTR_STORYID, D.OPT_ATTR_STORY]:
if len(stories) < 1:
story = model.story.Story(job)
stories.append(story)
else:
story = stories[0]
setattr(story, model.story.FIELDS[o], tdata[B.DATA_NODE_OPTION][o])
elif o in D.LIST_OPT_ATTR:
setattr(self, o, tdata[B.DATA_NODE_OPTION][o])
else:
attributes[o] = tdata[B.DATA_NODE_OPTION][o]
else:
job.m.logWarn("Keine Option-Daten in Testcase "+name)
if len(attributes) > 0:
self.attributes = attributes
if len(stories) > 0:
self.story = stories
pass
if B.DATA_NODE_STEPS in tdata:
for s in tdata[B.DATA_NODE_STEPS]:
if s in B.LIST_DATA_NODE:
continue
step = model.step.Step(job, project=job.par.project, name=s)
pass
if B.DATA_NODE_TABLES in tdata:
for t in tdata[B.DATA_NODE_TABLES]:
table = model.datatable.Datatable(job, project=job.par.project, name=t)
pass
# for o in tdata[B.option
# header = tdata[B.DATA_NODE_STEPS][] LIST
# reference
#
# for t in tdata[B.tables
#raise Exception(B.EXCEPT_NOT_IMPLEMENT)
def select_entity(self, job, name):
"""
reads the entity from the database
it should get the same result like read_entity
:param job:
:param name:
:return:
"""
raise Exception(B.EXCEPT_NOT_IMPLEMENT)
def select_testcase(job, project, testcase):
"""
to select a concrete testcase
:param job:
:param project:
:param testcase:
:return:
"""
jobProj = None
if hasattr(job.par, B.PAR_PROJ):
jobProj = getattr(job.par, B.PAR_PROJ)
setattr(job.par, B.PAR_PROJ, project)
path = tools.path_tool.compose_path(job, P.P_TDROOT, None)
specpath = os.path.join(path, testcase, D.DFILE_TESTCASE_NAME + ".csv")
spec = model.entity.read_spec(job, testcase, J.GRAN_TS, specpath)
if jobProj is None:
delattr(job.par, B.PAR_PROJ)
else:
setattr(job.par, B.PAR_PROJ, jobProj)
print("select_testcase "+str(spec))
return spec
def select_testcases(job, projList, appList):
out = {}
jobProj = None
if hasattr(job.par, B.PAR_PROJ):
jobProj = getattr(job.par, B.PAR_PROJ)
for proj in projList:
setattr(job.par, B.PAR_PROJ, proj)
path = tools.path_tool.compose_path(job, P.P_TDROOT, None)
if os.path.exists(path):
for d in os.listdir(path):
if not os.path.isdir(os.path.join(path, d)):
continue
if d[0:1] == "_":
continue
specpath = os.path.join(path, d, D.DFILE_TESTCASE_NAME + ".csv")
spec = model.entity.read_spec(job, d, J.GRAN_TS, specpath)
if spec is None:
continue
out[d] = spec
out[d][B.SUBJECT_PROJECTS] = [proj]
if jobProj is None:
delattr(job.par, B.PAR_PROJ)
else:
setattr(job.par, B.PAR_PROJ, jobProj)
return out