#!/usr/bin/python3
import http.client
import json
import time
import os
import requests
# HttpDbLogger application host (it will be some kind of Java applications server - Tomcat/Jetty/etc
WEBSERVER_URL = "localhost:8080"
# ats-httpdblogger-4.0.6 is the name of the deployed .war file
# and /service/logger is the full path to the logger sevice
HTTP_DB_LOGGER_LOGGER_URL = "/ats-httpdblogger-4.0.6/service/logger"
# Relative URLs for each logging operation
START_RUN_REL_URL = "startRun"
START_SUITE_REL_URL = "startSuite"
START_TESTCASE_REL_URL = "startTestcase"
INSERT_MESSAGE_REL_URL = "insertMessage"
INSERT_MESSAGES_REL_URL = "insertMessages"
ADD_RUN_METAINFO_REL_URL = "addRunMetainfo"
ATTACH_FILE_REL_URL = "attachFile"
ADD_SCENARIO_METAINFO_REL_URL = "addScenarioMetainfo"
ADD_TESTCASE_METAINFO_REL_URL = "addTestcaseMetainfo"
UPDATE_RUN_REL_URL = "updateRun"
UPDATE_SUITE_REL_URL = "updateSuite"
END_TESTCASE_REL_URL = "endTestcase"
END_SUITE_REL_URL = "endSuite"
END_RUN_REL_URL = "endRun"
# JSON keys, used in the creation the requests' bodies
START_RUN_KEYS = ["dbHost", "dbPort", "dbName", "dbUser", "dbPassword", "runName", "osName", "productName", "buildName", "versionName", "userNote", "hostName", "timestamp"]
START_SUITE_KEYS = ["suiteName", "packageName", "timestamp", "parentId", "parentType","sessionId"]
START_TESTCASE_KEYS = ["sessionId", "testcaseName", "scenarioName", "scenarioDescription", "timestamp", "parentId", "parentType"]
INSERT_MESSAGE_KEYS = ["sessionId", "machineName", "threadName", "level", "message", "timestamp", "parentId", "parentType"]
INSERT_MESSAGES_KEYS = ["sessionId", "parentType", "parentId", "timestamp", "messages"]
ADD_RUN_METAINFO_KEYS = ["sessionId","metaKey","metaValue"]
ATTACH_FILE_KEYS = ["sessionId","parentId","fileName"]
ADD_SCENARIO_METAINFO_KEYS = ["sessionId","parentId","metaKey","metaValue"]
ADD_TESTCASE_METAINFO_KEYS = ["sessionId","parentId","metaKey","metaValue"]
UPDATE_RUN_KEYS = ["sessionId", "runName", "osName", "productName", "buildName", "versionName", "userNote", "hostName"]
UPDATE_SUITE_KEYS = ["sessionId", "suiteId", "suiteName", "userNote"]
END_TESTCASE_KEYS = ["sessionId", "result", "timestamp", "testcaseId"]
END_SUITE_KEYS = ["suiteId", "sessionId", "timestamp"]
END_RUN_KEYS = ["sessionId", "timestamp"]
# enable logging of message on each HTTP method execution
DEBUG=True
# this function will additionally process the json value
def checkJsonValue(value):
if value == None:
return "null"
elif type(value) is list:
return json.dumps(value)
else:
return "\""+str(value)+"\""
# this can be replaced with the built-in JSON functionality
def createJson(keys, values):
json = "{"
for i in range(len(keys)):
json += "\"" + keys[i] + "\":" + checkJsonValue(values[i]) + ","
json = json[0:len(json)-1] # remove trailing comma
json += "}"
return json
def doHttpMethod(methodName, baseUrl, relUrl, headers={}, body=None):
if DEBUG:
print("Executing '{}' HTTP method to URL '{}' with headers '{}' and body '{}'".format(methodName, baseUrl+"/"+relUrl, headers, body))
conn = http.client.HTTPConnection(baseUrl)
conn.request(methodName, relUrl, body, headers)
resp = conn.getresponse().read().decode("utf-8")
conn.close()
return resp
def httpPost(baseUrl, relUrl, headers, body):
return doHttpMethod("POST", baseUrl, relUrl, headers, body)
def httpGet(baseUrl, relUrl, headers):
return doHttpMethod("GET", baseUrl, relUrl, headers)
def httpPut(baseUrl, relUrl, headers, body):
return doHttpMethod("PUT", baseUrl, relUrl, headers, body)
def startRun(dbHost, dbPort, dbName, dbUser, dbPassword, runName, osName, productName, buildName, versionName, userNote, hostName, timestamp):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+START_RUN_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(START_RUN_KEYS, [dbHost, dbPort, dbName, dbUser, dbPassword, runName, osName, productName, buildName, versionName, userNote, hostName, timestamp])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def startSuite(suiteName, packageName, timestamp, parentId, parentType, sessionId):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+START_SUITE_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(START_SUITE_KEYS, [suiteName, packageName, timestamp, parentId, parentType, sessionId])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def startTestcase(sessionId, testcaseName, scenarioName, description, timestamp, parentId, parentType):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+START_TESTCASE_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(START_TESTCASE_KEYS, [sessionId, testcaseName, scenarioName, description, timestamp, parentId, parentType])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def endTestcase(sessionId, result, timestamp, testcaseId):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+END_TESTCASE_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(END_TESTCASE_KEYS, [sessionId, result, timestamp, testcaseId])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def endSuite(suiteId, sessionId, timestamp):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+END_SUITE_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(END_SUITE_KEYS, [suiteId, sessionId, timestamp])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def endRun(sessionId, timestamp):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+END_RUN_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(END_RUN_KEYS, [sessionId, timestamp])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def insertMessage(sessionId, machineName, threadName, level, message, timestamp, parentId, parentType):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+INSERT_MESSAGE_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(INSERT_MESSAGE_KEYS, [sessionId, machineName, threadName, level, message, timestamp, parentId, parentType])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def insertMessages(sessionId, parentType, parentId, timestamp, messages):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+INSERT_MESSAGES_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(INSERT_MESSAGES_KEYS, [sessionId, parentType, parentId, timestamp, messages])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def updateRun(sessionId, runName, osName, productName, buildName, versionName, userNote, hostName):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+UPDATE_RUN_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(UPDATE_RUN_KEYS, [sessionId, runName, osName, productName, buildName, versionName, userNote, hostName])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def updateSuite(sessionId, suiteId, suiteName, userNote):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+UPDATE_SUITE_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(UPDATE_SUITE_KEYS, [sessionId, suiteId, suiteName, userNote])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def addRunMetaInfo(sessionId, metaKey, metaValue):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+ADD_RUN_METAINFO_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(ADD_RUN_METAINFO_KEYS, [sessionId, metaKey, metaValue])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
def attachFile(sessionId, parentId, fileName, fileStream):
relUrl = 'http://' + WEBSERVER_URL + HTTP_DB_LOGGER_LOGGER_URL + "/" + ATTACH_FILE_REL_URL
print("Executing '{}' HTTP method to URL '{}'".format('PUT', relUrl))
attach_file_details = json.dumps(createJson(ATTACH_FILE_KEYS, [sessionId, parentId, fileName]))
return requests.put(relUrl, files={'attach_file_details': attach_file_details, 'stream' : fileStream})
def addScenarioMetaInfo(sessionId, testcaseId, metaKey, metaValue):
relUrl = HTTP_DB_LOGGER_LOGGER_URL+"/"+ADD_SCENARIO_METAINFO_REL_URL
headers = {"Content-type": "application/json", "Accept": "application/json"}
body = createJson(ADD_SCENARIO_METAINFO_KEYS, [sessionId, testcaseId, metaKey, metaValue])
return httpPost(WEBSERVER_URL, relUrl, headers, body)
# variables for storing responses' data
sessionId = None
runIds = []
suiteIds = []
testcaseIds = []
# start a run
responseBody = startRun("localhost", "", "TestDb","AtsUser","AtsPassword","testRun1","LINUX","Ats HttpDbLogger","1","4.0.6",
"first run","ws",str(int(round(time.time() * 1000)))) # if the db port is skipped, the default one for MSSQL will be used (1433)
print(responseBody)
responseBody = json.loads(responseBody)
sessionId = responseBody['sessionId']
runId = responseBody['runId']
runIds.append(runId)
# start a suite
responseBody = startSuite("SuiteOne", "com.example.ats", str(int(round(time.time() * 1000))), "-1", "RUN", sessionId)
responseBody = json.loads(responseBody)
suiteId = responseBody['suiteId']
suiteIds.append(suiteId)
# start a testcase
responseBody = startTestcase(sessionId, "TestCase1", "Scenario1", "The first scenario/testcase", str(int(round(time.time() * 1000))), "-1", "SUITE")
responseBody = json.loads(responseBody)
testcaseId = responseBody['testcaseId']
testcaseIds.append(testcaseId)
# insert single run and suite message
insertMessage(sessionId, "ws", "main", "INFO", "Some run message with log level INFO", str(int(round(time.time() * 1000))), str(runId), "RUN")
for i in suiteIds:
insertMessage(sessionId, "ws", "main", "INFO", "Some suite message with log level INFO", str(int(round(time.time() * 1000))), str(i), "SUITE")
# simulate some work by sleeping for 1 minute
os.system("sleep 10")
# create simple file for each testcase and attach that file to the corresponsing testcase
for i in testcaseIds:
f = open('log_file_' + str(i) + '.txt', 'w+');
f.write('Some log file');
f.flush()
f.close()
f = open('log_file_' + str(i) + '.txt', 'rb');
attachFile(sessionId, str(i),'log_file_' + str(i) + '.txt', f);
f.close()
# end all testcases
# in order to do that, we have to disable/skip the default event state checking
# and this is done by simply providing testcaseId, instead of -1
# now instead of checking whether we can end a testcase
# the HttpDbLogger will just check if the testcase, which we want to end is indeed already running and whether it was started by the current session
for i in testcaseIds:
endTestcase(sessionId, "PASSED", str(int(round(time.time() * 1000))), str(i)) # here we are providing the testcaseId
# insert more than one message for the first testcase
# as you can see, by providing parentType and parentId,
# we can insert messages in already ended/closed testcases
# we also provide custom time stamp, which is the current time of the test executor (e.g. our machine where this script will be executed)
message1 = {
'machineName':'ws',
'threadName':'main',
'level':'ERROR',
'message':'1/2 testcase messages logged at once',
'timestamp':str(int(round(time.time() * 1000))),
'parentId':str(testcaseIds[0]),
'parentType':'TESTCASE'
}
message2 = {
'machineName':'ws',
'threadName':'main',
'level':'ERROR',
'message':'2/2 testcase messages logged at once',
'timestamp':'-1',
'parentId':str(testcaseIds[0]),
'parentType':'TESTCASE'
}
messages = [
message1,
message2
] # TODO dump messages list to a valid JSON string
insertMessages(sessionId, "TESTCASE", str(i), '-1', messages)
# end all suites
# again as with the ending of all the testcases,
# we are providing suiteId, so the HttpDbLogger will skip any event logging state checking, check if the requested suite (refered by the suiteId) is started by the current session
# and if everything is OK, it will stop the suite
# if an error occurred, it's cause and Java stacktrace will be returned with the response's body
for i in suiteIds:
endSuite(str(i), sessionId, str(int(round(time.time() * 1000))))
# end the run
endRun(sessionId, str(int(round(time.time() * 1000))))
# update the already ended run
updateRun(sessionId, "New testRun1", None, None, None, None, None, "my workstation at home")
# update each suite, that was started by this session
for i in suiteIds:
updateSuite(sessionId, str(i), "Some new suite name for suite with ID " + str(i), "Suite with ID " + str(i))
# add run metainfo
# currently the only available metaKey value is type
addRunMetaInfo(sessionId, "type", "progression")
# add scenario metainfo for each testcase
for i in testcaseIds:
if i % 2 == 0:
addScenarioMetaInfo(sessionId, str(i), "group", "even")
addTestcaseMetaInfo(sessionId, str(i), "group", "even")
else:
addScenarioMetaInfo(sessionId, str(i), "group", "odd")
addTestcaseMetaInfo(sessionId, str(i), "group", "odd")