#!/usr/bin/env python import os import sys import argparse import logging import ConfigParser from external.testopia import Testopia from testopia_update.product import get_products, get_product_class from testopia_update.utils.wikimaker import create_wiki DEFAULT_CONFIG_FILE = "testopia_update.config" DEFAULT_STORE_LOCATION = "/tmp/testopia_update" ACTIONS = ('create', 'update', 'setup') BRANCHES = ('master', 'jethro', 'dizzy', 'daisy', 'noexists', 'morty', "krogoth", "pyro", 'rocko') CATEGORIES = ('AUTO', 'MANUAL') def update_test_run(env, build, test_run, results): missing = product.update_test_run(test_run, results) for tcid in missing: logger.warn("%s: Test run %d, Case %d wasn't updated" % (sys.argv[0], test_run['run_id'], tcid)) def load_results(results_log): if not results_log: logger.error("%s: For action update --results-log needs to be specified" % (sys.argv[0])) sys.exit(1) if not os.path.exists(args.results_log): logger.error("%s: Results log (%s) doesn't exists." % (sys.argv[0], results_log)) sys.exit(1) res = product.parse_results_log(args.results_log) return res def load_opts(args, opts_list, opts): invalid_opts = ['old_project_version', 'clone_templates', 'new_branch'] if args.action == "create" or args.action == "update": for invarg in invalid_opts: if getattr(args, invarg): logger.error("option %s not availabe for %s action " % (invarg, args.action)) sys.exit(1) for to in opts_list: if to in vars(args): arg = getattr(args, to) if arg: setattr(opts, to, arg) if not hasattr(opts, to): logger.error("%s: Requires testopia %s in arguments or config." % \ (sys.argv[0], to)) if args.action == "update": logger.warn('for action update you can use only --testrun-id ' + 'and --results-log if test run was already created') sys.exit(1) def connect_to_testopia(): config = None opts = Options() testopia_config = ['url', 'username', 'password'] if not args.config and os.path.exists(DEFAULT_CONFIG_FILE): args.config = DEFAULT_CONFIG_FILE if args.config: config = ConfigParser.SafeConfigParser() config.read(args.config) for to in testopia_config: setattr(opts, to, config.get("Testopia", to)) load_opts(args, testopia_config, opts) if not os.path.exists(DEFAULT_STORE_LOCATION): os.makedirs(DEFAULT_STORE_LOCATION) return opts, config class Options(object): pass def get_args(): parser = argparse.ArgumentParser(description="Update testopia script.") parser.add_argument('--config', dest="config", required=False, help='Configuration file.') parser.add_argument('--url', dest="url", required=False, help='URL of Testopia instance.') parser.add_argument('--username', dest="username", required=False, help='Username of Testopia instance.') parser.add_argument('--password', dest="password", required=False, help='Password of Testopia instance.') parser.add_argument('--list-products', required=False, action="store_true", dest="list_products", default=False, help='List available products.') parser.add_argument('--list-templates', required=False, action="store_true", dest="list_templates", default=False, help='List available templates.') parser.add_argument('-a', '--action', required=False, dest='action', choices=ACTIONS, help='Action to execute can be create, update or setup') parser.add_argument('-p', '--product', required=False, dest="product_name", help='Product to create or update.') parser.add_argument('-c', '--category', required=False, choices=CATEGORIES, dest="category_name", help='Category for create or update.') parser.add_argument('-b', '--branch', required=False, choices=BRANCHES, dest="branch_name", help='Branch for create or update.') parser.add_argument('-e', '--environment', required=False, dest="env_name", help='Enviroment for create or update.') parser.add_argument('-o', '--optional', required=False, dest="optional", help='Optional parameter for get Test runs.') parser.add_argument('--project-version', required=False, dest="project_version", help='Version of the project.') parser.add_argument('--project-milestone', required=False, dest="project_milestone", help='Milestone of the project.') parser.add_argument('--project-revision', required=False, dest="project_revision", help='SCM Revision of the project.') parser.add_argument('--project-date', required=False, dest="project_date", help='SCM version/revision date of the project.') parser.add_argument('--test-plan', required=False, dest="plan_name", help='Name of the test plan of the product, used when \ test plan name is different from product name.') parser.add_argument('--testrun-id', required=False, dest="trun_id", help='Number of the test run to be updated, this \ option should be used along with update action.') parser.add_argument('--results-log', required=False, dest="results_log", help='Results log.') parser.add_argument('--old-project-version', required=False, dest="old_project_version", help='Version of the project to clone from') parser.add_argument('--clone-templates', required=False, dest="clone_templates", help='clone templates from one branch to \ another or same branch (only available) \ with setup action', const='Y', nargs='?') parser.add_argument('--create-wiki', required=False, dest="create_wiki", help='create a wiki page for the final report of \ the QA test cycle (only available \ with setup action)', const='Y', nargs='?') parser.add_argument('--new-branch', required=False, dest="new_branch", help='New branch to clone the Templates') parser.add_argument('--verbose', required=False, action="store_true", dest="verbose", default=False, help='Enable verbose mode.') parser.add_argument('--debug', required=False, action="store_true", dest="debug", default=False, help='Enable debug mode.') return parser.parse_args() if __name__ == '__main__': args = get_args() logger = None opts = Options() if args.verbose or args.debug: logging.basicConfig(stream=sys.stdout) root = logging.getLogger() root.setLevel(logging.DEBUG if args.debug else logging.INFO) else: logging.basicConfig(stream=sys.stderr) logger = logging.getLogger() testopia_config = ['url', 'username', 'password', 'store_location'] testopia_opts = ['action', 'product_name', 'category_name', 'project_version', 'project_milestone', 'project_revision', 'project_date'] kwargs = {} if args.plan_name: kwargs['plan_name'] = args.plan_name opts, config = connect_to_testopia() testopia = Testopia(opts.username, opts.password, opts.url, sslverify=False) products = get_products(testopia, opts, logger, config, **kwargs) if args.list_products: print("List of available products: \n") for p in products: print("%s\n" % p.name) sys.exit(0) if args.list_templates: if not args.project_version: logger.error("--project-version should be specified") else: args.product_name = 'Dummy' product = get_product_class(args.product_name, products) summary = 'TRTEMP_' + args.project_version templates = product.get_test_run_list(None, summary) for t in templates: print ("%s - %s " % (t['run_id'], t['summary'])) sys.exit(0) if args.action == 'setup': if args.clone_templates: setup_opts = ['clone_templates', 'project_version','branch_name', 'old_project_version', 'product_name'] load_opts(args, setup_opts, opts) product = get_product_class(args.product_name, products) test_plan = product.get_test_plan(args.branch_name) temp_summary = 'TRTEMP_' + args.old_project_version temp_list = product.get_test_run_list(test_plan,temp_summary) if not temp_list: logger.error("%s: No templates found with %s string on %s" % (sys.argv[0], temp_summary, args.branch_name)) for tr in temp_list: if args.new_branch and args.new_branch != args.branch_name: kwargs['new_branch'] = args.new_branch new_template = product.clone_template(tr, args.old_project_version,args.project_version, **kwargs) logger.info("%s: Template was created with (%d), Summary (%s)" % (sys.argv[0], new_template['run_id'], new_template['summary'])) elif args.create_wiki: setup_opts = ['create_wiki', 'project_date', 'project_version'] load_opts(args, setup_opts, opts) args.product_name = 'Dummy' product = get_product_class(args.product_name, products) summary = args.project_date + '_' + args.project_version templates = product.get_test_run_list(None, summary) wikivars = '' wikivars_list = [] idx=0 for t in templates: idx += 1 plan = product.get_test_plan_by_id(t['plan_id']) prod = testopia.product_lookup_name_by_id(plan['product_id']) env = product.get_environment_by_id(t['environment_id']) env_name = env['name'].replace(' ','_') var = str(idx) + '_' + str(prod['name']) + '_' + env_name wikivars_list.append(var) wikivars += ''.join(["{{#vardefine:", var, '| ', str(t['run_id']), '}}', '\n' ]) print(wikivars) create_wiki(wikivars, wikivars_list) else: logger.error("Sub arguments --clone-templates or --create-wiki should be given") sys.exit(0) if args.action == 'update' and args.trun_id: args.product_name = 'Dummy' product = get_product_class(args.product_name, products) try: tr = product.get_existing_test_run(int(args.trun_id)) except Exception as e: logger.error("%s: Problem found with Test Run %s: \n==>%s" % (sys.argv[0], args.trun_id, e)) sys.exit(1) results = load_results(args.results_log) update_test_run(tr['environment_id'], tr['build_id'], tr, results) sys.exit(0) load_opts(args, testopia_opts, opts) params = ['action', 'product_name', 'branch_name', 'env_name'] for p in params: if not getattr(args, p): logger.error("%s: Requires %s to be specified." % (sys.argv[0], p)) sys.exit(1) product = get_product_class(args.product_name, products) if not product: logger.error("%s: Product %s isn't supported, use --list-products for "\ "list available products." % \ (sys.argv[0], args.product_name)) sys.exit(1) test_plan = product.get_test_plan(args.branch_name) if not test_plan: logger.error("%s: Test plan %s for product %s and branch %s not exists."\ % (sys.argv[0], product.plan ,args.product_name, args.branch_name)) sys.exit(1) env = product.get_environment(test_plan, args.env_name) if not env: if args.action == "create": env = product.create_environment(test_plan, args.env_name) logger.info("%s: Create environment %s for product %s."\ % (sys.argv[0], args.env_name, args.product_name)) else: logger.error("%s: Product %s have invalid environment %s."\ % (sys.argv[0], args.product_name, args.env_name)) logger.error("Available environments are:") for env_name in product.get_environment_names(test_plan): logger.error(env_name) sys.exit(1) build = product.get_build(test_plan, args.project_version, args.project_milestone, args.project_revision, args.project_date) if not build: if args.action == "create": build = product.create_build(test_plan, args.project_version, args.project_milestone, args.project_revision, args.project_date) logger.info("%s: Create build for product %s with: "\ "%s, %s, %s, %s." % (sys.argv[0], args.product_name, args.project_version, args.project_milestone, args.project_revision, args.project_date)) else: logger.error("%s: Product %s can't find build with: "\ "%s, %s, %s, %s." % (sys.argv[0], args.product_name, args.project_version, args.project_milestone, args.project_revision, args.project_date)) sys.exit(1) if args.action == "create": template_test_run = product.get_template_test_run(test_plan, args.project_version, args.category_name, args.optional) if not template_test_run: logger.error("%s: Product %s can't find test run with: "\ "%s, %s, %s." % (sys.argv[0], args.product_name, args.project_version, args.category_name, args.optional)) sys.exit(1) test_run = product.create_test_run(test_plan, env, build, template_test_run, args.project_version, args.project_date) if not test_run: logger.error("%s: Product %s can't create test run with: "\ "%s, %s, %s, %s." % (sys.argv[0], args.product_name, args.project_version, args.project_date, args.category_name, args.optional)) sys.exit(1) logger.info("%s: Test run was created with Template (%d), Summary (%s)"\ " and ID (%s)." % (sys.argv[0], template_test_run['run_id'], test_run['summary'], test_run['run_id'])) elif args.action == "update": results = load_results(args.results_log) test_run = product.get_test_run(test_plan, env, build, args.project_date, args.project_version, args.category_name, args.optional) if not test_run: logger.error("%s: Product %s can't find test run with: "\ "%s, %s, %s, %s." % (sys.argv[0], args.product_name, args.project_date, args.project_version, args.category_name, args.optional)) sys.exit(1) update_test_run(env, build, test_run, results) sys.exit(0)