scripts/avocado-run-testplan
#!/usr/bin/env python3
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; specifically version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: RedHat 2015
# Author: Cleber Rosa <cleber@redhat.com>
import argparse
import datetime
import getpass
import json
import os
import subprocess
import sys
class Parser(argparse.ArgumentParser):
def __init__(self):
super(Parser, self).__init__(
prog='avocado-run-testplan',
description='Tracks manual test plans progress and results')
self.add_argument('-t', '--template', type=argparse.FileType('r'),
help='Template file with the predefined test plan')
self.add_argument('-o', '--output',
help='Output (test plan results) file location')
self.add_argument('-i', '--input', type=argparse.FileType('r'),
help=('A previously saved result file to use. This '
'will show a human readable report for the '
'given result file'))
RESULT_MAP = {"P": "PASS",
"p": "PASS",
"F": "FAIL",
"f": "FAIL",
"S": "SKIP",
"s": "SKIP"}
class App:
def __init__(self):
self.parser = Parser()
self.json = None
self.datetime = None
self.results = []
self.args = None
self.user_identification = None
def run(self):
self.args, _ = self.parser.parse_known_args()
if not (self.args.template or self.args.input):
self.parser.print_usage()
return 0
if self.args.input:
self.report()
else:
try:
self.run_test_plan()
except KeyboardInterrupt:
print("\nTest Plan interrupted by the user")
return 1
def run_test_plan(self):
self.json = json.load(self.args.template)
self.user_identification = None
self.datetime = datetime.datetime.now()
print("Name: %s" % self.json.get("name"))
print("Description: %s\n" % self.json.get("description"))
test_count = len(self.json.get("tests"))
current = 1
for test in self.json.get("tests"):
print("Test %d/%d: %s" % (current, test_count, test.get("name")))
print("Description: %s\n" % test.get("description"))
current += 1
result = None
while True:
result = input("Result ([P]ass, [F]ail, [S]kip): ")
if result in RESULT_MAP.keys():
notes = input("Additional Notes: ")
break
print("")
self.results.append({"name": test.get("name"),
"result": RESULT_MAP.get(result),
"notes": notes.strip()})
user = input("Your identification [%s]: " % getpass.getuser())
if not user:
user = getpass.getuser()
self.user_identification = user
self.save()
return 0
def get_output_file_name(self, suffix='json'):
"""
Return the user given or default output file name
"""
if self.args.output:
return self.args.output
name = self.json.get("name")
name = name.strip()
name = name.replace(" ", "_")
return "%s_%s_%s.%s" % (name,
self.user_identification,
self.datetime.isoformat(),
suffix)
def result_to_output_format(self):
return {"name": self.json.get("name"),
"user_identification": self.user_identification,
"datetime": self.datetime.isoformat(),
"results": self.results}
def save(self):
"""
Save the test plan execution result to a file
"""
filename = self.get_output_file_name()
with open(filename, 'w') as output:
json.dump(self.result_to_output_format(), output)
print("Wrote results to: %s" % filename)
def report(self):
"""
Write the test plan execution result to a human readable report
"""
if self.args.input:
data = json.load(self.args.input)
else:
data = self.result_to_output_format()
print("Test Plan: %s" % data.get("name"))
print("Run by '%s' at %s" % (data.get("user_identification"),
data.get("datetime")))
print("")
for result in data.get("results"):
print("%s: '%s': %s" % (result.get("result"),
result.get("name"),
result.get("notes")))
print("")
for name in sorted(os.listdir(os.path.pardir)):
path = os.path.join(os.path.pardir, name)
if not os.path.isdir(path):
continue
proc = subprocess.Popen("cd '%s' && git rev-parse HEAD" % path,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True)
out = proc.communicate()[0].strip().decode()
if not proc.poll():
print("%s: %s" % (name, out))
return 0
if __name__ == '__main__':
app = App()
sys.exit(app.run())