diff --git a/test/appium/tests/base_test_case.py b/test/appium/tests/base_test_case.py index f8d9dc9faa..92b74e4fb4 100644 --- a/test/appium/tests/base_test_case.py +++ b/test/appium/tests/base_test_case.py @@ -396,35 +396,37 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase): requests_session = requests.Session() requests_session.auth = (sauce_username, sauce_access_key) try: - cls.drivers + for _, driver in cls.drivers.items(): + session_id = driver.session_id + try: + sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__) + except (RemoteDisconnected, SauceException): + pass + try: + driver.quit() + except WebDriverException: + pass + url = 'https://api.%s/rest/v1/%s/jobs/%s/assets/%s' % (apibase, sauce_username, session_id, "log.json") + try: + WebDriverWait(driver, 60, 2).until(lambda _: requests_session.get(url).status_code == 200) + commands = requests_session.get(url).json() + for command in commands: + try: + if command['message'].startswith("Started "): + for test in test_suite_data.tests: + if command['message'] == "Started %s" % test.name: + test.testruns[-1].first_commands[session_id] = commands.index(command) + 1 + except KeyError: + continue + except (RemoteDisconnected, requests.exceptions.ConnectionError): + pass except AttributeError: pass - for _, driver in cls.drivers.items(): - session_id = driver.session_id + finally: try: - sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__) - except (RemoteDisconnected, SauceException): + cls.loop.close() + except AttributeError: pass - try: - driver.quit() - except WebDriverException: - pass - url = 'https://api.%s/rest/v1/%s/jobs/%s/assets/%s' % (apibase, sauce_username, session_id, "log.json") - try: - WebDriverWait(driver, 60, 2).until(lambda _: requests_session.get(url).status_code == 200) - commands = requests_session.get(url).json() - for command in commands: - try: - if command['message'].startswith("Started "): - for test in test_suite_data.tests: - if command['message'] == "Started %s" % test.name: - test.testruns[-1].first_commands[session_id] = commands.index(command) + 1 - except KeyError: - continue - except (RemoteDisconnected, requests.exceptions.ConnectionError): - pass - if cls.loop: - cls.loop.close() for test in test_suite_data.tests: github_report.save_test(test) diff --git a/test/appium/tests/conftest.py b/test/appium/tests/conftest.py index d574249858..f860de130e 100644 --- a/test/appium/tests/conftest.py +++ b/test/appium/tests/conftest.py @@ -1,6 +1,8 @@ import os import re +import signal import urllib.request +from contextlib import contextmanager from dataclasses import dataclass from datetime import datetime from http.client import RemoteDisconnected @@ -203,21 +205,51 @@ def pytest_configure(config): description='e2e tests are running') if config.getoption('env') == 'sauce': if not is_uploaded(): + def _upload_and_check_response(apk_file_path): + @contextmanager + def _upload_time_limit(seconds): + def signal_handler(signum, frame): + raise TimeoutError("Apk upload took more than %s seconds" % seconds) + + signal.signal(signal.SIGALRM, signal_handler) + signal.alarm(seconds) + try: + yield + finally: + signal.alarm(0) + + with _upload_time_limit(600): + class UploadApkException(Exception): + pass + + with open(apk_file_path, 'rb') as f: + resp = sauce.storage._session.request('post', '/v1/storage/upload', + files={'payload': f}) + try: + if resp['item']['name'] != apk_name: + raise UploadApkException( + "Incorrect apk was uploaded to Sauce storage, response:\n%s" % resp) + except KeyError: + raise UploadApkException( + "Error when uploading apk to Sauce storage, response:\n%s" % resp) + if 'http' in config.getoption('apk'): apk_name = config.getoption('apk').split("/")[-1] # it works with just a file_name, but I've added full path because not sure how it'll behave on the remote run (Jenkins) - file_path = os.path.join(os.path.dirname(__file__), apk_name) - for _ in range(3): - try: - urllib.request.urlretrieve(config.getoption('apk'), - filename=file_path) # if url is not valid it raises an error - sauce.storage.upload(file_path) - os.remove(file_path) - break - except (ConnectionError, RemoteDisconnected): - sleep(10) + file_path, to_remove = os.path.join(os.path.dirname(__file__), apk_name), True + urllib.request.urlretrieve(config.getoption('apk'), + filename=file_path) # if url is not valid it raises an error else: - sauce.storage.upload(config.getoption('apk')) + file_path, to_remove = config.getoption('apk'), False + + for _ in range(3): + try: + _upload_and_check_response(apk_file_path=file_path) + break + except (ConnectionError, RemoteDisconnected): + sleep(10) + if to_remove: + os.remove(file_path) def pytest_unconfigure(config):