""" All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or its licensors. For complete copyright and license terms please see the LICENSE at the root of this distribution (the "License"). All use of this software is governed by the License, or, if provided, by the license below or the license accompanying this file. Do not remove or modify any license notices. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Unit tests for ~/TestRailImporter/lib/testrail_importer/testrail_importer.py """ try: # py2 import mock except ImportError: # py3 import unittest.mock as mock try: # py2 import __builtin__ builtin_module = '__builtin__' except ImportError: #py3 import builtins builtin_module = 'builtins' import argparse import os import pytest import sys import lib.testrail_importer.testrail_importer as testrail_importer DEFAULT_ARGS = [ {'name': "--testrail-xml", 'nargs': '?', 'required': True, 'help': 'help text', }, {'name': "--testrail-url", 'nargs': '?', 'required': True, 'help': 'help text', }, {'name': "--testrail-user", 'nargs': '?', 'required': True, 'help': 'help text', }, {'name': "--testrail-project-id", 'required': True, 'help': 'help text', }, {'name': "--testrail-password", 'help': 'help text', }, {'name': "--testrun-name", 'help': 'help text', 'default': 'Automated TestRail Report' }, {'name': "--logs-folder", 'help': 'help text', 'default': 'reports' }, {'name': "--testrun-id", 'help': 'help text' }, {'name': "--testrail-suite-id", 'help': 'help text', }, ] DEFAULT_LAUNCH_CMD = ['--testrail-xml', 'xml-path', '--testrail-url', 'https://url-string.dummyurl', '--testrail-user', 'user@email.email', '--testrail-project-id', '1234567890'] def create_parser(arg_values): parser = argparse.ArgumentParser(description="Mocked") for value in arg_values: parser.add_argument(value.get('name', None), nargs=value.get('nargs', None), required=value.get('required', None), help=value.get('help', None), default=value.get('default', None), ) return parser class MockedTTY(object): """Python2 cannot mock sys.stdin.isatty(), so this proxy object is required.""" def __init__(self, underyling, tty_status): self.__underlying = underyling self.tty_status = tty_status def __getattr__(self, name): return getattr(self.__underlying, name) def isatty(self): return self.tty_status @mock.patch('os.path.realpath', mock.MagicMock(return_value='dummy_realpath')) @mock.patch('os.path.dirname', mock.MagicMock(return_value='dummy_dirname')) @mock.patch("{}.open".format(builtin_module), mock.mock_open()) @pytest.mark.unit class TestImporter: @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_Init_ValidArgParse_SetsCliArgs(self, mock_cli_args): mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args under_test = testrail_importer.TestRailImporter() assert under_test._cli_args == mock_args @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_FilterTestCases_HasCaseIDs_ReturnsList(self, mock_cli_args): mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args testrun_results = [{'case_ids': [12345]}, {'case_ids': [11111]}] under_test = testrail_importer.TestRailImporter()._TestRailImporter__filter_test_cases( testrun_results) assert under_test == [{'case_id': 12345, 'case_ids': [12345]}, {'case_id': 11111, 'case_ids': [11111]}] @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_FilterTestCaseIDs_HasCaseIDs_ReturnsListWithValues(self, mock_cli_args): mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args test_result = {'random_key_from_xml': 'test', 'case_ids': [12345, 11111]} under_test = testrail_importer.TestRailImporter()._TestRailImporter__filter_test_case_ids( test_result) assert under_test == [ {'random_key_from_xml': 'test', 'case_id': 12345, 'case_ids': [12345, 11111]}, {'random_key_from_xml': 'test', 'case_id': 11111, 'case_ids': [12345, 11111]} ] @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_FilterTestCaseIDs_NoCaseIDs_ReturnsEmptyList(self, mock_cli_args): mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args test_result = {'random_key_from_xml': 'test', 'some_other_key': 'something'} under_test = testrail_importer.TestRailImporter()._TestRailImporter__filter_test_case_ids( test_result) assert under_test == [] @mock.patch('lib.testrail_importer.testrail_importer.argparse.ArgumentParser') def test_CliArgs_AllCLIArgs_ReturnsParsedArgs(self, mock_arg_parser): expected_attribute_values = { 'testrail_xml': 'xml-path', 'testrail_url': 'https://url.url.asdf', 'testrail_user': 'user@email.email', 'testrail_project_id': '1234567890', 'testrail_password': 'always_censor_me', 'testrun_name': 'Test Run Name', 'logs_folder': 'dummy_name', 'testrun_id': '11111111111', 'testrail_suite_id': '1212121212', } mock_arg_parser.return_value = mock.MagicMock() for mock_attribute in expected_attribute_values.keys(): mock_arg_parser.add_argument.side_effect = [ setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]), setattr(mock_arg_parser, mock_attribute, expected_attribute_values[mock_attribute]) ] testrail_importer.TestRailImporter() # cli_args() called in __init__() for expected_attribute in expected_attribute_values.keys(): assert getattr(mock_arg_parser, expected_attribute) == expected_attribute_values[expected_attribute] @mock.patch('lib.testrail_importer.testrail_tools.testrail_connection') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_ProjectSuiteCheck_HasSuitesHasSuiteIDHasRunID_ReturnsTrue(self, mock_cli_args, mock_testrail_connection): mock_testrail_connection.get_suites.return_value = [{u'id': 123}, {u'id': 456}] mock_parser = create_parser(DEFAULT_ARGS) new_launch_cmd = [] new_launch_cmd.extend(DEFAULT_LAUNCH_CMD) new_launch_cmd.extend(['--testrail-suite-id', '123']) mock_args = mock_parser.parse_args(new_launch_cmd) mock_cli_args.return_value = mock_args under_test = testrail_importer.TestRailImporter().project_suite_check(mock_testrail_connection, '1') assert under_test is True @mock.patch('lib.testrail_importer.testrail_tools.testrail_connection') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_ProjectSuiteCheck_HasSuitesNoSuiteIDNoRunID_RaisesTestRailImporterError(self, mock_cli_args, mock_testrail_connection): mock_testrail_connection.get_suites.return_value = [{u'id': 123}, {u'id': 456}] mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args with pytest.raises(testrail_importer.TestRailImporterError): testrail_importer.TestRailImporter().project_suite_check(mock_testrail_connection, '1') @mock.patch('lib.testrail_importer.testrail_tools.testrail_connection') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_ProjectSuiteCheck_HasSuitesNoSuiteIDHasRunID_ReturnsTrue(self, mock_cli_args, mock_testrail_connection): mock_testrail_connection.get_suites.return_value = [] mock_parser = create_parser(DEFAULT_ARGS) new_launch_cmd = [] new_launch_cmd.extend(DEFAULT_LAUNCH_CMD) new_launch_cmd.extend(['--testrun-id', '123']) mock_args = mock_parser.parse_args(new_launch_cmd) mock_cli_args.return_value = mock_args under_test = testrail_importer.TestRailImporter().project_suite_check(mock_testrail_connection, '1') assert under_test is True @mock.patch('os.path.isdir') @mock.patch('lib.testrail_importer.testrail_importer.logging') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_StartLog_HasLogDirectory_SetsLogging(self, mock_cli_args, mock_logging, mock_isdir): mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args logs_folder = 'dummy_logs_folder' mock_isdir.return_value = True testrail_importer.TestRailImporter().start_log(logs_folder) assert mock_logging.Formatter.call_count == 2 mock_logging.FileHandler.assert_called_once() mock_logging.StreamHandler.assert_called_once() @mock.patch('lib.testrail_importer.testrail_importer.logging', mock.MagicMock()) @mock.patch('os.makedirs') @mock.patch('os.path.isdir') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_StartLog_NoLogDirectory_CreatesLogDirectorySetsLogging(self, mock_cli_args, mock_isdir, mock_makedirs): mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args logs_folder = 'dummy_logs_folder' mock_isdir.return_value = False testrail_importer.TestRailImporter().start_log(logs_folder) mock_makedirs.assert_called_with( os.path.join( 'dummy_dirname', '..', '..', 'dummy_logs_folder')) @mock.patch( 'lib.testrail_importer.testrail_tools.testrail_report_converter.TestRailReportConverter', mock.MagicMock()) @mock.patch('getpass.getpass', mock.MagicMock(return_value='password')) @mock.patch('lib.testrail_importer.testrail_tools.testrail_connection.TestRailConnection') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.project_suite_check') @mock.patch('lib.testrail_importer.testrail_importer.TestRailImporter.cli_args') def test_Main_HasTTYNoID_PostsTestResults(self, mock_cli_args, mock_suite_check, mock_testrail_connection): sys.stdin = MockedTTY(sys.stdin, True) mock_parser = create_parser(DEFAULT_ARGS) mock_args = mock_parser.parse_args(DEFAULT_LAUNCH_CMD) mock_cli_args.return_value = mock_args testrail_importer.TestRailImporter().main() mock_testrail_connection.assert_called_with(password='password', url='https://url-string.dummyurl', user='user@email.email') mock_suite_check.assert_called_once() sys.stdin = sys.stdin