BrowserFactory.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. from baangt.base.BrowserHandling.BrowserHandling import BrowserDriver
  2. from baangt.base.ProxyRotate import ProxyRotate
  3. from baangt.base.Utils import utils
  4. import baangt.base.GlobalConstants as GC
  5. import logging
  6. from os import getcwd
  7. from time import sleep
  8. logger = logging.getLogger("pyC")
  9. class BrowserFactory:
  10. """
  11. This is a class, that holds the interface to browser-sessions.
  12. """
  13. def __init__(self, testrun):
  14. self.testrun = testrun
  15. self.rotatingProxiesService = None
  16. self.browser = {}
  17. self.browserInstances = {}
  18. self.timing = self.testrun.timing
  19. self.globalSettings = testrun.globalSettings
  20. self.browserServer = BrowserFactory.__getBrowserServer() \
  21. if self.globalSettings.get('TC.' + GC.EXECUTION_NETWORK_INFO) == True else None
  22. self.browsersMobProxies = {}
  23. self.callsPerBrowserInstance = {}
  24. self.__startRotatingProxies()
  25. def __startRotatingProxies(self):
  26. if self.globalSettings.get("TC.UseRotatingProxies"):
  27. reReadProxies = False
  28. if self.globalSettings.get("TC.ReReadProxies"):
  29. reReadProxies = True
  30. self.rotatingProxiesService = ProxyRotate(reReadProxies=reReadProxies)
  31. if self.globalSettings.get("TC.ReReadProxies"):
  32. self.rotatingProxiesService.recheckProxies(forever=True)
  33. def getBrowser(self, browserInstance=0, browserName=None, browserAttributes=None,
  34. mobileType=None, mobileApp=None, desired_app=None,
  35. mobile_app_setting=None, browserWindowSize = None):
  36. """
  37. This method is called whenever a browser instance (existing or new) is needed. If called without
  38. parameters it will create one instance of Firefox (geckodriver).
  39. if global setting TC.EXECUTION_SLOW is set, inform the browser instance about it.
  40. @param browserInstance: Number of the requested browser instance. If none is provided, always the
  41. default browser instance 0 will be returned
  42. @param browserName: one of the browser names (e.g. FF, Chrome) from GC.BROWSER*
  43. @param browserAttributes: optional Browser Attributes
  44. @return: the browser instance of base class BrowserDriver
  45. """
  46. if mobileType == 'True':
  47. logger.info(f"opening new Appium instance {browserInstance} of Appium browser {browserName}")
  48. self._getBrowserInstance(browserInstance=browserInstance)
  49. self.setBrowserProxy(browserInstance=browserInstance)
  50. if self.browsersMobProxies:
  51. browserMobProxy = self.browsersMobProxies[browserInstance]
  52. else:
  53. browserMobProxy = None
  54. self.browser[browserInstance].createNewBrowser(mobileType=mobileType,
  55. mobileApp=mobileApp,
  56. desired_app=desired_app,
  57. mobile_app_setting=mobile_app_setting,
  58. browserName=browserName,
  59. desiredCapabilities=browserAttributes,
  60. browserProxy=browserMobProxy,
  61. browserInstance=browserInstance)
  62. if self.globalSettings.get("TC." + GC.EXECUTION_SLOW):
  63. self.browser[browserInstance].slowExecutionToggle()
  64. return self.browser[browserInstance]
  65. else:
  66. lRestartBrowserSession = self.checkMaxBrowserInstanceCallsUsedToRestart(browserInstance)
  67. if self.globalSettings.get("TC.RestartBrowser") or lRestartBrowserSession:
  68. if browserInstance in self.browser.keys():
  69. logger.debug(f"Instance {browserInstance}: TC.RestartBrowser was set or Threshold-Limit for Testcases reached. Quitting old browser.")
  70. lBrowser = self.browser[browserInstance]
  71. lBrowser.closeBrowser()
  72. del self.browser[browserInstance]
  73. if browserInstance not in self.browser.keys():
  74. logger.info(f"opening new instance {browserInstance} of browser {browserName}")
  75. self._getBrowserInstance(browserInstance=browserInstance)
  76. self.setBrowserProxy(browserInstance=browserInstance)
  77. if self.browsersMobProxies: # Locale call of browserMob-Proxy
  78. browserMobProxy = self.browsersMobProxies[browserInstance]
  79. else:
  80. browserMobProxy = None
  81. randomProxy = None
  82. if self.globalSettings.get("TC.UseRotatingProxies"):
  83. # returns a Dict of ip and port
  84. randomProxy = self.rotatingProxiesService.random_proxy()
  85. self.browser[browserInstance].createNewBrowser(mobileType=mobileType,
  86. mobileApp=mobileApp,
  87. desired_app=desired_app,
  88. mobile_app_setting=mobile_app_setting,
  89. browserName=browserName,
  90. desiredCapabilities=browserAttributes,
  91. browserProxy=browserMobProxy,
  92. browserInstance=browserInstance,
  93. randomProxy=randomProxy)
  94. if self.globalSettings.get("TC." + GC.EXECUTION_SLOW):
  95. self.browser[browserInstance].slowExecutionToggle()
  96. if browserWindowSize:
  97. self.setBrowserWindowSize(self.browser[browserInstance], browserWindowSize)
  98. if self.globalSettings.get("TC." + GC.BROWSER_ZOOM_FACTOR):
  99. self.browser[browserInstance].setZoomFactor(self.globalSettings["TC." + GC.BROWSER_ZOOM_FACTOR])
  100. else:
  101. logger.debug(f"Using existing instance of browser {browserInstance}")
  102. return self.browser[browserInstance]
  103. def checkMaxBrowserInstanceCallsUsedToRestart(self, browserInstance):
  104. """
  105. for each browserInstance we record how often it was used by a testcase.
  106. If there's a Number n RestartBrowserAfter Global parameter and we're higher than that,
  107. we restart the browser.
  108. :param browserInstance:
  109. :return:
  110. """
  111. lRestartBrowserSession = False
  112. self.callsPerBrowserInstance[browserInstance] = self.callsPerBrowserInstance.get(browserInstance, 0) + 1
  113. if self.callsPerBrowserInstance[browserInstance] > int(
  114. self.globalSettings.get("TC.RestartBrowserAfter", 99999999)):
  115. lRestartBrowserSession = True
  116. logger.debug(f"Reached threshold for browser restart in instance {browserInstance}. Restarting Browser.")
  117. self.callsPerBrowserInstance[browserInstance] = 0
  118. return lRestartBrowserSession
  119. @staticmethod
  120. def setBrowserWindowSize(lBrowserInstance: BrowserDriver, browserWindowSize):
  121. lBrowserInstance.setBrowserWindowSize(browserWindowSize)
  122. def _getBrowserInstance(self, browserInstance):
  123. if self.testrun.classesForObjects.browserHandling:
  124. lClass = utils.dynamicImportOfClasses(fullQualifiedImportName=self.testrun.classesForObjects.browserHandling)
  125. self.browser[browserInstance] = lClass(timing=self.timing)
  126. else:
  127. # !Sic: code duplication for convenince reasons. Pure Duck-Typing would prevent where-used-list to work.
  128. self.browser[browserInstance] = BrowserDriver(timing=self.timing)
  129. @staticmethod
  130. def __getBrowserServer():
  131. from browsermobproxy import Server
  132. server = Server(getcwd() + GC.BROWSER_PROXY_PATH)
  133. logger.info("Starting browsermob proxy")
  134. server.start()
  135. return server
  136. def setBrowserProxy(self, browserInstance):
  137. sleep(1)
  138. proxy = self.browserServer.create_proxy() if self.browserServer else None
  139. if not proxy:
  140. return
  141. sleep(1)
  142. self.browsersMobProxies[browserInstance] = proxy
  143. def teardown(self):
  144. network_info = {}
  145. if not self.globalSettings.get("TC." + GC.EXECUTION_DONTCLOSEBROWSER):
  146. for browserInstance in self.browser.keys():
  147. self.browser[browserInstance].closeBrowser()
  148. elif self.globalSettings.get("TC." + GC.EXECUTION_DONTCLOSEBROWSER) == "False":
  149. for browserInstance in self.browser.keys():
  150. self.browser[browserInstance].closeBrowser()
  151. if self.browserServer:
  152. network_info = [info.har if info else {} for info in self.browsersMobProxies.values()]
  153. self.browserServer.stop()
  154. return network_info