воскресенье, 29 ноября 2020 г.

суббота, 24 октября 2020 г.

Использование переменной в локаторе (XPATH).

Нужно проверить правильная ли цена отображается на сайте.

Переменная var будет разной в зависимости от продукта (или региона, например). 

Мы можем использовать данную функцию для поиска и проверки всех цен, меняется только  expected_price и var.


@allure.step("Check that price is correct")
def is_price_correct(driver, expected_price, var):
price_locator = (
By.XPATH,
'//div[@id="buySASub1"]//span[contains(@data-type, "upgrade")
         and contains(@data-tier, "'+var+'")]'
)
return is_element_price_correct(driver, expected_price, price_locator)

пятница, 23 октября 2020 г.

Как правильно переносить текст при использовании CSS-селекторов (CSS-Selector)

  def click_buy_button(driver):

    a_button_locator = (

        By.XPATH, 

        "//a[contains(@class, 'product-purchase') "

        "and contains(@href, '" + Config.ps_base_url + "')]"

    )

    a_button = Button(driver, a_button_locator)

    a_button.click()

Описание XPath с помощью Contains

 Contains примеры:


1) Класс

//a[contains(@class, 'product-formatted-price')



2) Текст


a[contains(text(),"Get")]



3) Ссылку


//a[contains(@class, 'product-purchase') and contains(@href, '" + Config.ps_base_url + "')]



4) ID


//div[contains(@id,"content")]



5) Другие (data-type...)


//span[contains(@data-type, 'no')]



6) Содержит сразу 2 условия


//span[contains(@data-type, 'no') and contains(@data-time, '0')]



7) Описать элемент, который находится внутри секции buySub1


//div[@id="buySub1"]//span[contains(@data-type, 'no') and contains(@data-tier, '0')]

четверг, 22 октября 2020 г.

Как обновить Allure, Pytest, Selenium и др. в PyCharm. Как использовать Pytest в PyCharm

Чтобы использовать Pytest для тестирования в PyCharm:

1. PyCharm - Preferences


2. Tools - Python Integrated Tools

3. В Default test runner выбираем Pytest



4. Apply - Сохраняем изменения


 Чтобы ОБНОВИТЬ пакеты программ для Python в PyCharm (Allure, Pytest, Selenium, BrowserStack Local, Pip, Cryptography, myOpenSSL, Webdriver Manager и другие):

1. PyCharm - Preferences

2. Project (там должен быть указан ваш проект) - Python Interpreter


3. В первой колонке видим все уже установленные пакеты, во второй - текущая версия пакета, в трeтьей - доступная последняя версия.
Если текущая и последняя версия не совпадают, то мы видим треугольник возле Latest Version, это означает, что мы можем ее обновить.



4. Для того, чтобы обновить пакет ставим курсор на нужную строку (в примере выше это attrs), кликаем на треугольничек внизу (выделила его на рисунке). Пакет обновится.



Установить ALLURE для Mac (Мак)

 Чтобы установить Allure (Алюр) на ваш компьютер в Терминале введите следуюший текст:




- для Mac

brew install allure

вторник, 20 октября 2020 г.

Switch to iFrame - Если нужно переключиться на frame и обратно

Например, существует иконка Помощника (Help), которая должна отображаться на всех страницах вебсайта. Пользователь может кликнуть на нее и пообщаться с Службой поддержки.

Сейчас существует много сервисов, которые позволяют использовать их инструмент для такого окна - Intercom, Helpscout, Zendesk....


АВТОТЕСТ:

- Проверить, что иконка помощника отображается на странице. 

Открываем trial_download_signup_page старницу.

Переключаемся на Frame, где эта иконка находится. Потом ищем иконку, проверяем ее видимость на странице и переключаемся обратно на исходную страницу.

Дальше нам надо еще ввести и-мейл, согласиться с условиями и кликнуть кнопку Download.

На открывшейся старницы мы тоже проверяем наличие Help иконки.


Для переключения на рамку будем использовать функцию - switch_to_frame 

Для возвращения на исходную страницу - switch_to_default_content


def test_user_should_see_help_icon_on_trial_download_signup_page(driver):
trial_download_signup_page.open(driver)
assert trial_download_signup_page.help.is_icon_displayed(driver), \
"Help icon is not displayed on Trial Download Signup page"
driver.switch_to_default_content()
trial_download_signup_page.set_email(driver, TestData.get_random_email())
trial_download_signup_page.agree_to_terms_and_policy(driver)
trial_download_signup_page.click_download_button(driver)
assert trial_download_signup_page.help.is_icon_displayed(driver), \
"Help icon is not displayed on SA Signup Follow page"

in Help file:

@allure.step("Check if Help icon is displayed on the page")
def is_icon_displayed(driver):
iframe = HtmlElement(driver, (By.CSS_SELECTOR, "selector"
]'))
iframe.
switch_to_frame()
help_icon = HtmlElement(driver, (By.CSS_SELECTOR, "selector"
]'))
return helpscout_icon.is_element_visible()

Как проверить что элемент содержит определенный класс (пример - Error class)?

 

Как проверить что элемент содержит определенный класс? Python-Selenium



Задача:

Существует форма, которую пользователь должен заполнить. В форме есть обязательные поля. Если пользователь их не заполнил, то поле подсвечивается красным цветом. За подсветку поля отвечает класс ERROR. Этот класс присваивается элементу, если поле не заполнено.

Нужно проверить содержит ли элемент этот класс. Задача усложняется тем,  что все элементы имеют не только этот один класс, а нужно проверить именно его наличие.


def test_user_should_see_warning_if_fields_are_not_filled(driver):
    support_page.open(driver)
    support_page.click_send_message_button(driver)
   assert support_page.is_name_field_has_error_class(driver), \
       "The Name field has no Error class"

@allure.step("Check that Name field has Error class when this field does not filled")
def is_name_field_has_error_class(driver):
    name_input_field = HtmlElement(driver, (By.CSS_SELECTOR, '[name="name"]'))
    return 'error' in name_input_field.get_attribute("class")

class HtmlElement:
    def __init__(self, driver, locator):
        self.driver = driver
        self.element_locator = locator

def get_attribute(self, attribute_name, timeout=30):
    wait = WebDriverWait(self.driver, timeout)
    try:
        element = wait.until(expected_conditions.presence_of_element_located(self.element_locator))
        return element.get_attribute(attribute_name)
    except TimeoutException:
        raise NoSuchElementException("Can't find element with locator " + str(self.element_locator) +
                                     " after " + str(timeout) + " seconds.")

понедельник, 19 октября 2020 г.

Как проверить, чтобы статистика передается в Facebook и Google Analytics.

 Наш сайт использует GTM (Google Tag Manager) для сбора статистики для Гугл Аналитикс (Google Analytics) и Фейсбук (Facebook). 

Чтобы проверить что сайт отправляет запрос на GA и Facebook нужно сделать следующие шаги:

1. Заходим в DevTools - Inspect

2. Выбираем Network

3. Ставим галочку Preserve Log


4. В окошко Filter вводим facebook (для Facebook проверки) или collect (для Google Analytics) после выполнения действия, которое должно быть записано в аналитику.

5. Выбираем закладку Headers

6. Ищем там Query String Parameters


7. Для Facebook ищем - ev - Pageview  or Lead or Complete Registration (это зависит от того, как ваши события названы в FB)
Для GA - t - Pageview or Event.


 Вывод - событие Event (в данном примере) передается в Гугл Аналитику.




суббота, 23 мая 2020 г.

Тип данных - Словарь (Dictionary)

Иногда обычного списка недостаточно.
Например мы имеем список с оценками студентов за экзамен

student_grades = [12, 5, 6, 10, 11, 10, 9, 8, 7]

Но имея этот список мы не знаем какой студент получил какую оценку. Чтобы привязать имя студента к оценке, мы используем Dictionary (Словарь):

student_grades = {"Marie": 12, "John": 5, "Max": 6, "Michael": 10, "Anna": 11}


Marie - это ключ (key)
12 - это значение (value)


МЕТОД 1 - VALUES()

Используется, чтобы получить значения (value) из словаря (dictionary).

student_grades.values()

Получаем список только из значений:
dict_values = ([12, 5, 6, 10, 11])

Если нам нужно посчитать СРЕДНЮЮ оценку

sum = sum(student_grades.values())

length = len(student_grades)

average = sum/length

print(average)


МЕТОД 2 - KEYS()


student_grades.keys()

dict_keys = (['Marie', 'John', 'Max', 'Michael', 'Anna'])



Все методы, которые мы можем использовать с переменной


['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']


class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)
 |  
 |  Built-in subclasses:
 |      StgDict
 |  
 |  Methods defined here:
 |  
 |  __contains__(self, key, /)
 |      True if the dictionary has the specified key, else False.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __ior__(self, value, /)
 |      Return self|=value.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __or__(self, value, /)
 |      Return self|value.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(self, /)
 |      Return a reverse iterator over the dict keys.
 |  
 |  __ror__(self, value, /)
 |      Return value|self.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -> size of D in memory, in bytes
 |  
 |  clear(...)
 |      D.clear() -> None.  Remove all items from D.
 |  
 |  copy(...)
 |      D.copy() -> a shallow copy of D
 |  
 |  get(self, key, default=None, /)
 |      Return the value for key if key is in the dictionary, else default.

Пример

Вывести оценку определенного студента


student_grades = {"Marie": 12, "John": 5, "Max": 6, "Michael": 10, "Anna": 11}

marie_grade = student_grades.get("Marie")

print(marie_grade)



 |  
 |  items(...)
 |      D.items() -> a set-like object providing a view on D's items
 |  
 |  keys(...)
 |      D.keys() -> a set-like object providing a view on D's keys
 |  
 |  pop(...)
 |      D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
 |      
 |      If key is not found, default is returned if given, otherwise KeyError is raised
 |  
 |  popitem(self, /)
 |      Remove and return a (key, value) pair as a 2-tuple.
 |      
 |      Pairs are returned in LIFO (last-in, first-out) order.
 |      Raises KeyError if the dict is empty.
 |  
 |  setdefault(self, key, default=None, /)
 |      Insert key with a value of default if key is not in the dictionary.
 |      
 |      Return the value for key if key is in the dictionary, else default.
 |  
 |  update(...)
 |      D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
 |      If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
 |      If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
 |      In either case, this is followed by: for k in F:  D[k] = F[k]
 |  
 |  values(...)
 |      D.values() -> an object providing a view on D's values
 |  
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |  
 |  __class_getitem__(...) from builtins.type
 |      See PEP 585
 |  
 |  fromkeys(iterable, value=None, /) from builtins.type
 |      Create a new dictionary with keys from iterable and values set to value.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None



Посчитать сколько раз элемент встречается в списке

Например, нам надо посчитать сколько студентов с балом 10 в списке.

student_grades list содержит оценки студентов за экзамер.

Функция COUNT() считает сколько раз определенный элемент попадается в списке.




student_grades = [9.1, 8.8, 10.0, 7.7, 6.8, 8.0, 10.0, 8.1, 10.0, 9.9]
n = student_grades.count(10.0)
print(n)

Результат:
3

Самые полезные ФУНКЦИИ Пайтона

 1)  PRINT - выводит на печать переменную, указанную в скобках print (average)   2)  LEN - посчитать количество элементов в списке student...