All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] scripts/test-case-mgmt: store test result & log into git repository
@ 2018-10-25  8:37 Yeoh Ee Peng
  0 siblings, 0 replies; only message in thread
From: Yeoh Ee Peng @ 2018-10-25  8:37 UTC (permalink / raw)
  To: openembedded-core

These scripts were developed as an alternative testcase management
tool to Testopia. Using these scripts, user can store test result &
log from OEQA automated testcase execution.

These scripts will store test result & log in GIT repository.
To use these scripts, first source oe environment, then run the
entry point script to look for help.
    $ test-case-mgmt

To store test result for OEQA automated testcase, execute the below
    $ test-case-mgmt store <source_dir> <git_branch>

Signed-off-by: Yeoh Ee Peng <ee.peng.yeoh@intel.com>
---
 scripts/lib/testcasemgmt/__init__.py |   0
 scripts/lib/testcasemgmt/gitstore.py | 129 +++++++++++++++++++++++++++++++++++
 scripts/lib/testcasemgmt/store.py    |  40 +++++++++++
 scripts/test-case-mgmt               |  92 +++++++++++++++++++++++++
 4 files changed, 261 insertions(+)
 create mode 100644 scripts/lib/testcasemgmt/__init__.py
 create mode 100644 scripts/lib/testcasemgmt/gitstore.py
 create mode 100644 scripts/lib/testcasemgmt/store.py
 create mode 100755 scripts/test-case-mgmt

diff --git a/scripts/lib/testcasemgmt/__init__.py b/scripts/lib/testcasemgmt/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/scripts/lib/testcasemgmt/gitstore.py b/scripts/lib/testcasemgmt/gitstore.py
new file mode 100644
index 0000000..2063ce8
--- /dev/null
+++ b/scripts/lib/testcasemgmt/gitstore.py
@@ -0,0 +1,129 @@
+# test case management tool - store test result & log to git repository
+#
+# Copyright (c) 2018, Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+import tempfile
+import os
+import subprocess
+import shutil
+import scriptpath
+scriptpath.add_bitbake_lib_path()
+scriptpath.add_oe_lib_path()
+from oeqa.utils.git import GitRepo, GitError
+from oe.path import copytree
+
+class GitStore(object):
+
+    def _check_if_dir_contain_sub_dir(self, dir, sub_dir):
+        if os.path.exists(os.path.join(dir, sub_dir)):
+            return True
+        else:
+            return False
+
+    def _git_init(self, git_repo):
+        try:
+            repo = GitRepo(git_repo, is_topdir=True)
+        except GitError:
+            print("Non-empty directory that is not a Git repository "
+                   "at {}\nPlease specify an existing Git repository, "
+                   "an empty directory or a non-existing directory "
+                   "path.".format(git_repo))
+        return repo
+
+    def _run_git_cmd(self, repo, cmd):
+        try:
+            output = repo.run_cmd(cmd)
+            return True, output
+        except GitError:
+            return False, None
+
+    def _check_if_git_repo_and_git_branch_exist(self, git_repo, git_branch):
+        git_dir = '%s/.git' % git_repo
+        if not os.path.exists(git_dir):
+            return False
+        repo = self._git_init(git_repo)
+        status, output = self._git_checkout_git_repo(repo, git_branch)
+        return status
+
+    def _git_checkout_git_repo(self, repo, git_branch):
+        cmd = 'checkout %s' % git_branch
+        return self._run_git_cmd(repo, cmd)
+
+    def _create_temporary_workspace_dir(self):
+        return tempfile.mkdtemp(prefix='testresultlog.')
+
+    def _remove_temporary_workspace_dir(self, workspace_dir):
+        return subprocess.run(["rm", "-rf",  workspace_dir])
+
+    def _make_directories(self, logger, target_dir):
+        logger.debug('Creating directories: %s' % target_dir)
+        bb.utils.mkdirhier(target_dir)
+
+    def _copy_files_from_source_to_destination_dir(self, logger, source_dir, destination_dir):
+        if os.path.exists(source_dir) and os.path.exists(destination_dir):
+            logger.debug('Copying test result & log from %s to %s' % (source_dir, destination_dir))
+            copytree(source_dir, destination_dir)
+
+    def _push_testresult_files_to_git_repo(self, logger, file_dir, git_repo, git_branch, sub_dir):
+        logger.debug('Storing test result & log inside git repository (%s) and branch (%s)'
+                     % (git_repo, git_branch))
+        commit_msg_subject = 'Store %s from {hostname}' % os.path.join(git_repo, sub_dir)
+        commit_msg_body = 'git dir: %s\nsub dir list: %s\nhostname: {hostname}' % (git_repo, sub_dir)
+        return subprocess.run(["oe-git-archive",
+                               file_dir,
+                               "-g", git_repo,
+                               "-b", git_branch,
+                               "--commit-msg-subject", commit_msg_subject,
+                               "--commit-msg-body", commit_msg_body])
+
+    def _store_test_result_from_empty_git(self, logger, source_dir, git_branch, dest_dir, dest_sub_dir):
+        workspace_dir = self._create_temporary_workspace_dir()
+        full_workspace_dir = os.path.join(workspace_dir, dest_sub_dir)
+        self._make_directories(logger, full_workspace_dir)
+        self._copy_files_from_source_to_destination_dir(logger, source_dir, full_workspace_dir)
+        self._push_testresult_files_to_git_repo(logger, workspace_dir, dest_dir, git_branch, dest_sub_dir)
+        self._remove_temporary_workspace_dir(workspace_dir)
+
+    def _store_test_result_from_existing_git(self, logger, source_dir, git_branch, dest_dir, dest_sub_dir):
+        self._make_directories(logger, os.path.join(dest_dir, dest_sub_dir))
+        self._copy_files_from_source_to_destination_dir(logger, source_dir, os.path.join(dest_dir, dest_sub_dir))
+        self._push_testresult_files_to_git_repo(logger, dest_dir, dest_dir, git_branch, dest_sub_dir)
+
+    def checkout_git_branch(self, git_dir, git_branch):
+        if self._check_if_git_repo_and_git_branch_exist(git_dir, git_branch):
+            repo = self._git_init(git_dir)
+            self._git_checkout_git_repo(repo, git_branch)
+            return True
+        else:
+            return False
+
+    def store_test_result(self, logger, source_dir, git_branch, dest_dir, dest_sub_dir, overwrite_result):
+        logger.debug('Initializing store the test result & log')
+        if self._check_if_git_repo_and_git_branch_exist(dest_dir, git_branch):
+            self.checkout_git_branch(dest_dir, git_branch)
+            logger.debug('Found destination git directory and git branch: %s %s' % (dest_dir, git_branch))
+            if self._check_if_dir_contain_sub_dir(dest_dir, dest_sub_dir):
+                logger.debug('Found existing sub (%s) directories inside: %s' % (dest_sub_dir, dest_dir))
+                if overwrite_result:
+                    logger.debug('Overwriting existing testresult inside: %s' % (os.path.join(dest_dir, dest_sub_dir)))
+                    shutil.rmtree(os.path.join(dest_dir, dest_sub_dir))
+                    self._store_test_result_from_existing_git(logger, source_dir, git_branch, dest_dir, dest_sub_dir)
+                else:
+                    logger.debug('Skipped storing test result & log as it already exist. '
+                                 'Specify overwrite if you wish to delete existing testresult and store again.')
+            else:
+                logger.debug('Could not find existing sub (%s) directories inside: %s' % (dest_sub_dir, dest_dir))
+                self._store_test_result_from_existing_git(logger, source_dir, git_branch, dest_dir, dest_sub_dir)
+        else:
+            logger.debug('Could not find destination git directory (%s) or git branch (%s)' % (dest_dir, git_branch))
+            self._store_test_result_from_empty_git(logger, source_dir, git_branch, dest_dir, dest_sub_dir)
+
diff --git a/scripts/lib/testcasemgmt/store.py b/scripts/lib/testcasemgmt/store.py
new file mode 100644
index 0000000..c6386c8a
--- /dev/null
+++ b/scripts/lib/testcasemgmt/store.py
@@ -0,0 +1,40 @@
+# test case management tool - store test result
+#
+# Copyright (c) 2018, Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+from testcasemgmt.gitstore import GitStore
+
+def store(args, logger):
+    gitstore = GitStore()
+    gitstore.store_test_result(logger, args.source_dir, args.git_branch, args.dest_dir, args.dest_sub_dir,
+                               args.overwrite_result)
+    return 0
+
+def register_commands(subparsers):
+    """Register subcommands from this plugin"""
+    parser_build = subparsers.add_parser('store', help='Store test result files into git repository.',
+                                         description='Store test result files into git repository.',
+                                         group='store')
+    parser_build.set_defaults(func=store)
+    parser_build.add_argument('source_dir',
+                              help='Source directory that contain the test result files to be stored.')
+    parser_build.add_argument('git_branch', help='Git branch used to store the test result files.')
+    parser_build.add_argument('-d', '--dest_dir', default='',
+                              help='(Optional) Destination directory to be used/created as git repository '
+                                   'to store the test result files from the source directory. '
+                                   'Default location for destination directory will be <top_dir>/testresults.git.')
+    parser_build.add_argument('-s', '--dest_sub_dir', default='',
+                              help='(Optional) Additional sub directory to be used/created under the destination '
+                                   'git repository, this sub directory will be used to hold the test result files. '
+                                   'Use sub directory if needing separate directories to hold multiple test files.')
+    parser_build.add_argument('-o', '--overwrite_result', action='store_true',
+                              help='(Optional) To overwrite existing testresult file with new file provided.')
diff --git a/scripts/test-case-mgmt b/scripts/test-case-mgmt
new file mode 100755
index 0000000..9219b8d
--- /dev/null
+++ b/scripts/test-case-mgmt
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+#
+# test case management tool - store test result and log, reporting, manual test
+# execution and management
+#
+# As part of the initiative to provide LITE version Test Case Management System
+# with command-line and plain-text files (eg. manual test case file, test plan
+# file to specify list of test case to be executed, test result and log file)
+# to replace Testopia.
+# test-case-mgmt script was designed as part of the helper script for below purpose:
+# 1. To store test result & log inside git repository
+# 2. (Future) To provide test reporting in text-based test summary report
+# 3. (Future) To manage manual test case execution, store test result
+#
+# To look for help information.
+#    $ test-case-mgmt
+#
+# To store test result & log, execute the below
+#    $ test-case-mgmt store <source_dir> <git_branch>
+#
+# Copyright (c) 2018, Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+
+import os
+import sys
+import argparse
+import logging
+script_path = os.path.dirname(os.path.realpath(__file__))
+lib_path = script_path + '/lib'
+sys.path = sys.path + [lib_path]
+import argparse_oe
+import scriptutils
+import testcasemgmt.store
+#import testcasemgmt.view
+logger = scriptutils.logger_create('test-case-mgmt')
+
+def _validate_user_input_arguments(args):
+    if hasattr(args, "dest_sub_dir"):
+        if '/' in args.dest_sub_dir:
+            logger.error('dest_sub_dir argument cannot contain / : %s' % args.dest_sub_dir)
+            return False
+        if '\\' in r"%r" % args.dest_sub_dir:
+            logger.error('dest_sub_dir argument cannot contain \\ : %r' % args.dest_sub_dir)
+            return False
+    return True
+
+def _set_default_arg_value_for_dest_dir(args):
+    if hasattr(args, "dest_dir"):
+        if args.dest_dir == '':
+            base_path = script_path + '/..'
+            args.dest_dir = os.path.join(os.path.abspath(base_path), 'testresults.git')
+        logger.debug('Set dest_dir argument: %s' % args.dest_dir)
+
+def main():
+    parser = argparse_oe.ArgumentParser(description="OpenEmbedded testcase management tool, to store test result then to view test summary report.",
+                                        add_help=False,
+                                        epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
+    parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
+                        help='show this help message and exit')
+    parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
+    parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
+    subparsers = parser.add_subparsers(dest="subparser_name", title='subcommands', metavar='<subcommand>')
+    subparsers.required = True
+    subparsers.add_subparser_group('store', 'Store test result & log', 100)
+    testcasemgmt.store.register_commands(subparsers)
+    args = parser.parse_args()
+    if args.debug:
+        logger.setLevel(logging.DEBUG)
+    elif args.quiet:
+        logger.setLevel(logging.ERROR)
+
+    if not _validate_user_input_arguments(args):
+        return -1
+    _set_default_arg_value_for_dest_dir(args)
+
+    try:
+        ret = args.func(args, logger)
+    except argparse_oe.ArgumentUsageError as ae:
+        parser.error_subcommand(ae.message, ae.subcommand)
+    return ret
+
+if __name__ == "__main__":
+    sys.exit(main())
-- 
2.7.4



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-10-25  8:52 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-25  8:37 [PATCH v2] scripts/test-case-mgmt: store test result & log into git repository Yeoh Ee Peng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.