Skip to content
Snippets Groups Projects
render-test-case 7.28 KiB
Newer Older
# Create a HTML page from a YAML test case file.
import shutil
from jinja2 import Environment, FileSystemLoader
from argparse import ArgumentParser
from parser import parse_format
# This command parses each line of a list and returns a structure of the form
# (comment, command, output) to apply the following formatting for the respective
# sections:
#  - Start line with '$' for commands.
#  - Start line with '>' for command output.
#  - Start line with '@' to attach image.
#  - Start line with '~' to add web link.
#  - Everything else is a comment.
# run: steps: (only for automated tests)
#  - Start line with '#' for comments , everything else is a command.
def parse_list(lines, automated_run=False):
    processed_lines = []
    for line in lines:        
        p, c = '', ''
        sline = line.strip()
        if not sline:
            continue

        if automated_run:
            if sline[0] == '#':
                # Remove the '#' with the slice [1:]
                processed_lines.append((sline[1:], '', '', '', ''))
            else:
                # Add the '$ ' in the line for the command
                processed_lines.append(('', '$ '+sline, '', '', ''))
                processed_lines.append(('', sline, '', '', ''))
                processed_lines.append(('', '', sline[1:].split('\n'), '', ''))
            elif sline[0] == '@':
                processed_lines.append(('', '', '', sline[1:], ''))
            elif sline[0] == '~':
                processed_lines.append(('', '', '', '', sline[1:]))
                processed_lines.append((sline, '', '', '', ''))
def priority_color(priority):
    return \
        (priority == 'low'      and 'secondary') or \
        (priority == 'medium'   and 'info')      or \
        (priority == 'high'     and 'warning')   or \
        (priority == 'critical' and 'danger')    or 'light'

def get_template_values(testcase_data):
    is_automated = False

    # Mandatory fields
    metadata = testcase_data.get('metadata')
    if not metadata:
        print("Error: missing mandatory field metadata")
        sys.exit(1)

    for mv in ['name', 'image-type', 'image-arch', 'type',
               'exec-type', 'priority', 'description', 'expected']:
        value = metadata.get(mv)
        if value:
            if mv == 'exec-type' and value == 'automated':
                is_automated = True
                template_values.update({ mv : parse_list(value) })
                # Set also the prority_color
                if mv == 'priority':
                    template_values.update({ 'priority_color' :
                                             priority_color(value) })
                template_values.update({ mv.replace('-', '_') : value })
        else:
            print("Error: missing mandatory field", mv)
            sys.exit(1)

    run = testcase_data.get('run')
    if not run:
        print("Error: missing mandatory field run")
        sys.exit(1)
    else:
        steps = run.get('steps')
        if not steps:
            print("Error: missing mandatory field steps for run")
            sys.exit(1)
        # 'is_automated' so automated tests steps are parsed differently.
        template_values.update({ 'run_steps' :
                                 parse_list(steps, automated_run=is_automated) })
    for nm in ['notes', 'format', 'maintainer', 'resources',
               'pre-conditions', 'post-conditions']:
        value = metadata.get(nm)
        if value:
            template_values.update({ nm.replace('-', '_') : parse_list(value)
                                     if nm in ['notes', 'pre-conditions',
                                               'post-conditions']
                                     else value })

    install = testcase_data.get('install')
    if install:
        deps = install.get('deps')
        if not deps:
            print("Error: missing mandatory field deps for install")
            sys.exit(1)
        template_values.update({ 'install_steps' : deps })
        # A install.deps directive will always add a preconditions section
        # to install the required packages using the macro to install packages.
        template_values.update({ 'packages_list' : ' '.join(deps) })
    # Macros variables
    ostree_preconditions = metadata.get('macro_ostree_preconditions')
    if ostree_preconditions:
        template_values.update({ 'pkgname' : ostree_preconditions })

    packages_list = metadata.get('macro_install_packages_preconditions')
    if packages_list:
        template_values.update({ 'packages_list' :  packages_list })

    modules_preconditions = metadata.get('macro_modules_preconditions')
    if modules_preconditions:
        template_values.update({ 'libname' : modules_preconditions })

def generate_test_case(tc_file, directory):
        with open(tc_file) as testcase:
            tc_data = yaml.safe_load(testcase)
    except yaml.scanner.ScannerError as e:
        print("yaml format error:", e)
        sys.exit(1)

    # Parse file to detect any syntax error.
    print("Parsing file", tc_file)
    parse_format(tc_data)
    env = Environment(loader=FileSystemLoader([TEMPLATE_DIR]))
    # Get template from environment and render it.
    data = env.get_template('templates/index.html').render(get_template_values(tc_data))

    filename = os.path.splitext(os.path.basename(tc_file))[0] + ".html"
    print("Generating test case page", filename)
    with open(os.path.join(directory, filename), 'w') as html_file:
        html_file.write(data)

if '__main__' == __name__:
    cli_parser = ArgumentParser(description="make_page")
    cli_parser.add_argument('-d', '--test-case-dir',
                            help="Directory path for generated test cases")
    cli_parser.add_argument('yaml_files',
                            help="YAML file or files directory")
    args = cli_parser.parse_args()

    directory = '.'
    if args.test_case_dir:
        directory = args.test_case_dir
        try:
            os.mkdir(directory)
        except FileExistsError:
            print("Directory '{}' already exists".format(directory))
        except e:
            print("Error:", e)
            sys.exit(1)

    if os.path.isfile(args.yaml_files):
        generate_test_case(args.yaml_files, directory)
    else:
        for root, _, files in os.walk(args.yaml_files):
            for f in files:
                tc_file = os.path.join(root, f)
                if os.path.isfile(tc_file):
                    generate_test_case(tc_file, directory)
                    c += 1
        print("Total of test cases processed:", c)
    # Copy CSS and images directory
    cssdir = os.path.join(directory, 'css')
    if not (os.path.exists(cssdir) and os.path.isdir(cssdir)):
        print("Copying css style to", cssdir)
        shutil.copytree('css/', cssdir)

    imagesdir = os.path.join(directory, 'images')
    if not (os.path.exists(imagesdir) and os.path.isdir(imagesdir)):
        print("Copying images to", imagesdir)
        shutil.copytree('images/', imagesdir)