Best Python code snippet using gherkin-python
testlinkapigeneric_offline_test.py
Source:testlinkapigeneric_offline_test.py  
1#! /usr/bin/python2# -*- coding: UTF-8 -*-34#  Copyright 2013-2019 Luiko Czub, TestLink-API-Python-client developers5#6#  Licensed under the Apache License, Version 2.0 (the "License");7#  you may not use this file except in compliance with the License.8#  You may obtain a copy of the License at9#10#       http://www.apache.org/licenses/LICENSE-2.011#12#  Unless required by applicable law or agreed to in writing, software13#  distributed under the License is distributed on an "AS IS" BASIS,14#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15#  See the License for the specific language governing permissions and16#  limitations under the License.17#18# ------------------------------------------------------------------------1920# this test works WITHOUT an online TestLink Server21# no calls are send to a TestLink Server2223import sys, os.path24import unittest25    26if sys.version_info[0] == 2 and sys.version_info[1] == 7:27    # py27 and py31 assertRaisesRegexp was renamed in py32 to assertRaisesRegex28    unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp29    # py27 and py31 assertRegexpMatches was renamed in py32 to assertRegex30    unittest.TestCase.assertRegex = unittest.TestCase.assertRegexpMatches31    3233from testlink import TestlinkAPIGeneric, TestLinkHelper34from testlink.testlinkerrors import TLArgError, TLResponseError, TLAPIError353637#from testlink.testlinkapigeneric import positionalArgNamesDefault38# scenario_a includes response from a testlink 1.9.8 server39SCENARIO_A = {'repeat' : 'You said: One World',40              'sayHello' : 'Hey Folks!',41              'doesUserExist' : {42                'Big Bird' :  [{'message': '(doesUserExist) - Cannot Find User Login provided (Big Bird).', 43                                'code': 10000}],44                'admin' : True },45              'getProjectTestPlans' : {46                'onePlan' : [{'name': 'TestPlan_API', 47                         'notes': 'New TestPlan created with the API', 48                         'active': '1', 'is_public': '1', 49                         'testproject_id': '21', 'id': '22'}] ,50                'noPlan' : '' },51              'getBuildsForTestPlan' : {'noBuild' : '' },52              'getTestPlanPlatforms' : {53                'twoPlatforms' : [{'notes': '', 'id': '1', 'name': 'dutch'}, 54                                  {'notes': '', 'id': '2', 'name': 'platt'}],55                'noPlatform' : [{'message': 'Test plan (noPlatform) has no platforms linked', 56                         'code': 3041}]},57              'getTestSuitesForTestPlan' : {'noSuite' : ''},58              'getTestSuitesForTestSuite' : {'noSuite' : ''},59              'getFirstLevelTestSuitesForTestProject' : {60                'noSuite' : [{'message': 'Test Project (noSuite) is empty.', 61                              'code': 7008}]},62              'getTestCasesForTestSuite' : {'noTestCase' : [] },63              'getTestCasesForTestPlan'  : {'noTestCase' : [] },64              'getTestCaseIDByName' : {65                'dictResult' :  {'1': {'parent_id': '24', 'tc_external_id': '2', 66                                       'id': '33', 'tsuite_name': 'B - First Level', 67                                       'name': 'TESTCASE_B'}}, 68                'listResult' : [{'parent_id': '25', 'tc_external_id': '1', 69                                 'id': '26', 'tsuite_name': 'AA - Second Level', 70                                 'name': 'TESTCASE_AA'}]},71              'getProjectPlatforms' : {72                   'twoPlatforms' : {'dutch' : {'id': '1', 'name': 'dutch'}, 73                                     'platt' : {'id': '2', 'name': 'platt'}},74                    'noPlatform'  : {}   75                    },76              'reportTCResult' :  [{'status': True, 'operation': 'reportTCResult', 77                                    'message': 'Success!', 'overwrite': False, 'id': '773'}],              78              'getProjectKeywords' : {79                   'twoKeywords' : {'25': 'KeyWord01', '26': 'KeyWord02'},80                   'noKeyword'   : {}   81                    },              82              'getTestCaseKeywords' : {83                   'twoKeywords' : {'25': 'KeyWord01', '26': 'KeyWord02'},84                   'noKeyword'   : {}85                   }   86              }8788# scenario_tl198 used by test with older responses, changed in TL 1.9.989SCENARIO_TL198 = {'testLinkVersion' : 'unknown',90                  'about' : 'Testlink API Version: 1.0 ...'}9192# scenario_tl199 used by test with newer responses, changed in TL 1.9.993SCENARIO_TL199 = {'testLinkVersion' : '1.9.9',94                  'about' : 'Testlink API Version: 1.0 ...'}9596# scenario_custom_fields defines response for custom field request97# {'default_value': '', 'enable_on_execution': '1', 'name': 'cf_tc_ex_string', 'location': '1', 'enable_on_design': '0', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 'value': 'a custom string', 'label': 'CF Exec String', 'show_on_testplan_design': '0', 'display_order': '1', 'length_max': '0', 'show_on_design': '0', 'required': '0', 'show_on_execution': '1', 'type': '0', 'id': '24', 'node_id': '7691', 'enable_on_testplan_design': '0'}98SCENARIO_CUSTOM_FIELDS = {99            'getTestCaseCustomFieldDesignValue' : {100                'cf_notAssigned' : [{'message': '(getTestCaseCustomFieldDesignValue) - Custom Field (name:cf_tc_sd_string), is not assigned to Test Project(name=PROJECT_API_GENERIC-8 / id=7760)', 101                                  'code': 9003}],102                'cf_full' : {'default_value': '', 'enable_on_execution': '0', 'name': 'cf_tc_sd_string', 103                          'location': '1', 'enable_on_design': '1', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 104                          'value': 'a custom spec design string', 'label': 'CF SpecDesign String', 'show_on_testplan_design': '0', 105                          'display_order': '1', 'length_max': '0', 'show_on_design': '1', 'required': '0', 'show_on_execution': '1', 106                          'type': '0', 'id': '22', 'node_id': '7691', 'enable_on_testplan_design': '0'},107                'cf_value'  : 'a custom spec design string',108                'cf_valueEmpty'  : '',109                'cf_simple' : {'type': '0', 'name': 'cf_tc_sd_string', 110                            'value': 'a custom spec design string', 'label': 'CF SpecDesign String'}111                                                     },112            'updateTestCaseCustomFieldDesignValue' : {113                'cf_notAssigned' : '',114                'a_string' : ''115                },116                          117            'getTestCaseCustomFieldExecutionValue' : {118                'cf_notAssigned' : '',119                'cf_full' : {'default_value': '', 'enable_on_execution': '1', 'name': 'cf_tc_ex_string', 120                             'location': '1', 'enable_on_design': '0', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 121                             'value': 'a custom exec string', 'label': 'CF Exec String', 'show_on_testplan_design': '0', 122                             'display_order': '1', 'length_max': '0', 'show_on_design': '0', 'required': '0', 'show_on_execution': '1', 123                             'type': '0', 'id': '24', 'node_id': '7691', 'enable_on_testplan_design': '0'}124                                                      },125126            'getTestCaseCustomFieldTestPlanDesignValue' : {127                'cf_notAssigned' : '',128                'cf_full' : {'default_value': '', 'enable_on_execution': '0', 'name': 'cf_tc_pd_string', 129                             'enable_on_design': '0', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 130                             'value': 'a custom PlanDesign string', 'label': 'CF PlanDesign String', 'show_on_testplan_design': '1', 131                             'display_order': '1', 'length_max': '0', 'show_on_design': '0', 'required': '0', 'show_on_execution': '1', 132                             'type': '0', 'id': '28', 'node_id': '779', 'enable_on_testplan_design': '1'}133                                                           },134            'getTestSuiteCustomFieldDesignValue' : {135                'cf_notAssigned' : '',136                'cf_full' : {'default_value': '', 'enable_on_execution': '0', 'name': 'cf_ts_string', 'location': '1', 137                             'enable_on_design': '1', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 138                             'value': 'a custom TSuite string', 'label': 'CF TestSuite String', 'show_on_testplan_design': '0', 139                             'display_order': '1', 'length_max': '0', 'show_on_design': '1', 'required': '0', 'show_on_execution': '1', 140                             'type': '0', 'id': '30', 'node_id': '', 'enable_on_testplan_design': '0'}141                                                    },142143            'getTestPlanCustomFieldDesignValue' : {144                'cf_notAssigned' : '',145                'cf_full' : {'default_value': '', 'enable_on_execution': '0', 'name': 'cf_tp_string', 'location': '1', 146                             'enable_on_design': '1', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 147                             'value': 'a custom TPlan string', 'label': 'CF TPlan String', 'show_on_testplan_design': '0',148                             'display_order': '1', 'length_max': '0', 'show_on_design': '1', 'required': '0', 'show_on_execution': '1', 149                             'type': '0', 'id': '31', 'node_id': '', 'enable_on_testplan_design': '0'}150                                                   },151                          152            'getReqSpecCustomFieldDesignValue' :  {153                'cf_notAssigned' : '',154                'cf_full' : {'default_value': '', 'enable_on_execution': '0', 'name': 'cf_req_sd_string', 'location': '1', 155                             'enable_on_design': '1', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 156                             'value': 'a custom ReqSpec string', 'label': 'CF ReqSpec String', 'show_on_testplan_design': '0', 157                             'display_order': '1', 'length_max': '0', 'show_on_design': '1', 'required': '0', 'show_on_execution': '0', 158                             'type': '0', 'id': '32', 'node_id': '', 'enable_on_testplan_design': '0'}159                                                   },160            'getRequirementCustomFieldDesignValue' : {161                'cf_notAssigned' : '',162                'cf_full' : {'default_value': '', 'enable_on_execution': '0', 'name': 'cf_req_string', 'location': '1', 163                             'enable_on_design': '1', 'valid_regexp': '', 'length_min': '0', 'possible_values': '', 164                             'value': 'a custom Req string', 'label': 'CF Req String', 'show_on_testplan_design': '0', 165                             'display_order': '1', 'length_max': '0', 'show_on_design': '1', 'required': '0', 'show_on_execution': '0', 166                             'type': '0', 'id': '33', 'node_id': '', 'enable_on_testplan_design': '0'}167                                                      }168169                          }170171# scenario_keywords defines response with keywords172SCENARIO_KEYWORDS = {'getTestCasesForTestSuite' : {173                    'noTestCase' : [] ,174                    'keyWords'  : [{'node_order': '0', 'is_open': '1', 175                        'keywords': {'1': {'keyword_id': '1', 'notes': 'a key word', 'testcase_id': '8144', 'keyword': 'KeyWord01'}, 176                                     '3': {'keyword_id': '3', 'notes': 'a third key word', 'testcase_id': '8144', 'keyword': 'KeyWord03'}}, 177                        'id': '8144', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '2', 'parent_id': '8134', 178                        'version': '1', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1', 179                        'tsuite_name': 'B - First Level', 'importance': '3', 'modification_ts': '2014-06-30 20:45:40', 180                        'execution_type': '1', 'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 181                        'creation_ts': '2014-06-28 22:06:17', 'node_table': 'testcases', 'tcversion_id': '8145', 182                        'name': 'TESTCASE_B', 'summary': '<p>\n\tThis is the summary of the Test Case B</p>\n', 183                        'steps': [{'step_number': '1', 'actions': 'Step action 1 -b ', 'execution_type': '2', 'active': '1', 'id': '8151', 'expected_results': 'Step result 1 - b'}, 184                                  {'step_number': '2', 'actions': 'Step action 2 -b ', 'execution_type': '2', 'active': '1', 'id': '8152', 'expected_results': 'Step result 2 - b'}, 185                                  {'step_number': '3', 'actions': 'action 3 createTestCaseSteps.update', 'execution_type': '2', 'active': '1', 'id': '8153', 'expected_results': 'update - cause step 3 already exist'}, 186                                  {'step_number': '4', 'actions': 'Step action 4 -b ', 'execution_type': '2', 'active': '1', 'id': '8154', 'expected_results': 'Step result 4 - b'}, 187                                  {'step_number': '5', 'actions': 'Step action 5 -b changed by updateTestCase', 'execution_type': '2', 'active': '1', 'id': '8155', 'expected_results': 'Step result 5 - b changed'}, 188                                  {'step_number': '6', 'actions': 'Step action 6 -b added by updateTestCase', 'execution_type': '2', 'active': '1', 'id': '8156', 'expected_results': 'Step result 6 - b added'}, 189                                  {'step_number': '7', 'actions': 'action 7 createTestCaseSteps.create', 'execution_type': '2', 'active': '1', 'id': '8157', 'expected_results': 'create - cause step 7 not yet exist'}, 190                                  {'step_number': '8', 'actions': 'action 8 createTestCaseSteps.update', 'execution_type': '2', 'active': '1', 'id': '8158', 'expected_results': 'create - cause step 8 not yet exist'}], 191                                    'author_id': '1', 'external_id': 'GPROAPI10-2'}]192                                            } 193                     }194195# scenario_no_project simulates a fresh empty test link application196SCENARIO_NO_PROJECT = {'getProjects' : [] }197198# scenario_requirements defines response with requirements199SCENARIO_REQUIREMENTS = {200    'getRequirements' : {201            'allReqs' : [{'id': '15344', 'req_doc_id': 'use-case-01'}, 202                             {'id': '15346', 'req_doc_id': 'none-function-01'}, 203                             {'id': '15350', 'req_doc_id': 'restriction-01'}, 204                             {'id': '15352', 'req_doc_id': 'user-gui-01'}, 205                             {'id': '15356', 'req_doc_id': 'system-func-01'}, 206                             {'id': '15358', 'req_doc_id': 'feature-01'}],207            'noReqs' : [],208            'with_srs_id' : [{'id': '15344', 'req_doc_id': 'use-case-01', 'srs_id': '15342'}, 209                             {'id': '15346', 'req_doc_id': 'none-function-01', 'srs_id': '15342'}, 210                             {'id': '15350', 'req_doc_id': 'restriction-01', 'srs_id': '15348'}, 211                             {'id': '15352', 'req_doc_id': 'user-gui-01', 'srs_id': '15348'}, 212                             {'id': '15356', 'req_doc_id': 'system-func-01', 'srs_id': '15354'}, 213                             {'id': '15358', 'req_doc_id': 'feature-01', 'srs_id': '15354'}] 214                         },215    'getReqCoverage' : {216            'reqCovered' : [{'id': '15326', 'name': 'TESTCASE_B', 'tc_external_id': '2', 217                             'login': 'pyTLapi', 'creation_ts': '2017-04-05 20:55:51'}],218            'reqNotCovered' : '',219            'reqUnknown' : [{'code': 11004, 220                             'message': '(getReqCoverage) - Requirement (docid=req_doc_unknown) does not belong to project (id=15312).'}]221                         }222                         }223224225# example text file attachment = this python file226# why not using os.path.realpath(__file__)227# -> cause __file__ could be compiled python file *.pyc, if the test run is 228#    repeated without changing the test code229ATTACHMENT_EXAMPLE_TEXT= os.path.join(os.path.dirname(__file__), 230                                      'testlinkapigeneric_offline_test.py')231232                          233class DummyAPIGeneric(TestlinkAPIGeneric):234    """ Dummy for Simulation TestLinkAPIGeneric. 235    Overrides 236    - _callServer() Method to return test scenarios237    - extend positional_arg_names for  method 'DummyMethod'238    """239240    __slots__ = ['scenario_data', 'callArgs']241  242    def __init__(self, server_url, devKey, **args):243        super(DummyAPIGeneric, self).__init__(server_url, devKey, **args)244        self._positionalArgNames['DummyMethod'] = ['Uno', 'due', 'tre']245        self.scenario_data = {}246        self.callArgs = None247248249    def loadScenario(self, a_scenario):250        self.scenario_data = a_scenario251        self.callArgs = None252253    def _callServer(self, methodAPI, argsAPI=None):254        self.callArgs = argsAPI255        response = None256        if methodAPI in ['DummyMethod']:257            response = [argsAPI]258        else:259            data = self.scenario_data[methodAPI]260            if methodAPI in ['doesUserExist']:261                response = data[argsAPI['user']]262            elif methodAPI in ['getProjectTestPlans', 'getProjectPlatforms',263                               'getFirstLevelTestSuitesForTestProject', 264                               'getProjectKeywords', 'getRequirements',265                               'getReqCoverage']:266                response = data[argsAPI['testprojectid']]267            elif methodAPI in ['getBuildsForTestPlan', 'getTestPlanPlatforms', 268                        'getTestSuitesForTestPlan', 'getTestCasesForTestPlan']:269                response = data[argsAPI['testplanid']]270            elif methodAPI in ['getTestSuitesForTestSuite', 271                               'getTestCasesForTestSuite']:272                response = data[argsAPI['testsuiteid']]273            elif methodAPI in ['getTestCaseIDByName']:274                response = data[argsAPI['testcasename']]275            elif methodAPI in ['getTestCaseKeywords']:276                response = data[argsAPI['testcaseid']]277            elif methodAPI in ['testLinkVersion']:278                response = data279                if data == 'unknown':280                    raise TLAPIError('problems calling the API method testLinkVersion1')281            elif methodAPI == 'updateTestCaseCustomFieldDesignValue':282                response = data[argsAPI['customfields']['cf_field1']]               283            elif 'CustomField' in methodAPI:284                response = data[argsAPI['customfieldname']]285            else:286                response = data287        return response288    289    290class TestLinkAPIGenericOfflineTestCase(unittest.TestCase):291    """ TestCases for TestlinkAPIGeneric - does not interacts with a TestLink Server.292    works with DummyAPIGeneric which returns special test data293    """294295    @classmethod296    def setUpClass(cls):297        cls.api = TestLinkHelper().connect(DummyAPIGeneric)298299#    def tearDown(self):300#        pass301302303    def test_convertPositionalArgs(self):304        response = self.api._convertPostionalArgs('DummyMethod',  [1,2,3])305        self.assertEqual({'Uno' : 1, 'due' :2, 'tre' : 3}, response)306        307    def test__convertPositionalArgs_missingConf(self):308        client = self.api309        def a_func(a_api): a_api._convertPostionalArgs('NoConfigMethod',  [1,2])310        self.assertRaises(TLArgError, a_func, client)311        312    def test__convertPositionalArgs_lessValues(self):313        client = self.api314        def a_func(a_api): a_api._convertPostionalArgs('DummyMethod',  [1,2])315        self.assertRaises(TLArgError, a_func, client)316        317    def test__convertPositionalArgs_moreValues(self):318        client = self.api319        def a_func(a_api): a_api._convertPostionalArgs('DummyMethod',  [1,2,3,4])320        self.assertRaises(TLArgError, a_func, client)321322    def test_callServerWithPosArgs_pos(self):323        self.api.callServerWithPosArgs('DummyMethod',  1,2,3)324        self.assertEqual({'Uno' : 1, 'due' :2, 'tre' : 3}, self.api.callArgs)325326    def test_callServerWithPosArgs_pos_opt(self):327        self.api.callServerWithPosArgs('DummyMethod',  1,2,3, quad=4)328        self.assertEqual({'Uno' : 1, 'due' :2, 'tre' : 3, 'quad' : 4}, self.api.callArgs)329330    def test_callServerWithPosArgs_opt(self):331        self.api.callServerWithPosArgs('DummyMethod',  quad=4)332        self.assertEqual({'quad' : 4}, self.api.callArgs)333334    def test_callServerWithPosArgs_none(self):335        self.api.callServerWithPosArgs('DummyMethod')336        self.assertEqual({}, self.api.callArgs)337        338    def test_checkResponse_emptyResponse(self):339        client = self.api340        def a_func(a_api, response): 341            a_api._checkResponse(response, 'DummyMethod',  342                                 {'Uno' : 1, 'due' :2, 'tre' : 3})343        self.assertRaises(TLResponseError, a_func, client, '')344        self.assertRaises(TLResponseError, a_func, client, [])345        346    def test_checkResponse_errorResponse(self):347        client = self.api348        responseA = [{'message': '(reportTCResult) - TC ID 709 does not exist!', 349                      'code': 5000}]350        def a_func(a_api, response): 351            a_api._checkResponse(response, 'DummyMethod',  352                                 {'Uno' : 1, 'due' :2, 'tre' : 3})353        self.assertRaises(TLResponseError, a_func, client, responseA)354355    def test_checkResponse_okResponse(self):356        self.api._checkResponse(357                        [{'message': 'all fine, cause no key with name code'}],358                         'DummyMethod', {'Uno' : 1, 'due' :2, 'tre' : 3})359        self.api._checkResponse(360                        'some API Call juts returns one string without codes',361                         'DummyMethod', {'Uno' : 1, 'due' :2, 'tre' : 3})362        363    def test_checkResponse_booleanResponse(self):364        response = True365        self.api._checkResponse(response, 'DummyMethod', 366                                {'Uno' : 1, 'due' :2, 'tre' : 3})367        368    def test_checkResponse_dictionaryResponse(self):369        response = {'note' : 'uploadAttachment Calls return {..} and not [{..}]'}370        self.api._checkResponse(response, 'DummyMethod', 371                                {'Uno' : 1, 'due' :2, 'tre' : 3})372        373    def test_checkResponse_errorResponse_sringCode(self):374        client = self.api375        376        responseA = [{'message': '(getUserByID) - Cannot Find User with DB ID (4711).', 377                      'code': 'NO_USER_BY_ID_LOGIN'}]378        def a_func(a_api, response): 379            a_api._checkResponse(response, 'getUserByID',  380                                 {'userid' : 4711})381        self.assertRaises(TLResponseError, a_func, client, responseA)382383    def test__apiMethodArgNames_noArgs(self):384        response = self.api._apiMethodArgNames('sayHello')385        self.assertEqual(response, ([], [], []))386387    def test__apiMethodArgNames_onlyOptionalArgs(self):388        response = self.api._apiMethodArgNames('getTestCaseAttachments')389        self.assertEqual(response[0], [])390        self.assertGreater(len(response[1]), 0)391        self.assertEqual(response[2], [])392393    def test__apiMethodArgNames__OptionalAndPositionalArgs(self):394        response = self.api._apiMethodArgNames('createBuild')395        self.assertGreater(len(response[0]), 0)396        self.assertGreater(len(response[1]), 0)397        self.assertEqual(response[2], [])398399    def test__apiMethodArgNames__MandatoryArgs(self):400        response = self.api._apiMethodArgNames('uploadExecutionAttachment')401        self.assertGreater(len(response[0]), 0)402        self.assertGreater(len(response[1]), 0)403        self.assertGreater(len(response[2]), 0)404405    def test_noWrapperName_apiMethods(self):406        " decorator test: API Methods internal function name should be unchanged "407        408        # apiMethod with decorator @decoApiCallWithoutArgs409        self.assertEqual('sayHello', self.api.sayHello.__name__)410        # apiMethod with decorator @decoApiCallWithArgs411        self.assertEqual('repeat', self.api.repeat.__name__)412        # apiMethod with decorator @decoApiCallAddDevKey 413        self.assertEqual('createBuild', self.api.createBuild.__name__)414        # apiMethod with decorator @decoMakerApiCallReplaceTLResponseError()415        self.assertEqual('getProjectTestPlans', self.api.getProjectTestPlans.__name__)416        # apiMethod with decorator @decoApiCallAddAttachment417        self.assertEqual('uploadExecutionAttachment', self.api.uploadExecutionAttachment.__name__)418        419    def test_ping(self):420        self.api.loadScenario(SCENARIO_A)421        response = self.api.ping()422        self.assertEqual('Hey Folks!', response)423        424        425    def test_getProjectTestPlans_noPlan(self):426        self.api.loadScenario(SCENARIO_A)427        response = self.api.getProjectTestPlans('noPlan')428        self.assertEqual([], response)429        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])430        431    def test_getProjectTestPlans_onePlan(self):432        self.api.loadScenario(SCENARIO_A)433        response = self.api.getProjectTestPlans('onePlan')434        self.assertEqual('21', response[0]['testproject_id'])435        self.assertEqual(1, len(response))436        437    def test_getProjectPlatforms_noPlatform(self):438        self.api.loadScenario(SCENARIO_A)439        response = self.api.getProjectPlatforms('noPlatform')440        self.assertEqual({}, response)441        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])442        443    def test_getProjectPlatforms_twoPlatforms(self):444        self.api.loadScenario(SCENARIO_A)445        response = self.api.getProjectPlatforms('twoPlatforms')446        self.assertEqual('1', response['dutch']['id'])447        self.assertEqual(2, len(response))448        449        450    def test_getBuildsForTestPlan_noBuild(self):451        self.api.loadScenario(SCENARIO_A)452        response = self.api.getBuildsForTestPlan('noBuild')453        self.assertEqual([], response)454        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])455        456    def test_getTestPlanPlatforms_noPlatform(self):457        self.api.loadScenario(SCENARIO_A)458        response = self.api.getTestPlanPlatforms('noPlatform')459        self.assertEqual([], response)460        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])461        462    def test_getTestPlanPlatforms_twoPlatforms(self):463        self.api.loadScenario(SCENARIO_A)464        response = self.api.getTestPlanPlatforms('twoPlatforms')465        self.assertEqual('dutch', response[0]['name'])466        self.assertEqual(2, len(response))467468    def test_getTestSuitesForTestPlan_noSuite(self):469        self.api.loadScenario(SCENARIO_A)470        response = self.api.getTestSuitesForTestPlan('noSuite')471        self.assertEqual([], response)472        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])473       474    def test_getTestSuitesForTestSuite_noSuite(self):475        self.api.loadScenario(SCENARIO_A)476        response = self.api.getTestSuitesForTestSuite('noSuite')477        self.assertEqual([], response)478        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])479        480    def test_getFirstLevelTestSuitesForTestProject_noSuite(self):481        self.api.loadScenario(SCENARIO_A)482        response = self.api.getFirstLevelTestSuitesForTestProject('noSuite')483        self.assertEqual([], response)484        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])485        486    def test_getTestCasesForTestSuite_noTestCase(self):487        self.api.loadScenario(SCENARIO_A)488        response = self.api.getTestCasesForTestSuite('noTestCase')489        self.assertEqual([], response)490        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])491492    def test_getTestCasesForTestSuite_keyWords(self):493        self.api.loadScenario(SCENARIO_KEYWORDS)494        response = self.api.getTestCasesForTestSuite('keyWords', details='full', 495                                                     getkeywords=True)496        self.assertIn('keywords', response[0])497        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])498           499    def test_getTestCasesForTestPlan_noTestCase(self):500        self.api.loadScenario(SCENARIO_A)501        response = self.api.getTestCasesForTestPlan('noTestCase')502        self.assertEqual([], response)503        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])504        505    def test_getTestCaseIDByName_dictResult(self):506        self.api.loadScenario(SCENARIO_A)507        response = self.api.getTestCaseIDByName('dictResult', 508                                            testprojectname='NEW_PROJECT_API')509        self.assertEqual(dict, type(response))510        self.assertEqual('TESTCASE_B', response['1']['name']) 511        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])512        513    def test_getTestCaseIDByName_listResult(self):514        self.api.loadScenario(SCENARIO_A)515        response = self.api.getTestCaseIDByName('listResult')516        self.assertEqual(list, type(response))517        self.assertEqual('TESTCASE_AA', response[0]['name']) 518        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])519520    def test_testLinkVersion_beforeTL199(self):521        self.api.loadScenario(SCENARIO_TL198)522        response = self.api.testLinkVersion()523        self.assertEqual('<= 1.9.8', response)524        525    def test_testLinkVersion_withTL199(self):526        self.api.loadScenario(SCENARIO_TL199)527        response = self.api.testLinkVersion()528        self.assertEqual('1.9.9', response)529        530    def test_connectionInfo_beforeTL199(self):531        self.api.loadScenario(SCENARIO_TL198)532        response = self.api.connectionInfo()533        self.assertRegex(response, r'\d*\.\d*\.\d*')534        535    def test_getTestCaseCustomFieldDesignValue_notAssigned(self):536        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)537        with self.assertRaisesRegex(TLResponseError, '9003.*Custom Field.*not assigned'):538            response = self.api.getTestCaseCustomFieldDesignValue('GPROAPI8-2', 539                            1, '7760', 'cf_notAssigned', details='full')540            541    def test_getTestCaseCustomFieldDesignValue_full(self):542        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)543        response = self.api.getTestCaseCustomFieldDesignValue('GPROAPI8-2', 544                            1, '7760', 'cf_full', details='full') 545        self.assertEqual('a custom spec design string', response['value'])           546        self.assertEqual('1', response['enable_on_design'])           547        self.assertEqual('0', response['enable_on_testplan_design']) 548        self.assertEqual('0', response['enable_on_execution'])           549550    def test_getTestCaseCustomFieldDesignValue_value(self):551        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)552        response = self.api.getTestCaseCustomFieldDesignValue('GPROAPI8-2', 553                            1, '7760', 'cf_value', details='value') 554        self.assertEqual('a custom spec design string', response)           555556    def test_getTestCaseCustomFieldDesignValue_valueEmpty(self):557        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)558        response = self.api.getTestCaseCustomFieldDesignValue('GPROAPI8-2', 559                            1, '7760', 'cf_valueEmpty', details='value') 560        self.assertEqual('', response)   561                562    def test_getTestCaseCustomFieldDesignValue_simple(self):563        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)564        response = self.api.getTestCaseCustomFieldDesignValue('GPROAPI8-2', 565                            1, '7760', 'cf_simple', details='simple') 566        self.assertEqual('a custom spec design string', response['value'])           567568    def test_updateTestCaseCustomFieldDesignValue_simple(self):569        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)570        response = self.api.updateTestCaseCustomFieldDesignValue('GPROAPI8-2', 571                            1, '7760', {'cf_field1'  : 'a_string'}) 572        self.assertEqual('', response)573574    def test_getTestCaseCustomFieldExecutionValue_notAssigned(self):575        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)576        response = self.api.getTestCaseCustomFieldExecutionValue(577                                    'cf_notAssigned', '7760', 1, '792', '7761') 578        self.assertEqual(None, response)579        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])580581    def test_getTestCaseCustomFieldExecutionValue_full(self):582        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)583        response = self.api.getTestCaseCustomFieldExecutionValue(584                                        'cf_full', '7760', 1, '792', '7761') 585        self.assertEqual('a custom exec string', response['value'])           586        self.assertEqual('0', response['enable_on_design']) 587        self.assertEqual('0', response['enable_on_testplan_design']) 588        self.assertEqual('1', response['enable_on_execution'])           589590    def test_getTestCaseCustomFieldTestPlanDesignValue_notAssigned(self):591        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)592        response = self.api.getTestCaseCustomFieldTestPlanDesignValue(593                                    'cf_notAssigned', '7760', 1, '7761', '779') 594        self.assertEqual(None, response)595        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])596597    def test_getTestCaseCustomFieldTestPlanDesignValue_full(self):598        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)599        response = self.api.getTestCaseCustomFieldTestPlanDesignValue(600                                        'cf_full', '7760', 1, '7761', '779') 601        self.assertEqual('a custom PlanDesign string', response['value'])           602        self.assertEqual('0', response['enable_on_design']) 603        self.assertEqual('1', response['enable_on_testplan_design']) 604        self.assertEqual('0', response['enable_on_execution'])           605606    def test_getTestSuiteCustomFieldDesignValue_notAssigned(self):607        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)608        response = self.api.getTestSuiteCustomFieldDesignValue(609                                            'cf_notAssigned', '7760', '7762') 610        self.assertEqual(None, response)611        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])612613    def test_getTestSuiteCustomFieldDesignValue_full(self):614        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)615        response = self.api.getTestSuiteCustomFieldDesignValue(616                                                    'cf_full', '7760', '7762') 617        self.assertEqual('a custom TSuite string', response['value'])           618        self.assertEqual('1', response['enable_on_design']) 619        self.assertEqual('0', response['enable_on_testplan_design']) 620        self.assertEqual('0', response['enable_on_execution'])           621622    def test_getTestPlanCustomFieldDesignValue_notAssigned(self):623        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)624        response = self.api.getTestPlanCustomFieldDesignValue(625                                            'cf_notAssigned', '7760', '7761') 626        self.assertEqual(None, response)627        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])628629    def test_getTestPlanCustomFieldDesignValue_full(self):630        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)631        response = self.api.getTestPlanCustomFieldDesignValue(632                                                    'cf_full', '7760', '7761') 633        self.assertEqual('a custom TPlan string', response['value'])           634        self.assertEqual('1', response['enable_on_design']) 635        self.assertEqual('0', response['enable_on_testplan_design']) 636        self.assertEqual('0', response['enable_on_execution'])           637638    def test_getReqSpecCustomFieldDesignValue_notAssigned(self):639        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)640        response = self.api.getReqSpecCustomFieldDesignValue(641                                            'cf_notAssigned', '7760', '7789') 642        self.assertEqual(None, response)643        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])644645    def test_getReqSpecCustomFieldDesignValue_full(self):646        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)647        response = self.api.getReqSpecCustomFieldDesignValue(648                                                    'cf_full', '7760', '7789') 649        self.assertEqual('a custom ReqSpec string', response['value'])           650        self.assertEqual('1', response['enable_on_design']) 651        self.assertEqual('0', response['enable_on_testplan_design']) 652        self.assertEqual('0', response['enable_on_execution'])           653654    def test_getRequirementCustomFieldDesignValue_notAssigned(self):655        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)656        response = self.api.getRequirementCustomFieldDesignValue(657                                            'cf_notAssigned', '7760', '7791') 658        self.assertEqual(None, response)659        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])660661    def test_getRequirementCustomFieldDesignValue_full(self):662        self.api.loadScenario(SCENARIO_CUSTOM_FIELDS)663        response = self.api.getRequirementCustomFieldDesignValue(664                                                    'cf_full', '7760', '7791') 665        self.assertEqual('a custom Req string', response['value'])           666        self.assertEqual('1', response['enable_on_design']) 667        self.assertEqual('0', response['enable_on_testplan_design']) 668        self.assertEqual('0', response['enable_on_execution'])   669        670    def test_reportTCResult_user(self):671        self.api.loadScenario(SCENARIO_A)672        response = self.api.reportTCResult(4712, 'p', testcaseid=4711, 673                                    buildname='build 4713', notes='note 4714',674                                    user='a login name') 675        self.assertEqual('reportTCResult', response[0]['operation']) 676        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])677        self.assertEqual('a login name', self.api.callArgs['user'])678        679    def test__getAttachmentArgs_textfile(self):680        "py3 issue #39 TypeError: expected bytes-like object, not str"681        # under py2, on windows text files should be open with 'r' mode and 682        # binary files with 'rb' 683        # see http://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files684        # under py3, text files open with 'r' on windows makes problem685        # see https://github.com/lczub/TestLink-API-Python-client/issues/39686        a_file=open(ATTACHMENT_EXAMPLE_TEXT)687        args = self.api._getAttachmentArgs(a_file)688        # repeating this test failed in second run, cause filename is then 689        # 'testlinkapigeneric_offline_test.pyc'690        self.assertEqual('testlinkapigeneric_offline_test.py', args['filename'])691        # filetype is also OS depended, either 'text/plain' or  'text/x-python' 692        self.assertIn('text/', args['filetype'])693        self.assertIsNotNone(args['content'])694       695    def test__getAttachmentArgs_filepath(self):696        "enhancement #40 handle file patch instead file object"697        args = self.api._getAttachmentArgs(ATTACHMENT_EXAMPLE_TEXT)698        self.assertEqual('testlinkapigeneric_offline_test.py', args['filename'])699        # filetype is also OS depended, either 'text/plain' or  'text/x-python' 700        self.assertIn('text/', args['filetype'])701        self.assertIsNotNone(args['content'])702703    def test___str__pyversion(self):704        self.api.loadScenario(SCENARIO_TL199)705        api_info = self.api.__str__()706        py_info = '(PY %i.' % sys.version_info[0]707        self.assertIn(py_info, api_info) 708        709    def test_getProjectKeywords_noKeywords(self):710        self.api.loadScenario(SCENARIO_A)711        response = self.api.getProjectKeywords('noKeyword')712        self.assertEqual({}, response)713        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])714        715    def test_getProjectKeywords_twoKeywords(self):716        self.api.loadScenario(SCENARIO_A)717        response = self.api.getProjectKeywords('twoKeywords')718        self.assertEqual('KeyWord01', response['25'])719        self.assertEqual('KeyWord02', response['26'])720               721    def test_getTestCaseKeywords_noKeywords(self):722        self.api.loadScenario(SCENARIO_A)723        response = self.api.getTestCaseKeywords(testcaseid='noKeyword')724        self.assertEqual({}, response)725        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])726        727    def test_getProjectKeywords_twoKeywords(self):728        self.api.loadScenario(SCENARIO_A)729        response = self.api.getTestCaseKeywords(testcaseid='twoKeywords')730        self.assertEqual('KeyWord01', response['25'])731        self.assertEqual('KeyWord02', response['26'])732               733    def test_getProjects_noProject(self):734        self.api.loadScenario(SCENARIO_NO_PROJECT)735        response = self.api.getProjects()736        self.assertEqual([], response)737        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])738        739    def test_connect_with_proxy(self):740        """ create a TestLink Generic API dummy with ProxiedTransport"""741        self.api = DummyAPIGeneric('http://SERVER-URL-71', 'DEVKEY-71', 742                                   transport='PROXY-71')743        self.assertEqual('PROXY-71', self.api.server.__call__('transport'))744                    745    def test_getRequirements_allRequirements(self):746        self.api.loadScenario(SCENARIO_REQUIREMENTS)747        response = self.api.getRequirements('allReqs')748        self.assertEqual('feature-01', response[5]['req_doc_id'])749        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])750751    def test_getRequirements_noRequirements(self):752        self.api.loadScenario(SCENARIO_REQUIREMENTS)753        response = self.api.getRequirements('noReqs')754        self.assertEqual([], response)755        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])756757    def Coveredtest_getReqCoverage_Covered(self):758        self.api.loadScenario(SCENARIO_REQUIREMENTS)759        response = self.api.getReqCoverage('reqCovered', 'a_req_doc_id')760        self.assertEqual('TESTCASE_B', response[0]['name'])761        self.assertEqual('15326', response[0]['id'])762        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])763        764    def test_getReqCoverage_notCovered(self):765        self.api.loadScenario(SCENARIO_REQUIREMENTS)766        response = self.api.getReqCoverage('reqNotCovered', 'a_req_doc_id')767        self.assertEqual([], response)768        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])769770    def test_connect_with_use_datetime(self):771        """ create a TestLink Generic API dummy with use_datetime"""772        self.api = DummyAPIGeneric('http://SERVER-URL-71', 'DEVKEY-71', 773                                   use_datetime='datetime?')774        a_transport = self.api.server.__call__('transport')775        self.assertEqual('datetime?', a_transport._use_datetime)776777    def test_connect_with_context(self):778        """ create a TestLink Generic API dummy with use_datetime"""779        self.api = DummyAPIGeneric('https://SERVER-URL-71', 'DEVKEY-71', 780                                   context='ssl_context')781        a_transport = self.api.server.__call__('transport')782        self.assertEqual('ssl_context', a_transport.context)783784if __name__ == "__main__":785    #import sys;sys.argv = ['', 'Test.testName']
...testlinkapi_offline_test.py
Source:testlinkapi_offline_test.py  
1#! /usr/bin/python2# -*- coding: UTF-8 -*-3#  Copyright 2012-2019 Luiko Czub, TestLink-API-Python-client developers4#5#  Licensed under the Apache License, Version 2.0 (the "License");6#  you may not use this file except in compliance with the License.7#  You may obtain a copy of the License at8#9#       http://www.apache.org/licenses/LICENSE-2.010#11#  Unless required by applicable law or agreed to in writing, software12#  distributed under the License is distributed on an "AS IS" BASIS,13#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14#  See the License for the specific language governing permissions and15#  limitations under the License.16#17# ------------------------------------------------------------------------18# this test works WITHOUT an online TestLink Server19# no calls are send to a TestLink Server20import sys21import unittest22if sys.version_info[0] == 2 and sys.version_info[1] == 7:23    # py27 and py31 assertRaisesRegexp was renamed in py32 to assertRaisesRegex24    unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp25from testlink import TestlinkAPIClient, TestLinkHelper26from testlink.testlinkerrors import TLArgError27# scenario_a includes response from a testlink 1.9.3 server28SCENARIO_A = {'getProjects' : [29               {'opt': {'requirementsEnabled': 0, 'testPriorityEnabled': 1, 30                        'automationEnabled': 1, 'inventoryEnabled': 0}, 31                'prefix': 'NPROAPI', 'name': 'NEW_PROJECT_API', 'color': '', 32                'notes': 'This is a Project created with the API', 33                'option_priority': '0', 34                'options': 'O:8:"stdClass":4:{s:19:"requirementsEnabled";i:0;s:19:"testPriorityEnabled";i:1;s:17:"automationEnabled";i:1;s:16:"inventoryEnabled";i:0;}', 35                'tc_counter': '2', 'option_reqs': '0', 'active': '1', 36                'is_public': '1', 'id': '21', 'option_automation': '0'}, 37               {'opt': {'requirementsEnabled': 1, 'testPriorityEnabled': 1, 38                        'automationEnabled': 1, 'inventoryEnabled': 1}, 39                'prefix': 'TP', 'name': 'TestProject', 'color': '', 40                'notes': '<p>Initiales TestProject, um  TestLink kennen zu lernen</p>', 41                'option_priority': '0', 42                'options': 'O:8:"stdClass":4:{s:19:"requirementsEnabled";i:1;s:19:"testPriorityEnabled";i:1;s:17:"automationEnabled";i:1;s:16:"inventoryEnabled";i:1;}', 43                'tc_counter': '0', 'option_reqs': '0', 'active': '1', 44                'is_public': '1', 'id': '1', 'option_automation': '0'}],45              'getProjectTestPlans' : {46                '21' : [{'name': 'TestPlan_API', 47                         'notes': 'New TestPlan created with the API', 48                         'active': '1', 'is_public': '1', 49                         'testproject_id': '21', 'id': '22'},50                        {'name': 'TestPlan_NoSuite', 51                         'notes': 'TestPlan with No Suites and No Platforms', 52                         'active': '1', 'is_public': '1', 53                         'testproject_id': '21', 'id': '222'}] ,54                '1' : '' },55              'getFirstLevelTestSuitesForTestProject' : {56                '21' :  [{'node_type_id': '2', 'name': 'A - First Level', 57                          'parent_id': '21', 'node_order': '0', 58                          'node_table': 'testsuites', 'id': '23'}, 59                         {'node_type_id': '2', 'name': 'B - First Level', 60                          'parent_id': '21', 'node_order': '0', 61                          'node_table': 'testsuites', 'id': '24'}],62                '1' : [{'message': '(getFirstLevelTestSuitesForTestProject) - Test Project (TestProject) is empty.', 63                        'code': 7008}] },64              'getTestSuitesForTestPlan' : {'22' : '', '222' : ''},65              'getTestCasesForTestPlan' : {'22' : '', '222' : ''},66              # TL(1.9.3)->getTestSuitesForTestSuite really returns {...} and not [{....}] !!!67              'getTestSuitesForTestSuite' : {68                '23' : {'node_type_id': '2', 'name': 'AA - Second Level', 69                        'parent_id': '23', 'node_order': '0', 70                        'details': 'Details of the Test Suite AA', 'id': '25'},71                '24' : ''},72              'getTestCasesForTestSuite' : {73                '23' : [{'node_type_id': '3', 'tcversion_id': '25', 74                         'name': 'TESTCASE_AA', 'parent_id': '25', 75                         'node_order': '0', 'node_table': 'testcases', 76                         'external_id': 'NPROAPI-1', 'id': '26'}],77                '24' : [{'node_type_id': '3', 'tcversion_id': '24', 78                         'name': 'TESTCASE_B', 'parent_id': '24', 79                         'node_order': '0', 'node_table': 'testcases', 80                         'external_id': 'NPROAPI-2', 'id': '33'}],81                '25' : [{'node_type_id': '3', 'tcversion_id': '25', 82                         'name': 'TESTCASE_AA', 'parent_id': '25', 83                         'node_order': '0', 'node_table': 'testcases', 84                         'external_id': 'NPROAPI-1',  'id': '26'}]85                 },86              'getTestPlanPlatforms' : {87                '22' : [{'notes': '', 'id': '1', 'name': 'dutch'}, {'notes': '', 'id': '2', 'name': 'platt'}],88                '222' : [{'message': 'Test plan (name:TestPlan_API) has no platforms linked', 89                         'code': 3041}]},90              'getBuildsForTestPlan' : {'22' : '', '222' : ''},91              'getTestCaseIDByName' : {92                'dictResult' :  {'1': {'parent_id': '24', 'tc_external_id': '2', 93                                       'id': '33', 'tsuite_name': 'B - First Level', 94                                       'name': 'TESTCASE_B'}}, 95                'listResult' : [{'parent_id': '25', 'tc_external_id': '1', 96                                 'id': '26', 'tsuite_name': 'AA - Second Level', 97                                 'name': 'TESTCASE_AA'}]},98              'getTestCase' : {99                '26-1' : [{'full_tc_external_id': 'NPROAPI-1', 'node_order': '0', 'is_open': '1', 'id': '27', 100                         'author_last_name': 'LkaTlinkD7', 'updater_login': '', 'layout': '1', 'tc_external_id': '1', 101                         'version': '1', 'estimated_exec_duration': '', 'testsuite_id': '25', 'updater_id': '', 102                         'status': '1', 'updater_first_name': '', 'testcase_id': '26', 'author_first_name': 'Tester', 103                         'importance': '2', 'modification_ts': '', 'execution_type': '1', 'preconditions': 'V1', 104                         'active': '1', 'creation_ts': '2013-12-26 21:17:43', 'name': 'TC-C', 'summary': 'SumSumSum', 105                         'updater_last_name': '', 106                         'steps': [{'step_number': '1', 'actions': 'Step action 1', 'execution_type': '2', 'active': '1', 107                                    'id': '5101', 'expected_results': 'Step result 1'}], 108                         'author_id': '3', 'author_login': 'tester'}],109                '26-2' : [{'full_tc_external_id': 'NPROAPI-1', 'node_order': '0', 'is_open': '1', 'id': '127', 110                         'author_last_name': 'LkaTlinkD7', 'updater_login': '', 'layout': '1', 'tc_external_id': '1', 111                         'version': '2', 'estimated_exec_duration': '', 'testsuite_id': '25', 'updater_id': '', 112                         'status': '1', 'updater_first_name': '', 'testcase_id': '26', 'author_first_name': 'Tester', 113                         'importance': '2', 'modification_ts': '', 'execution_type': '1', 'preconditions': 'V2', 114                         'active': '1', 'creation_ts': '2013-12-26 22:17:43', 'name': 'TC-C', 'summary': 'SumSumSum', 115                         'updater_last_name': '', 116                         'steps': [{'step_number': '1', 'actions': 'Step action 1', 'execution_type': '2', 'active': '1', 117                                    'id': '5101', 'expected_results': 'Step result 1'}], 118                         'author_id': '3', 'author_login': 'tester'}],119                '26-None' : [{'full_tc_external_id': 'NPROAPI-1', 'node_order': '0', 'is_open': '1', 'id': '127', 120                         'author_last_name': 'LkaTlinkD7', 'updater_login': '', 'layout': '1', 'tc_external_id': '1', 121                         'version': '2', 'estimated_exec_duration': '', 'testsuite_id': '25', 'updater_id': '', 122                         'status': '1', 'updater_first_name': '', 'testcase_id': '26', 'author_first_name': 'Tester', 123                         'importance': '2', 'modification_ts': '', 'execution_type': '1', 'preconditions': 'V2 None', 124                         'active': '1', 'creation_ts': '2013-12-26 22:17:43', 'name': 'TC-C', 'summary': 'SumSumSum', 125                         'updater_last_name': '', 126                         'steps': [{'step_number': '1', 'actions': 'Step action 1', 'execution_type': '2', 'active': '1', 127                                    'id': '5101', 'expected_results': 'Step result 1'}], 128                         'author_id': '3', 'author_login': 'tester'}]129                               130                               },131              'getFullPath' : {132                               133                26 : {'26' : ['NEW_PROJECT_API', 'A - First Level', 'AA - Second Level']},134                4711 : {'4711' : ['OLD_PROJECT_API']},135                    },136              'getTestProjectByName' : {137                'NEW_PROJECT_API' : {138                    'prefix': 'NPROAPI', 'name': 'NEW_PROJECT_API', 'color': '',139                    'notes': 'This is a Project created with the API', 140                    'is_public': '1', 'id': '21', 'option_automation': '0'},141                'OLD_PROJECT_API' : {142                     'prefix': 'OPROAPI', 'name': 'OLD_PROJECT_API', 'color': '',143                    'notes': 'This is a Project created with the API', 144                    'is_public': '1', 'id': '2211', 'option_automation': '0'},145                    },146              'createTestCase' : 'dummy response createTestCase',147              'reportTCResult' :  [{'status': True, 'operation': 'reportTCResult', 148                                    'message': 'Success!', 'overwrite': False, 'id': '773'}]              149              }150SCENARIO_STEPS = {'createTestCase' : ['noRealReponseData - ok for step tests']}151# scenario_keywords defines response with keywords152SCENARIO_KEYWORDS = {'getTestCasesForTestSuite' : {153                    'noTestCase' : [] ,154                    155                     'deepTrue1' : [{'node_order': '0', 'is_open': '1', 156                        'keywords': {'3': {'keyword_id': '3', 'notes': 'a third key word', 'testcase_id': '8136', 'keyword': 'KeyWord03'}}, 157                        'id': '8136', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '1', 'parent_id': '8135', 'version': '1', 158                        'estimated_exec_duration': '', 'updater_id': '2', 'status': '1', 'tsuite_name': 'AA - Second Level', 159                        'importance': '2', 'modification_ts': '2014-07-01 21:21:59', 'execution_type': '2', 160                        'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-06-28 22:06:17', 161                        'node_table': 'testcases', 'tcversion_id': '8137', 'name': 'TESTCASE_AA', 162                        'summary': '<p>\n\tThis is the summary of the Test Case AA</p>\n', 163                        'steps': [{'step_number': '1', 'actions': 'Step action 1 - aa', 'execution_type': '1', 'active': '1', 'id': '8138', 'expected_results': 'Step result 1 - aa'}, 164                                  {'step_number': '2', 'actions': 'Step action 2 - aa', 'execution_type': '1', 'active': '1', 'id': '8139', 'expected_results': 'Step result 2 - aa'}, 165                                  {'step_number': '3', 'actions': 'Step action 3 - aa', 'execution_type': '1', 'active': '1', 'id': '8140', 'expected_results': 'Step result 3 - aa'}, 166                                  {'step_number': '4', 'actions': 'Step action 4 - aa', 'execution_type': '1', 'active': '1', 'id': '8141', 'expected_results': 'Step result 4 - aa'}, 167                                  {'step_number': '5', 'actions': 'Step action 5 - aa', 'execution_type': '1', 'active': '1', 'id': '8142', 'expected_results': 'Step result 5 - aa'}], 168                        'author_id': '1', 'external_id': 'GPROAPI10-1'}],169                    170                    'deepFalse3' :  [{'node_order': '0', 'is_open': '1', 171                        'keywords': {'1': {'keyword_id': '1', 'notes': 'a key word', 'testcase_id': '8144', 'keyword': 'KeyWord01'}, 172                                     '3': {'keyword_id': '3', 'notes': 'a third key word', 'testcase_id': '8144', 'keyword': 'KeyWord03'}}, 173                        'id': '8144', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '2', 'parent_id': '8134', 'version': '1', 174                        'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1', 175                        'importance': '3', 'modification_ts': '2014-06-30 20:45:40', 'execution_type': '1', 176                        'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-06-28 22:06:17', 177                        'node_table': 'testcases', 'tcversion_id': '8145', 'name': 'TESTCASE_B', 178                        'summary': '<p>\n\tThis is the summary of the Test Case B</p>\n', 179                        'steps': [{'step_number': '1', 'actions': 'Step action 1 -b ', 'execution_type': '2', 'active': '1', 'id': '8151', 'expected_results': 'Step result 1 - b'}, 180                                  {'step_number': '2', 'actions': 'Step action 2 -b ', 'execution_type': '2', 'active': '1', 'id': '8152', 'expected_results': 'Step result 2 - b'}, 181                                  {'step_number': '3', 'actions': 'action 3 createTestCaseSteps.update', 'execution_type': '2', 'active': '1', 'id': '8153', 'expected_results': 'update - cause step 3 already exist'}, 182                                  {'step_number': '4', 'actions': 'Step action 4 -b ', 'execution_type': '2', 'active': '1', 'id': '8154', 'expected_results': 'Step result 4 - b'}, 183                                  {'step_number': '5', 'actions': 'Step action 5 -b changed by updateTestCase', 'execution_type': '2', 'active': '1', 'id': '8155', 'expected_results': 'Step result 5 - b changed'}, 184                                  {'step_number': '6', 'actions': 'Step action 6 -b added by updateTestCase', 'execution_type': '2', 'active': '1', 'id': '8156', 'expected_results': 'Step result 6 - b added'}, 185                                  {'step_number': '7', 'actions': 'action 7 createTestCaseSteps.create', 'execution_type': '2', 'active': '1', 'id': '8157', 'expected_results': 'create - cause step 7 not yet exist'}, 186                                  {'step_number': '8', 'actions': 'action 8 createTestCaseSteps.update', 'execution_type': '2', 'active': '1', 'id': '8158', 'expected_results': 'create - cause step 8 not yet exist'}], 187                        'author_id': '1'}, 188                                     {'node_order': '1', 'is_open': '1', 189                        'keywords': {'2': {'keyword_id': '2', 'notes': 'another key word', 'testcase_id': '8159', 'keyword': 'KeyWord02'}}, 190                        'id': '8159', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '3', 'parent_id': '8134', 'version': '1', 191                        'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1', 192                        'importance': '3', 'modification_ts': '2014-07-02 21:03:02', 'execution_type': '1', 193                        'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-07-02 20:53:45', 194                        'node_table': 'testcases', 'tcversion_id': '8160', 'name': 'TESTCASE_B2', 195                        'summary': '<p>\n\tThis is the summary of the Test Case B2</p>\n', 196                        'steps': [{'step_number': '1', 'actions': '<p>\n\tStep action 1 -b2</p>\n', 'execution_type': '2', 'active': '1', 'id': '8161', 'expected_results': '<p>\n\tStep result 1 - b2</p>\n'}, 197                                  {'step_number': '2', 'actions': '<p>\n\tStep action 2 -b2</p>\n', 'execution_type': '2', 'active': '1', 'id': '8162', 'expected_results': '<p>\n\tStep result 2 - b2</p>\n'}], 198                        'author_id': '2'}, 199                                     {'node_order': '2', 'is_open': '1', 200                     'id': '8169', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '4', 'parent_id': '8134', 'version': '1', 201                     'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1', 202                     'importance': '3', 'modification_ts': '2014-07-02 21:02:23', 'execution_type': '1', 203                     'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-07-02 20:55:46', 204                     'node_table': 'testcases', 'tcversion_id': '8170', 'name': 'TESTCASE_B3', 205                     'summary': '<p>\n\tThis is the summary of the Test Case B3</p>\n', 206                     'steps': [{'step_number': '1', 'actions': '<p>\n\tStep action 1 -b3</p>\n', 'execution_type': '2', 'active': '1', 'id': '8171', 'expected_results': '<p>\n\tStep result 1 - b3</p>\n'}, 207                               {'step_number': '2', 'actions': '<p>\n\tStep action 2 -b3</p>\n', 'execution_type': '2', 'active': '1', 'id': '8172', 'expected_results': '<p>\n\tStep result 2 - b3</p>\n'}], 208                     'author_id': '2'}],209                                                   210                '4711' :  [{'node_order': '0', 'is_open': '1', 211                        'keywords': {'1': {'keyword_id': '1', 'notes': 'a key word', 'testcase_id': '8144', 'keyword': 'KeyWord01'}, 212                                     '3': {'keyword_id': '3', 'notes': 'a third key word', 'testcase_id': '8144', 'keyword': 'KeyWord03'}}, 213                        'id': '8144', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '2', 'parent_id': '8134', 'version': '1', 214                        'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1', 215                        'importance': '3', 'modification_ts': '2014-06-30 20:45:40', 'execution_type': '1', 216                        'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-06-28 22:06:17', 217                        'node_table': 'testcases', 'tcversion_id': '8145', 'name': 'TESTCASE_B', 218                        'summary': '<p>\n\tThis is the summary of the Test Case B</p>\n', 219                        'steps': [{'step_number': '1', 'actions': 'Step action 1 -b ', 'execution_type': '2', 'active': '1', 'id': '8151', 'expected_results': 'Step result 1 - b'}], 220                        'author_id': '1'} ],221                'noKeywords' :  [{'node_order': '0', 'is_open': '1', 222                        'id': '8144', 'node_type_id': '3', 'layout': '1', 'tc_external_id': '2', 'parent_id': '8134', 'version': '1', 223                        'details': '<p>\n\tDetails of the Test Suite B</p>\n', 'estimated_exec_duration': '3.00', 'updater_id': '2', 'status': '1', 224                        'importance': '3', 'modification_ts': '2014-06-30 20:45:40', 'execution_type': '1', 225                        'preconditions': '<p>\n\tthese are the preconditions</p>\n', 'active': '1', 'creation_ts': '2014-06-28 22:06:17', 226                        'node_table': 'testcases', 'tcversion_id': '8145', 'name': 'TESTCASE_B', 227                        'summary': '<p>\n\tThis is the summary of the Test Case B</p>\n', 228                        'steps': [{'step_number': '1', 'actions': 'Step action 1 -b ', 'execution_type': '2', 'active': '1', 'id': '8151', 'expected_results': 'Step result 1 - b'}], 229                        'author_id': '1'} ]230                                            },231                     'getTestCase' : {232                                    '8144' : [{'full_tc_external_id': 'NPROAPI-2', 'id': '8145', 'tc_external_id': '2', 'version': '1', 233                                                    'testsuite_id': 'deepFalse3', 'testcase_id': '8144', 'name': 'TESTCASE_B'}],234                                    'NPROAPI-2' : [{'full_tc_external_id': 'NPROAPI-2', 'id': '8145', 'tc_external_id': '2', 'version': '1', 235                                                    'testsuite_id': 'deepFalse3', 'testcase_id': '8144', 'name': 'TESTCASE_B'}],236                                    '8159' : [{'full_tc_external_id': 'NPROAPI-3', 'id': '8160', 'tc_external_id': '3', 'version': '1', 237                                                    'testsuite_id': 'deepFalse3', 'testcase_id': '8159', 'name': 'TESTCASE_B2'}],238                                    'NPROAPI-3' : [{'full_tc_external_id': 'NPROAPI-3', 'id': '8160', 'tc_external_id': '3', 'version': '1', 239                                                    'testsuite_id': 'deepFalse3', 'testcase_id': '8159', 'name': 'TESTCASE_B2'}],240                                    '8169' : [{'full_tc_external_id': 'NPROAPI-4', 'id': '8170', 'tc_external_id': '3', 'version': '1', 241                                                    'testsuite_id': 'deepFalse3', 'testcase_id': '8169', 'name': 'TESTCASE_B3'}],242                                    'NPROAPI-4' : [{'full_tc_external_id': 'NPROAPI-4', 'id': '8170', 'tc_external_id': '3', 'version': '1', 243                                                    'testsuite_id': 'deepFalse3', 'testcase_id': '8169', 'name': 'TESTCASE_B3'}] },244                     'getTestCaseKeywords' : {245                                               #{'12622': {'34': 'KeyWord01', '36': 'KeyWord03'}}246                                    '8144' : {'8144' : {'1': 'KeyWord01', '3': 'KeyWord03'} },247                                    'NPROAPI-2' : {'8144' : {'1': 'KeyWord01', '3': 'KeyWord03'} },248                                    '8159' : {'8159' : {'2': 'KeyWord02'}},249                                    'NPROAPI-3' : {'8159' : {'2': 'KeyWord02'}},250                                    '8169' : {'8169' : {}},251                                    'NPROAPI-4' : {'8169' : {}} 252                                              }253                     }254# scenario_no_project simulates a fresh empty test link application255SCENARIO_NO_PROJECT = {'getProjects' : [] }256class DummyAPIClient(TestlinkAPIClient):257    """ Dummy for Simulation TestLinkAPICLient. 258    Overrides _callServer() Method to return test scenarios259    """260    __slots__ = ['scenario_data', 'callArgs']261    def __init__(self, server_url, devKey, **args):262        super(DummyAPIClient, self).__init__(server_url, devKey, **args)263        self.scenario_data = {}264        self.callArgs = None265    def loadScenario(self, a_scenario):266        self.scenario_data = a_scenario267        self.callArgs = None268    def _callServer(self, methodAPI, argsAPI=None):269        self.callArgs = argsAPI270        data = self.scenario_data[methodAPI]271        response = None272        if methodAPI in ['getProjectTestPlans', 273                         'getFirstLevelTestSuitesForTestProject']:274            response = data[argsAPI['testprojectid']]275        elif methodAPI in ['getTestSuitesForTestPlan', 276                           'getTestCasesForTestPlan', 'getTestPlanPlatforms',277                           'getBuildsForTestPlan']:278            response = data[argsAPI['testplanid']]279        elif methodAPI in ['getTestCasesForTestSuite', 280                           'getTestSuitesForTestSuite']:281            response = data[argsAPI['testsuiteid']]282        elif methodAPI in ['getTestCaseIDByName']:283            response = data[argsAPI['testcasename']]284        elif methodAPI in ['getTestCase', 'getTestCaseKeywords']:285            datakey = argsAPI.get('testcaseid')286            if datakey:287                datakey = str(datakey)288            else:289                datakey = argsAPI.get('testcaseexternalid', '')290            if 'version' in argsAPI:291                datakey += '-%(version)s' % argsAPI292            response = data[datakey]293        elif methodAPI in ['getFullPath']:294            response = data[argsAPI['nodeid']]295        elif methodAPI in ['getTestProjectByName']:296            response = data[argsAPI['testprojectname']]297        else:298            response = data299        return response300class TestLinkAPIOfflineTestCase(unittest.TestCase):301    """ TestCases for TestlinkAPIClient - does not interacts with a TestLink Server.302    works with DummyAPIClientm which returns special test data303    """304    example_steps = [{'step_number' : '1', 'actions' : "action A" , 305                'expected_results' : "result A", 'execution_type' : "0"},306                 {'step_number' : '2', 'actions' : "action B" , 307                'expected_results' : "result B", 'execution_type' : "1"},308                 {'step_number' : '3', 'actions' : "action C" , 309                'expected_results' : "result C", 'execution_type' : "0"}]310    @classmethod311    def setUpClass(cls):312        cls.api = TestLinkHelper().connect(DummyAPIClient)313        314    def setUp(self):315        self.api._emptyStepsList()316#    def tearDown(self):317#        pass318    def test_countProjects(self):319        self.api.loadScenario(SCENARIO_A)320        response = self.api.countProjects()321        self.assertEqual(2, response)322        323    def test_countProjects_NoProject(self):324        self.api.loadScenario(SCENARIO_NO_PROJECT)325        response = self.api.countProjects()326        self.assertEqual(0, response)327    def test_countTestPlans(self):328        self.api.loadScenario(SCENARIO_A)329        response = self.api.countTestPlans()330        self.assertEqual(2, response)331    def test_countTestPlans_NoProject(self):332        self.api.loadScenario(SCENARIO_NO_PROJECT)333        response = self.api.countTestPlans()334        self.assertEqual(0, response)335    def test_countTestSuites(self):336        self.api.loadScenario(SCENARIO_A)337        response = self.api.countTestSuites()338        self.assertEqual(0, response)339    def test_countTestSuites_NoProject(self):340        self.api.loadScenario(SCENARIO_NO_PROJECT)341        response = self.api.countTestSuites()342        self.assertEqual(0, response)343    def test_countTestCasesTP(self):344        self.api.loadScenario(SCENARIO_A)345        response = self.api.countTestCasesTP()346        self.assertEqual(0, response)347    def test_countTestCasesTP_NoProject(self):348        self.api.loadScenario(SCENARIO_NO_PROJECT)349        response = self.api.countTestCasesTP()350        self.assertEqual(0, response)351    def test_countTestCasesTS(self):352        self.api.loadScenario(SCENARIO_A)353        response = self.api.countTestCasesTS()354        self.assertEqual(0, response)355    def test_countTestCasesTS_NoProject(self):356        self.api.loadScenario(SCENARIO_NO_PROJECT)357        response = self.api.countTestCasesTS()358        self.assertEqual(0, response)359    def test_countPlatforms(self):360        self.api.loadScenario(SCENARIO_A)361        response = self.api.countPlatforms()362        self.assertEqual(2, response)363        364    def test_countPlatforms_NoProject(self):365        self.api.loadScenario(SCENARIO_NO_PROJECT)366        response = self.api.countPlatforms()367        self.assertEqual(0, response)368    def test_countBuilds(self):369        self.api.loadScenario(SCENARIO_A)370        response = self.api.countBuilds()371        self.assertEqual(0, response)372        373    def test_countBuilds_NoProject(self):374        self.api.loadScenario(SCENARIO_NO_PROJECT)375        response = self.api.countBuilds()376        self.assertEqual(0, response)377#    def test_listProjects(self):378#        self.api.loadScenario(SCENARIO_A)379#        self.api.listProjects()380#         no assert check cause method returns nothing381#         'just' prints to stdout382    def test_getProjectIDByName(self):383        self.api.loadScenario(SCENARIO_A)384        response = self.api.getProjectIDByName('NEW_PROJECT_API')385        self.assertEqual('21', response)386        response = self.api.getProjectIDByName('UNKNOWN_PROJECT')387        self.assertEqual(-1, response)388        389    def test_getProjectIDByName_NoProject(self):390        self.api.loadScenario(SCENARIO_NO_PROJECT)391        response = self.api.getProjectIDByName('UNKNOWN_PROJECT')392        self.assertEqual(-1, response)393        394    def test_initStep(self):395        self.api.initStep("action A", "result A", 0)396        steps = self.example_steps[:1]397        self.assertEqual(steps, self.api.stepsList)398    def test_appendStep(self):399        steps = self.example_steps400        self.api.stepsList = steps[:1] 401        self.api.appendStep("action B", "result B", 1)402        self.api.appendStep("action C", "result C", 0)403        self.assertEqual(steps, self.api.stepsList)404    def test_createTestCaseWithSteps(self):405        self.api.loadScenario(SCENARIO_STEPS)406        self.api.initStep("action A", "result A", 0)407        self.api.appendStep("action B", "result B", 1)408        self.api.appendStep("action C", "result C", 0)409        self.api.createTestCase('case 4711', 4712, 4713, 'Big Bird', 410                                'summary 4714')411        self.assertEqual(self.example_steps, self.api.callArgs['steps'])412        self.assertEqual([], self.api.stepsList)413    def test_createTestCaseWithConfusingSteps(self):414        self.api.loadScenario(SCENARIO_STEPS)415        self.api.initStep("action A", "result A", 0)416        self.api.appendStep("action B", "result B", 1)417        self.api.appendStep("action C", "result C", 0)418        with self.assertRaisesRegex(TLArgError, 'confusing createTestCase*'):419            self.api.createTestCase('case 4711', 4712, 4713, 'Big Bird', 420                                    'summary 4714', steps=[])421    def test_getTestCaseIDByName_dictResult(self):422        "test that getTestCaseIDByName converts dictionary result into a list"423        self.api.loadScenario(SCENARIO_A)424        # v0.4.0 version for optional args testsuitename + testprojectname425        #response = self.api.getTestCaseIDByName('dictResult', None, 'NEW_PROJECT_API')426        # v0.4.5 version427        response = self.api.getTestCaseIDByName('dictResult', 428                                            testprojectname='NEW_PROJECT_API')429        self.assertEqual(list, type(response))430        self.assertEqual('TESTCASE_B', response[0]['name']) 431        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])432    def test_getTestCaseIDByName_listResult(self):433        self.api.loadScenario(SCENARIO_A)434        response = self.api.getTestCaseIDByName('listResult')435        self.assertEqual(list, type(response))436        self.assertEqual('TESTCASE_AA', response[0]['name']) 437        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])438    def test_getProjectIDByNode(self):439        self.api.loadScenario(SCENARIO_A)440        self.assertEqual('2211', self.api.getProjectIDByNode('4711'))441    def test__copyTC_generate_new(self):442        self.api.loadScenario(SCENARIO_A)443        self.api._copyTC('26', {}, duplicateaction = 'generate_new')444        self.assertEqual('generate_new',  445                         self.api.callArgs['actiononduplicatedname'])446    def test__copyTC_create_new_version(self):447        self.api.loadScenario(SCENARIO_A)448        self.api._copyTC('26', {}, duplicateaction = 'create_new_version')449        self.assertEqual('create_new_version',  450                         self.api.callArgs['actiononduplicatedname'])451        self.assertEqual('V2 None', self.api.callArgs['preconditions'])452    def test__copyTC_changedArgs(self):453        self.api.loadScenario(SCENARIO_A)454        self.api._copyTC('26', {'testsuiteid' :'4711'}, 455                         duplicateaction = 'generate_new')456        self.assertEqual('4711', self.api.callArgs['testsuiteid'])457        self.assertEqual('2211', self.api.callArgs['testprojectid'])458    def test__copyTC_changedArgs_version(self):459        self.api.loadScenario(SCENARIO_A)460        self.api._copyTC('26', {'testsuiteid' :'4711'}, 1,461                         duplicateaction = 'generate_new')462        self.assertEqual('4711', self.api.callArgs['testsuiteid'])463        self.assertEqual('2211', self.api.callArgs['testprojectid'])464        self.assertEqual('V1', self.api.callArgs['preconditions'])465    def test_copyTCnewVersion(self):466        self.api.loadScenario(SCENARIO_A)467        self.api.copyTCnewVersion('26', summary = 'The summary has changed', 468                                    importance = '33')469        self.assertEqual('create_new_version',  470                         self.api.callArgs['actiononduplicatedname'])471        self.assertEqual('V2 None', self.api.callArgs['preconditions'])472        self.assertEqual('The summary has changed', self.api.callArgs['summary'])473        self.assertEqual('33', self.api.callArgs['importance'])474        self.assertEqual('TC-C', self.api.callArgs['testcasename'])475        self.assertEqual('25', self.api.callArgs['testsuiteid'])476        self.assertEqual('21', self.api.callArgs['testprojectid'])477    def test_copyTCnewVersion_version(self):478        self.api.loadScenario(SCENARIO_A)479        self.api.copyTCnewVersion('26', 1, summary = 'The summary has changed', 480                                    importance = '33')481        self.assertEqual('create_new_version',  482                         self.api.callArgs['actiononduplicatedname'])483        self.assertEqual('V1', self.api.callArgs['preconditions'])484        self.assertEqual('The summary has changed', self.api.callArgs['summary'])485        self.assertEqual('33', self.api.callArgs['importance'])486        self.assertEqual('TC-C', self.api.callArgs['testcasename'])487        self.assertEqual('25', self.api.callArgs['testsuiteid'])488        self.assertEqual('21', self.api.callArgs['testprojectid'])489    def test_copyTCnewTestCase(self):490        self.api.loadScenario(SCENARIO_A)491        self.api.copyTCnewTestCase('26', testsuiteid = '4711')492        self.assertEqual('generate_new',  493                         self.api.callArgs['actiononduplicatedname'])494        self.assertEqual('V2 None', self.api.callArgs['preconditions'])495        self.assertEqual('4711', self.api.callArgs['testsuiteid'])496        self.assertEqual('2211', self.api.callArgs['testprojectid'])497    def test_copyTCnewTestCase_version(self):498        self.api.loadScenario(SCENARIO_A)499        self.api.copyTCnewTestCase('26', 1, testsuiteid = '4711')500        self.assertEqual('generate_new',  501                         self.api.callArgs['actiononduplicatedname'])502        self.assertEqual('V1', self.api.callArgs['preconditions'])503        self.assertEqual('4711', self.api.callArgs['testsuiteid'])504        self.assertEqual('2211', self.api.callArgs['testprojectid'])505    def test_reportTCResult_user(self):506        self.api.loadScenario(SCENARIO_A)507        response = self.api.reportTCResult(4711, 4712, 'build 4713', 'p', 508                                           'note 4714', user='a login name') 509        self.assertEqual('reportTCResult', response[0]['operation']) 510        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])511        self.assertEqual('a login name', self.api.callArgs['user'])512        513    def test_getTestCasesForTestSuite_keyWords(self):514        self.api.loadScenario(SCENARIO_KEYWORDS)515        response = self.api.getTestCasesForTestSuite('deepFalse3', False, 516                                                     'full', getkeywords=True)517        self.assertIn('keywords', response[0])518        self.assertNotIn('keywords', response[2])519        self.assertEqual(self.api.devKey, self.api.callArgs['devKey'])520    def test_listKeywordsForTC_FullExternalId(self):521        self.api.loadScenario(SCENARIO_KEYWORDS)522        response = self.api.listKeywordsForTC('NPROAPI-2')523        self.assertEqual(set(['KeyWord01', 'KeyWord03']), set(response))524    def test_listKeywordsForTC_InternalId_Int(self):525        self.api.loadScenario(SCENARIO_KEYWORDS)526        response = self.api.listKeywordsForTC(8144)527        self.assertEqual(set(['KeyWord01', 'KeyWord03']), set(response))528    def test_listKeywordsForTC_InternalId_String(self):529        self.api.loadScenario(SCENARIO_KEYWORDS)530        response = self.api.listKeywordsForTC('8144')531        self.assertEqual(set(['KeyWord01', 'KeyWord03']), set(response))532    def test_listKeywordsForTC_One(self):533        self.api.loadScenario(SCENARIO_KEYWORDS)534        response = self.api.listKeywordsForTC('NPROAPI-3')535        self.assertEqual(['KeyWord02'], response)536    def test_listKeywordsForTC_None(self):537        self.api.loadScenario(SCENARIO_KEYWORDS)538        response = self.api.listKeywordsForTC('NPROAPI-4')539        self.assertEqual([], response)540    def test_listKeywordsForTS_NoneTC(self):541        self.api.loadScenario(SCENARIO_KEYWORDS)542        response = self.api.listKeywordsForTS('noTestCase')543        self.assertEqual({}, response)544    def test_listKeywordsForTS_NoneKW(self):545        self.api.loadScenario(SCENARIO_KEYWORDS)546        response = self.api.listKeywordsForTS('noKeywords')547        self.assertEqual({'8144': []}, response)548        549    def test_listKeywordsForTS_Id_Int(self):550        self.api.loadScenario(SCENARIO_KEYWORDS)551        response = self.api.listKeywordsForTS(4711)552        set_response = response553        for item in set_response:554            set_response[item] = set(response[item])555        self.assertEqual({'8144': set(['KeyWord01', 'KeyWord03'])}, set_response)556    def test_listKeywordsForTS_Id_String(self):557        self.api.loadScenario(SCENARIO_KEYWORDS)558        response = self.api.listKeywordsForTS('4711')559        set_response = response560        for item in set_response:561            set_response[item] = set(response[item])562        self.assertEqual({'8144': set(['KeyWord01', 'KeyWord03'])}, set_response)563    def test_listKeywordsForTS_Multi(self):564        self.api.loadScenario(SCENARIO_KEYWORDS)565        response = self.api.listKeywordsForTS('deepFalse3')566        set_response = response567        for item in set_response:568            set_response[item] = set(response[item])569        self.assertEqual({'8144': set(['KeyWord01', 'KeyWord03']),570                          '8159': set(['KeyWord02']), '8169': set()}, set_response)571    def test_connect_with_proxy(self):572        """ create a TestLink API dummy with ProxiedTransport"""573        self.api = DummyAPIClient('http://SERVER-URL-71', 'DEVKEY-71', 574                                   transport='PROXY-71')575        self.assertEqual('PROXY-71', self.api.server.__call__('transport'))        576    def test_connect_with_use_datetime(self):577        """ create a TestLink Generic API dummy with use_datetime"""578        self.api = DummyAPIClient('http://SERVER-URL-71', 'DEVKEY-71', 579                                   use_datetime='datetime?')580        a_transport = self.api.server.__call__('transport')581        self.assertEqual('datetime?', a_transport._use_datetime)582    def test_connect_with_context(self):583        """ create a TestLink Generic API dummy with use_datetime"""584        self.api = DummyAPIClient('https://SERVER-URL-71', 'DEVKEY-71', 585                                   context='ssl_context')586        a_transport = self.api.server.__call__('transport')587        self.assertEqual('ssl_context', a_transport.context)588if __name__ == "__main__":589    #import sys;sys.argv = ['', 'Test.testName']...parser.py
Source:parser.py  
1# -*- coding: utf-8 -*-2"""3A Gherkin parser written using pyparsing.4"""5import os6from collections import OrderedDict7from copy import copy8from gherkin.dialect import Dialect9from gherkin.errors import ParserError10from gherkin.parser import Parser11from gherkin.token_matcher import TokenMatcher12from aloe import strings13from aloe.exceptions import AloeSyntaxError14from aloe.utils import memoizedproperty15# Pylint can't figure out methods vs. properties and which classes are16# abstract17# pylint:disable=abstract-method18class LanguageTokenMatcher(TokenMatcher):19    """Gherkin 3 token matcher that always uses the given language."""20    def __init__(self, dialect_name='en'):21        self.actual_dialect_name = dialect_name22        super().__init__(dialect_name=dialect_name)23    def _change_dialect(self, dialect_name, location=None):24        """Force the dialect name given in the constructor."""25        super()._change_dialect(self.actual_dialect_name, location=location)26def cell_values(row):27    """Extract cell values from a table header or row."""28    return tuple(cell['value'] for cell in row['cells'])29class Node(object):30    """31    A base parse node.32    """33    def __init__(self, parsed, filename=None):34        """Construct the node from Gherkin parse results."""35        self.line = parsed['location']['line']36        self.col = parsed['location']['column']37        self.filename = filename38    @property39    def feature(self):40        """The feature this node ultimately belongs to."""41        raise NotImplementedError42    @property43    def location(self):44        """Location as 'filename:line'"""45        return '{filename}:{line}'.format(46            filename=os.path.relpath(self.filename),47            line=self.line,48        )49    @property50    def text(self):51        """The text for this node."""52        raise NotImplementedError53    indent = 0  # The indent to use when printing the node54    def represented(self):55        """A representation of the node."""56        result = ' ' * self.indent + self.text.strip()57        return result58class Step(Node):59    """60    A single statement within a test.61    A :class:`Scenario` or :class:`Background` is composed of multiple62    :class:`Step`.63    """64    table = None65    """66    A Gherkin table as an iterable of rows, themselves iterables of cells.67    e.g.:68    .. code-block:: gherkin69        Then I have fruit:70            | apples | oranges |71            | 0      | 2       |72    Becomes:73    .. code-block:: python74        (('apples', 'oranges'), ('0', '2'))75    """76    multiline = None77    """78    A Gherkin multiline string with the appropriate indenting removed.79    .. code-block:: gherkin80        Then I have poem:81            \"\"\"82            Glittering-Minded deathless Aphrodite,83            I beg you, Zeusâs daughter, weaver of snares,84            Donât shatter my heart with fierce85            Pain, goddess,86            \"\"\"87    """88    outline = None89    """90    If this step is a part of an outline, the reference to the outline.91    """92    def __init__(self, parsed, background=None, scenario=None, **kwargs):93        super().__init__(parsed, **kwargs)94        if background:95            self.background = background96        elif scenario:97            self.scenario = scenario98        else:99            raise ValueError(100                "Step must belong to either a scenario or a background.")101        self.sentence = parsed['keyword'] + parsed['text']102        """The sentence parsed for this step."""103        try:104            argument_type = parsed['argument']['type']105        except KeyError:106            argument_type = None107        if argument_type == 'DataTable':108            self.table = tuple(109                cell_values(row)110                for row in parsed['argument']['rows']111            )112        elif argument_type == 'DocString':113            self.multiline = parsed['argument']['content']114    @property115    def text(self):116        return self.sentence117    def __str__(self):118        return '<Step: "%s">' % self.sentence119    def __repr__(self):120        return str(self)121    @property122    def container(self):123        """The background or scenario that contains this step."""124        try:125            return self.background126        except AttributeError:127            return self.scenario128    def parse_steps_from_string(self, string, **kwargs):129        """130        Parse a number of steps, returns an iterable of :class:`Step`.131        This is used by :func:`step.behave_as`.132        """133        try:134            self.scenario  # pylint:disable=pointless-statement135            container_text = \136                '%s: scenario' % self.feature.dialect.scenario_keywords[0]137            is_scenario = True138        except AttributeError:139            container_text = \140                '%s: ' % self.feature.dialect.background_keywords[0]141            is_scenario = False142        # Gherkin can't parse anything other than complete features143        feature_string = """144        # language: {feature.language}145        {feature.keyword}: feature146        {container_text}147        {string}148        """.format(149            container_text=container_text,150            feature=self.feature,151            string=string,152        )153        feature = self.feature.parse(string=feature_string,154                                     filename=self.filename)155        if is_scenario:156            return feature.scenarios[0].steps157        else:158            return feature.background.steps159    @property160    def feature(self):161        """162        The :class:`Feature` this step is a part of.163        """164        return self.container.feature165    @memoizedproperty166    def keys(self):167        """168        Return the first row of a table if this statement contains one.169        """170        if self.table:171            return tuple(self.table[0])172        else:173            return ()174    @memoizedproperty175    def hashes(self):176        """177        Return the table attached to the step as an iterable of hashes, where178        the first row - the column headings - supplies keys for all the others.179        e.g.:180        .. code-block:: gherkin181            Then I have fruit:182                | apples | oranges |183                | 0      | 2       |184        Becomes:185        .. code-block:: python186            ({187                'apples': '0',188                'oranges': '2',189            },)190        """191        if not self.table:192            return ()193        keys = self.keys194        return tuple(195            dict(zip(keys, row))196            for row in self.table[1:]197        )198    @memoizedproperty199    def max_length(self):200        """201        The max length of the feature, description and child blocks202        """203        return max(204            0,205            strings.get_terminal_width(self.represented(table=False,206                                                        multiline=False)),207            *[strings.get_terminal_width(line)208              for line in self.represent_table().splitlines()]209        )210    indent = 4211    # pylint:disable=arguments-differ212    def represented(self, table=True, multiline=True, color=str):213        """214        Render the line.215        """216        lines = [color(super().represented())]217        if table and self.table:218            lines.append(self.represent_table(cell_wrap=color))219        if multiline and self.multiline:220            lines.append(self.represent_multiline(string_wrap=color))221        return '\n'.join(lines)222    # pylint:enable=arguments-differ223    def represent_table(self, **kwargs):224        """225        Render the table.226        :param cell_wrap: color to use inside the table cells227        """228        return strings.represent_table(229            self.table, indent=self.indent + 2, **kwargs)230    def represent_multiline(self, string_wrap=str):231        """232        Render the multiline.233        :param string_wrap: color to use inside the string234        """235        indent = self.indent + 2236        lines = [' ' * indent + '"""']237        lines += [' ' * indent + string_wrap(line)238                  for line in self.multiline.splitlines()]239        lines += [' ' * indent + '"""']240        return '\n'.join(lines)241    def resolve_substitutions(self, outline):242        """243        Creates a copy of the step with any <variables> resolved.244        """245        replaced = copy(self)246        def replace_vars(string):247            """Replace all the variables in a string."""248            for key, value in outline.items():249                key = '<{key}>'.format(key=key)250                string = string.replace(key, value)251            return string252        replaced.sentence = replace_vars(self.sentence)253        if self.multiline:254            replaced.multiline = replace_vars(self.multiline)255        if self.table:256            replaced.table = tuple(257                tuple(258                    replace_vars(cell)259                    for cell in row260                )261                for row in self.table262            )263        replaced.outline = outline264        return replaced265    def step_keyword(self, kind):266        """267        An appropriate keyword for a particular kind of step268        (Given, When, Then) for the language the current step is written in.269        """270        dialect = self.feature.dialect271        keywords = {272            'given': dialect.given_keywords,273            'when': dialect.when_keywords,274            'then': dialect.then_keywords,275        }[kind]276        # Gherkin allows '*' as a keyword; skip it to be sure the keyword is277        # specifically for the given kind278        return next(279            keyword for keyword in keywords280            if not keyword.startswith('*')281        )282class StepContainer(Node):283    """A node containing steps, e.g. Feature:, Scenario:"""284    step_class = Step285    container_name = 'container'  # override in subclasses286    @property287    def feature(self):288        return self._feature289    def __init__(self, parsed, feature=None, filename=None, **kwargs):290        super().__init__(parsed, filename=filename, **kwargs)291        self._feature = feature292        # Put a reference to the parent node into all the steps293        parent_ref = {self.container_name: self}294        self.steps = tuple(295            self.step_class(step, filename=filename, **parent_ref)296            for step in parsed['steps']297        )298    indent = 2299class HeaderNode(Node):300    """A node with a header consisting of a keyword and a name."""301    name_required = True302    def __init__(self, parsed, **kwargs):303        super().__init__(parsed, **kwargs)304        self.keyword = parsed['keyword']305        self.name = parsed['name'].strip()306        if self.name_required and self.name == '':307            raise AloeSyntaxError(308                self.filename,309                "{line}:{col} {klass} must have a name".format(310                    line=self.line,311                    col=self.col,312                    klass=self.__class__.__name__))313    def __str__(self):314        return '<{klass}: "{name}">'.format(315            klass=self.__class__.__name__,316            name=self.name)317    def __repr__(self):318        return str(self)319    @property320    def text(self):321        """The text for this block."""322        return '{keyword}: {name}'.format(keyword=self.keyword,323                                          name=self.name).strip()324class TaggedNode(Node):325    """A node with attached tags."""326    def __init__(self, parsed, **kwargs):327        super().__init__(parsed, **kwargs)328        self._tags = tuple(329            tag['name'][1:] for tag in parsed['tags']330        )331    @property332    def tags(self):333        """334        Tags for a feature.335        Tags are applied to a feature using the appropriate Gherkin syntax:336        .. code-block:: gherkin337            @tag1 @tag2338            Feature: Eat leaves339        """340        return self._tags341    def represent_tags(self):342        """343        Render the tags of a tagged block.344        """345        return ' ' * self.indent + '  '.join('@%s' % tag for tag in self.tags)346class Background(HeaderNode, StepContainer):347    """The background of all :class:`Scenario` in a :class:`Feature`."""348    container_name = 'background'349    name_required = False350class Outline(OrderedDict, Node):351    """An outline within a :class:`Scenario`."""352    def __init__(self, keys, table_row, filename=None):353        """Construct the outline."""354        # Extract values355        OrderedDict.__init__(self, zip(keys, cell_values(table_row)))356        # Store the file and line information357        Node.__init__(self, table_row, filename=filename)358class Scenario(HeaderNode, TaggedNode, StepContainer):359    """A scenario within a :class:`Feature`."""360    container_name = 'scenario'361    def __init__(self, parsed, **kwargs):362        super().__init__(parsed, **kwargs)363        # Build a list of outline hashes364        # A single scenario can have multiple example blocks, the returned365        # token is a list of table tokens366        self.outlines = ()367        for example_table in parsed.get('examples', ()):368            # the first row of the table is the column headings369            keys = cell_values(example_table['tableHeader'])370            self.outlines += tuple(371                Outline(keys, row)372                for row in example_table['tableBody']373            )374    indent = 2375    def represent_outlines(self):376        """377        Render the outlines table.378        """379        return strings.represent_table(380            self.outlines_table, indent=self.indent + 2)381    @memoizedproperty382    def max_length(self):383        """384        The max horizontal length of the feature, description and child blocks.385        """386        return max(387            0,388            strings.get_terminal_width(self.represented()),389            *([step.max_length for step in self.steps]390              + [strings.get_terminal_width(line)391                 for line in self.represent_outlines().splitlines()])392        )393    @memoizedproperty394    def outlines_table(self):395        """396        Return the scenario outline examples as a table.397        """398        # get the list of column headings399        headings_dict = OrderedDict()400        for outline in self.outlines:401            headings_dict.update(outline)402        headings = list(headings_dict.keys())403        table = [headings]404        # append the data to the table405        for outline in self.outlines:406            table.append([outline.get(cell, '') for cell in headings])407        return table408    @property409    def tags(self):410        """Tags for the :attr:`feature` and the scenario."""411        return self._tags + self.feature.tags412    @property413    def evaluated(self):414        """415        Yield the outline and steps.416        """417        for outline in self.outlines:418            steps = [step.resolve_substitutions(outline)419                     for step in self.steps]420            # set a backref to the scenario421            for step in steps:422                step.scenario = self423            yield (outline, steps)424class Description(Node):425    """426    The description block of a feature.427    """428    def __init__(self, parsed, **kwargs):429        super().__init__(parsed, **kwargs)430        description = parsed.get('description', '')431        self.lines = tuple(line.strip() for line in description.split('\n'))432    def __str__(self):433        return '\n'.join(self.lines)434    def __repr__(self):435        return str(self)436    indent = 2437    def represented(self):438        return '\n'.join(439            self.represent_line(n)440            for n, _ in enumerate(self.lines)441        )442    def represent_line(self, idx):443        """444        Render the nth line in the description.445        """446        line = self.lines[idx]447        if line:448            result = ' ' * self.indent + line449        else:450            result = ''451        return result452    @memoizedproperty453    def description_at(self):454        """455        Return a tuple of lines in the string containing the description.456        """457        offset = self.line458        return tuple(offset + lineno for lineno, _459                     in enumerate(self.lines))460    @memoizedproperty461    def max_length(self):462        """463        The maximum length of all description lines.464        """465        try:466            return max(467                strings.get_terminal_width(self.represent_line(n))468                for n, _ in enumerate(self.lines)469            )470        except ValueError:471            return 0472class Feature(HeaderNode, TaggedNode):473    """474    A complete Gherkin feature.475    Features can either be constructed :func:`from_file` or476    :func:`from_string`.477    """478    background_class = Background479    scenario_class = Scenario480    background = None481    def __init__(self, parsed, filename=None, **kwargs):482        # Gherkin's top level definition is a GherkinDocument, which doesn't483        # have a location484        parsed = parsed['feature']485        super().__init__(parsed, filename=filename, **kwargs)486        self.language = parsed['language']487        self.description_node = Description(parsed, filename=filename)488        scenarios = []489        for child in parsed['children']:490            if child['type'] == 'Background':491                # Gherkin syntax disallows multiple backgrounds492                assert not self.background, "Duplicate background found."493                self.background = self.background_class(child,494                                                        filename=filename,495                                                        feature=self)496            else:497                scenarios.append(child)498        self.scenarios = tuple(499            self.scenario_class(scenario, filename=filename, feature=self)500            for scenario in scenarios501        )502    @classmethod503    def parse(cls, string=None, filename=None, language=None):504        """505        Parse either a string or a file.506        """507        parser = Parser()508        if language:509            if language == 'pt-br':510                language = 'pt'511            token_matcher = LanguageTokenMatcher(language)512        else:513            token_matcher = TokenMatcher()514        try:515            return cls(516                parser.parse(string or filename, token_matcher=token_matcher),517                filename=filename,518            )519        except ParserError as ex:520            raise AloeSyntaxError(filename, str(ex)) from ex521    @classmethod522    def from_string(cls, string, language=None):523        """524        Parse a string into a :class:`Feature`.525        """526        return cls.parse(string=string, language=language)527    @classmethod528    def from_file(cls, filename, language=None):529        """530        Parse a file or filename into a :class:`Feature`.531        """532        return cls.parse(filename=filename, language=language)533    @property534    def description(self):535        """536        The description of the feature (the text that comes directly under537        the feature).538        """539        return str(self.description_node)540    @property541    def dialect(self):542        """543        The Gherkin dialect for the feature.544        """545        return Dialect.for_name(self.language)546    @property547    def feature(self):548        """549        Convenience property for generic functions.550        """551        return self552    @memoizedproperty553    def max_length(self):554        """555        The max horizontal length of the feature, description and child blocks.556        This is used for aligning rendered output.557        """558        return max(559            0,560            strings.get_terminal_width(561                self.represented(description=False)),562            self.description_node.max_length,563            *[scenario.max_length for scenario in self.scenarios]564        )565    # pylint:disable=arguments-differ566    def represented(self, description=True):567        result = super().represented()568        if description and self.description != '':569            result += '\n'570            result += self.description_node.represented()...rebuild_industries_with_filters.py
Source:rebuild_industries_with_filters.py  
1#!/usr/bin/python32# -*- coding: UTF-8 -*-3import argparse4from utils import *5from utils_industry import *6def readIndustryIds(name):7    print(f'\n\n\n*******************\nRead Industry Id file:{name}\n')8    return readSimpleLineFile(name)9def readCategoryNameMapper(name):10    print(f'\n\n\n*******************\nRead Category name mapper file:{name}\n')11    return readPropertiesFile(name)12def readCategoryPills(name):13    print(f'\n\n\n*******************\nRead Category pills file:{name}\n')14    return readComplexFile(name)15def readSeasonal(name):16    print(f'\n\n\n*******************\nRead Seasonal file:{name}\n')17    return readPropertiesFile(name)18def readScenario(name):19    print(f'\n\n\n*******************\nRead Scenario file:{name}\n')20    return readComplexFile(name)21def readFilterElevationAmount(name):22    print(f'\n\n\n*******************\nRead Filter Elevation Amount file:{name}\n')23    return readComplexFile(name)[0]24def readSubtitles(name):25    print(f'\n\n\n*******************\nRead Subtitles file:{name}\n')26    return readPropertiesFile(name)27def readCategoryAllList(name):28    print(f'\n\n\n*******************\nRead Category all list file:{name}\n')29    return readPropertiesFile(name)30def readCarouselForAll(name):31    print(f'\n\n\n*******************\nRead carousel category for all file:{name}\n')32    return readPropertiesFile(name)33def readFilterDefault(name):34    print(f'\n\n\n*******************\nRead filter default file:{name}\n')35    return readPropertiesFileAsArray(name)36def createFilters(37        industry_id,38        index_of_industry,39        categories,40        scenario,41        seasonal,42        category_discovery_list,43        category_all_list,44        category_name_mapper,45        filter_elevation_amount,46        filterDefault47):48    print(f"\nbuild filters {index_of_industry} for {industry_id}")49    filters = []50    for display_name, search_query in filterDefault[index_of_industry].items():51        node = createDefaultFilter(display_name, search_query)52        # print(f"\t{node}")53        appendToDict(filters, node)54    for category_display_name, search_query in categories[index_of_industry].items():55        node = createCategoryNode(category_discovery_list, category_all_list, category_display_name,56                                  category_name_mapper, industry_id,57                                  search_query)58        appendToDict(filters, node)59    new_line = True60    print(f"\tseasonal: {seasonal}")61    for seasonName, iconUrl in seasonal.items():62        # print(f"\tname:{seasonName}      url:{iconUrl}")63        node = createSeasonalFilter(seasonName, iconUrl, filter_elevation_amount, new_line)64        # print(f"\t{node}")65        new_line = False66        appendToDict(filters, node)67    for seasonName, iconUrl in scenario[index_of_industry].items():68        node = createScenarioFilter(seasonName, iconUrl, filter_elevation_amount)69        # print(f"\t{node}")70        appendToDict(filters, node)71    # print(f'{filters}')72    print(*filters, sep='\n')73    return filters74def createCarousels(75        categories,76        carousel_category_all,77        industry_id,78        index_of_industry,79        category_discovery_list,80        category_all_list,81        category_name_mapper82):83    print(f"\nbuild carousels {index_of_industry} for {industry_id}")84    carousels = []85    for category_display_name, search_query in categories[index_of_industry].items():86        node = createCategoryNode(category_discovery_list, category_all_list, category_display_name,87                                  category_name_mapper, industry_id,88                                  search_query)89        appendToDict(carousels, node)90    for category_name, category_id in carousel_category_all.items():91        node = create_category_for_carousel(category_name, category_id, None)92        appendToDict(carousels, node)93    print(*carousels, sep='\n')94    return carousels95def buildIndustriesWithFilters(96        industries,97        categoryDiscoveryList,98        category_all_list,99        categoryNameMapper,100        industryIds,101        categories,102        seasonal,103        scenario,104        filterElevationAmount,105        subtitles,106        carousel_categories,107        carousel_category_all,108        filterDefault109):110    print(f'\n\n\n*******************\nbuild industries with filters file\n')111    # print(f"build {industryIds}")112    total_industries = len(industryIds)113    # print(f"total_industries: {total_industries}")114    industry_list = industries['industries']115    for index in range(total_industries):116        industry_id = industryIds[index]117        filters = createFilters(118            industry_id,119            index,120            categories,121            scenario,122            seasonal,123            categoryDiscoveryList,124            category_all_list,125            categoryNameMapper,126            filterElevationAmount,127            filterDefault128        )129        carousels = createCarousels(130            carousel_categories,131            carousel_category_all,132            industry_id,133            index,134            categoryDiscoveryList,135            category_all_list,136            categoryNameMapper137        )138        industry = industry_list[findIndustryIndex(industry_id, industry_list)]139        if industry_id in subtitles:140            industry['subtitle'] = subtitles[industry_id]141        industry['filters'] = filters142        industry['carousels'] = carousels143        industry['elevationAmount'] = 30144    return industries145def saveIndustries(industries, out):146    print(f'\n\n\n*******************\nsave industries to {out}\n')147    # print(f"\nindustries:\n{industries}\n\n\n\n\n\n")148    result = json.dumps(industries, indent=2, sort_keys=False)149    # print(f"\n\nNEW industries:\n{result}")150    try:151        with open(out, "w") as file:152            file.write(result)153    except Exception as e:154        print(e)155        raise156    finally:157        file.close()158parser = argparse.ArgumentParser(description='Test for argparse')159parser.add_argument('--industries', '-in', help='industry json file 屿§ï¼éå¿
è¦åæ°', required=False)160parser.add_argument('--industryIds', '-inid', help='industry ID file 屿§ï¼éå¿
è¦åæ°', required=False)161parser.add_argument('--categoryDiscoveryList', '-cdf', help='category discovery jons file 屿§ï¼éå¿
è¦åæ°', required=False)162parser.add_argument('--category_all_list', '-cal', help='category all list file 屿§ï¼éå¿
è¦åæ°', required=False)163parser.add_argument('--categoryNameMapper', '-cn', help='category name mapper file 屿§ï¼éå¿
è¦åæ°', required=False)164parser.add_argument('--category', '-cf', help='category filter file 屿§ï¼éå¿
è¦åæ°', required=False)165parser.add_argument('--seasonal', '-ss', help='seasonal filter file 屿§ï¼éå¿
è¦åæ°', required=False)166parser.add_argument('--scenario', '-sf', help='scenario filter file 屿§ï¼éå¿
è¦åæ°', required=False)167parser.add_argument('--filterElevationAmount', '-fea', help='filter elevation amount file 屿§ï¼éå¿
è¦åæ°', required=False)168parser.add_argument('--filter_default', '-fd', help='filter default file 屿§ï¼éå¿
è¦åæ°', required=False)169parser.add_argument('--subtitles', '-st', help='subtitles file 屿§ï¼éå¿
è¦åæ°', required=False)170parser.add_argument('--carousel_category', '-cc', help='carousel category file 屿§ï¼éå¿
è¦åæ°', required=False)171parser.add_argument('--carousel_category_all', '-cca', help='carousel category for all file 屿§ï¼éå¿
è¦åæ°', required=False)172parser.add_argument('--out', '-o', help='output json file 屿§ï¼éå¿
è¦åæ°', required=False)173args = parser.parse_args()174if __name__ == '__main__':175    try:176        specialPath = "improvement/"177        baseFilesPath = "files/"178        baseFilesSpecialPath = f"{baseFilesPath}{specialPath}"179        industries = args.industries or f"{baseFilesSpecialPath}industries.json"180        industryIds = args.industryIds or f"{baseFilesSpecialPath}industry_ids"181        subtitles = args.subtitles or f"{baseFilesSpecialPath}subtitles.properties"182        categoryDiscoveryList = args.categoryDiscoveryList or f"{baseFilesPath}categoryDiscoveryList.json"183        category_all_list = args.category_all_list or f"{baseFilesPath}category_all_list.properties"184        filtersPath = "filters/"185        filtersSpecialPath = f"filters/{specialPath}"186        filterDefault = args.filter_default or f"{filtersSpecialPath}filter_default.properties"187        category = args.category or f"{filtersSpecialPath}categories"188        seasonal = args.seasonal or f"{filtersPath}seasonal_keywords.properties"189        scenario = args.scenario or f"{filtersSpecialPath}scenario_keywords"190        categoryNameMapper = args.categoryNameMapper or f"{filtersPath}category_name_mapper.properties"191        filterElevationAmount = args.filterElevationAmount or f"{filtersPath}filter_elevation_amount"192        carouselsPath = "carousel/"193        carousel_categories = args.carousel_category or f"{carouselsPath}categories"194        carousel_category_all = args.carousel_category_all or f"{carouselsPath}category_for_all.properties"195        industries_out = args.out or f"./out/industries_{getCurrentTimestamp()}.json"196        print(f"""197        industries file: {industries}198        industryIds file: {industryIds}199        subtitles file: {subtitles}200        categoryDiscoveryList file: {categoryDiscoveryList}201        category_all_list file: {category_all_list}202     203        filter default file: {filterDefault}204        category file: {category}205        seasonal file: {seasonal}206        scenario file: {scenario}207        category name mapper file: {categoryNameMapper}208        filter elevation amount file: {filterElevationAmount}209     210        carousel category file: {carousel_categories}211        carousel category for all file: {carousel_category_all}212     213        industries output file: {industries_out}214        """)215        industries = readJson(industries)216        industryIds = readIndustryIds(industryIds)217        subtitles = readSubtitles(subtitles)218        categoryDiscoveryList = readJson(categoryDiscoveryList)219        category_all_list = readCategoryAllList(category_all_list)220        filterDefault = readFilterDefault(filterDefault)221        category = readCategoryPills(category)222        seasonal = readSeasonal(seasonal)223        scenario = readScenario(scenario)224        categoryNameMapper = readCategoryNameMapper(categoryNameMapper)225        filterElevationAmount = readFilterElevationAmount(filterElevationAmount)226        carousel_categories = readCategoryPills(carousel_categories)227        carousel_category_all = readCarouselForAll(carousel_category_all)228        industries = buildIndustriesWithFilters(229            industries,230            categoryDiscoveryList,231            category_all_list,232            categoryNameMapper,233            industryIds,234            category,235            seasonal,236            scenario,237            filterElevationAmount,238            subtitles,239            carousel_categories,240            carousel_category_all,241            filterDefault242        )243        saveIndustries(industries, industries_out)244    except Exception as e:...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
