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.

347 lines
16 KiB

3 years ago
# abstract class for testrunning-functions
# ---------------------------------------------
"""
The test runs in 3 step:
1.1 precondition of system
1.2 test the system
1.3 postconditions of system incl. comparison
---
The main test is the testcase but there are superior granularities like
2.a test-sequence : few test-cases depending in a businessflow
therefore you test a testcase without resetting the system
2.b test-set : some independing test-cases
therefore you can test postconditions that works not directly
2.c test-matrix : a set of test-sets for the whole test
The granularity could be an implicite parameter in the main-module.
---
the test could be in different test-levels like
3.a component/service-test
a quick test to check single functions like in component-test, so you have the possibility to test x-product.
In difference of developer-test you can run large test-sets
3.b system-test
3.c integration-test
3.d acceptance-test
the test-level could be a configuration of the test-center or implicite of the application-definition.
---
the test can check different quality-measures like
4.a functionality
4.b
"""
from datetime import datetime
3 years ago
import basic.message
import basic.program
3 years ago
import inspect
3 years ago
import os
3 years ago
import utils.db_abstract
import basic.toolHandling
3 years ago
import components.component
3 years ago
import basic.componentHandling
3 years ago
import utils.path_tool
import utils.file_tool
3 years ago
import utils.match_tool
import utils.match_const as M
3 years ago
import utils.tdata_tool
3 years ago
import basic.constants as B
3 years ago
3 years ago
class Testexecuter():
3 years ago
def prepare_system(self, granularity):
"""
In order to preparate the test system test data should be cleaned and loaded with actual data.
This can happen on different granularities: for each testcase or for each test sequences or for a test set or
for a whole test.
The loaded test data should be selected for a later comparison.
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = -1+job.getDebugLevel(self.name)
self.m.logInfo("--- " + str(inspect.currentframe().f_code.co_name) + "() started at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
self.reset_TData(granularity)
self.m.setMsg("prepare_system for " + self.name +" "+ granularity + " is OK")
3 years ago
self.m.logInfo("--- " + str(inspect.currentframe().f_code.co_name) + "() finished at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
pass
def reset_TData(self, granularity):
"""
the testdata in the component of the testsystem will be resetted
correponding with the configuration of the componend
:param granularity:
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = -1+job.getDebugLevel(self.name)
self.m.debug(verify, "--- "+str(inspect.currentframe().f_code.co_name)+"() started at "
+ datetime.now().strftime("%Y%m%d_%H%M%S")+" for " + str(self.name).upper())
if B.ATTR_ARTS_LOG in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("log rotate in "+ self.name)
if "db" in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("delete content "+ self.name)
dbi = basic.toolHandling.getDbTool(self)
dbi.deleteTables()
if B.ATTR_ARTS_LOB in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("lob is deleted with flaskdb "+ self.name)
if B.ATTR_ARTS_FILE in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("rm files in "+ self.name)
self.m.setMsg("resetInstance for " + self.name + " is OK")
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() finished at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
3 years ago
def load_TData(self, granularity, testdata):
"""
the testdata will be loaded into the componend especially into databses
or with import-functions of the component
:param granularity:
:param testdata:
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = -1+job.getDebugLevel(self.name)
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() started at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
3 years ago
plainname = basic.componentHandling.getPlainCompname(self.name)
if plainname in testdata:
print("plainname in testdata "+plainname)
if "db" in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("delete content "+ self.name)
dbi = basic.toolHandling.getDbTool(self)
dbi.insertTables(testdata)
3 years ago
self.m.setMsg("data loaded for " + self.name + " is OK")
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() finished at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
3 years ago
def collect_TcArtifacts(self):
"""
collects the artifacts from the test-system.
the result is written as original in subfolder {tsorigin}
:return:
"""
job = basic.program.Job.getInstance()
verify = -1+job.getDebugLevel(self.name)
self.read_TData("nachher", B.PAR_TESTCASE)
def read_TData(self, subdir, granularity):
3 years ago
"""
:param granularity:
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = -1+job.getDebugLevel(self.name)
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() started at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
if "db" in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("select db-content "+ self.name)
dbi = basic.toolHandling.getDbTool(self)
dbi.selectTables()
if B.ATTR_ARTS_LOB in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("check lob if is deleted with flaskdb "+ self.name)
self.m.setMsg("readInstance for " + self.name + " is OK")
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() finished at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
3 years ago
3 years ago
def composeFileClauses(self, pattern):
job = basic.program.Job.getInstance()
out = {}
attr = utils.db_abstract.getDbAttributes(self, "null")
while "{" in pattern:
pre = pattern[0:pattern.index("{")]
pat = pattern[pattern.index("{"):pattern.index("}")]
post = pattern[pattern.index("}"):]
pattern = pre+attr[pat]+post
if (hasattr(job.par, B.PAR_DB_PARTITION)) and (attr[B.ATTR_DB_PARTITION] != "n"):
parts = getattr(job.par, B.PAR_DB_PARTITION)
a = parts.split(",")
for p in a:
pattern = pattern.replace(attr[B.ATTR_DB_PARTITION], p)
out[p] = pattern
else:
out["ALL"] = pattern
return out
@staticmethod
def getStringIndex(text, intern):
if intern in text:
return text.index(intern)
return 999
@staticmethod
def parseCondition(condition):
out = []
for operator in [">=", "<=", ">", "<", "=", " like ", " in "]:
if operator in condition:
i = condition.lower().index(operator)
field = condition[0:i]
attr = condition[i+len(operator):]
out = [operator, field, attr]
return out
return out
3 years ago
def composeSqlClauses(self, sql):
job = basic.program.Job.getInstance()
out = {}
print("-------- composeSqlClauses "+sql)
3 years ago
table = sql[sql.upper().index(" FROM ")+6:].strip()
print("table "+table)
3 years ago
sql_new = sql[0:sql.upper().index(" FROM ")+5]
print("sql_new "+sql_new)
3 years ago
attr = utils.db_abstract.getDbAttributes(self, table)
if attr[B.ATTR_DB_TABNAME] != "":
table = attr[B.ATTR_DB_TABNAME]
if attr[B.ATTR_DB_SCHEMA] != "":
table = attr[B.ATTR_DB_SCHEMA]+"."+table
sql_new += " "+attr[B.ATTR_DB_DATABASE]+"."+table
print("sql_new "+sql_new)
3 years ago
if (hasattr(job.par, B.PAR_DB_WHERE)):
parts = utils.db_abstract.parseSQLwhere(getattr(job.par, B.PAR_DB_WHERE), self.conf[B.DATA_NODE_DDL][table])
# Felder und Operationen
# print(dbwhere)
3 years ago
sql_new += " WHERE "+getattr(job.par, B.PAR_DB_WHERE)
if sql_new[0:6] == "SELECT":
sql_new += " ORDER BY id"
print("sql_new "+sql_new)
3 years ago
sql_new = sql_new.replace('!', "\'")
if (hasattr(job.par, B.PAR_DB_PARTITION)) and (attr[B.ATTR_DB_PARTITION] != "n"):
parts = getattr(job.par, B.PAR_DB_PARTITION)
a = parts.split(",")
for p in a:
sql_part = sql_new
sql_part = sql_part.replace(attr[B.ATTR_DB_PARTITION], p)
out[p] = sql_part
else:
out["ALL"] = sql_new
print("---> out "+str(out))
3 years ago
return out
3 years ago
def test_System(self, granularity):
"""
:param granularity:
:return:
"""
def create_Request(self, granularity):
pass
def send_Request(self, granularity):
pass
def get_Response(self, granularity):
pass
def finish_Test(self, granularity):
"""
initialization-routine for finish-step
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = -1+job.getDebugLevel(self.name)
self.m.logInfo("--- " + str(inspect.currentframe().f_code.co_name) + "() started at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
self.m.logInfo("something in "+ self.name)
self.m.setMsg("checkInstance for " + self.name + " is OK")
self.m.logInfo("--- " + str(inspect.currentframe().f_code.co_name) + "() finished at " + datetime.now().strftime("%Y%m%d_%H%M%S") + " for " + str(self.name).upper())
def collect_system(self, granularity):
"""
After the test the test data of each component should be selected again - to get the post-condition.
In each component is configured how these data can be collected.
In this phase the collected data have to be transformed to comparable files.
:return:
"""
pass
def collect_TcArtifact(self, granularity):
"""
collects the artifacts from the test-system.
the result is written as original in subfolder {tcorigin}
post: a further contact zo the test-system is not necessary
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = job.getDebugLevel(self.name)
if B.ATTR_ARTS_LOG in self.conf[B.SUBJECT_ARTS]:
self.m.logInfo("get files in for "+ self.name + " in " + self.conf[B.SUBJECT_ARTS][B.ATTR_ARTS_LOG]["path"])
if "flaskdb" in self.conf[B.SUBJECT_ARTS]:
3 years ago
self.m.logInfo("select flaskdb-content "+ self.name)
if B.ATTR_ARTS_LOB in self.conf[B.SUBJECT_ARTS]:
3 years ago
pass # after selection get file from flaskdb
if B.ATTR_ARTS_FILE in self.conf[B.SUBJECT_ARTS]:
self.m.logInfo("get files in for "+ self.name + " in " + self.conf[B.SUBJECT_ARTS][B.ATTR_ARTS_FILE]["path"])
3 years ago
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() " + str(self.name))
def split_TcResult(self, granularity):
"""
transforms the result from subfolder {tcorigin}.
the result is written as utf-8-readable parts in subfolder {tcparts}
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = job.getDebugLevel(self.name)
self.m.debug(verify, "--- "+str(inspect.currentframe().f_code.co_name)+"() "+str(self.name))
if B.ATTR_ARTS_LOG in self.conf[B.SUBJECT_ARTS]:
3 years ago
pass #
if "flaskdb" in self.conf[B.SUBJECT_ARTS]:
3 years ago
pass # stored in table
if B.ATTR_ARTS_LOB in self.conf[B.SUBJECT_ARTS]:
self.m.logInfo("tidy files in for "+self.name+" in "+self.conf[B.SUBJECT_ARTS][B.ATTR_ARTS_LOB]["format"])
if B.ATTR_ARTS_FILE in self.conf[B.SUBJECT_ARTS]:
self.m.logInfo("tidy files in for "+self.name+" in "+self.conf[B.SUBJECT_ARTS][B.ATTR_ARTS_FILE]["format"])
3 years ago
def fix_TcResult(self, granularity):
"""
fixes the result which is collected and transformed from the test-system.
the result is written in comparable form in folder {tcresult}
with the identifiable name - like in target
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
3 years ago
verify = job.getDebugLevel(self.name)
self.m.debug(verify, "--- " + str(inspect.currentframe().f_code.co_name) + "() " + str(self.name))
def compare_results(self, report):
3 years ago
"""
to compare the actual result with the target result has three steps:
1 matching each element so you get a comparable pair
2 comparing this pair so maybe you get differences
3 rating the difference if this can be accepted
:return:
"""
3 years ago
job = basic.program.Job.getInstance()
verify = job.getDebugLevel(self.name)
cm = basic.componentHandling.ComponentManager.getInstance()
data = {}
matching = utils.match_tool.Matching()
if "db" in self.conf[B.SUBJECT_ARTS]:
for t in self.conf[B.SUBJECT_ARTS]["db"]:
3 years ago
if t in ["type"]:
continue
# fill each data into matching-object
for side in M.MATCH_SIDES:
if side == M.MATCH_SIDE_PRESTEP:
if "prestep" in self.conf[B.SUBJECT_ARTS]["db"][t]:
a = self.conf[B.SUBJECT_ARTS]["db"][t]["prestep"].split(":")
3 years ago
if a[0] != self.name:
comp = cm.getComponent(a[0])
else:
comp = self
path = os.path.join(utils.path_tool.composePattern(
"{"+M.MATCH[M.MATCH_SIDE_POSTACTUAL][M.M_FILEPATTERN]+"}", comp), a[1]+".csv")
3 years ago
pass
elif side == M.MATCH_SIDE_TESTCASE:
3 years ago
if hasattr(job.par, "testcase_example"):
path = os.path.join(utils.path_tool.composePattern(
"{"+M.MATCH[M.MATCH_SIDE_POSTEXPECT][M.M_FILEPATTERN]+"}", self), t+".csv")
path.replace(getattr(job.par, B.PAR_TESTCASE), getattr(job.par, "testcase_example"))
3 years ago
else:
path = os.path.join(utils.path_tool.composePattern("{" + M.MATCH[side][M.M_FILEPATTERN] + "}", self), t + ".csv")
3 years ago
filedata = utils.tdata_tool.readCsv(self.m, path, self)
data[side] = M.MATCH[side]
3 years ago
data[side]["path"] = path
data[side]["data"] = filedata
# execute the matches
for type in M.MATCH_TYPES:
3 years ago
matching.setData(data, type)
report.setPaths(job.par.testcase, self.name, t, type, matching.matchfiles["A"], matching.matchfiles["B"])
3 years ago
text = utils.match_tool.matchTree(matching)
report.setMatchResult(job.par.testcase, self.name, t, type, matching.cssClass, matching.diffText)
path = os.path.join(utils.path_tool.composePattern("{tcresult}", self),
t+"_"+M.MATCH[type]["filename"]+".html")
utils.file_tool.writeFileText(self.m, path, text)
3 years ago
# write text
pass
3 years ago
pass