From 3343bc675eec38d836c37283c18ba99280e0a5a6 Mon Sep 17 00:00:00 2001 From: Vladimir Druzhinin <128374224+StateOf-Vlado@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:26:05 +0200 Subject: [PATCH] Fix AUT AttachError (#180) * Fix AUT AttachError #174 * Test close by port * Method to add a screenshot on fail added for multiple instances AUT #177 --- test/e2e/configs/squish.py | 1 - test/e2e/conftest.py | 9 +---- test/e2e/driver/aut.py | 69 +++++++++++++++++++++++++------------- test/e2e/driver/server.py | 12 +++---- 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/test/e2e/configs/squish.py b/test/e2e/configs/squish.py index f0179c5d24..df1b8bd2de 100644 --- a/test/e2e/configs/squish.py +++ b/test/e2e/configs/squish.py @@ -1,3 +1,2 @@ AUT_PORT = 61500 -MAX_INSTANCES = 3 SERVET_PORT = 4322 diff --git a/test/e2e/conftest.py b/test/e2e/conftest.py index 5f482aeef4..6aebc0c625 100644 --- a/test/e2e/conftest.py +++ b/test/e2e/conftest.py @@ -62,12 +62,5 @@ def pytest_exception_interact(node): name='Screenshot on fail', body=screenshot.read_bytes(), attachment_type=allure.attachment_type.PNG) - driver.context.detach() - # The maximum count of multiple instances in tests now is 3 - max_instances = configs.squish.MAX_INSTANCES - for port in range(configs.squish.AUT_PORT, configs.squish.AUT_PORT + (max_instances * 1000), 1000): - pid = local_system.find_process_by_port(port) - if pid is not None: - local_system.kill_process(pid, verify=True) except Exception as ex: - _logger.debug(ex) + _logger.debug(ex) \ No newline at end of file diff --git a/test/e2e/driver/aut.py b/test/e2e/driver/aut.py index 27bdd558a0..cf31d92fdf 100644 --- a/test/e2e/driver/aut.py +++ b/test/e2e/driver/aut.py @@ -3,6 +3,7 @@ from datetime import datetime import allure import squish +from PIL import ImageGrab import configs import driver @@ -18,16 +19,13 @@ class AUT: def __init__( self, app_path: system_path.SystemPath = configs.APP_DIR, - host: str = '127.0.0.1', - port: int = local_system.find_free_port(configs.squish.AUT_PORT, 1000), user_data: SystemPath = None ): super(AUT, self).__init__() self.path = app_path - self.host = host - self.port = int(port) self.ctx = None self.pid = None + self.port = None self.aut_id = f'AUT_{datetime.now():%H%M%S}' self.app_data = configs.testpath.STATUS_DATA / f'app_{datetime.now():%H%M%S_%f}' if user_data is not None: @@ -40,7 +38,14 @@ class AUT: def __enter__(self): return self.launch() - def __exit__(self, *args): + def __exit__(self, exc_type, exc_value, traceback): + if exc_type: + screenshot = configs.testpath.RUN / 'screenshot.png' + if screenshot.exists(): + screenshot = configs.testpath.RUN / f'screenshot_{datetime.now():%H%M%S}.png' + ImageGrab.grab().save(screenshot) + allure.attach( + name='Screenshot on fail', body=screenshot.read_bytes(), attachment_type=allure.attachment_type.PNG) self.detach().stop() @allure.step('Attach Squish to Test Application') @@ -64,30 +69,46 @@ class AUT: @allure.step('Close application') def stop(self): - local_system.kill_process(self.pid, verify=True) + if self.pid is not None: + local_system.kill_process(self.pid, verify=True) + self.pid = None + if self.port is not None: + assert driver.waitFor(lambda: local_system.find_process_by_port(self.port) is None, + configs.timeouts.PROCESS_TIMEOUT_SEC), \ + f'Port {self.port} still in use by process: {local_system.find_process_by_port(self.port)}' + self.port = None @allure.step("Start application") - def launch(self, ) -> 'AUT': - SquishServer().set_aut_timeout() + def launch(self, attempt: int = 2) -> 'AUT': + try: + self.port = local_system.find_free_port(configs.squish.AUT_PORT, 1000) + SquishServer().set_aut_timeout() + if configs.ATTACH_MODE: + SquishServer().add_attachable_aut(self.aut_id, self.port) + command = [ + configs.testpath.SQUISH_DIR / 'bin' / 'startaut', + f'--port={self.port}', + f'"{self.path}"', + f'-d={self.app_data}' + ] + local_system.execute(command) + else: + SquishServer().add_executable_aut(self.aut_id, self.path.parent) + command = [self.aut_id, f'-d={self.app_data}'] + self.ctx = squish.startApplication(' '.join(command), configs.timeouts.PROCESS_TIMEOUT_SEC) - if configs.ATTACH_MODE: - SquishServer().add_attachable_aut(self.aut_id, self.port) - command = [ - configs.testpath.SQUISH_DIR / 'bin' / 'startaut', - f'--port={self.port}', - f'"{self.path}"', - f'-d={self.app_data}' - ] - local_system.execute(command) self.attach() - else: - SquishServer().add_executable_aut(self.aut_id, self.path.parent) - command = [self.aut_id, f'-d={self.app_data}'] - self.ctx = squish.startApplication(' '.join(command), configs.timeouts.PROCESS_TIMEOUT_SEC) + self.pid = self.ctx.pid + assert squish.waitFor(lambda: self.ctx.isRunning, configs.timeouts.PROCESS_TIMEOUT_SEC) + return self + except AssertionError as err: + _logger.debug(err) + if attempt: + self.detach().stop() + return self.launch(attempt-1) + else: + raise err - self.pid = self.ctx.pid - assert squish.waitFor(lambda: self.ctx.isRunning, configs.timeouts.PROCESS_TIMEOUT_SEC) - return self @allure.step('Restart application') def restart(self): diff --git a/test/e2e/driver/server.py b/test/e2e/driver/server.py index 2e3a298ce8..ee8d45ef0a 100644 --- a/test/e2e/driver/server.py +++ b/test/e2e/driver/server.py @@ -11,18 +11,15 @@ _logger = logging.getLogger(__name__) class SquishServer: - def __init__( - self, - host: str = '127.0.0.1', - port: int = local_system.find_free_port(configs.squish.SERVET_PORT, 100) - ): + def __init__(self): self.path = configs.testpath.SQUISH_DIR / 'bin' / 'squishserver' self.config = configs.testpath.ROOT / 'squish_server.ini' - self.host = host - self.port = port + self.host = '127.0.0.1' + self.port = None self.pid = None def start(self): + self.port = local_system.find_free_port(configs.squish.SERVET_PORT, 100) cmd = [ f'"{self.path}"', '--configfile', str(self.config), @@ -35,6 +32,7 @@ class SquishServer: if self.pid is not None: local_system.kill_process(self.pid, verify=True) self.pid = None + self.port = None # https://doc-snapshots.qt.io/squish/cli-squishserver.html def configuring(self, action: str, options: typing.Union[int, str, list]):