e2e: configurable datacenter

This commit is contained in:
Churikova Tetiana 2022-11-03 12:26:53 +01:00
parent f17f57cc5e
commit add00a5609
No known key found for this signature in database
GPG Key ID: 0D4EA7B33B47E6D8
8 changed files with 125 additions and 47 deletions

View File

@ -7,7 +7,7 @@ from sauceclient import SauceException
import re
from support.test_data import SingleTestData
from tests.cloudbase_test_api import sauce, apibase
class BaseTestReport:
TEST_REPORT_DIR = "%s/../report" % os.path.dirname(os.path.abspath(__file__))
@ -102,7 +102,7 @@ class BaseTestReport:
def get_sauce_job_url(self, job_id, first_command=0):
token = self.get_sauce_token(job_id)
url = 'https://eu-central-1.saucelabs.com/jobs/%s?auth=%s' % (job_id, token)
url = 'https://%s/jobs/%s?auth=%s' % (apibase, job_id, token)
if first_command > 0:
url += "#%s" % first_command
return url
@ -114,11 +114,10 @@ class BaseTestReport:
def get_sauce_final_screenshot_url(self, job_id):
token = self.get_sauce_token(job_id)
from tests.cloudbase_test_api import sauce
for _ in range(10):
try:
scr_number = sauce.jobs.get_job_assets(job_id)['screenshots'][-1]
return 'https://assets.eu-central-1.saucelabs.com/jobs/%s/%s?auth=%s' % (job_id, scr_number, token)
return 'https://assets.%s/jobs/%s/%s?auth=%s' % (apibase, job_id, scr_number, token)
except SauceException:
time.sleep(3)

View File

@ -310,8 +310,12 @@ class TestrailReport(BaseTestReport):
return None
def get_not_executed_tests(self, test_run_id):
results = self.get("get_tests/%s&status_id=3" % test_run_id)
return [result['case_id'] for result in results["tests"]]
try:
results = self.get("get_tests/%s&status_id=3" % test_run_id)
return [result['case_id'] for result in results["tests"]]
except KeyError:
print('Cannot extract result for %s' % test_run_id)
pass
@staticmethod
def make_error_with_gh_issue_link(error, issue_id):

View File

@ -1,4 +1,5 @@
import asyncio
import base64
import logging
import re
import subprocess
@ -6,6 +7,7 @@ import sys
from abc import ABCMeta, abstractmethod
from http.client import RemoteDisconnected
from os import environ
from re import findall
import pytest
import requests
@ -16,21 +18,18 @@ from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.support.wait import WebDriverWait
from tests import transl
from tests.conftest import option
from support.api.network_api import NetworkApi
from support.github_report import GithubHtmlReport
from tests import test_suite_data, start_threads, appium_container, pytest_config_global
import base64
from re import findall
from tests.cloudbase_test_api import sauce
from tests import transl
from tests.cloudbase_test_api import sauce, apibase
sauce_username = environ.get('SAUCE_USERNAME')
sauce_access_key = environ.get('SAUCE_ACCESS_KEY')
executor_sauce_lab = 'https://%s:%s@ondemand.eu-central-1.saucelabs.com:443/wd/hub' % (sauce_username, sauce_access_key)
executor_sauce_lab = 'https://%s:%s@ondemand.%s:443/wd/hub' % (sauce_username, sauce_access_key, apibase)
executor_local = 'http://localhost:4723/wd/hub'
@ -303,6 +302,7 @@ def create_shared_drivers(quantity):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
capabilities = {'maxDuration': 3600}
print('SC Executor: %s' % executor_sauce_lab)
drivers = loop.run_until_complete(start_threads(quantity,
Driver,
drivers,
@ -397,7 +397,10 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
driver.quit()
except WebDriverException:
pass
url = 'https://eu-central-1.saucelabs.com/rest/v1/%s/jobs/%s/assets/%s' % (sauce_username, session_id, "log.json")
if option.datacenter == 'eu-central-1':
url = 'https://eu-central-1.saucelabs.com/rest/v1/%s/jobs/%s/assets/%s' % (sauce_username, session_id, "log.json")
else:
url = sauce.jobs.get_job_asset_url(job_id=session_id, filename="log.json")
WebDriverWait(driver, 60, 2).until(lambda _: requests_session.get(url).status_code == 200)
commands = requests_session.get(url).json()
for command in commands:

View File

@ -6,6 +6,8 @@ from time import sleep
from sauceclient import SauceClient, SauceException
from tests.conftest import option
try:
import http.client as http_client
from urllib.parse import urlencode
@ -18,7 +20,12 @@ sauce_username = environ.get('SAUCE_USERNAME')
sauce_access_key = environ.get('SAUCE_ACCESS_KEY')
sauce = SauceClient(sauce_username, sauce_access_key)
apibase = 'eu-central-1.saucelabs.com'
if option.datacenter == 'us-west-1':
apibase = 'saucelabs.com'
elif option.datacenter == 'eu-central-1':
apibase = 'eu-central-1.saucelabs.com'
else:
raise NotImplementedError("Unknown SauceLabs datacenter")
def request(method, url, body=None, content_type='application/json'):
@ -34,9 +41,11 @@ def request(method, url, body=None, content_type='application/json'):
response.status, response.reason), response=response)
return json.loads(data.decode('utf-8'))
sauce.request = request
def upload_from_url(apk_path = str()):
def upload_from_url(apk_path=str()):
response = requests.get(apk_path, stream=True)
response.raise_for_status()
apk_name = apk_path.split("/")[-1]
@ -44,7 +53,7 @@ def upload_from_url(apk_path = str()):
del response
for _ in range(3):
try:
requests.post('https://eu-central-1.saucelabs.com/rest/v1/storage/'
requests.post('https://' + apibase + '/rest/v1/storage/'
+ sauce_username + '/' + apk_name + '?overwrite=true',
auth=(sauce_username, sauce_access_key),
data=file,

View File

@ -1,31 +1,26 @@
import time
import requests
import pytest
import re
from _pytest.runner import runtestprotocol
from dataclasses import dataclass
from datetime import datetime
from http.client import RemoteDisconnected
from os import environ
import pytest
from _pytest.runner import runtestprotocol
from sauceclient import SauceClient, SauceException
import tests
from support.device_stats_db import DeviceStatsDB
from support.test_rerun import should_rerun_test
from tests import test_suite_data, appium_container
from datetime import datetime
from os import environ
from io import BytesIO
from sauceclient import SauceClient, SauceException
import tests.cloudbase_test_api
from support.api.network_api import NetworkApi
from support.github_report import GithubHtmlReport
from support.testrail_report import TestrailReport
from tests.users import transaction_senders
import tests
# from support.testrail_report import TestrailReport
#
# testrail_report = TestrailReport()
sauce_username = environ.get('SAUCE_USERNAME')
sauce_access_key = environ.get('SAUCE_ACCESS_KEY')
github_token = environ.get('GIT_HUB_TOKEN')
sauce = SauceClient(sauce_username, sauce_access_key)
github_report = GithubHtmlReport()
testrail_report = TestrailReport()
def pytest_addoption(parser):
@ -41,6 +36,10 @@ def pytest_addoption(parser):
action='store',
default='sauce',
help='Specify environment: local/sauce/api')
parser.addoption('--datacenter',
action='store',
default='eu-central-1',
help='For sauce only: us-west-1, eu-central-1')
parser.addoption('--platform_version',
action='store',
default='8.0',
@ -139,18 +138,37 @@ def pytest_addoption(parser):
help='Database name for device stats db')
@dataclass
class Option:
datacenter: str = None
option = Option()
testrail_report = None
github_report = None
def is_master(config):
return not hasattr(config, 'workerinput')
def is_uploaded():
stored_files = tests.cloudbase_test_api.sauce.storage.get_stored_files()
from tests.cloudbase_test_api import sauce
stored_files = sauce.storage.get_stored_files()
for i in range(len(stored_files['files'])):
if stored_files['files'][i]['name'] == test_suite_data.apk_name:
return True
def pytest_configure(config):
global option
option = config.option
from support.testrail_report import TestrailReport
global testrail_report
testrail_report = TestrailReport()
from support.github_report import GithubHtmlReport
global github_report
github_report = GithubHtmlReport()
tests.pytest_config_global = vars(config.option)
config.addinivalue_line("markers", "testrail_id(name): empty")
if config.getoption('log_steps'):
@ -176,10 +194,11 @@ def pytest_configure(config):
description='e2e tests are running')
if config.getoption('env') == 'sauce':
if not is_uploaded():
from tests.cloudbase_test_api import sauce, upload_from_url
if 'http' in config.getoption('apk'):
tests.cloudbase_test_api.upload_from_url(config.getoption('apk'))
upload_from_url(config.getoption('apk'))
else:
tests.cloudbase_test_api.sauce.storage.upload_file(config.getoption('apk'))
sauce.storage.upload_file(config.getoption('apk'))
def pytest_unconfigure(config):
@ -251,7 +270,8 @@ def pytest_runtest_makereport(item, call):
report.passed)
if error:
test_suite_data.current_test.testruns[-1].error = final_error
github_report.save_test(test_suite_data.current_test)
from support.github_report import GithubHtmlReport
GithubHtmlReport().save_test(test_suite_data.current_test)
if report.when == 'call':
current_test = test_suite_data.current_test
@ -290,9 +310,10 @@ def pytest_runtest_makereport(item, call):
def update_sauce_jobs(test_name, job_ids, passed):
from tests.cloudbase_test_api import sauce
for job_id in job_ids.keys():
try:
tests.cloudbase_test_api.sauce.jobs.update_job(job_id, name=test_name, passed=passed)
sauce.jobs.update_job(job_id, name=test_name, passed=passed)
except (RemoteDisconnected, SauceException):
pass

View File

@ -328,6 +328,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@marks.testrail_id(695843)
# moved without edit
def test_1_1_chat_text_message_edit_delete_push_disappear(self):
self.device_2.just_fyi(
"Device 1 sends text message and edits it in 1-1 chat. Device2 checks edited message is shown")
@ -1218,7 +1219,7 @@ class TestEnsStickersMultipleDevicesMerged(MultipleSharedDeviceTestCase):
@pytest.mark.xdist_group(name="one_2")
@marks.new_ui_critical
class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase):
def prepare_devices(self):
self.drivers, self.loop = create_shared_drivers(2)
@ -1227,6 +1228,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
self.home_2 = self.device_2.create_user(enable_notifications=True)
self.profile_1 = self.home_1.get_profile_view()
self.public_key_1, self.default_username_1 = self.home_1.get_public_key_and_username(return_username=True)
self.profile_1.switch_push_notifications()
self.public_key_2, self.default_username_2 = self.home_2.get_public_key_and_username(return_username=True)
self.profile_1.chats_tab.click()
self.chat_1 = self.home_1.add_contact(self.public_key_2)
@ -1271,13 +1273,10 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
self.chat_2.just_fyi("Send messages with non-latin symbols")
messages = ['hello', '¿Cómo estás tu año?', 'ё, доброго вечерочка', '® æ ç ♥']
for message in messages:
self.chat_2.send_message(message)
[self.chat_2.send_message(message) for message in messages]
if not self.chat_1.chat_message_input.is_element_displayed():
self.chat_1.click_system_back_button_until_element_is_shown()
self.home_1.get_chat(self.default_username_2).click()
for message in messages:
if not self.chat_1.chat_element_by_text(message).is_element_displayed():
self.errors.append("Message with test '%s' was not received" % message)
@ -1287,7 +1286,6 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
sent_time_variants = self.chat_2.convert_device_time_to_chat_timestamp()
if timestamp not in sent_time_variants:
self.errors.append('Timestamp on message %s does not correspond expected [%s]' % (timestamp, *sent_time_variants))
for message in [messages[1], messages[2]]:
if self.chat_2.chat_element_by_text(message).member_photo.is_element_displayed():
self.errors.append('%s is not stack to 1st(they are sent in less than 5 minutes)!' % message)
@ -1314,3 +1312,41 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
if self.chat_2.chat_element_by_text(message).member_photo.is_element_differs_from_template("member.png", diff=5):
self.errors.append("Image of user in 1-1 chat is too different from template!")
self.errors.verify_no_errors()
@marks.testrail_id(702733)
def test_1_1_chat_text_message_delete_push_disappear(self):
if not self.chat_1.chat_message_input.is_element_displayed():
self.home_1.get_chat(self.default_username_2).click()
self.device_2.just_fyi("Verify Device1 can not edit and delete received message from Device2")
message_after_edit_1_1 = 'smth I should edit'
self.chat_2.send_message(message_after_edit_1_1)
chat_1_element = self.chat_1.chat_element_by_text(message_after_edit_1_1)
chat_1_element.long_press_element()
for action in ("edit", "delete-for-everyone"):
if self.chat_1.element_by_translation_id(action).is_element_displayed():
self.errors.append('Option to %s someone else message available!' % action)
self.home_1.click_system_back_button()
self.device_2.just_fyi("Delete message for everyone and check it is not shown in chat preview on home")
self.chat_2.delete_message_in_chat(message_after_edit_1_1)
for chat in (self.chat_2, self.chat_1):
if chat.chat_element_by_text(message_after_edit_1_1).is_element_displayed(30):
self.errors.append("Deleted message is shown in chat view for 1-1 chat")
self.chat_1.click_system_back_button_until_element_is_shown()
if self.home_1.element_by_text(message_after_edit_1_1).is_element_displayed(30):
self.errors.append("Deleted message is shown on chat element on home screen")
self.device_2.just_fyi("Send one more message and check that PN will be deleted with message deletion")
message_to_delete = 'DELETE ME'
self.home_1.put_app_to_background()
self.chat_2.send_message(message_to_delete)
self.home_1.open_notification_bar()
if not self.home_1.get_pn(message_to_delete):
self.errors.append("Push notification doesn't appear")
self.chat_2.delete_message_in_chat(message_to_delete)
pn_to_disappear = self.home_1.get_pn(message_to_delete)
if pn_to_disappear:
if not pn_to_disappear.is_element_disappeared(30):
self.errors.append("Push notification was not removed after initial message deletion")
self.errors.verify_no_errors()

View File

@ -847,10 +847,11 @@ class ChatView(BaseView):
self.chat_message_input.send_keys(message_to_update)
self.send_message_button.click()
def delete_message_in_chat(self, message):
def delete_message_in_chat(self, message, everyone=True):
self.driver.info("Looking for message '%s' to delete it" % message)
self.element_by_text_part(message).long_press_element()
self.element_by_translation_id("delete").click()
for_everyone, for_me = self.element_by_translation_id("delete-for-everyone"), self.element_by_translation_id("delete-for-me")
for_everyone.click() if everyone else for_me.click()
def copy_message_text(self, message_text):
self.driver.info("Copying '%s' message via long press" % message_text)

View File

@ -372,6 +372,11 @@ class ProfileView(BaseView):
chat.confirm_until_presence_of_element(self.add_new_contact_button)
self.click_system_back_button_until_element_is_shown()
def switch_push_notifications(self):
self.driver.info("Enabling push notifications via Profile")
self.profile_notifications_button.scroll_and_click()
self.profile_notifications_toggle_button.click()
self.click_system_back_button_until_element_is_shown()
def add_custom_network(self, rpc_url: str, name: str, symbol: str, netwrok_id:str):
self.driver.info("## Add custom network", device=False)