tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_SHOW_NULL_HELP_LINE = \
    '--show-null In the TABLE output formats, show properties with no '
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_FILTER_QUERY_LINE = \
    '--fq, --filter-query QUERY-STRING When pull operations are used, filter ' \
    'the instances in the result'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_ASSOCIATION_FILTER_HELP_LINE = \
    '--association / --no-association'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_HELP_HELP_LINE = \
    '-h, --help Show this help message.'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_NAMES_ONLY_HELP_LINE = \
    '--no, --names-only Retrieve only the object paths (names).'
tests/unit/pywbemcli/cli_test_extensions.py
class CLITestsBase(object):
    # pylint: disable=too-few-public-methods, useless-object-inheritance
    """
        Defines methods to execute tests on pywbemcli.

    """
    def command_test(self, desc, command_grp, inputs, exp_response, mock_files,
                     condition, verbose=False):
        # pylint: disable=line-too-long, no-self-use
        """
        Test method to execute test on pywbemcli by calling the executable
        pywbemcli for the command defined by command with arguments defined
        by args. This can execute pywbemcli either with a mock environment
        by using the mock_files variable or without mock if the mock_files
        parameter is None. The method tests the results of the execution
        of pywbemcli using the exp_response parameter.

        Parameters:
          desc (:term:`string`):
            Description of the test

          command_grp (:term:`string`):
            Pywbemcli command group for this test. This is the first level of
            the command, e.g. 'class' or 'instance'.

          inputs (:term:`string` or tuple/list of :term:`string` or :class:`py:dict`):

            * If inputs is a string or a tuple/list of strings, it contains the
              command line arguments, without the command name or command group.

              Each single argument must be its own item in the iterable;
              combining the arguments into a string does not work, and the
              string is not split into words (anymore).

              The arguments may be binary strings encoded in UTF-8, or unicode
              strings.

            * If inputs is a dict it can contain the following optional items:

              - 'connections_file_args': tuple(conn_file, conn_content) that can
                specify a connections file to be prepared for the test.
                The tuple items are passed as arguments to the
                'connections_file()' context manager. See there for details.

              - 'args': String or tuple/list of strings with local
                (command-level) options that will be added to the command
                line after the command name.

                Each single argument (e.g. option name and option arguments)
                must be its own item in the iterable.

              - 'general': String or tuple/list of strings with general
                options that will be added to the command line before the
                command name.

                Each single argument (e.g. option name and option arguments)
                must be its own item in the iterable.

              - 'env': Dictionary of environment variables where key is the
                variable name; dict value is the variable value (without any
                shell escaping needed).

                If omitted, None, or empty, no environment variables will be
                set for the test.

              - 'stdin': A string or a tuple/list of strings, that contains the
                standard input for the command.

                This can be used for commands in interactive mode, and for
                responding to prompts.

                If present, the command group specified in the `command_grp`
                parameter is not added to the command line, but the local and
                global options are added.

                If specified as a tuple/list of strings, these strings are
                joined into a single string separated by an EOL char. Each line
                is processed as a separate repl line or prompt input by
                pybemcli.

                If omitted or None, no standard input will be provided to the
                pywbemcli command.

          exp_response (:class:`py:dict`)

            Keyword arguments for expected response.

            Includes the following possible keys:

               'stdout' or 'stderr' - Defines which return is expected (the
               expected response). The value is a string or iterable defining
               the data expected in the response. The data definition in
               this dictionary entry must be compatible with the definition
               of expected data for the test selected.
               Only one of these keys may exist.

               'test' - If it exists defines the test used to compare the
               returned data with the expected returned data defined as the
               value of 'stdout'/'stderr'.

               The tests define are:

                 'startswith' - Expected Response must be a single string
                 The returned text defined starts with the defined string

                 'lines' -  Expected response may be either a list of strings or
                 single string

                 Compares for exact match between the expected response and the
                 returned data line by line. The number of lines and the data
                 in each line must match.  If the expected response is a single
                 string it is split into lines separated at each new line
                 before the match

                 'linesnows' - Expected response may be either list of strings
                 or single string. Compares as with lines except that all
                 whitespace is removed from the strings before the compare.

                 'patterns' - Expected response must be same as lines test
                 except that each line in the expected response is treated as
                 a regex expression and a regex match is executed for each line.

                 'regex' - Expected response is a single string or list of
                 strings. Each string is considered a regex expression. The
                 regex expression is tested against each line in the output
                 using regex search. All strings in the expected response must
                 be found in actual response to pass the test

                 'in' - Expected response is string or list of strings.
                 Tests the complete response line by line to determine if each
                 entry in expected response is in the response data as a single
                 test.

                 'innows' - Like 'in, except that differences in whitespace are
                 ignored.

                 Executes a single regex search of the entire
                 response data to match with each entry in the expected
                 response

               'rc' expected exit_code from pywbemcli.  If None, code 0
               is expected.

          mock_files (:term:`string` or list of string or None):
            If this is a string, this test will be executed using the
            --mock-server pywbemcl option with this file as the name of the
            objects to be compiled or executed. This should be just a file name
            and this method assumes the file is in the tests/unit directory.

            If it is a list, the same rules apply to each entry in the list.

            If None, test is executed without the --mock-server input parameter
            and defines an artificial server name  Used to test commands
            and options that do not communicate with a server.  It is faster
            than installing the mock repository

          condition (True, False, 'pdb', or 'verbose'):
            If True, the test is executed.
            If False, the test is skipped.
            If 'pdb', the test breaks in the debugger.
            If 'verbose', verbose mode is enabled for the test.

          verbose (:class:`py:bool`):
            If True, verbose mode is enabled for the test.

            In verbose mode, the assembled command line, the environment
            variables set by 'env', and other details will be displayed.
        """  # noqa: E501
        # pylint: enable=line-too-long

        if not condition:
            pytest.skip('Condition for test case {} not met'.format(desc))

        env = None
        stdin = None
        general_args = None
        connections_file_args = (None, None)
        if isinstance(inputs, dict):
            connections_file_args = inputs.get(
                "connections_file_args", (None, None))
            general_args = inputs.get("general", None)
            local_args = inputs.get("args", None)
            env = inputs.get("env", None)
            stdin = inputs.get('stdin', None)
            if stdin:
                if isinstance(stdin, (tuple, list)):
                    stdin = '\n'.join(stdin)
        elif isinstance(inputs, six.string_types):
            local_args = inputs
        elif isinstance(inputs, (list, tuple)):
            local_args = inputs
        else:
            assert False, 'Invalid inputs param to test {!r}. Allowed types ' \
                'are dict, string, list, tuple.'.format(inputs)

        if stdin and condition == 'pdb':
            assert False, "Condition 'pdb' cannot be used on testcases that " \
                "specify stdin"

        if isinstance(local_args, six.string_types):
            # Is not split into words anymore
            local_args = [local_args]

        if isinstance(general_args, six.string_types):
            # Is not split into words anymore
            general_args = [general_args]

        cmd_line = []

        if condition == 'pdb':
            capture = False
            cmd_line.append('--pdb')
        else:
            capture = True

        if general_args:
            cmd_line.extend(general_args)

        if mock_files:
            if isinstance(mock_files, (list, tuple)):
                for item in mock_files:
                    cmd_line.extend(['--mock-server',
                                     os.path.join(TEST_DIR, item)])
            elif isinstance(mock_files, six.string_types):
                cmd_line.extend(['--mock-server',
                                 os.path.join(TEST_DIR, mock_files)])
            else:
                assert False, \
                    'CLI_TEST_EXTENSIONS mock_file {} invalid' \
                    .format(mock_files)

        if not stdin:
            cmd_line.append(command_grp)

        if local_args:
            cmd_line.extend(local_args)

        if not verbose:
            verbose = condition == 'verbose'

        with connections_file(*connections_file_args):
            rc, stdout, stderr = execute_command(
                'pywbemcli', cmd_line, env=env, stdin=stdin, verbose=verbose,
                capture=capture)

        exp_rc = exp_response['rc'] if 'rc' in exp_response else 0
        assert_rc(exp_rc, rc, stdout, stderr, desc)

        if exp_response['test']:
            test_definition = exp_response['test']
        else:
            test_definition = None

        if 'stdout' in exp_response:
            test_value = exp_response['stdout']
            rtn_value = stdout
            rtn_type = 'stdout'
        elif 'stderr' in exp_response:
            test_value = exp_response['stderr']
            rtn_value = stderr
            rtn_type = 'stderr'
        else:
            assert False, 'Expected "stdout" or "stderr" key. One of these ' \
                          'keys required in exp_response.'

        if test_definition:
            if 'test' in exp_response:
                test_definition = exp_response['test']
                # test that rtn_value starts with test_value
                if test_definition == 'startswith':
                    assert isinstance(test_value, six.string_types)
                    assert rtn_value.startswith(test_value), \
                        "Unexpected start of line on {} in test:\n" \
                        "{}\n" \
                        "Expected start of line:\n" \
                        "------------\n" \
                        "{}\n" \
                        "------------\n" \
                        "Actual output line(s):\n" \
                        "------------\n" \
                        "{}\n" \
                        "------------\n". \
                        format(rtn_type, desc, test_value, rtn_value)
                # test that lines match between test_value and rtn_value
                # base on regex match
                elif test_definition == 'patterns':
                    if isinstance(test_value, six.string_types):
                        test_value = test_value.splitlines()
                    assert isinstance(test_value, (list, tuple))
                    assert_patterns(test_value, rtn_value.splitlines(),
                                    rtn_type, desc)
                # test that each line in the test value matches the
                # corresponding line in the rtn_value exactly
                elif test_definition == 'lines':
                    if isinstance(test_value, six.string_types):
                        test_value = test_value.splitlines()
                    if isinstance(test_value, (list, tuple)):
                        assert_lines(test_value, rtn_value.splitlines(),
                                     rtn_type, desc)
                    else:
                        assert(isinstance(test_value, six.string_types))
                        assert_lines(test_value.splitlines(),
                                     rtn_value.splitlines(),
                                     rtn_type, desc)
                # compress test_value and rtn_value into whitespace single
                # strings and assert_lines.
                elif test_definition == 'linesnows':
                    assert_lines(remove_ws(test_value),
                                 remove_ws(rtn_value),
                                 rtn_type, desc)

                # test with a regex search that all values in list exist in
                # the return. Build rtn_value into single string and do
                # re.search against it for each test_value
                elif test_definition == 'regex':
                    assert isinstance(rtn_value, six.string_types)
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for regex in test_value:
                        assert isinstance(regex, six.string_types)
                        match_result = re.search(regex, rtn_value, re.MULTILINE)
                        assert match_result, \
                            "Missing pattern on {} in test:\n" \
                            "{}\n" \
                            "Expected pattern in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, regex, rtn_value)
                elif test_definition == 'in':
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for test_str in test_value:
                        assert test_str in rtn_value, \
                            "Missing in-string on {} in test:\n" \
                            "{}\n" \
                            "Expected in-string in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, test_str, rtn_value)
                elif test_definition == 'innows':
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for test_str in test_value:
                        assert remove_ws(test_str, join=True) in \
                            remove_ws(rtn_value, join=True), \
                            "Missing ws-agnostic in-string on {} in test:\n" \
                            "{}\n" \
                            "Expected ws-agnostic in-string in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, test_str, rtn_value)
                elif test_definition == 'not-innows':
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for test_str in test_value:
                        assert remove_ws(test_str, join=True) not in \
                            remove_ws(rtn_value, join=True), \
                            "Unexpected ws-agnostic in-string on {} in test:\n"\
                            "{}\n" \
                            "Unexpected ws-agnostic in-string in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, test_str, rtn_value)
                else:
                    raise AssertionError(
                        "Test validation {!r} is invalid in test:\n"
                        "{}\n".format(test_definition, desc))
pywbemtools/_version.py

tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INCLUDE_QUALIFIERS_GET_HELP_LINE = \
    '--iq, --include-qualifiers Include qualifiers in the returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_LOCAL_ONLY_INSTANCE_GET_HELP_LINE = \
    '--lo, --local-only Do not include superclass properties in the returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_HELP_INSTANCENAME_HELP_LINE = \
    '--hi, --help-instancename Show help message for specifying INSTANCENAME'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_LEAFCLASSES_FILTER_HELP_LINE = \
    "Filter the returned classes to return only"
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_SUMMARY_HELP_LINE = \
    '-s, --summary Show only a summary (count) of the objects.'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_MULTIPLE_NAMESPACE_HELP_LINE = \
    '-n, --namespace NAMESPACE  Add a namespace to the search scope. May be'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INDICATION_FILTER_HELP_LINE = \
    '--indication / --no-indication'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_EXPERIMENTAL_FILTER_HELP_LINE = \
    '--experimental / --no-experimental'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INCLUDE_QUALIFIERS_LIST_HELP_LINE = \
    '--iq, --include-qualifiers When traditional operations are used, ' \
    'include qualifiers in the returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_VERIFY_HELP_LINE = \
    '-V, --verify Prompt for confirmation before performing a change'
tests/unit/pywbemcli/cli_test_extensions.py
FAKEURL_STR = '//FakedUrl:5988' if PYWBEM_1 else '//FakedUrl'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_PROPERTYLIST_HELP_LINE = \
    '--pl, --propertylist PROPERTYLIST Filter the properties included in'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_FILTER_QUERY_LANGUAGE_LINE = \
    '--filter-query-language QUERY-LANGUAGE The filter query language to be ' \
    'used'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_NAMESPACE_HELP_LINE = \
    '-n, --namespace NAMESPACE Namespace to use for this command'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_KEYS_HELP_LINE = \
    '-k, --key KEYNAME=VALUE         Value for a key in keybinding of'
tests/unit/pywbemcli/cli_test_extensions.py
PYWBEM_0 = not PYWBEM_1
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INCLUDE_CLASSORIGIN_HELP_LINE = \
    '--ico, --include-classorigin Include class origin information in the ' \
    'returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_LOCAL_ONLY_INSTANCE_LIST_HELP_LINE = \
    '--lo, --local-only When traditional operations are used, do not include ' \
    'superclass properties'


Question: import os
import pytest
from packaging.version import parse as parse_version
from pywbem import __version__ as pywbem_version
from .cli_test_extensions import CLITestsBase, FAKEURL_STR, PYWBEM_0
from .common_options_help_lines import CMD_OPTION_NAMES_ONLY_HELP_LINE, \
    CMD_OPTION_HELP_HELP_LINE, CMD_OPTION_SUMMARY_HELP_LINE, \
    CMD_OPTION_NAMESPACE_HELP_LINE, CMD_OPTION_PROPERTYLIST_HELP_LINE, \
    CMD_OPTION_INCLUDE_CLASSORIGIN_HELP_LINE, CMD_OPTION_VERIFY_HELP_LINE, \
    CMD_OPTION_INCLUDE_QUALIFIERS_LIST_HELP_LINE, \
    CMD_OPTION_INCLUDE_QUALIFIERS_GET_HELP_LINE, \
    CMD_OPTION_FILTER_QUERY_LINE, \
    CMD_OPTION_FILTER_QUERY_LANGUAGE_LINE, \
    CMD_OPTION_LOCAL_ONLY_INSTANCE_LIST_HELP_LINE, \
    CMD_OPTION_LOCAL_ONLY_INSTANCE_GET_HELP_LINE, \
    CMD_OPTION_MULTIPLE_NAMESPACE_HELP_LINE, \
    CMD_OPTION_KEYS_HELP_LINE, \
    CMD_OPTION_ASSOCIATION_FILTER_HELP_LINE, \
    CMD_OPTION_INDICATION_FILTER_HELP_LINE, \
    CMD_OPTION_EXPERIMENTAL_FILTER_HELP_LINE, \
    CMD_OPTION_HELP_INSTANCENAME_HELP_LINE, \
    CMD_OPTION_LEAFCLASSES_FILTER_HELP_LINE, \
    CMD_OPTION_SHOW_NULL_HELP_LINE
     {'stdout': ['Deleted'],
      'rc': 0,
      'test': 'innows'},
     SIMPLE_MOCK_FILE, OK],

    ['Verify instance command delete, valid delete, explicit ns',
     ['delete', 'CIM_Foo.InstanceID="CIM_Foo1"', '-n', 'root/cimv2'],
     {'stdout': '',
      'rc': 0,
      'test': 'lines'},
     SIMPLE_MOCK_FILE, OK],

    ['Verify instance command delete, valid delete, explicit ns',
     ['delete', 'CIM_Foo.InstanceID="CIM_Foo1"', '--namespace', 'root/cimv2'],
     {'stdout': '',
      'rc': 0,
      'test': 'lines'},
     SIMPLE_MOCK_FILE, OK],

    ['Verify instance command delete with wildcard keybinding',
     {'general': [],
      'args': ['delete', 'TST_Person.?'],
      'env': {MOCK_DEFINITION_ENVVAR: GET_TEST_PATH_STR(MOCK_PROMPT_0_FILE)}},
     {'stdout':
      ['root/cimv2:TST_Person.name="Mike"'],
      'rc': 0,
      'test': 'in'},
     ASSOC_MOCK_FILE, OK],

    #
    # Delete command error tests
    #
    ['Verify instance command delete, missing instance name',
     ['delete'],
     {'stderr':
      ['Usage: pywbemcli [GENERAL-OPTIONS] instance delete INSTANCENAME', ],
      'rc': 2,
      'test': 'in'},
     SIMPLE_MOCK_FILE, OK],

    ['Verify instance command delete, instance name invalid',
     ['delete', "blah"],
     {'stderr':
      ['Invalid format for an instance path in WBEM URI', ],
      'rc': 1,
      'test': 'in'},
     SIMPLE_MOCK_FILE, OK],

    ['Verify instance command delete, instance name not in repo',
     ['delete', 'CIM_Foo.InstanceID="xxxxx"', '--namespace', 'root/cimv2'],
     {'stderr':
      ["CIMError", "6", "CIM_ERR_NOT_FOUND"],
      'rc': 1,
      'test': 'in'},
     SIMPLE_MOCK_FILE, OK],

    ['Verify instance command delete, namespace not in repo',
     ['delete', 'CIM_Foo.InstanceID=1', '--namespace', 'Argh'],
     {'stderr':
      ["CIMError", "3", "CIM_ERR_INVALID_NAMESPACE"],
      'rc': 1,
      'test': 'in'},
     SIMPLE_MOCK_FILE, OK],

    #
    #  instance references command
    #
    ['Verify instance command references --help response',
     ['references', '--help'],
     {'stdout': INSTANCE_REFERENCES_HELP_LINES,
      'rc': 0,
      'test': 'innows'},
     None, OK],

    ['Verify instance command references -h response',
     ['references', '-h'],
     {'stdout': INSTANCE_REFERENCES_HELP_LINES,
      'rc': 0,
      'test': 'innows'},
     None, OK],

    ['Verify instance command references --help-instancename response',
     ['references', '--help-instancename'],
     {'stdout': INSTANCE_HELP_INSTANCENAME_LINES,
      'rc': 0,
      'test': 'innows'},
     None, OK],

    ['Verify instance command references --hi response',
     ['references', '--hi'],
     {'stdout': INSTANCE_HELP_INSTANCENAME_LINES,
      'rc': 0,
      'test': 'innows'},
     None, OK],

    ['Verify instance command references, returns instances',
     ['references', 'TST_Person.name="Mike"'],
     {'stdout': REF_INSTS,
      'rc': 0,
      'test': 'linesnows'},
     ASSOC_MOCK_FILE, OK],

    ['Verify instance command references with --key, returns instances',
     ['references', 'TST_Person', '--key', 'name=Mike'],
     {'stdout': REF_INSTS,
      'rc': 0,
      'test': 'linesnows'},
     ASSOC_MOCK_FILE, OK],

    ['Verify instance command references, returns instances, explicit ns',
     ['references', 'TST_Person.name="Mike"', '-n', 'root/cimv2'],
     {'stdout': REF_INSTS,
      'rc': 0,
      'test': 'linesnows'},
     ASSOC_MOCK_FILE, OK],

    ['Verify instance command references --no, returns paths',
     ['references', 'TST_Person.name="Mike"', '--no'],
     {'stdout': ['"root/cimv2:TST_FamilyCollection.name=\\"Family2\\"",member',
                 '=\"root/cimv2:TST_Person.name=\\"Mike\\""',

Answer:                  FAKEURL_STR + '/root/cimv2:TST_Lineage.InstanceID="MikeSofi"',