Added screenshots for failed tests and device number to errors

Signed-off-by: yevh-berdnyk <ie.berdnyk@gmail.com>
This commit is contained in:
yevh-berdnyk 2018-08-15 15:51:52 +03:00
parent 4ddb9d582a
commit a22d13fd80
No known key found for this signature in database
GPG Key ID: E9B425FDFC4DEA9C
23 changed files with 177 additions and 159 deletions

View File

@ -1,7 +1,7 @@
import logging
import pytest
import requests
import time
from tests import info
class NetworkApi:
@ -39,7 +39,7 @@ class NetworkApi:
transactions = self.get_transactions(address=address)
for transaction in transactions:
if transaction['hash'] == transaction_hash:
info('Transaction is found in Ropsten network')
logging.info('Transaction is found in Ropsten network')
return
pytest.fail('Transaction is not found in Ropsten network')
@ -57,11 +57,12 @@ class NetworkApi:
transactions = self.get_token_transaction(address=address)
else:
transactions = self.get_transactions(address=address)
info('Looking for a transaction with unique amount %s in list of transactions, address is %s' %
logging.info('Looking for a transaction with unique amount %s in list of transactions, address is %s' %
(amount, address))
for transaction in transactions:
if float(int(transaction['value']) / 10 ** decimals) == float(amount):
info('Transaction with unique amount %s is found in list of transactions, address is %s' %
logging.info(
'Transaction with unique amount %s is found in list of transactions, address is %s' %
(amount, address))
return transaction
@ -82,9 +83,9 @@ class NetworkApi:
elif initial_balance == self.get_balance(recipient_address):
counter += 10
time.sleep(10)
info('Waiting %s seconds for funds' % counter)
logging.info('Waiting %s seconds for funds' % counter)
else:
info('Transaction is received')
logging.info('Transaction is received')
return
def verify_balance_is(self, expected_balance: int, recipient_address: str, errors: list):
@ -106,9 +107,9 @@ class NetworkApi:
elif self.get_balance(address) == initial_balance:
counter += 10
time.sleep(10)
info('Waiting %s seconds for donation' % counter)
logging.info('Waiting %s seconds for donation' % counter)
else:
info('Got %s for %s' % (response["amount_eth"], address))
logging.info('Got %s for %s' % (response["amount_eth"], address))
return
def start_chat_bot(self, chat_name: str, messages_number: int, interval: int = 1) -> list:

View File

@ -1,12 +1,14 @@
import time
import json
import hmac
import os
from hashlib import md5
from sauceclient import SauceException
from support.test_data import SingleTestData
class BaseTestReport:
TEST_REPORT_DIR = "%s/../report" % os.path.dirname(os.path.abspath(__file__))
def __init__(self, sauce_username, sauce_access_key):
@ -67,10 +69,23 @@ class BaseTestReport:
passed.append(test)
return passed
def get_sauce_job_url(self, job_id):
token = hmac.new(bytes(self.sauce_username + ":" + self.sauce_access_key, 'latin-1'),
def get_sauce_token(self, job_id):
return hmac.new(bytes(self.sauce_username + ":" + self.sauce_access_key, 'latin-1'),
bytes(job_id, 'latin-1'), md5).hexdigest()
return "https://saucelabs.com/jobs/%s?auth=%s" % (job_id, token)
def get_sauce_job_url(self, job_id):
token = self.get_sauce_token(job_id)
return 'https://saucelabs.com/jobs/%s?auth=%s' % (job_id, token)
def get_sauce_final_screenshot_url(self, job_id):
token = self.get_sauce_token(job_id)
from tests.conftest import sauce
for _ in range(10):
try:
scr_number = sauce.jobs.get_job_assets(job_id)['screenshots'][-1]
return 'https://assets.saucelabs.com/jobs/%s/%s?auth=%s' % (job_id, scr_number, token)
except SauceException:
time.sleep(3)
@staticmethod
def is_test_successful(test):

View File

@ -1,10 +1,9 @@
import logging
from selenium.common.exceptions import WebDriverException
from tests import info
def start_web_browser(driver):
info('Start web browser')
logging.info('Start web browser')
try:
driver.start_activity('org.chromium.webview_shell', 'WebViewBrowserActivity')
except WebDriverException:

View File

@ -3,7 +3,6 @@ from support.base_test_report import BaseTestReport
class GithubHtmlReport(BaseTestReport):
TEST_REPORT_DIR = "%s/../report" % os.path.dirname(os.path.abspath(__file__))
def __init__(self, sauce_username, sauce_access_key):
@ -53,7 +52,7 @@ class GithubHtmlReport(BaseTestReport):
return html
def build_test_row_html(self, index, test):
html = "<tr><td><b>%d. %s</b></td></tr>" % (index+1, test.name)
html = "<tr><td><b>%d. %s</b></td></tr>" % (index + 1, test.name)
html += "<tr><td>"
test_steps_html = list()
last_testrun = test.testruns[-1]
@ -70,15 +69,18 @@ class GithubHtmlReport(BaseTestReport):
html += "<code>%s</code>" % last_testrun.error
html += "<br/><br/>"
if last_testrun.jobs:
html += self.build_device_sessions_html(last_testrun.jobs)
html += self.build_device_sessions_html(last_testrun.jobs, last_testrun)
html += "</td></tr>"
return html
def build_device_sessions_html(self, jobs):
html = "<ins>Device sessions:</ins>"
def build_device_sessions_html(self, jobs, test_run):
html = "<ins>Device sessions</ins>"
html += "<p><ul>"
for i, job_id in enumerate(jobs):
html += "<li><a href=\"%s\">Device %d</a></li>" % (self.get_sauce_job_url(job_id), i+1)
for job_id, i in jobs.items():
html += "Device %d:" % i
html += "<p><ul>"
html += "<li><a href=\"%s\">Steps, video, logs</a></li>" % self.get_sauce_job_url(job_id)
if test_run.error:
html += "<li><a href=\"%s\">Failure screenshot</a></li>" % self.get_sauce_final_screenshot_url(job_id)
html += "</ul></p>"
return html

View File

@ -13,7 +13,7 @@ class SingleTestData(object):
self.error = error
def create_new_testrun(self):
self.testruns.append(SingleTestData.TestRunData(list(), list(), None))
self.testruns.append(SingleTestData.TestRunData(list(), dict(), None))
class TestSuiteData(object):

View File

@ -19,12 +19,6 @@ def get_current_time():
return datetime.now().strftime('%-m%-d%-H%-M%-S')
def info(text: str):
if "Base" not in text:
logging.info(text)
test_suite_data.current_test.testruns[-1].steps.append(text)
def debug(text: str):
logging.debug(text)

View File

@ -56,14 +56,13 @@ class TestSignInOffline(MultipleDeviceTestCase):
@marks.testrail_id(1432)
def test_offline_login(self):
self.create_drivers(1, offline_mode=True)
driver = self.drivers[0]
sign_in = SignInView(driver)
sign_in = SignInView(self.drivers[0])
sign_in.create_user()
driver.close_app()
driver.set_network_connection(1) # airplane mode
sign_in.driver.close_app()
sign_in.driver.set_network_connection(1) # airplane mode
driver.launch_app()
sign_in.driver.launch_app()
sign_in.accept_agreements()
home = sign_in.sign_in()
home.home_button.wait_for_visibility_of_element()

View File

@ -162,7 +162,7 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
chat_2.chat_message_input.send_keys(message)
chat_2.send_message_button.click()
self.drivers[1].quit()
chat_2.driver.quit()
chat_element = chat_1.chat_element_by_text(message)
chat_element.find_element()

View File

@ -328,7 +328,7 @@ class TestCommandsMultipleDevices(MultipleDeviceTestCase):
chat_2 = home_2.get_chat_with_user(sender['username']).click()
self.network_api.wait_for_confirmation_of_transaction(recipient['address'], amount)
if not chat_2.chat_element_by_text(amount).contains_text('Confirmed', 60):
pytest.fail('Transaction state is not updated on the recipient side')
chat_2.driver.fail('Transaction state is not updated on the recipient side')
@marks.chat

View File

@ -35,22 +35,21 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
@marks.smoke_1
def test_offline_messaging_1_1_chat(self):
self.create_drivers(2, offline_mode=True)
device_1, device_2 = self.drivers[0], self.drivers[1]
sign_in_1, sign_in_2 = SignInView(device_1), SignInView(device_2)
sign_in_1, sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
username_2 = 'user_2'
home_1, home_2 = sign_in_1.create_user(), sign_in_2.create_user(username=username_2)
public_key_1 = home_1.get_public_key()
home_1.home_button.click()
device_1.set_network_connection(1) # airplane mode on primary device
home_1.driver.set_network_connection(1) # airplane mode on primary device
chat_2 = home_2.add_contact(public_key_1)
message_1 = 'test message'
chat_2.chat_message_input.send_keys(message_1)
chat_2.send_message_button.click()
device_2.set_network_connection(1) # airplane mode on secondary device
chat_2.driver.set_network_connection(1) # airplane mode on secondary device
device_1.set_network_connection(2) # turning on WiFi connection on primary device
home_1.driver.set_network_connection(2) # turning on WiFi connection on primary device
home_1.connection_status.wait_for_invisibility_of_element(20)
chat_element = home_1.get_chat_with_user(username_2)
@ -58,15 +57,15 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
chat_1 = chat_element.click()
chat_1.chat_element_by_text(message_1).wait_for_visibility_of_element(2)
device_2.set_network_connection(2) # turning on WiFi connection on secondary device
device_1.set_network_connection(1) # airplane mode on primary device
chat_2.driver.set_network_connection(2) # turning on WiFi connection on secondary device
home_1.driver.set_network_connection(1) # airplane mode on primary device
chat_2.element_by_text('Connecting to peers...').wait_for_invisibility_of_element(60)
message_2 = 'one more message'
chat_2.chat_message_input.send_keys(message_2)
chat_2.send_message_button.click()
device_1.set_network_connection(2) # turning on WiFi connection on primary device
home_1.driver.set_network_connection(2) # turning on WiFi connection on primary device
chat_1 = chat_element.click()
chat_1.chat_element_by_text(message_2).wait_for_visibility_of_element(180)
@ -75,14 +74,13 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
@marks.testrail_id(3701)
def test_resend_message_offline(self):
self.create_drivers(2, offline_mode=True)
device_1, device_2 = self.drivers[0], self.drivers[1]
sign_in_1, sign_in_2 = SignInView(device_1), SignInView(device_2)
sign_in_1, sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
username_1 = 'user_%s' % get_current_time()
home_1, home_2 = sign_in_1.create_user(username_1), sign_in_2.create_user()
public_key_2 = home_2.get_public_key()
home_2.home_button.click()
device_1.set_network_connection(1) # airplane mode on primary device
home_1.driver.set_network_connection(1) # airplane mode on primary device
chat_1 = home_1.add_contact(public_key_2)
message = 'test message'
@ -92,7 +90,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
if not 5 < progress_time < 30:
self.errors.append('Progress indicator is shown during %s seconds' % progress_time)
device_1.set_network_connection(2) # turning on WiFi connection
home_1.driver.set_network_connection(2) # turning on WiFi connection
chat_1.element_by_text('Connecting to peers...').wait_for_invisibility_of_element(30)
chat_1.element_by_text('Not sent. Tap for options').click()
if not chat_1.element_by_text('Delete message').is_element_displayed():
@ -114,12 +112,9 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
@marks.smoke_1
def test_messaging_in_different_networks(self):
self.create_drivers(2)
device_1, device_2 = self.drivers[0], self.drivers[1]
sign_in_1, sign_in_2 = SignInView(device_1), SignInView(device_2)
sign_in_1, sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
username_1 = 'user_%s' % get_current_time()
sign_in_1.create_user(username_1)
sign_in_2.create_user()
home_1, home_2 = sign_in_1.get_home_view(), sign_in_2.get_home_view()
home_1, home_2 = sign_in_1.create_user(username_1), sign_in_2.create_user()
public_key_2 = home_2.get_public_key()
profile_2 = home_2.get_profile_view()
profile_2.switch_network('Mainnet with upstream RPC')
@ -266,8 +261,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
@marks.smoke_1
def test_offline_status(self):
self.create_drivers(1, offline_mode=True)
driver = self.drivers[0]
sign_in = SignInView(driver)
sign_in = SignInView(self.drivers[0])
home_view = sign_in.create_user()
# Dismiss "Welcome to Status" placeholder.
@ -275,7 +269,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
wallet_view = home_view.wallet_button.click()
wallet_view.home_button.click()
driver.set_network_connection(1) # airplane mode
sign_in.driver.set_network_connection(1) # airplane mode
if home_view.connection_status.text != 'Offline':
self.errors.append('Offline status is not shown in home screen')
@ -405,8 +399,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
@marks.testrail_id(2781)
def test_timestamp_in_chats(self):
self.create_drivers(2)
device_1, device_2 = self.drivers[0], self.drivers[1]
sign_in_1, sign_in_2 = SignInView(device_1), SignInView(device_2)
sign_in_1, sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
username_1 = 'user_%s' % get_current_time()
device_1_home, device_2_home = sign_in_1.create_user(username=username_1), sign_in_2.create_user()
device_2_public_key = device_2_home.get_public_key()
@ -417,7 +410,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
message = 'test text'
device_1_chat.chat_message_input.send_keys(message)
device_1_chat.send_message_button.click()
sent_time = datetime.strptime(device_1.device_time, '%a %b %d %H:%M:%S GMT %Y').strftime("%I:%M %p")
sent_time = datetime.strptime(device_1_chat.driver.device_time, '%a %b %d %H:%M:%S GMT %Y').strftime("%I:%M %p")
if not device_1_chat.chat_element_by_text(message).contains_text(sent_time):
self.errors.append('Timestamp is not displayed in 1-1 chat for the sender')
if device_1_chat.chat_element_by_text(message).member_photo.is_element_displayed():
@ -437,7 +430,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
device_2_chat.chat_message_input.send_keys(message)
device_2_chat.send_message_button.click()
sent_time = datetime.strptime(device_2.device_time, '%a %b %d %H:%M:%S GMT %Y').strftime("%I:%M %p")
sent_time = datetime.strptime(device_2_chat.driver.device_time, '%a %b %d %H:%M:%S GMT %Y').strftime("%I:%M %p")
if not device_2_chat.chat_element_by_text(message).contains_text(sent_time):
self.errors.append('Timestamp is not displayed in public chat for the sender')
if device_2_chat.chat_element_by_text(message).member_photo.is_element_displayed():

View File

@ -61,13 +61,14 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
chat_1.element_by_text(message_3).is_element_present()
for message in message_1, message_2:
if chat_1.element_starts_with_text(message).is_element_present():
pytest.fail("Message '%s' is shown, but public chat history has been cleared" % message)
chat_1.driver.fail("Message '%s' is shown, but public chat history has been cleared" % message)
home_1 = chat_1.get_back_to_home_view()
home_1.relogin()
home_1.element_by_text('#' + chat_name).click()
for message in message_1, message_2:
if chat_1.element_starts_with_text(message).is_element_present():
pytest.fail("Message '%s' is shown after re-login, but public chat history has been cleared" % message)
chat_1.driver.fail(
"Message '%s' is shown after re-login, but public chat history has been cleared" % message)
@marks.testrail_id(3729)
def test_unread_messages_counter_public_chat(self):

View File

@ -1,3 +1,4 @@
import logging
import pytest
import sys
import re
@ -10,7 +11,7 @@ from os import environ
from appium import webdriver
from abc import ABCMeta, abstractmethod
from selenium.common.exceptions import WebDriverException
from tests import test_suite_data, start_threads, marks
from tests import test_suite_data, start_threads
from appium.webdriver.common.mobileby import MobileBy
from selenium.common.exceptions import NoSuchElementException
from support.github_report import GithubHtmlReport
@ -132,6 +133,22 @@ class AbstractTestCase:
% self.get_alert_text(driver)
class Driver(webdriver.Remote):
@property
def number(self):
return test_suite_data.current_test.testruns[-1].jobs[self.session_id]
def info(self, text: str):
if "Base" not in text:
text = 'Device %s: %s' % (self.number, text)
logging.info(text)
test_suite_data.current_test.testruns[-1].steps.append(text)
def fail(self, text: str):
pytest.fail('Device %s: %s' % (self.number, text))
class SingleDeviceTestCase(AbstractTestCase):
def setup_method(self, method):
@ -140,10 +157,10 @@ class SingleDeviceTestCase(AbstractTestCase):
'sauce': {'executor': self.executor_sauce_lab,
'capabilities': self.capabilities_sauce_lab}}
self.driver = webdriver.Remote(capabilities[self.environment]['executor'],
self.driver = Driver(capabilities[self.environment]['executor'],
capabilities[self.environment]['capabilities'])
test_suite_data.current_test.testruns[-1].jobs[self.driver.session_id] = 1
self.driver.implicitly_wait(self.implicitly_wait)
test_suite_data.current_test.testruns[-1].jobs.append(self.driver.session_id)
def teardown_method(self, method):
if self.environment == 'sauce':
@ -165,9 +182,9 @@ class LocalMultipleDeviceTestCase(AbstractTestCase):
def create_drivers(self, quantity):
capabilities = self.add_local_devices_to_capabilities()
for driver in range(quantity):
self.drivers[driver] = webdriver.Remote(self.executor_local, capabilities[driver])
self.drivers[driver] = Driver(self.executor_local, capabilities[driver])
test_suite_data.current_test.testruns[-1].jobs[self.drivers[driver].session_id] = driver + 1
self.drivers[driver].implicitly_wait(self.implicitly_wait)
test_suite_data.current_test.testruns[-1].jobs.append(self.drivers[driver].session_id)
def teardown_method(self, method):
for driver in self.drivers:
@ -193,14 +210,14 @@ class SauceMultipleDeviceTestCase(AbstractTestCase):
if offline_mode:
capabilities['platformVersion'] = '6.0'
self.drivers = self.loop.run_until_complete(start_threads(quantity,
webdriver.Remote,
Driver,
self.drivers,
self.executor_sauce_lab,
self.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)
test_suite_data.current_test.testruns[-1].jobs.append(self.drivers[driver].session_id)
def teardown_method(self, method):
for driver in self.drivers:

View File

@ -1,3 +1,4 @@
import time
import requests
import pytest
import re
@ -146,14 +147,14 @@ def pytest_runtest_makereport(item, call):
error = report.longreprtext
exception = re.findall('E.*:', error)
if exception:
error = error.replace(re.findall('E.*:', report.longreprtext)[0], '')
error = error.replace(re.findall('E.*Message:|E.*Error:|E.*Failed:', report.longreprtext)[0], '')
current_test.testruns[-1].error = error
if is_sauce_env:
update_sauce_jobs(current_test.name, current_test.testruns[-1].jobs, report.passed)
def update_sauce_jobs(test_name, job_ids, passed):
for job_id in job_ids:
for job_id in job_ids.keys():
sauce.jobs.update_job(job_id, name=test_name, passed=passed)

View File

@ -10,7 +10,7 @@ from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from tests import info, marks
from tests import marks
from tests.base_test_case import MessageReliabilityTestCase
from views.base_element import BaseButton
from views.sign_in_view import SignInView
@ -61,7 +61,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
user_b_message_time[duration_time] = user_b_receive_time
user_b_received_messages += 1
except TimeoutException:
info("Message with text '%s' was not received by user_b" % message_1)
device_2_chat.driver.info("Message with text '%s' was not received by user_b" % message_1)
message_2 = ''.join(random.sample(string.ascii_lowercase, k=10))
device_2_chat.chat_message_input.send_keys(message_2)
device_2_chat.send_message_button.click()
@ -74,7 +74,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
user_a_message_time[duration_time] = user_a_receive_time
user_a_received_messages += 1
except TimeoutException:
info("Message with text '%s' was not received by user_a" % message_2)
device_1_chat.driver.info("Message with text '%s' was not received by user_a" % message_2)
finally:
self.one_to_one_chat_data['user_a'] = {'sent_messages': user_a_sent_messages,
'message_time': user_a_message_time}
@ -132,8 +132,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
self.public_chat_data['message_time'] = dict()
self.create_drivers(1, max_duration=10800, custom_implicitly_wait=2, offline_mode=True)
driver = self.drivers[0]
sign_in_view = SignInView(driver)
sign_in_view = SignInView(self.drivers[0])
home_view = sign_in_view.create_user()
chat_name = chat_name if chat_name else home_view.get_public_chat_name()
home_view.join_public_chat(chat_name)
@ -142,12 +141,12 @@ class TestMessageReliability(MessageReliabilityTestCase):
iterations = int(messages_number / 10 if messages_number > 10 else messages_number)
for _ in range(iterations):
home_view.get_back_to_home_view()
driver.set_network_connection(1) # airplane mode
home_view.driver.set_network_connection(1) # airplane mode
sent_messages_texts = self.network_api.start_chat_bot(chat_name=chat_name, messages_number=10)
self.public_chat_data['sent_messages'] += 10
driver.set_network_connection(2) # turning on WiFi connection
home_view.driver.set_network_connection(2) # turning on WiFi connection
home_view.get_chat_with_user('#' + chat_name).click()
chat_view = home_view.get_chat_view()
@ -170,8 +169,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
user_b_message_time = dict()
try:
self.create_drivers(2, max_duration=10800, custom_implicitly_wait=2, offline_mode=True)
device_1, device_2 = self.drivers[0], self.drivers[1]
sign_in_1, sign_in_2 = SignInView(device_1), SignInView(device_2)
sign_in_1, sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
sign_in_1.create_user(username='user_a')
sign_in_2.create_user(username='user_b')
device_1_home, device_2_home = sign_in_1.get_home_view(), sign_in_2.get_home_view()
@ -188,7 +186,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
iterations = int((messages_number / 10 if messages_number > 10 else messages_number) / 2)
start_time = time.time()
for i in range(iterations):
device_2.set_network_connection(1) # airplane mode
device_2_home.driver.set_network_connection(1) # airplane mode
messages_1 = list()
for _ in range(10):
@ -199,7 +197,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
messages_1.append(messages_1)
user_a_sent_messages += 1
device_2.set_network_connection(2) # turning on WiFi connection
device_2_home.driver.set_network_connection(2) # turning on WiFi connection
for message in messages_1:
try:
@ -210,7 +208,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
user_b_message_time[duration_time] = user_b_receive_time
user_b_received_messages += 1
except TimeoutException:
info("Message with text '%s' was not received by user_b" % message)
device_2_home.driver.info("Message with text '%s' was not received by user_b" % message)
messages_2 = list()
for _ in range(10):
@ -229,7 +227,7 @@ class TestMessageReliability(MessageReliabilityTestCase):
user_a_message_time[duration_time] = user_a_receive_time
user_a_received_messages += 1
except TimeoutException:
info("Message with text '%s' was not received by user_a" % message)
device_1_home.driver.info("Message with text '%s' was not received by user_a" % message)
finally:
self.one_to_one_chat_data['user_a'] = {'sent_messages': user_a_sent_messages,
'message_time': user_a_message_time}
@ -238,27 +236,26 @@ class TestMessageReliability(MessageReliabilityTestCase):
def test_message_reliability_push_notifications(self, message_wait_time):
self.create_drivers(2, max_duration=10800, custom_implicitly_wait=2)
device_1, device_2 = self.drivers[0], self.drivers[1]
sign_in_1, sign_in_2 = SignInView(device_1), SignInView(device_2)
sign_in_1, sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
sign_in_1.create_user(username='user_a')
sign_in_2.create_user(username='user_b')
device_1_home, device_2_home = sign_in_1.get_home_view(), sign_in_2.get_home_view()
device_2_public_key = device_2_home.get_public_key()
device_2_home.home_button.click()
device_2.close_app()
device_2_home.driver.close_app()
device_1_home.add_contact(device_2_public_key)
device_1_chat = device_1_home.get_chat_view()
device_1_chat.chat_message_input.send_keys('hello')
device_1_chat.send_message_button.click()
device_2.open_notifications()
device_2_home.driver.open_notifications()
try:
WebDriverWait(device_2, message_wait_time) \
WebDriverWait(device_2_home.driver, message_wait_time) \
.until(
expected_conditions.presence_of_element_located((MobileBy.XPATH, '//*[contains(@text, "Status")]')))
element = BaseButton(device_2)
element = BaseButton(device_2_home.driver)
element.locator = element.Locator.xpath_selector("//*[contains(@text,'Status')]")
element.click()
except TimeoutException as exception:

View File

@ -12,7 +12,6 @@ from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from tests import info
class BaseElement(object):
@ -61,7 +60,8 @@ class BaseElement(object):
try:
return self.driver.find_element(self.locator.by, self.locator.value)
except NoSuchElementException:
raise NoSuchElementException("'%s' is not found on the screen" % self.name) from None
raise NoSuchElementException(
"Device %s: '%s' is not found on the screen" % (self.driver.number, self.name)) from None
except Exception as exception:
if 'Internal Server Error' in str(exception):
continue
@ -71,47 +71,50 @@ class BaseElement(object):
def click(self):
self.find_element().click()
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
def wait_for_element(self, seconds=10):
try:
return WebDriverWait(self.driver, seconds) \
.until(expected_conditions.presence_of_element_located((self.locator.by, self.locator.value)))
except TimeoutException:
raise TimeoutException("'%s' is not found on the screen" % self.name) from None
raise TimeoutException(
"Device %s: '%s' is not found on the screen" % (self.driver.number, self.name)) from None
def wait_for_visibility_of_element(self, seconds=10, ignored_exceptions=None):
try:
return WebDriverWait(self.driver, seconds, ignored_exceptions=ignored_exceptions) \
.until(expected_conditions.visibility_of_element_located((self.locator.by, self.locator.value)))
except TimeoutException:
raise TimeoutException("'%s' is not found on the screen" % self.name) from None
raise TimeoutException(
"Device %s: '%s' is not found on the screen" % (self.driver.number, self.name)) from None
def wait_for_invisibility_of_element(self, seconds=10):
try:
return WebDriverWait(self.driver, seconds) \
.until(expected_conditions.invisibility_of_element_located((self.locator.by, self.locator.value)))
except TimeoutException:
raise TimeoutException("'%s' is not found on the screen" % self.name) from None
raise TimeoutException("Device %s: '%s' is still visible on the screen after %s seconds" % (
self.driver.number, self.name, seconds)) from None
def scroll_to_element(self):
for _ in range(9):
try:
return self.find_element()
except NoSuchElementException:
info('Scrolling down to %s' % self.name)
self.driver.info('Scrolling down to %s' % self.name)
self.driver.swipe(500, 1000, 500, 500)
def is_element_present(self, sec=5):
try:
info('Wait for %s' % self.name)
self.driver.info('Wait for %s' % self.name)
return self.wait_for_element(sec)
except TimeoutException:
return False
def is_element_displayed(self, sec=5, ignored_exceptions=None):
try:
info('Wait for %s' % self.name)
self.driver.info('Wait for %s' % self.name)
return self.wait_for_visibility_of_element(sec, ignored_exceptions=ignored_exceptions)
except TimeoutException:
return False
@ -149,7 +152,7 @@ class BaseElement(object):
def long_press_element(self):
element = self.find_element()
info('Long press %s' % self.name)
self.driver.info('Long press %s' % self.name)
action = TouchAction(self.driver)
action.long_press(element).release().perform()
@ -173,25 +176,25 @@ class BaseEditBox(BaseElement):
def send_keys(self, value):
self.find_element().send_keys(value)
info("Type '%s' to %s" % (value, self.name))
self.driver.info("Type '%s' to %s" % (value, self.name))
def set_value(self, value):
self.find_element().set_value(value)
info("Type '%s' to %s" % (value, self.name))
self.driver.info("Type '%s' to %s" % (value, self.name))
def clear(self):
self.find_element().clear()
info('Clear text in %s' % self.name)
self.driver.info('Clear text in %s' % self.name)
def delete_last_symbols(self, number_of_symbols_to_delete: int):
info('Delete last %s symbols from %s' % (number_of_symbols_to_delete, self.name))
self.driver.info('Delete last %s symbols from %s' % (number_of_symbols_to_delete, self.name))
self.click()
for _ in range(number_of_symbols_to_delete):
time.sleep(1)
self.driver.press_keycode(67)
def paste_text_from_clipboard(self):
info('Paste text from clipboard into %s' % self.name)
self.driver.info('Paste text from clipboard into %s' % self.name)
self.long_press_element()
time.sleep(2)
action = TouchAction(self.driver)
@ -200,7 +203,7 @@ class BaseEditBox(BaseElement):
action.press(x=x + 100, y=y - 50).release().perform()
def cut_text(self):
info('Cut text in %s' % self.name)
self.driver.info('Cut text in %s' % self.name)
location = self.find_element().location
x, y = location['x'], location['y']
action = TouchAction(self.driver)
@ -217,7 +220,7 @@ class BaseText(BaseElement):
@property
def text(self):
text = self.find_element().text
info('%s is %s' % (self.name, text))
self.driver.info('%s is %s' % (self.name, text))
return text
@ -228,16 +231,16 @@ class BaseButton(BaseElement):
def click(self):
self.find_element().click()
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
return self.navigate()
def click_until_presence_of_element(self, desired_element, attempts=3):
counter = 0
while not desired_element.is_element_present(1) and counter <= attempts:
try:
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
self.find_element().click()
info('Wait for %s' % desired_element.name)
self.driver.info('Wait for %s' % desired_element.name)
desired_element.wait_for_element(5)
return self.navigate()
except (NoSuchElementException, TimeoutException):

View File

@ -5,7 +5,7 @@ import base64
import pytest
import re
import zbarlight
from tests import info, common_password, test_fairy_warning_text
from tests import common_password, test_fairy_warning_text
from eth_keys import datatypes
from selenium.common.exceptions import NoSuchElementException, TimeoutException, StaleElementReferenceException
from PIL import Image
@ -22,7 +22,7 @@ class BackButton(BaseButton):
def click(self, times_to_click: int = 1):
for _ in range(times_to_click):
self.find_element().click()
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
return self.navigate()
@ -35,7 +35,7 @@ class AllowButton(BaseButton):
try:
for _ in range(3):
self.find_element().click()
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
except NoSuchElementException:
pass
@ -114,7 +114,7 @@ class WalletButton(TabButton):
return WalletView(self.driver)
def click(self):
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
from views.wallet_view import SetUpButton, SendTransactionButton
for _ in range(3):
self.find_element().click()
@ -179,7 +179,7 @@ class SendMessageButton(BaseButton):
def click(self):
self.find_element().click()
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
class ConnectionStatusText(BaseText):
@ -299,7 +299,7 @@ class BaseView(object):
raise TimeoutError('Logcat is empty')
def confirm(self):
info("Tap 'Confirm' on native keyboard")
self.driver.info("Tap 'Confirm' on native keyboard")
self.driver.press_keycode(66)
def confirm_until_presence_of_element(self, desired_element, attempts=3):
@ -307,26 +307,26 @@ class BaseView(object):
while not desired_element.is_element_present(1) and counter <= attempts:
try:
self.confirm()
info('Wait for %s' % desired_element.name)
self.driver.info('Wait for %s' % desired_element.name)
desired_element.wait_for_element(5)
return
except TimeoutException:
counter += 1
def click_system_back_button(self):
info('Click system back button')
self.driver.info('Click system back button')
self.driver.press_keycode(4)
def cut_text(self):
info('Cut text')
self.driver.info('Cut text')
self.driver.press_keycode(277)
def copy_text(self):
info('Copy text')
self.driver.info('Copy text')
self.driver.press_keycode(278)
def paste_text(self):
info('Paste text')
self.driver.info('Paste text')
self.driver.press_keycode(279)
def send_as_keyevent(self, string):
@ -339,7 +339,7 @@ class BaseView(object):
'k': 39, 'l': 40, 'm': 41, 'n': 42, 'o': 43, 'p': 44, 'q': 45, 'r': 46, 's': 47, 't': 48,
'u': 49, 'v': 50, 'w': 51, 'x': 52, 'y': 53, 'z': 54}
time.sleep(3)
info("Enter '%s' using native keyboard" % string)
self.driver.info("Enter '%s' using native keyboard" % string)
for i in string:
if type(keys[i]) is list:
keycode, metastate = keys[i][0], keys[i][1]
@ -348,49 +348,49 @@ class BaseView(object):
self.driver.press_keycode(keycode=keycode, metastate=metastate)
def find_full_text(self, text, wait_time=60):
info("Looking for full text: '%s'" % text)
self.driver.info("Looking for full text: '%s'" % text)
element = BaseElement(self.driver)
element.locator = element.Locator.text_selector(text)
return element.wait_for_element(wait_time)
def find_text_part(self, text, wait_time=60):
info("Looking for a text part: '%s'" % text)
self.driver.info("Looking for a text part: '%s'" % text)
element = BaseElement(self.driver)
element.locator = element.Locator.text_part_selector(text)
return element.wait_for_element(wait_time)
def element_by_text(self, text, element_type='button'):
info("Looking for an element by text: '%s'" % text)
self.driver.info("Looking for an element by text: '%s'" % text)
element = self.element_types[element_type](self.driver)
element.locator = element.Locator.text_selector(text)
return element
def element_by_text_part(self, text, element_type='button'):
info("Looking for an element by text part: '%s'" % text)
self.driver.info("Looking for an element by text part: '%s'" % text)
element = self.element_types[element_type](self.driver)
element.locator = element.Locator.text_part_selector(text)
return element
def element_starts_with_text(self, text, element_type='base'):
info("Looking for full text: '%s'" % text)
self.driver.info("Looking for full text: '%s'" % text)
element = self.element_types[element_type](self.driver)
element.locator = element.Locator.xpath_selector("//*[starts-with(@text,'%s')]" % text)
return element
def wait_for_element_starts_with_text(self, text, wait_time=60):
info("Looking for full text: '%s'" % text)
self.driver.info("Looking for full text: '%s'" % text)
element = BaseElement(self.driver)
element.locator = element.Locator.xpath_selector("//*[starts-with(@text,'%s')]" % text)
return element.wait_for_element(wait_time)
def element_by_accessibility_id(self, accessibility_id, element_type='button'):
info("Looking for an element by accessibility id: '%s'" % accessibility_id)
self.driver.info("Looking for an element by accessibility id: '%s'" % accessibility_id)
element = self.element_types[element_type](self.driver)
element.locator = element.Locator.accessibility_id(accessibility_id)
return element
def element_by_xpath(self, xpath, element_type='button'):
info("Looking for an element by xpath: '%s'" % xpath)
self.driver.info("Looking for an element by xpath: '%s'" % xpath)
element = self.element_types[element_type](self.driver)
element.locator = element.Locator.xpath_selector(xpath)
return element
@ -492,7 +492,7 @@ class BaseView(object):
connect_status.wait_for_invisibility_of_element()
except TimeoutException as e:
if i == 2:
e.msg = "Can't reconnect to mail server after 3 attempts"
e.msg = "Device %s: Can't reconnect to mail server after 3 attempts" % self.driver.number
raise e
def check_no_values_in_logcat(self, **kwargs):

View File

@ -1,8 +1,6 @@
import time
import pytest
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from tests import info
from views.base_element import BaseButton, BaseEditBox, BaseText
from views.base_view import BaseView, ProgressBar
from views.profile_view import ProfilePictureElement, PublicKeyText
@ -178,7 +176,7 @@ class ChatElementByText(BaseText):
"//*[starts-with(@text,'%s')]/ancestor::android.view.ViewGroup[@content-desc='chat-item']" % text)
def find_element(self):
info("Looking for message with text '%s'" % self.message_text)
self.driver.info("Looking for message with text '%s'" % self.message_text)
for _ in range(2):
try:
return super(ChatElementByText, self).find_element()
@ -272,11 +270,11 @@ class ChatView(BaseView):
self.public_key_text = PublicKeyText(self.driver)
def wait_for_syncing_complete(self):
info('Waiting for syncing complete:')
self.driver.info('Waiting for syncing complete:')
while True:
try:
sync = self.find_text_part('Syncing', 10)
info(sync.text)
self.driver.info(sync.text)
except TimeoutException:
break
@ -345,7 +343,7 @@ class ChatView(BaseView):
chat_elem.wait_for_visibility_of_element()
chat_elem.progress_bar.wait_for_invisibility_of_element(20)
if chat_elem.status.text not in ('Sent', 'Delivered', 'Seen'):
pytest.fail('Sent transaction message was not sent')
self.driver.fail('Sent transaction message was not sent')
def send_transaction_in_group_chat(self, amount, password, recipient):
self.commands_button.click()
@ -368,7 +366,7 @@ class ChatView(BaseView):
self.send_message_button.click()
def chat_element_by_text(self, text):
info("Looking for a message by text: '%s'" % text)
self.driver.info("Looking for a message by text: '%s'" % text)
return ChatElementByText(self.driver, text)
def verify_message_is_under_today_text(self, text, errors):

View File

@ -1,4 +1,3 @@
from tests import info
import time
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from views.base_element import BaseButton, BaseText, BaseElement
@ -45,7 +44,7 @@ class ChatElement(BaseButton):
return self.navigate()
def find_element(self):
info('Looking for %s' % self.name)
self.driver.info('Looking for %s' % self.name)
for i in range(2):
try:
return super(ChatElement, self).find_element()
@ -53,7 +52,7 @@ class ChatElement(BaseButton):
if i == 0:
HomeView(self.driver).reconnect()
else:
e.msg = 'Unable to find chat with user %s' % self.username
e.msg = 'Device %s: Unable to find chat with user %s' % (self.driver.number, self.username)
raise e
@property
@ -108,11 +107,11 @@ class HomeView(BaseView):
self.chat_url_text = ChatUrlText(self.driver)
def wait_for_syncing_complete(self):
info('Waiting for syncing complete:')
self.driver.info('Waiting for syncing complete:')
while True:
try:
sync = self.find_text_part('Syncing', 10)
info(sync.text)
self.driver.info(sync.text)
except TimeoutException:
break

View File

@ -1,5 +1,4 @@
import time
from tests import info
from tests.base_test_case import AbstractTestCase
from views.base_element import BaseText, BaseButton, BaseEditBox, BaseElement
from views.base_view import BaseView
@ -14,7 +13,7 @@ class PublicKeyText(BaseText):
@property
def text(self):
text = self.scroll_to_element().text
info('%s is %s' % (self.name, text))
self.driver.info('%s is %s' % (self.name, text))
return text
@ -166,7 +165,7 @@ class AdvancedButton(BaseButton):
def click(self):
self.scroll_to_element().click()
info('Tap on %s' % self.name)
self.driver.info('Tap on %s' % self.name)
return self.navigate()

View File

@ -149,4 +149,5 @@ class SignInView(BaseView):
try:
self.account_button.find_elements()[position].click()
except IndexError:
raise NoSuchElementException('Unable to find account by position %s' % position) from None
raise NoSuchElementException(
'Device %s: Unable to find account by position %s' % (self.driver.number, position)) from None

View File

@ -93,7 +93,7 @@ class TransactionTable(BaseElement):
except NoSuchElementException:
time.sleep(5)
self.refresh_transactions()
pytest.fail('Transaction was not found on Wallet/Transaction screen')
self.driver.fail('Transaction was not found on Wallet/Transaction screen')
def refresh_transactions(self):
self.driver.swipe(500, 500, 500, 1000)

View File

@ -1,4 +1,3 @@
from tests import info
import time
from views.base_view import BaseView
from views.base_element import BaseButton, BaseText
@ -152,7 +151,7 @@ class AssetCheckBox(BaseButton):
def click(self):
self.scroll_to_element().click()
info('Click %s asset checkbox' % self.asset_name)
self.driver.info('Click %s asset checkbox' % self.asset_name)
class TotalAmountText(BaseText):
@ -228,21 +227,21 @@ class WalletView(BaseView):
if percentage_diff > 2:
errors.append('Difference between current (%s) and expected (%s) USD balance > 2%%!!' % (usd, expected_usd))
else:
info('Current USD balance %s is ok' % usd)
self.driver.info('Current USD balance %s is ok' % usd)
def wait_balance_changed_on_wallet_screen(self, expected_balance=0.1, wait_time=300):
counter = 0
while True:
if counter >= wait_time:
info('Balance is not changed during %s seconds!' % wait_time)
self.driver.info('Balance is not changed during %s seconds!' % wait_time)
return
elif self.get_eth_value() != expected_balance:
counter += 10
time.sleep(10)
self.swipe_down()
info('Waiting %s seconds for ETH update' % counter)
self.driver.info('Waiting %s seconds for ETH update' % counter)
else:
info('Transaction received, balance updated!')
self.driver.info('Transaction received, balance updated!')
return
def get_sign_in_phrase(self):

View File

@ -87,7 +87,7 @@ class BaseWebView(BaseView):
time.sleep(1)
counter += 1
if counter > wait_time:
pytest.fail("Page is not loaded during %s seconds" % wait_time)
self.driver.fail("Page is not loaded during %s seconds" % wait_time)
def open_in_webview(self):
self.web_view_browser.click()