From 032c254d1961494ca69d26ab1de392910b9afc12 Mon Sep 17 00:00:00 2001 From: Yevheniia Berdnyk Date: Thu, 8 Jun 2023 05:57:38 +0300 Subject: [PATCH] e2e: Updated report --- test/appium/support/base_test_report.py | 7 ++-- test/appium/tests/base_test_case.py | 14 +++---- test/appium/tests/conftest.py | 21 ++++++----- .../critical/chats/test_1_1_public_chats.py | 37 ++++++++++++------- .../critical/test_public_chat_browsing.py | 9 ++--- test/appium/views/chat_view.py | 37 +++++++++++-------- 6 files changed, 71 insertions(+), 54 deletions(-) diff --git a/test/appium/support/base_test_report.py b/test/appium/support/base_test_report.py index e00f700152..cafb0595a9 100644 --- a/test/appium/support/base_test_report.py +++ b/test/appium/support/base_test_report.py @@ -1,10 +1,9 @@ -import time -import json import hmac +import json import os -from hashlib import md5 -from sauceclient import SauceException import re +from hashlib import md5 + from support.test_data import SingleTestData diff --git a/test/appium/tests/base_test_case.py b/test/appium/tests/base_test_case.py index 9ad80b12ad..9108bb317a 100644 --- a/test/appium/tests/base_test_case.py +++ b/test/appium/tests/base_test_case.py @@ -18,10 +18,9 @@ from selenium.webdriver.support.wait import WebDriverWait from urllib3.exceptions import MaxRetryError, ProtocolError 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 from tests import transl -from tests.conftest import sauce_username, sauce_access_key, apibase +from tests.conftest import sauce_username, sauce_access_key, apibase, github_report executor_sauce_lab = 'https://%s:%s@ondemand.%s:443/wd/hub' % (sauce_username, sauce_access_key, apibase) @@ -127,7 +126,6 @@ class AbstractTestCase: return pytest_config_global['env'] network_api = NetworkApi() - github_report = GithubHtmlReport() @staticmethod def get_alert_text(driver): @@ -215,7 +213,7 @@ class SingleDeviceTestCase(AbstractTestCase): except (WebDriverException, AttributeError): pass finally: - self.github_report.save_test(test_suite_data.current_test, + github_report.save_test(test_suite_data.current_test, {'%s_geth.log' % test_suite_data.current_test.name: geth_content}) @@ -277,7 +275,7 @@ class SauceMultipleDeviceTestCase(AbstractTestCase): except (WebDriverException, AttributeError): pass 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) + github_report.save_test(test_suite_data.current_test, geth) @classmethod def teardown_class(cls): @@ -377,7 +375,7 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase): finally: try: geth = {geth_names[i]: geth_contents[i] for i in range(len(geth_names))} - test_suite_data.current_test.geth_paths = self.github_report.save_geth(geth) + test_suite_data.current_test.geth_paths = github_report.save_geth(geth) except IndexError: pass @@ -419,7 +417,7 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase): if cls.loop: cls.loop.close() for test in test_suite_data.tests: - cls.github_report.save_test(test) + github_report.save_test(test) if pytest_config_global['env'] == 'local': @@ -436,4 +434,4 @@ class NoDeviceTestCase(AbstractTestCase): pass def teardown_method(self, method): - self.github_report.save_test(test_suite_data.current_test) + github_report.save_test(test_suite_data.current_test) diff --git a/test/appium/tests/conftest.py b/test/appium/tests/conftest.py index c7a6d21ecd..d574249858 100644 --- a/test/appium/tests/conftest.py +++ b/test/appium/tests/conftest.py @@ -1,15 +1,16 @@ +import os import re +import urllib.request from dataclasses import dataclass from datetime import datetime from http.client import RemoteDisconnected from os import environ from time import sleep -import os -import urllib.request import pytest from _pytest.runner import runtestprotocol from requests.exceptions import ConnectionError as c_er + import tests from support.device_stats_db import DeviceStatsDB from support.test_rerun import should_rerun_test @@ -20,7 +21,6 @@ sauce_access_key = environ.get('SAUCE_ACCESS_KEY') github_token = environ.get('GIT_HUB_TOKEN') - def pytest_addoption(parser): parser.addoption("--build", action="store", @@ -158,6 +158,7 @@ def is_uploaded(): if stored_files[i].name == test_suite_data.apk_name: return True + def pytest_configure(config): global option option = config.option @@ -178,7 +179,7 @@ def pytest_configure(config): else: raise NotImplementedError("Unknown SauceLabs datacenter") global sauce - sauce = SauceLab('https://api.' + apibase +'/', sauce_username, sauce_access_key) + sauce = SauceLab('https://api.' + apibase + '/', sauce_username, sauce_access_key) if config.getoption('log_steps'): import logging logging.basicConfig(level=logging.INFO) @@ -208,7 +209,8 @@ def pytest_configure(config): 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 + 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 @@ -263,7 +265,8 @@ def pytest_runtest_makereport(item, call): is_group = "xdist_group" in item.keywords._markers or "xdist_group" in item.parent.keywords._markers error_intro, error = 'Test setup failed:', '' final_error = '%s %s' % (error_intro, error) - if (hasattr(report, 'wasxfail') and not case_ids_set) or (hasattr(report, 'wasxfail') and (str([mark.args[0] for mark in item.iter_markers(name='testrail_id')][0]) in str(case_ids_set))): + if (hasattr(report, 'wasxfail') and not case_ids_set) or (hasattr(report, 'wasxfail') and ( + str([mark.args[0] for mark in item.iter_markers(name='testrail_id')][0]) in str(case_ids_set))): if '[NOTRUN]' in report.wasxfail: test_suite_data.set_current_test(item.name, testrail_case_id=get_testrail_case_id(item)) test_suite_data.current_test.create_new_testrun() @@ -287,15 +290,15 @@ def pytest_runtest_makereport(item, call): report.passed) if error: test_suite_data.current_test.testruns[-1].error = final_error - from support.github_report import GithubHtmlReport - GithubHtmlReport().save_test(test_suite_data.current_test) + github_report.save_test(test_suite_data.current_test) if report.when == 'call': current_test = test_suite_data.current_test error = catch_error() if report.failed: current_test.testruns[-1].error = error - if (hasattr(report, 'wasxfail') and not case_ids_set) or (hasattr(report, 'wasxfail') and (str([mark.args[0] for mark in item.iter_markers(name='testrail_id')][0]) in str(case_ids_set))): + if (hasattr(report, 'wasxfail') and not case_ids_set) or (hasattr(report, 'wasxfail') and ( + str([mark.args[0] for mark in item.iter_markers(name='testrail_id')][0]) in str(case_ids_set))): current_test.testruns[-1].xfail = report.wasxfail if error: current_test.testruns[-1].error = '%s [[%s]]' % (error, report.wasxfail) diff --git a/test/appium/tests/critical/chats/test_1_1_public_chats.py b/test/appium/tests/critical/chats/test_1_1_public_chats.py index ba65d660a8..c05b9b3f7b 100644 --- a/test/appium/tests/critical/chats/test_1_1_public_chats.py +++ b/test/appium/tests/critical/chats/test_1_1_public_chats.py @@ -926,11 +926,14 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): self.home_2.just_fyi("Check 'Open in Status' option") url_message = 'http://status.im' self.chat_1.send_message(url_message) - self.chat_2.element_starts_with_text(url_message, 'button').wait_for_visibility_of_element(120) - self.chat_2.element_starts_with_text(url_message, 'button').click_inside_element_by_coordinate(0.2, 0.5) - web_view = self.chat_2.open_in_status_button.click() - if not web_view.element_by_text('Private, Secure Communication').is_element_displayed(60): - self.errors.append('URL was not opened from 1-1 chat') + try: + self.chat_2.element_starts_with_text(url_message, 'button').wait_for_visibility_of_element(120) + self.chat_2.element_starts_with_text(url_message, 'button').click_inside_element_by_coordinate(0.2, 0.5) + web_view = self.chat_2.open_in_status_button.click() + if not web_view.element_by_text('Private, Secure Communication').is_element_displayed(60): + self.errors.append('URL was not opened from 1-1 chat') + except TimeoutException: + self.errors.append("Message with URL was not received") self.errors.verify_no_errors() @@ -1124,6 +1127,8 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): self.errors.append("PN are keep staying after message was seen by user") self.errors.verify_no_errors() + @marks.xfail( + reason="Message is being in status 'Sending' for a long time: https://github.com/status-im/status-mobile/issues/15385") @marks.testrail_id(702855) def test_1_1_chat_edit_message(self): [home.click_system_back_button_until_element_is_shown() for home in self.homes] @@ -1160,14 +1165,20 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase): self.device_2.just_fyi("Delete message for me and check it is only deleted for the author") self.chat_2.send_message(message_to_delete_for_me) - self.chat_2.chat_element_by_text(message_to_delete_for_me).wait_for_status_to_be("Delivered") - self.chat_2.delete_message_in_chat(message_to_delete_for_me, everyone=False) - if not self.chat_2.chat_element_by_text(message_to_delete_for_me).is_element_disappeared(20): - self.errors.append("Deleted for me message is shown in chat for the author of message") - if not self.chat_2.element_by_translation_id('message-deleted-for-you').is_element_displayed(20): - self.errors.append("System message about deletion for you is not displayed") - if not self.chat_1.chat_element_by_text(message_to_delete_for_me).is_element_displayed(20): - self.errors.append("Deleted for me message is deleted for both users") + try: + timeout = 60 + self.chat_2.chat_element_by_text(message_to_delete_for_me).wait_for_status_to_be("Delivered", timeout) + self.chat_2.delete_message_in_chat(message_to_delete_for_me, everyone=False) + except TimeoutException: + self.errors.append( + "Message status was not changed to 'Delivered' after %s s, https://github.com/status-im/status-mobile/issues/15385" % timeout) + else: + if not self.chat_2.chat_element_by_text(message_to_delete_for_me).is_element_disappeared(20): + self.errors.append("Deleted for me message is shown in chat for the author of message") + if not self.chat_2.element_by_translation_id('message-deleted-for-you').is_element_displayed(20): + self.errors.append("System message about deletion for you is not displayed") + if not self.chat_1.chat_element_by_text(message_to_delete_for_me).is_element_displayed(20): + self.errors.append("Deleted for me message is deleted for both users") 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) diff --git a/test/appium/tests/critical/test_public_chat_browsing.py b/test/appium/tests/critical/test_public_chat_browsing.py index 98900c5730..a0084b5092 100644 --- a/test/appium/tests/critical/test_public_chat_browsing.py +++ b/test/appium/tests/critical/test_public_chat_browsing.py @@ -455,8 +455,7 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.channel_1.verify_message_is_under_today_text(message, self.errors) new_message = "new message" self.channel_1.send_message(message) - self.channel_1.chat_element_by_text(message).wait_for_status_to_be('Delivered', timeout=120) - self.channel_2.verify_message_is_under_today_text(new_message, self.errors) + self.channel_2.verify_message_is_under_today_text(new_message, self.errors, 60) if self.channel_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) self.errors.verify_no_errors() @@ -502,9 +501,8 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): self.home_1.just_fyi('Send image in 1-1 chat from Gallery') image_description = 'description' self.channel_1.send_images_with_description(image_description) - self.channel_1.chat_element_by_text(image_description).wait_for_status_to_be('Delivered', timeout=120) - self.channel_1.chat_element_by_text(image_description).image_in_message.click() - self.channel_1.click_system_back_button_until_element_is_shown(element='chat') + # self.channel_1.chat_element_by_text(image_description).image_in_message.click() + # self.channel_1.click_system_back_button_until_element_is_shown(element='chat') # TODO: options for image are still WIP; add case with edit description of image and after 15901 fix self.home_2.just_fyi('check image, description and options for receiver') @@ -533,6 +531,7 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase): # # self.channel_2.chat_element_by_text(image_description).image_in_message.save_new_screenshot_of_element('images_test.png') + self.channel_2.chat_element_by_text(image_description).wait_for_visibility_of_element(60) if not self.channel_2.chat_element_by_text( image_description).image_in_message.is_element_image_similar_to_template('image_sent_in_community.png'): self.errors.append("Not expected image is shown to the receiver") diff --git a/test/appium/views/chat_view.py b/test/appium/views/chat_view.py index 6403bb00de..8d96683a0e 100644 --- a/test/appium/views/chat_view.py +++ b/test/appium/views/chat_view.py @@ -220,11 +220,12 @@ class ChatElementByText(Text): def wait_for_status_to_be(self, expected_status: str, timeout: int = 30): self.driver.info("Waiting for message to be sent for %s sec" % timeout) start_time = time.time() + current_status = self.status while time.time() - start_time <= timeout: - if self.status == expected_status: + if current_status == expected_status: return time.sleep(1) - raise TimeoutException("Message status was not changed to %s" % expected_status) + raise TimeoutException("Message status was not changed to %s, it's %s" % (expected_status, current_status)) @property def sent_status_checkmark(self) -> object: @@ -285,7 +286,8 @@ class ChatElementByText(Text): @property def image_container_in_message(self): try: - self.driver.info("Trying to access images (image container) inside message with text '%s'" % self.message_text) + self.driver.info( + "Trying to access images (image container) inside message with text '%s'" % self.message_text) ChatElementByText(self.driver, self.message_text).wait_for_sent_state(60) return Button(self.driver, xpath='%s//*[@content-desc="image-container"]' % self.locator) except NoSuchElementException: @@ -363,8 +365,9 @@ class CommunityView(HomeView): self.invite_button = Button(self.driver, accessibility_id="community-invite-people") # Community info page - self.community_membership_request_value = Text(self.driver, translation_id="members-label", - suffix='/following-sibling::android.view.ViewGroup/android.widget.TextView') + self.community_membership_request_value = Text( + self.driver, translation_id="members-label", + suffix='/following-sibling::android.view.ViewGroup/android.widget.TextView') self.members_button = Button(self.driver, translation_id="members-label") self.community_info_picture = Button(self.driver, accessibility_id="chat-icon") self.leave_community_button = Button(self.driver, translation_id="leave-community") @@ -393,7 +396,6 @@ class CommunityView(HomeView): self.checkbox_button.scroll_and_click() self.join_community_button.scroll_and_click() - def get_channel(self, channel_name: str): self.driver.info("Getting %s channel element in community" % channel_name) chat_element = self.get_chat(username=channel_name, community_channel=True, wait_time=30) @@ -732,9 +734,11 @@ class ChatView(BaseView): self.chat_message_input = ChatMessageInput(self.driver) self.cancel_reply_button = Button(self.driver, accessibility_id="reply-cancel-button") self.url_preview_composer = Button(self.driver, accessibility_id="url-preview") - self.url_preview_composer_text = Text(self.driver, xpath='//*[@content-desc="url-preview"]//*[@content-desc="title"]') - self.quote_username_in_message_input = EditBox(self.driver, - xpath="//*[@content-desc='reply-cancel-button']/preceding::android.widget.TextView[3]") + self.url_preview_composer_text = Text(self.driver, + xpath='//*[@content-desc="url-preview"]//*[@content-desc="title"]') + self.quote_username_in_message_input = EditBox( + self.driver, + xpath="//*[@content-desc='reply-cancel-button']/preceding::android.widget.TextView[3]") self.chat_item = Button(self.driver, xpath="(//*[@content-desc='chat-item'])[1]") self.chat_name_editbox = EditBox(self.driver, accessibility_id="chat-name-input") self.commands_button = CommandsButton(self.driver) @@ -938,10 +942,10 @@ class ChatView(BaseView): self.driver.info("Looking for a message by text: %s" % chat_element.exclude_emoji(text)) return chat_element - def verify_message_is_under_today_text(self, text, errors): + def verify_message_is_under_today_text(self, text, errors, timeout=10): self.driver.info("Verifying that '%s' is under today" % text) message_element = self.chat_element_by_text(text) - message_element.wait_for_visibility_of_element() + message_element.wait_for_visibility_of_element(timeout) message_location = message_element.find_element().location['y'] today_text_element = self.element_by_text('Today').find_element() today_location = today_text_element.location['y'] @@ -1043,8 +1047,10 @@ class ChatView(BaseView): self.chat_message_input.click() self.show_stickers_button.click() self.get_stickers.click() - element = Button(self.driver, - xpath="//*[@content-desc='sticker-pack-name'][@text='%s']/..//*[@content-desc='sticker-pack-price']" % pack_name) + element = Button( + self.driver, + xpath="//*[@content-desc='sticker-pack-name'][@text='%s']/..//*[@content-desc='sticker-pack-price']" + % pack_name) element.scroll_to_element(depth=21) element.click() element.wait_for_invisibility_of_element() @@ -1118,7 +1124,7 @@ class ChatView(BaseView): "%I:%M %p") timestamp_obj = datetime.strptime(timestamp, '%I:%M %p') possible_timestamps_obj = [timestamp_obj + timedelta(0, 0, 0, 0, 1), timestamp_obj, - timestamp_obj - timedelta(0, 0, 0, 0, 1), timestamp_obj - timedelta(0, 0, 0, 0, 2)] + timestamp_obj - timedelta(0, 0, 0, 0, 1), timestamp_obj - timedelta(0, 0, 0, 0, 2)] timestamps = list(map(lambda x: x.strftime("%I:%M %p"), possible_timestamps_obj)) final_timestamps = [t[1:] if t[0] == '0' else t for t in timestamps] return final_timestamps @@ -1146,7 +1152,8 @@ class ChatView(BaseView): self.chat_message_input.send_keys("@") try: self.mentions_list.wait_for_element() - self.driver.find_element(MobileBy.XPATH, "//*[@content-desc='user-list']//*[@text='%s']" % user_name).click() + self.driver.find_element(MobileBy.XPATH, + "//*[@content-desc='user-list']//*[@text='%s']" % user_name).click() except TimeoutException: self.driver.fail("Mentions list is not shown")