TestCaseMaster.py 8.5 KB

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