diff --git a/test/appium/requirements.txt b/test/appium/requirements.txt index 3579f46760..0e0f3ea7bb 100644 --- a/test/appium/requirements.txt +++ b/test/appium/requirements.txt @@ -12,8 +12,9 @@ lxml==3.8.0 multidict==3.1.3 namedlist==1.7 py==1.4.34 -pytest==3.1.3 -pytest-xdist==1.18.2 +pytest==3.2.1 +pytest-forked==0.2 +pytest-xdist==1.20.0 requests==2.18.3 sauceclient==1.0.0 selenium==2.53.6 diff --git a/test/appium/tests/basetestcase.py b/test/appium/tests/basetestcase.py index 2bbf643046..d044a0102a 100644 --- a/test/appium/tests/basetestcase.py +++ b/test/appium/tests/basetestcase.py @@ -38,7 +38,7 @@ class AbstractTestCase: desired_caps['deviceOrientation'] = "portrait" desired_caps['name'] = tests_data.name desired_caps['build'] = pytest.config.getoption('build') - desired_caps['idleTimeout'] = 500 + desired_caps['idleTimeout'] = 800 return desired_caps def get_public_url(self, driver): @@ -80,7 +80,7 @@ class SingleDeviceTestCase(AbstractTestCase): def setup_method(self, method): self.driver = webdriver.Remote(self.executor_sauce_lab, self.capabilities_sauce_lab) - self.driver.implicitly_wait(10) + self.driver.implicitly_wait(30) def teardown_method(self, method): self.print_sauce_lab_info(self.driver) @@ -99,7 +99,7 @@ class MultiplyDeviceTestCase(AbstractTestCase): self.capabilities_sauce_lab)) loop.close() for driver in self.driver_1, self.driver_2: - driver.implicitly_wait(10) + driver.implicitly_wait(30) def teardown_method(self, method): for driver in self.driver_1, self.driver_2: diff --git a/test/appium/tests/test_chats.py b/test/appium/tests/test_chats.py index 7b78bb2339..117e70da21 100644 --- a/test/appium/tests/test_chats.py +++ b/test/appium/tests/test_chats.py @@ -2,23 +2,24 @@ import pytest from tests.basetestcase import MultiplyDeviceTestCase from tests.preconditions import set_password_as_new_user from views.home import HomeView +from views.base_view import ElementByName @pytest.mark.sanity class TestChats(MultiplyDeviceTestCase): - def test_private_chat(self): + def test_one_to_one_chat(self): device_1, device_2 = HomeView(self.driver_1), HomeView(self.driver_2) set_password_as_new_user(device_1, device_2) - device_1.back_button.click() + chats_d1 = device_1.get_chats() chats_d1.profile_button.click() profile_d1 = chats_d1.profile_icon.click() key = profile_d1.public_key_text.text - device_2.back_button.click() + chats_d2 = device_2.get_chats() chats_d2.plus_button.click() chats_d2.add_new_contact.click() @@ -26,8 +27,21 @@ class TestChats(MultiplyDeviceTestCase): chats_d2.confirm() chats_d2.confirm_public_key_button.click() - chats_d2.chat_message_input.send_keys('SOMETHING') + message_1 = 'SOMETHING' + message_2 = 'another SOMETHING' + user_d1_name = chats_d2.user_name_text.text + + chats_d2.chat_message_input.send_keys(message_1) chats_d2.send_message_button.click() - profile_d1.back_button.click() - profile_d1.find_text('SOMETHING') + chats_d1.back_button.click() + chats_d1.find_text(message_1) + + one_to_one_chat_d2 = ElementByName(self.driver_2, user_d1_name) + one_to_one_chat_d2.click() + chats_d2.chat_message_input.send_keys(message_2) + chats_d2.send_message_button.click() + + one_to_one_chat_d1 = ElementByName(self.driver_1, message_2) + one_to_one_chat_d1.click() + chats_d1.find_text(message_2) diff --git a/test/appium/tests/test_group_chats.py b/test/appium/tests/test_group_chats.py index 44fa358007..eb27e22ef6 100644 --- a/test/appium/tests/test_group_chats.py +++ b/test/appium/tests/test_group_chats.py @@ -2,18 +2,16 @@ import pytest from tests.basetestcase import MultiplyDeviceTestCase from tests.preconditions import set_password_as_new_user from views.home import HomeView -from views.chats import UserNameText +from views.base_view import ElementByName @pytest.mark.sanity -class TestDev(MultiplyDeviceTestCase): +class TestGroupChats(MultiplyDeviceTestCase): def test_group_chat(self): device_1, device_2 = HomeView(self.driver_1), \ HomeView(self.driver_2) - set_password_as_new_user(device_2, device_1) - device_1.back_button.click() chats_d1 = device_1.get_chats() chats_d1.profile_button.click() @@ -34,16 +32,27 @@ class TestDev(MultiplyDeviceTestCase): chats_d2.new_group_chat_button.click() profile_d1.back_button.click() - - user_contact = UserNameText.UserContactByName(self.driver_2, user_d1_name) + user_contact = ElementByName(self.driver_2, user_d1_name) user_contact.scroll_to_element() user_contact.click() - chats_d2.next_button.click() - chats_d2.name_edit_box.send_keys('new_chat') - chats_d2.save_button.click() - chats_d2.chat_message_input.send_keys('SOMETHING') + chat_name = 'new_chat' + message_1 = 'SOMETHING' + message_2 = 'another SOMETHING' + + chats_d2.name_edit_box.send_keys(chat_name) + chats_d2.save_button.click() + chats_d2.chat_message_input.send_keys(message_1) chats_d2.send_message_button.click() - profile_d1.find_text('SOMETHING') + profile_d1.find_text(message_1) + + group_chat_d2 = ElementByName(self.driver_2, chat_name) + group_chat_d2.click() + chats_d2.chat_message_input.send_keys(message_2) + chats_d2.send_message_button.click() + + group_chat_d1 = ElementByName(self.driver_1, chat_name) + group_chat_d1.click() + profile_d1.find_text(message_2) diff --git a/test/appium/tests/test_sanity.py b/test/appium/tests/test_sanity.py index 10f307b127..2fce37f8ce 100644 --- a/test/appium/tests/test_sanity.py +++ b/test/appium/tests/test_sanity.py @@ -9,15 +9,15 @@ class TestSanity(SingleDeviceTestCase): @pytest.mark.parametrize("verification", ["short", "mismatch", "valid"]) def test_password(self, verification): - verifications = {"short": {"input": "qwe1", - "outcome": - "Password should be not less then 6 symbols."}, - "mismatch": {"input": "mismatch1234", - "outcome": - "Password confirmation doesn\'t match password."}, - "valid": {"input": "qwerty1234", - "outcome": - "Tap here to enter your phone number & I\'ll find your friends"}} + verifications = {"short": + {"input": "qwe1", + "outcome": "Password should be not less then 6 symbols."}, + "valid": + {"input": "qwerty1234", + "outcome": "Tap here to enter your phone number & I\'ll find your friends"}, + "mismatch": + {"input": "mismatch1234", + "outcome": "Password confirmation doesn\'t match password."}} home = HomeView(self.driver) home.request_password_icon.click() home.type_message_edit_box.send_keys(verifications[verification]["input"]) diff --git a/test/appium/views/base_element.py b/test/appium/views/base_element.py index 759158a6d1..f5ca856e2f 100644 --- a/test/appium/views/base_element.py +++ b/test/appium/views/base_element.py @@ -1,9 +1,8 @@ -from selenium.webdriver.common.by import By +from appium.webdriver.common.mobileby import By, MobileBy from selenium.common.exceptions import NoSuchElementException, TimeoutException from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions from appium.webdriver.common.touch_action import TouchAction -import pytest class BaseElement(object): @@ -18,6 +17,10 @@ class BaseElement(object): def xpath_selector(locator, value): return locator(By.XPATH, value) + @classmethod + def accessibility_id(locator, value): + return locator(MobileBy.ACCESSIBILITY_ID, value) + def __str__(self, *args, **kwargs): return "%s:%s" % (self.by, self.value) diff --git a/test/appium/views/base_view.py b/test/appium/views/base_view.py index 82c8539e0f..df746b5c2a 100644 --- a/test/appium/views/base_view.py +++ b/test/appium/views/base_view.py @@ -8,6 +8,12 @@ class BackButton(BaseButton): self.locator = self.Locator.xpath_selector("//*[@content-desc='toolbar-back-button']") +class ElementByName(BaseButton): + def __init__(self, driver, user_name): + super(ElementByName, self).__init__(driver) + self.locator = self.Locator.xpath_selector('//*[@text="' + user_name + '"]') + + class BaseViewObject(object): def __init__(self, driver): @@ -18,9 +24,9 @@ class BaseViewObject(object): self.driver.keyevent(66) def find_text(self, text): - element = BaseButton(self.driver) + element = BaseElement(self.driver) element.locator = element.Locator.xpath_selector('//*[@text="' + text + '"]') - return element.wait_for_element(100) + return element.wait_for_element(120) def get_chats(self): from views.chats import ChatsViewObject diff --git a/test/appium/views/chats.py b/test/appium/views/chats.py index 63b4f21f33..b3a14a9c34 100644 --- a/test/appium/views/chats.py +++ b/test/appium/views/chats.py @@ -6,17 +6,14 @@ class ProfileButton(BaseButton): def __init__(self, driver): super(ProfileButton, self).__init__(driver) - self.locator = self.Locator.xpath_selector( - "//android.support.v4.view.ViewPager//android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.View" - ) + self.locator = self.Locator.accessibility_id('toolbar-hamburger-menu') class ProfileIcon(BaseButton): def __init__(self, driver): super(ProfileIcon, self).__init__(driver) - self.locator = self.Locator.xpath_selector( - "//android.widget.EditText/../android.view.ViewGroup") + self.locator = self.Locator.accessibility_id('drawer-profile-icon') def navigate(self): from views.profile import ProfileViewObject @@ -46,18 +43,6 @@ class NewGroupChatButton(BaseButton): self.locator = self.Locator.xpath_selector( "//android.widget.TextView[@text='New group chat']") - class AugurContact(BaseButton): - def __init__(self, driver): - super(NewGroupChatButton.AugurContact, self).__init__(driver) - self.locator = self.Locator.xpath_selector( - "//android.widget.TextView[@text='Augur']") - - class JarradContact(BaseButton): - def __init__(self, driver): - super(NewGroupChatButton.JarradContact, self).__init__(driver) - self.locator = self.Locator.xpath_selector( - "//android.widget.TextView[@text='Jarrad']") - class NextButton(BaseButton): def __init__(self, driver): super(NewGroupChatButton.NextButton, self).__init__(driver) @@ -90,26 +75,21 @@ class ConfirmPublicKeyButton(BaseButton): def __init__(self, driver): super(ConfirmPublicKeyButton, self).__init__(driver) self.locator = \ - self.Locator.xpath_selector("//android.widget.TextView[@text='Add new contact']" - "/following-sibling::android.view.ViewGroup/" - "android.widget.ImageView") + self.Locator.accessibility_id('toolbar-action') class ChatMessageInput(BaseEditBox): def __init__(self, driver): super(ChatMessageInput, self).__init__(driver) - self.locator = self.Locator.xpath_selector("//*[@content-desc='chat-message-input']") + self.locator = self.Locator.accessibility_id('chat-message-input') class SendMessageButton(BaseButton): def __init__(self, driver): super(SendMessageButton, self).__init__(driver) - self.locator = \ - self.Locator.xpath_selector("//android.widget.FrameLayout//" - "android.view.ViewGroup[3]//" - "android.view.ViewGroup[2]//android.widget.ImageView") + self.locator = self.Locator.accessibility_id("send-message-button") class UserNameText(BaseText): @@ -119,12 +99,6 @@ class UserNameText(BaseText): self.locator = \ self.Locator.xpath_selector("//android.widget.ScrollView//android.widget.TextView") - class UserContactByName(BaseButton): - - def __init__(self, driver, user_name): - super(UserNameText.UserContactByName, self).__init__(driver) - self.locator = self.Locator.xpath_selector('//*[@text="' + user_name + '"]') - class ChatsViewObject(BaseViewObject): @@ -140,13 +114,11 @@ class ChatsViewObject(BaseViewObject): self.public_key_edit_box = PublicKeyEditBox(self.driver) self.confirm_public_key_button = ConfirmPublicKeyButton(self.driver) - self.chat_message_input = ChatMessageInput(self.driver) - self.send_message_button = SendMessageButton(self.driver) - self.user_name_text = UserNameText(self.driver) - self.new_group_chat_button = NewGroupChatButton(self.driver) - self.augur_contact = NewGroupChatButton.AugurContact(self.driver) - self.jarrad_contact = NewGroupChatButton.JarradContact(self.driver) self.next_button = NewGroupChatButton.NextButton(self.driver) self.name_edit_box = NewGroupChatButton.NameEditBox(self.driver) self.save_button = NewGroupChatButton.SaveButton(self.driver) + + self.chat_message_input = ChatMessageInput(self.driver) + self.send_message_button = SendMessageButton(self.driver) + self.user_name_text = UserNameText(self.driver) diff --git a/test/appium/views/home.py b/test/appium/views/home.py index e2a74b3d56..3c3ce67ea7 100644 --- a/test/appium/views/home.py +++ b/test/appium/views/home.py @@ -1,27 +1,28 @@ from views.base_view import BaseViewObject from views.base_element import * +from tests import tests_data -class ContinueButton(BaseButton): +class OkButtonAPK(BaseButton): def __init__(self, driver): - super(ContinueButton, self).__init__(driver) - self.locator = self.Locator.xpath_selector("//*[@text='Continue']") - - -class OkButton(BaseButton): - - def __init__(self, driver): - super(OkButton, self).__init__(driver) + super(OkButtonAPK, self).__init__(driver) self.locator = self.Locator.xpath_selector("//*[@text='OK']") +class ContinueButtonAPK(BaseButton): + + def __init__(self, driver): + super(ContinueButtonAPK, self).__init__(driver) + self.locator = self.Locator.xpath_selector("//*[@text='Continue']") + + class TypeMessageEditBox(BaseEditBox): def __init__(self, driver): super(TypeMessageEditBox, self).__init__(driver) self.locator = \ - self.Locator.xpath_selector("//android.widget.EditText[@content-desc!='chat-message-input']") + self.Locator.xpath_selector("//*[@content-desc!='chat-message-input']") class RequestPasswordIcon(BaseButton): @@ -35,10 +36,10 @@ class HomeView(BaseViewObject): def __init__(self, driver): super(HomeView, self).__init__(driver) - self.continue_button = ContinueButton(driver) - self.ok_button = OkButton(driver) + self.continue_button_apk = ContinueButtonAPK(driver) + self.ok_button_apk = OkButtonAPK(driver) - for i in self.ok_button, self.continue_button: + for i in self.ok_button_apk, self.continue_button_apk: try: i.click() except (NoSuchElementException, TimeoutException): diff --git a/test/appium/views/profile.py b/test/appium/views/profile.py index bfc29dc356..21b1548469 100644 --- a/test/appium/views/profile.py +++ b/test/appium/views/profile.py @@ -6,7 +6,7 @@ class PublicKeyText(BaseText): def __init__(self, driver): super(PublicKeyText, self).__init__(driver) - self.locator = self.Locator.xpath_selector("//android.widget.TextView[@instance='7']") + self.locator = self.Locator.accessibility_id('profile-public-key') class ProfileViewObject(BaseViewObject):