TestCaseMaster.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from baangt.base import GlobalConstants as GC
  2. from baangt.base.Timing.Timing import Timing
  3. from baangt.TestSteps.Exceptions import *
  4. from baangt.base.RuntimeStatistics import Statistic
  5. from baangt.base.Utils import utils
  6. class TestCaseMaster:
  7. def __init__(self, executeDirect=True, **kwargs):
  8. self.name = None
  9. self.description = None
  10. self.testSteps = {}
  11. self.apiInstance = None
  12. self.numberOfParallelRuns = None
  13. self.statistic = Statistic()
  14. self.kwargs = kwargs
  15. self.timing = Timing() # Use own instance of the timing class, so that we can record timing also in
  16. # parallel runs.
  17. self.testRunInstance = kwargs.get(GC.KWARGS_TESTRUNINSTANCE)
  18. self.testRunUtils = self.testRunInstance.testRunUtils
  19. self.testSequence = self.testRunUtils.getSequenceByNumber(testRunName=self.testRunInstance.testRunName,
  20. sequence=kwargs.get(GC.STRUCTURE_TESTCASESEQUENCE))
  21. self.testCaseSettings = self.testRunUtils.getTestCaseByNumber(self.testSequence,
  22. kwargs.get(GC.STRUCTURE_TESTCASE))
  23. self.testSteps = self.testCaseSettings[2][GC.STRUCTURE_TESTSTEP]
  24. self.testCaseType = self.testCaseSettings[1][GC.KWARGS_TESTCASETYPE]
  25. self.sequenceNumber = self.kwargs.get(GC.KWARGS_SEQUENCENUMBER)
  26. # In Unit-Tests this is a problem. When we run within the main loop of TestRun we are expected to directly
  27. # execute on __init__.
  28. if executeDirect:
  29. try:
  30. self.executeTestCase()
  31. except Exception as e:
  32. logger.warning(f"Uncought exception {e}")
  33. utils.traceback(exception_in=e)
  34. self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS_STOPERROR] = True
  35. self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS] = GC.TESTCASESTATUS_ERROR
  36. def executeTestCase(self):
  37. self.timingName = self.timing.takeTime(self.__class__.__name__, forceNew=True)
  38. if self.testCaseType == GC.KWARGS_BROWSER:
  39. self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS] = GC.TESTCASESTATUS_SUCCESS # We believe in a good outcome
  40. self.__getBrowserForTestCase()
  41. elif self.testCaseType == GC.KWARGS_API_SESSION:
  42. # FIXME: For now we're using session_number always = 1. We need to be able to run e.g. 10 sessions with
  43. # FIXME: Parallel API-Test.
  44. self.apiInstance = self.testRunInstance.getAPI()
  45. self.kwargs[GC.KWARGS_API_SESSION] = self.apiInstance
  46. # For API-Tests we assume status = Passed and actively set it to error if not.
  47. self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS] = GC.TESTCASESTATUS_SUCCESS
  48. self.execute()
  49. self.tearDown()
  50. def __getBrowserForTestCase(self):
  51. logger.info(f"Settings for this TestCase: {str(self.testCaseSettings)[0:100]}")
  52. self.browserType = self.testCaseSettings[1][GC.KWARGS_BROWSER].upper()
  53. self.browserSettings = self.testCaseSettings[1][GC.BROWSER_ATTRIBUTES]
  54. self.mobileType = self.testCaseSettings[1].get(GC.KWARGS_MOBILE)
  55. self.mobileApp = self.testCaseSettings[1].get(GC.KWARGS_MOBILE_APP)
  56. browserWindowSize = self.testCaseSettings[1].get(GC.BROWSER_WINDOW_SIZE)
  57. self.mobile_desired_app = {}
  58. self.mobile_app_setting = {}
  59. if self.mobileType:
  60. self.mobile_desired_app[GC.MOBILE_PLATFORM_NAME] = self.testCaseSettings[1][GC.MOBILE_PLATFORM_NAME]
  61. self.mobile_desired_app[GC.MOBILE_DEVICE_NAME] = self.testCaseSettings[1][GC.MOBILE_DEVICE_NAME]
  62. self.mobile_desired_app[GC.MOBILE_PLATFORM_VERSION] = self.testCaseSettings[1][GC.MOBILE_PLATFORM_VERSION]
  63. self.mobile_app_setting[GC.MOBILE_APP_URL] = self.testCaseSettings[1][GC.MOBILE_APP_URL]
  64. self.mobile_app_setting[GC.MOBILE_APP_PACKAGE] = self.testCaseSettings[1][GC.MOBILE_APP_PACKAGE]
  65. self.mobile_app_setting[GC.MOBILE_APP_ACTIVITY] = self.testCaseSettings[1][GC.MOBILE_APP_ACTIVITY]
  66. self.browser = self.testRunInstance.getBrowser(browserInstance=self.sequenceNumber,
  67. browserName=self.browserType,
  68. browserAttributes=self.browserSettings,
  69. mobileType=self.mobileType,
  70. mobileApp=self.mobileApp,
  71. desired_app=self.mobile_desired_app,
  72. mobile_app_setting=self.mobile_app_setting,
  73. browserWindowSize=browserWindowSize)
  74. self.kwargs[GC.KWARGS_BROWSER] = self.browser
  75. def execute(self):
  76. # Save timing Class from Testrun for later:
  77. lTestRunTiming = self.kwargs[GC.KWARGS_TIMING]
  78. # Replace Timing class with current, local timing class:
  79. self.kwargs[GC.KWARGS_TIMING] = self.timing
  80. # Get all the TestSteps for the global loop, that are kept within this TestCase:
  81. lTestStepClasses = {}
  82. for testStepSequenceNumer, testStep in enumerate(self.testSteps.keys(), start=1):
  83. if self.testSteps[testStep][0]["TestStepClass"]:
  84. lTestStepClasses[testStepSequenceNumer] = self.testSteps[testStep][0]["TestStepClass"]
  85. try:
  86. self.testRunInstance.executeDictSequenceOfClasses(lTestStepClasses, GC.STRUCTURE_TESTSTEP, **self.kwargs)
  87. except baangtTestStepException as e:
  88. self.kwargs[GC.KWARGS_DATA][GC.TESTCASEERRORLOG] += '\n' + "Exception-Text: " + str(e)
  89. self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS] = GC.TESTCASESTATUS_ERROR
  90. finally:
  91. self._finalizeTestCase()
  92. # Switch back to global Timing class:
  93. self.kwargs[GC.KWARGS_TIMING] = lTestRunTiming
  94. def _finalizeTestCase(self):
  95. tcData = self.kwargs[GC.KWARGS_DATA]
  96. tcData[GC.TIMING_DURATION] = self.timing.takeTime(self.timingName) # Write the End-Record for this Testcase
  97. tcData[GC.TIMELOG] = self.timing.returnTime()
  98. self.timing.resetTime(self.timingName)
  99. def _checkAndSetTestcaseStatusIfFailExpected(self):
  100. """
  101. If this Testcase is supposed to fail and failed, he's actually successful.
  102. If this Testcase is supposed to fail and doesn't, he's actually failed.
  103. @return: Directly sets the Testcasestatus accordingly.
  104. """
  105. tcData = self.kwargs[GC.KWARGS_DATA]
  106. if tcData.get(GC.TESTCASE_EXPECTED_ERROR_FIELD) == 'X':
  107. if tcData[GC.TESTCASESTATUS] == GC.TESTCASESTATUS_ERROR:
  108. tcData[GC.TESTCASESTATUS] = GC.TESTCASESTATUS_SUCCESS
  109. elif tcData[GC.TESTCASESTATUS] == GC.TESTCASESTATUS_SUCCESS:
  110. tcData[GC.TESTCASESTATUS] = GC.TESTCASESTATUS_ERROR
  111. def tearDown(self):
  112. data = self.kwargs[GC.KWARGS_DATA]
  113. # If TestcaseErrorlog is not empty, the testcase status should be error.
  114. if data[GC.TESTCASEERRORLOG]:
  115. data[GC.TESTCASESTATUS] = GC.TESTCASESTATUS_ERROR
  116. if self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS] == GC.TESTCASESTATUS_ERROR:
  117. # Try taking a Screenshot
  118. if self.testCaseType == GC.KWARGS_BROWSER:
  119. lShot = self.browser.takeScreenshot()
  120. if lShot: # Otherwise browser was already closed. Nothing we can do...
  121. lShot = lShot.strip()
  122. if data[GC.SCREENSHOTS]:
  123. if isinstance(data[GC.SCREENSHOTS], str):
  124. # From where does this come, damn it?!
  125. data[GC.SCREENSHOTS] = [lShot, data[GC.SCREENSHOTS]]
  126. pass
  127. else:
  128. data[GC.SCREENSHOTS].extend([lShot])
  129. else:
  130. data[GC.SCREENSHOTS] = [lShot]
  131. # If Testcase-Status was not set, we'll set error. Shouldn't happen anyways.
  132. if not self.kwargs[GC.KWARGS_DATA][GC.TESTCASESTATUS]:
  133. data[GC.TESTCASESTATUS] = GC.TESTCASESTATUS_ERROR
  134. data[GC.TESTCASEERRORLOG] += "\nTestcase had not status - setting error"
  135. logger.critical("Testcase had no status - setting error")
  136. self._checkAndSetTestcaseStatusIfFailExpected()
  137. if data[GC.TESTCASESTATUS] == GC.TESTCASESTATUS_SUCCESS:
  138. self.statistic.update_success()
  139. elif data[GC.TESTCASESTATUS] == GC.TESTCASESTATUS_ERROR:
  140. self.statistic.update_error()
  141. elif data[GC.TESTCASESTATUS] == GC.TESTCASESTATUS_WAITING:
  142. self.statistic.update_waiting()
  143. logger.info(
  144. f"Testcase {self.kwargs.get(GC.STRUCTURE_TESTSTEP, '')} finished with status: {data[GC.TESTCASESTATUS]}")