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!!