e2e: setup and teardown with shared drivers
This commit is contained in:
parent
2c23ab4c5d
commit
b18d7b6a2a
|
@ -1,6 +1,6 @@
|
|||
[pytest]
|
||||
norecursedirs = .git views
|
||||
addopts = -s -v --tb=line --junitxml=result.xml
|
||||
addopts = -s -v --tb=line --junitxml=result.xml --dist loadgroup -n 5
|
||||
junit_family=legacy
|
||||
markers =
|
||||
critical: TCs by priority
|
||||
|
|
|
@ -30,9 +30,9 @@ pycryptodome==3.9.9
|
|||
pyethash==0.1.27
|
||||
pyparsing==2.4.7
|
||||
pysha3==1.0.2
|
||||
pytest==6.1.2
|
||||
pytest==6.2.0
|
||||
pytest-forked==1.3.0
|
||||
pytest-xdist==2.2.0
|
||||
pytest-xdist==2.5.0
|
||||
python-dateutil==2.8.1
|
||||
pytz==2020.4
|
||||
PyYAML==5.4
|
||||
|
|
|
@ -1,26 +1,35 @@
|
|||
import emoji
|
||||
import random
|
||||
from dateutil import parser
|
||||
from tests import marks
|
||||
from tests.base_test_case import MultipleDeviceTestCase, SingleDeviceTestCase
|
||||
from views.sign_in_view import SignInView
|
||||
from datetime import timedelta
|
||||
from time import sleep
|
||||
|
||||
import emoji
|
||||
import pytest
|
||||
from dateutil import parser
|
||||
|
||||
class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
||||
from tests import marks
|
||||
from tests.base_test_case import MultipleDeviceTestCase, SingleDeviceTestCase, create_shared_drivers, \
|
||||
MultipleSharedDeviceTestCase
|
||||
from views.home_view import HomeView
|
||||
from views.sign_in_view import SignInView
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="public_chat")
|
||||
class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.drivers, cls.loop = create_shared_drivers(2)
|
||||
device_1, device_2 = SignInView(cls.drivers[0]), SignInView(cls.drivers[1])
|
||||
home_1, home_2 = device_1.create_user(), device_2.create_user()
|
||||
profile_1 = home_1.profile_button.click()
|
||||
cls.username_1 = profile_1.default_username_text.text
|
||||
profile_1.home_button.click()
|
||||
home_2.home_button.click()
|
||||
|
||||
@marks.testrail_id(5313)
|
||||
@marks.critical
|
||||
def test_public_chat_messaging_emojis_timestamps(self):
|
||||
self.create_drivers(2)
|
||||
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
||||
home_1, home_2 = device_1.create_user(), device_2.create_user()
|
||||
profile_1 = home_1.profile_button.click()
|
||||
default_username_1 = profile_1.default_username_text.text
|
||||
profile_1.home_button.click()
|
||||
home_2.home_button.click()
|
||||
|
||||
home_1, home_2 = HomeView(self.drivers[0]), HomeView(self.drivers[1])
|
||||
home_1.just_fyi("Check preselected chats, redirect to status chat")
|
||||
home_1.plus_button.click_until_presence_of_element(home_1.join_public_chat_button)
|
||||
home_1.join_public_chat_button.click()
|
||||
|
@ -50,8 +59,8 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
|||
if timestamp not in sent_time_variants:
|
||||
self.errors.append(
|
||||
"Timestamp is not shown, expected '%s', in fact '%s'" % (sent_time_variants.join(','), timestamp))
|
||||
if chat_2.chat_element_by_text(message).username.text != default_username_1:
|
||||
self.errors.append("Default username '%s' is not shown next to the received message" % default_username_1)
|
||||
if chat_2.chat_element_by_text(message).username.text != self.username_1:
|
||||
self.errors.append("Default username '%s' is not shown next to the received message" % self.username_1)
|
||||
|
||||
chat_1.send_message(emoji_message)
|
||||
for chat in chat_1, chat_2:
|
||||
|
@ -63,13 +72,11 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
|||
@marks.testrail_id(5360)
|
||||
@marks.critical
|
||||
def test_unread_messages_counter_public_chat(self):
|
||||
self.create_drivers(2)
|
||||
driver_2 = self.drivers[1]
|
||||
home_1, home_2 = SignInView(self.drivers[0]).create_user(), SignInView(self.drivers[1]).create_user()
|
||||
profile_1 = home_1.profile_button.click()
|
||||
username_1 = profile_1.default_username_text.text
|
||||
profile_1.home_button.click()
|
||||
|
||||
home_1, home_2 = HomeView(self.drivers[0]), HomeView(self.drivers[1])
|
||||
home_1.get_back_to_home_view()
|
||||
home_2.get_back_to_home_view()
|
||||
home_1.home_button.click()
|
||||
home_2.home_button.click()
|
||||
chat_name = home_1.get_random_chat_name()
|
||||
chat_1, chat_2 = home_1.join_public_chat(chat_name), home_2.join_public_chat(chat_name)
|
||||
chat_1.send_message('пиу')
|
||||
|
@ -87,7 +94,7 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
|||
|
||||
home_1.just_fyi("Check unread message counter when mentioned in public chat")
|
||||
chat_2 = home_2.get_chat_view()
|
||||
chat_2.select_mention_from_suggestion_list(username_1, username_1[:2])
|
||||
chat_2.select_mention_from_suggestion_list(self.username_1, self.username_1[:2])
|
||||
chat_2.send_message_button.click()
|
||||
chat_element.new_messages_counter.wait_for_element(30)
|
||||
chat_element.new_messages_counter.wait_for_element_text("1", 60)
|
||||
|
@ -104,6 +111,7 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
|||
chat_2.chat_element_by_text(message_2).wait_for_element(20)
|
||||
|
||||
home_2.just_fyi("Check that unread message indicator is not reappeared after relogin")
|
||||
driver_2 = self.drivers[1]
|
||||
driver_2.close_app()
|
||||
driver_2.launch_app()
|
||||
SignInView(driver_2).sign_in()
|
||||
|
@ -112,6 +120,9 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
|||
self.errors.append('New messages counter is shown after relogin')
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
|
||||
class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
|
||||
|
||||
@marks.testrail_id(6270)
|
||||
@marks.medium
|
||||
def test_mark_all_messages_as_read_public_chat(self):
|
||||
|
|
|
@ -19,47 +19,89 @@ from tests import test_suite_data, start_threads, appium_container, pytest_confi
|
|||
import base64
|
||||
from re import findall
|
||||
|
||||
sauce_username = environ.get('SAUCE_USERNAME')
|
||||
|
||||
|
||||
sauce_access_key = environ.get('SAUCE_ACCESS_KEY')
|
||||
|
||||
executor_sauce_lab = 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (sauce_username, sauce_access_key)
|
||||
|
||||
executor_local = 'http://localhost:4723/wd/hub'
|
||||
|
||||
implicit_wait = 5
|
||||
|
||||
|
||||
def get_capabilities_local():
|
||||
desired_caps = dict()
|
||||
if pytest_config_global['docker']:
|
||||
# apk is in shared volume directory
|
||||
apk = '/root/shared_volume/%s' % pytest_config_global['apk']
|
||||
else:
|
||||
apk = pytest_config_global['apk']
|
||||
desired_caps['app'] = apk
|
||||
desired_caps['deviceName'] = 'nexus_5'
|
||||
desired_caps['platformName'] = 'Android'
|
||||
desired_caps['appiumVersion'] = '1.9.1'
|
||||
desired_caps['platformVersion'] = '10.0'
|
||||
desired_caps['newCommandTimeout'] = 600
|
||||
desired_caps['fullReset'] = False
|
||||
desired_caps['unicodeKeyboard'] = True
|
||||
desired_caps['automationName'] = 'UiAutomator2'
|
||||
desired_caps['setWebContentDebuggingEnabled'] = True
|
||||
return desired_caps
|
||||
|
||||
|
||||
def add_local_devices_to_capabilities():
|
||||
updated_capabilities = list()
|
||||
raw_out = re.split(r'[\r\\n]+', str(subprocess.check_output(['adb', 'devices'])).rstrip())
|
||||
for line in raw_out[1:]:
|
||||
serial = re.findall(r"(([\d.\d:]*\d+)|\bemulator-\d+)", line)
|
||||
if serial:
|
||||
capabilities = get_capabilities_local()
|
||||
capabilities['udid'] = serial[0][0]
|
||||
updated_capabilities.append(capabilities)
|
||||
return updated_capabilities
|
||||
|
||||
|
||||
def get_capabilities_sauce_lab():
|
||||
desired_caps = dict()
|
||||
desired_caps['app'] = 'sauce-storage:' + test_suite_data.apk_name
|
||||
|
||||
desired_caps['build'] = pytest_config_global['build']
|
||||
desired_caps['name'] = test_suite_data.current_test.name
|
||||
desired_caps['platformName'] = 'Android'
|
||||
desired_caps['appiumVersion'] = '1.18.1'
|
||||
desired_caps['platformVersion'] = '10.0'
|
||||
desired_caps['deviceName'] = 'Android GoogleAPI Emulator'
|
||||
desired_caps['deviceOrientation'] = "portrait"
|
||||
desired_caps['commandTimeout'] = 600
|
||||
desired_caps['idleTimeout'] = 600
|
||||
desired_caps['unicodeKeyboard'] = True
|
||||
desired_caps['automationName'] = 'UiAutomator2'
|
||||
desired_caps['setWebContentDebuggingEnabled'] = True
|
||||
desired_caps['ignoreUnimportantViews'] = False
|
||||
desired_caps['enableNotificationListener'] = True
|
||||
desired_caps['maxDuration'] = 1800
|
||||
return desired_caps
|
||||
|
||||
|
||||
def update_capabilities_sauce_lab(new_capabilities: dict):
|
||||
caps = get_capabilities_sauce_lab().copy()
|
||||
caps.update(new_capabilities)
|
||||
return caps
|
||||
|
||||
|
||||
class AbstractTestCase:
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@property
|
||||
def sauce_username(self):
|
||||
return environ.get('SAUCE_USERNAME')
|
||||
|
||||
@property
|
||||
def sauce_access_key(self):
|
||||
return environ.get('SAUCE_ACCESS_KEY')
|
||||
|
||||
@property
|
||||
def executor_sauce_lab(self):
|
||||
return 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (self.sauce_username, self.sauce_access_key)
|
||||
|
||||
@property
|
||||
def executor_local(self):
|
||||
return 'http://localhost:4723/wd/hub'
|
||||
|
||||
@staticmethod
|
||||
def print_sauce_lab_info(driver):
|
||||
def print_sauce_lab_info(self, driver):
|
||||
sys.stdout = sys.stderr
|
||||
print("SauceOnDemandSessionID=%s job-name=%s" % (driver.session_id,
|
||||
pytest_config_global['build']))
|
||||
|
||||
@staticmethod
|
||||
def get_translation_by_key(key):
|
||||
def get_translation_by_key(self, key):
|
||||
return transl[key]
|
||||
|
||||
def add_local_devices_to_capabilities(self):
|
||||
updated_capabilities = list()
|
||||
raw_out = re.split(r'[\r\\n]+', str(subprocess.check_output(['adb', 'devices'])).rstrip())
|
||||
for line in raw_out[1:]:
|
||||
serial = re.findall(r"(([\d.\d:]*\d+)|\bemulator-\d+)", line)
|
||||
if serial:
|
||||
capabilities = self.capabilities_local
|
||||
capabilities['udid'] = serial[0][0]
|
||||
updated_capabilities.append(capabilities)
|
||||
return updated_capabilities
|
||||
|
||||
@property
|
||||
def app_path(self):
|
||||
app_path = '/storage/emulated/0/Android/data/im.status.ethereum.pr/files/Download/' if findall(r'pr\d\d\d\d\d',
|
||||
|
@ -71,53 +113,6 @@ class AbstractTestCase:
|
|||
def geth_path(self):
|
||||
return self.app_path + 'geth.log'
|
||||
|
||||
@property
|
||||
def capabilities_sauce_lab(self):
|
||||
desired_caps = dict()
|
||||
desired_caps['app'] = 'sauce-storage:' + test_suite_data.apk_name
|
||||
|
||||
desired_caps['build'] = pytest_config_global['build']
|
||||
desired_caps['name'] = test_suite_data.current_test.name
|
||||
desired_caps['platformName'] = 'Android'
|
||||
desired_caps['appiumVersion'] = '1.18.1'
|
||||
desired_caps['platformVersion'] = '10.0'
|
||||
desired_caps['deviceName'] = 'Android GoogleAPI Emulator'
|
||||
desired_caps['deviceOrientation'] = "portrait"
|
||||
desired_caps['commandTimeout'] = 600
|
||||
desired_caps['idleTimeout'] = 600
|
||||
desired_caps['unicodeKeyboard'] = True
|
||||
desired_caps['automationName'] = 'UiAutomator2'
|
||||
desired_caps['setWebContentDebuggingEnabled'] = True
|
||||
desired_caps['ignoreUnimportantViews'] = False
|
||||
desired_caps['enableNotificationListener'] = True
|
||||
desired_caps['maxDuration'] = 1800
|
||||
return desired_caps
|
||||
|
||||
def update_capabilities_sauce_lab(self, new_capabilities: dict):
|
||||
caps = self.capabilities_sauce_lab.copy()
|
||||
caps.update(new_capabilities)
|
||||
return caps
|
||||
|
||||
@property
|
||||
def capabilities_local(self):
|
||||
desired_caps = dict()
|
||||
if pytest_config_global['docker']:
|
||||
# apk is in shared volume directory
|
||||
apk = '/root/shared_volume/%s' % pytest_config_global['apk']
|
||||
else:
|
||||
apk = pytest_config_global['apk']
|
||||
desired_caps['app'] = apk
|
||||
desired_caps['deviceName'] = 'nexus_5'
|
||||
desired_caps['platformName'] = 'Android'
|
||||
desired_caps['appiumVersion'] = '1.9.1'
|
||||
desired_caps['platformVersion'] = pytest_config_global['platform_version']
|
||||
desired_caps['newCommandTimeout'] = 600
|
||||
desired_caps['fullReset'] = False
|
||||
desired_caps['unicodeKeyboard'] = True
|
||||
desired_caps['automationName'] = 'UiAutomator2'
|
||||
desired_caps['setWebContentDebuggingEnabled'] = True
|
||||
return desired_caps
|
||||
|
||||
@abstractmethod
|
||||
def setup_method(self, method):
|
||||
raise NotImplementedError('Should be overridden from a child class')
|
||||
|
@ -130,10 +125,6 @@ class AbstractTestCase:
|
|||
def environment(self):
|
||||
return pytest_config_global['env']
|
||||
|
||||
@property
|
||||
def implicitly_wait(self):
|
||||
return 5
|
||||
|
||||
network_api = NetworkApi()
|
||||
github_report = GithubHtmlReport()
|
||||
|
||||
|
@ -197,13 +188,13 @@ class SingleDeviceTestCase(AbstractTestCase):
|
|||
appium_container.start_appium_container(pytest_config_global['docker_shared_volume'])
|
||||
appium_container.connect_device(pytest_config_global['device_ip'])
|
||||
|
||||
(executor, capabilities) = (self.executor_sauce_lab, self.capabilities_sauce_lab) if \
|
||||
self.environment == 'sauce' else (self.executor_local, self.capabilities_local)
|
||||
(executor, capabilities) = (executor_sauce_lab, get_capabilities_sauce_lab()) if \
|
||||
self.environment == 'sauce' else (executor_local, get_capabilities_local())
|
||||
for key, value in kwargs.items():
|
||||
capabilities[key] = value
|
||||
self.driver = Driver(executor, capabilities)
|
||||
test_suite_data.current_test.testruns[-1].jobs[self.driver.session_id] = 1
|
||||
self.driver.implicitly_wait(self.implicitly_wait)
|
||||
self.driver.implicitly_wait(implicit_wait)
|
||||
self.errors = Errors()
|
||||
|
||||
if pytest_config_global['docker']:
|
||||
|
@ -241,7 +232,7 @@ class LocalMultipleDeviceTestCase(AbstractTestCase):
|
|||
def teardown_method(self, method):
|
||||
for driver in self.drivers:
|
||||
try:
|
||||
self.add_alert_text_to_report(driver)
|
||||
self.add_alert_text_to_report(self.drivers[driver])
|
||||
self.drivers[driver].quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
@ -263,12 +254,12 @@ class SauceMultipleDeviceTestCase(AbstractTestCase):
|
|||
self.drivers = self.loop.run_until_complete(start_threads(quantity,
|
||||
Driver,
|
||||
self.drivers,
|
||||
self.executor_sauce_lab,
|
||||
self.update_capabilities_sauce_lab(capabilities)))
|
||||
executor_sauce_lab,
|
||||
update_capabilities_sauce_lab(capabilities)))
|
||||
for driver in range(quantity):
|
||||
test_suite_data.current_test.testruns[-1].jobs[self.drivers[driver].session_id] = driver + 1
|
||||
self.drivers[driver].implicitly_wait(
|
||||
custom_implicitly_wait if custom_implicitly_wait else self.implicitly_wait)
|
||||
custom_implicitly_wait if custom_implicitly_wait else implicit_wait)
|
||||
|
||||
def teardown_method(self, method):
|
||||
geth_names, geth_contents = [], []
|
||||
|
@ -290,10 +281,97 @@ class SauceMultipleDeviceTestCase(AbstractTestCase):
|
|||
cls.loop.close()
|
||||
|
||||
|
||||
def create_shared_drivers(quantity):
|
||||
drivers = dict()
|
||||
if pytest_config_global['env'] == 'local':
|
||||
capabilities = add_local_devices_to_capabilities()
|
||||
for i in range(quantity):
|
||||
driver = Driver(executor_local, capabilities[i])
|
||||
test_suite_data.current_test.testruns[-1].jobs[driver.session_id] = i + 1
|
||||
driver.implicitly_wait(implicit_wait)
|
||||
drivers[i] = driver
|
||||
loop = None
|
||||
else:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
capabilities = {'maxDuration': 1800}
|
||||
drivers = loop.run_until_complete(start_threads(quantity,
|
||||
Driver,
|
||||
drivers,
|
||||
executor_sauce_lab,
|
||||
update_capabilities_sauce_lab(capabilities)))
|
||||
for i in range(quantity):
|
||||
test_suite_data.current_test.testruns[-1].jobs[drivers[i].session_id] = i + 1
|
||||
drivers[i].implicitly_wait(implicit_wait)
|
||||
return drivers, loop
|
||||
|
||||
|
||||
class LocalSharedMultipleDeviceTestCase(AbstractTestCase):
|
||||
|
||||
def setup_method(self, method):
|
||||
jobs = test_suite_data.current_test.testruns[-1].jobs
|
||||
if not jobs:
|
||||
for index, driver in self.drivers.items():
|
||||
jobs[driver.session_id] = index + 1
|
||||
self.errors = Errors()
|
||||
|
||||
def teardown_method(self, method):
|
||||
for driver in self.drivers:
|
||||
try:
|
||||
self.add_alert_text_to_report(self.drivers[driver])
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
for driver in cls.drivers:
|
||||
try:
|
||||
cls.drivers[driver].quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
|
||||
|
||||
class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
|
||||
|
||||
def setup_method(self, method):
|
||||
jobs = test_suite_data.current_test.testruns[-1].jobs
|
||||
if not jobs:
|
||||
for index, driver in self.drivers.items():
|
||||
jobs[driver.session_id] = index + 1
|
||||
self.errors = Errors()
|
||||
|
||||
def teardown_method(self, method):
|
||||
geth_names, geth_contents = [], []
|
||||
for driver in self.drivers:
|
||||
try:
|
||||
self.print_sauce_lab_info(self.drivers[driver])
|
||||
self.add_alert_text_to_report(self.drivers[driver])
|
||||
geth_names.append(
|
||||
'%s_geth%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
|
||||
geth_contents.append(self.pull_geth(self.drivers[driver]))
|
||||
|
||||
except (WebDriverException, AttributeError):
|
||||
pass
|
||||
finally:
|
||||
geth = {geth_names[i]: geth_contents[i] for i in range(len(geth_names))}
|
||||
self.github_report.save_test(test_suite_data.current_test, geth)
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
for driver in cls.drivers:
|
||||
try:
|
||||
cls.drivers[driver].quit()
|
||||
except WebDriverException:
|
||||
pass
|
||||
cls.loop.close()
|
||||
|
||||
|
||||
if pytest_config_global['env'] == 'local':
|
||||
MultipleDeviceTestCase = LocalMultipleDeviceTestCase
|
||||
MultipleSharedDeviceTestCase = LocalSharedMultipleDeviceTestCase
|
||||
else:
|
||||
MultipleDeviceTestCase = SauceMultipleDeviceTestCase
|
||||
MultipleSharedDeviceTestCase = SauceSharedMultipleDeviceTestCase
|
||||
|
||||
|
||||
class NoDeviceTestCase(AbstractTestCase):
|
||||
|
|
|
@ -282,7 +282,8 @@ def pytest_runtest_protocol(item, nextitem):
|
|||
for i in range(rerun_count):
|
||||
reports = runtestprotocol(item, nextitem=nextitem)
|
||||
for report in reports:
|
||||
if report.failed and should_rerun_test(report.longreprtext):
|
||||
is_in_group = [i for i in item.iter_markers(name='xdist_group')]
|
||||
if report.failed and should_rerun_test(report.longreprtext) and not is_in_group:
|
||||
break # rerun
|
||||
else:
|
||||
return True # no need to rerun
|
||||
|
|
Loading…
Reference in New Issue