Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Выбор, установка и настройка плагина Allure для Pytest

pytest
allure
testng
python
Теги: #<Tag:0x00007fedbc62e3d0> #<Tag:0x00007fedbc62e218> #<Tag:0x00007fedbc62df98> #<Tag:0x00007fedbc62dd40>

(Natalia Abakumova) #1

Уважаемые тестировщики, объясните пожалуйста новичку, какой плагин для генерации отчетов Allure использовать для Pytest и как его правильно установить и настроить? Я просмотрела все плагины, но ни с одним не смогла разобраться. Если можно, объясните чайнику пошагово. Заранее благодарю!


Allure - подборка типичных проблем возникающих в процессе использования и их решения
(rmerkushin) #2
  1. Установка Allure Commandline:
    Download the latest version as zip archive from https://github.com/allure-framework/allure-core/releases/latest.
    Unpack the archive to allure-commandline directory.
    Navigate to bin directory.
    Use allure.bat for Windows and allure for other Unix platforms.

  2. Установка allure-adaptor для #pytest

pip install pytest-allure-adaptor

Использование:

py.test --alluredir [path_to_report_dir]
allure generate directory-with-results/

P.S.: Еще советую посмотреть статью от Яндекса: https://habrahabr.ru/company/yandex/blog/242795/


(Natalia Abakumova) #3

Благодарю! Я попыталась это сделать еще до создания темы, но, видимо, неправильно пишу вот эту часть py.test --alluredir [path_to_report_dir]. Вы не могли бы подсказать, к чему именно нужно указать этот путь (я не очень понимаю, что за report_dir - это папка с тестом, или с аллюром, или с плагином, или просто новая) и как он правильно пишется? На примере. Поясните пожалуйста темному человеку.


(Дмитрий Золкин) #4

У меня вот такой скрипт и работает.
py.test [название теста который запускаю].py -v --assert=‘plain’ --alluredir report(директория куда положить отчет)
allure generate /root/Pycharm/tests_pytest/report -o /root/Pycharm/tests_pytest/report (в этой директории после прохождения теста создается index.html и еще куча файлов.При открытии index.html показывается отчет в браузере.


(Natalia Abakumova) #5

Спасибо!
Я пробую, вот что:
py.test test_func1.py --alluredir=report
allure generate /report/test1

Во-первых, прошу прощения за глупый вопрос - как в командной строке сделать перенос для вставки такой конструкции? Иначе команды выполняются сначала одна, потом другая… или так и должно быть…?
Во-вторых, при запуске первой строки py.test test_func1.py --alluredir=report пишет мне вот что:
platform win32 – Python 3.5.2, pytest-2.9.0, py-1.4.32, pluggy-0.3.1
rootdir: C:\Python\python+selenium\Тестирование\sberbank\test, inifile:
plugins: allure-adaptor-1.7.6
collected 0 items / 1 errors

=================================== ERRORS ====================================
_______________________ ERROR collecting test_func1.py ________________________
test_func1.py:93: in
money.test_input_amount()
c:\users\nsaba\appdata\local\programs\python\python35-32\lib\site-packages\allure\common.py:56: in impl
with StepContext(self.allure, self.title.format(*a, **kw)):
c:\users\nsaba\appdata\local\programs\python\python35-32\lib\site-packages\allure\common.py:34: in enter
self.step = self.allure.start_step(self.title)
c:\users\nsaba\appdata\local\programs\python\python35-32\lib\site-packages\allure\pytest_plugin.py:159: in start_step
self.stack[-1].steps.append(step)
E AttributeError: ‘AllureTestListener’ object has no attribute ‘stack’
=========================== 1 error in 3.65 seconds ===========================
Что ж такое…


(Maxim Zaitsev) #6

Путь к папке, в которой будут собираются файлы для отчета

directory-with-results == path_to_report_dir


(Natalia Abakumova) #7

Так значит это одна и та же папка?


(Maxim Zaitsev) #8

Ага


(Natalia Abakumova) #9

Благодарю! Я примерно так и сделала, но вот вылезла ошибка - E AttributeError: ‘AllureTestListener’ object has no attribute ‘stack’ - не подскажете, как с этим бороться? Сам тест без allure в командной строке работает без ошибок.


(Maxim Zaitsev) #10

Давайте посмотрим на код теста money.test_input_amount()


(Natalia Abakumova) #11

Только не пугайтесь, я знаю, что там много костылей и все ужасно и сыро)) Я в самом начале пути :slight_smile:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
import pytest
import allure
import time

driver = webdriver.Chrome()

@allure.feature('Функциональное тестирование')
@allure.story('Ввод суммы для конвертации, получение результата, проверка того, что использовалась    введенная нами сумма')
class CalculatorMoneyCurrency:
@allure.step('Запуск браузера Chrome, открытие и загрузка страницы с кальулятором.')
def setup_method(self):
    
    """
    Открытие браузера Chrome v. 55.0.2883.87 m (64-bit)
    Загрузка калькулятора иностранных валют
    Проверка работоспособности поля ввода суммы и кнопки "Показать" для получения резульатата
    """
    
    driver.maximize_window()
    driver.get('http://www.sberbank.ru/ru/quotes/converter')
    assert 'Калькулятор иностранных валют' in driver.title
    driver.implicitly_wait(15)

@allure.step('Возврат в исходное состояние, закрытие браузера.')
def teardown_method(self):
    
    """
    Закрытие браузера
    """
    
    driver.quit()

@allure.step('Ввод валидных данных в поле ввода суммы и проверка результата.')
def test_input_amount(self):
    
        amount = ['1', '1 250', '999 999 999 999', '3 600,57', '666 745,95'] #список валидных вводных данных (с пробелами, чтобы проще было сравнить потом с результатом, который тоже выводится с пробелами)
        start_end = CalculatorMoneyCurrency() #готовим страницу, открываем сайт, дожидаемся загрузки всех элементов
        start_end.setup_method()
        input_amount_field = driver.find_element_by_xpath("//input[@data-reactid='.0.$1.$0.0.1.0.0.0']") #находим поле для ввода суммы для конвертации
        input_amount_field.click() #кликаем по полю для ввода суммы
        
        for option in amount: #перебираем варианты вводимых данных
            input_amount_field.clear() #очищаем поле
            input_amount_field.send_keys(option) #вводим значения по очереди из списка правильных вариантов
            button_convert = driver.find_element_by_xpath("//button[@data-reactid='.0.$1.$0.6.0']").click() #клик по кнопке "Показать" конвертера

            with allure.step('При вводе валидных данных появляется результат конвертации'):
                assert driver.find_element_by_xpath("//div[@class='converter-result' and @data-reactid='.0.$1.$1']"), 'Конвертация не осуществлена.' #подтверждаем, что появился блок с результатом конвертации
                                    
                time.sleep(1)
                num1 = driver.find_element_by_xpath("//span[@data-reactid='.0.$1.$1.1.0']").text #сумма 1 (отображается в результатах)
                val1 = driver.find_element_by_xpath("//span[@data-reactid='.0.$1.$1.1.1']").text #валюта 1 (отображается в результатах)
                #option = option + ',00' #добавляем десятичную часть, чтобы можно было сравнить с выводимым текстовым результатом (убеждаемся, что это не сумма по умолчанию)
                if ',' not in option: #если нет дробной части в варианте (точки), то добавляем ее, чтобы можно было сравнить с информацией в результате
                    option = option + ',00'

                with allure.step('Сравниваем введенную сумму с отображаемой в резульате'):
                    assert option == num1, 'Суммы не совпадают.'

        start_end.teardown_method() #возвращаем страницу в исходное состояние (закрываем)

money = CalculatorMoneyCurrency()
money.test_input_amount()

Здесь нужно применять параметризацию, но я пока не научилась :slight_smile:


(Ильдар Бекмансуров) #12

На всякий случай дополню, что после выполнения allure generate directory-with-results/ отчет в виде index.html сгенерится в allure-commandline/bin/allure-report/
Если же хочется поместить этот index.html куда-то в другое место, то выполняем
allure generate directory-with-results/ -o directory-where-u-want-indexhtmlreport-to-be-generated/


(Natalia Abakumova) #13

Спасибо, полезная информация!


(Maxim Zaitsev) #14

Поправил код. Браузер использовал FireFox. Что-то хром у меня глючит на компе.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
import pytest
import allure
import time

driver = webdriver.Firefox()

@allure.feature('Функциональное тестирование')
@allure.story('Ввод суммы для конвертации, получение результата, проверка того, что использовалась    введенная нами сумма')
class TestCalculatorMoneyCurrency:
    @allure.step('Запуск браузера Chrome, открытие и загрузка страницы с кальулятором.')
    def setup_method(self, method):

        """
        Открытие браузера Chrome v. 55.0.2883.87 m (64-bit)
        Загрузка калькулятора иностранных валют
        Проверка работоспособности поля ввода суммы и кнопки "Показать" для получения резульатата
        """

        driver.maximize_window()
        driver.get('http://www.sberbank.ru/ru/quotes/converter')
        assert 'Калькулятор иностранных валют' in driver.title
        driver.implicitly_wait(15)

    @allure.step('Возврат в исходное состояние, закрытие браузера.')
    def teardown_method(self, method):

        """
        Закрытие браузера
        """

        driver.quit()

    @allure.step('Ввод валидных данных в поле ввода суммы и проверка результата.')
    def test_input_amount(self):

            amount = ['1', '1 250', '999 999 999 999', '3 600,57', '666 745,95'] #список валидных вводных данных (с пробелами, чтобы проще было сравнить потом с результатом, который тоже выводится с пробелами)
            input_amount_field = driver.find_element_by_xpath("//input[@data-reactid='.0.$1.$0.0.1.0.0.0']") #находим поле для ввода суммы для конвертации
            input_amount_field.click() #кликаем по полю для ввода суммы

            for option in amount: #перебираем варианты вводимых данных
                input_amount_field.clear() #очищаем поле
                input_amount_field.send_keys(option) #вводим значения по очереди из списка правильных вариантов
                button_convert = driver.find_element_by_xpath("//button[@data-reactid='.0.$1.$0.6.0']").click() #клик по кнопке "Показать" конвертера

                with allure.step('При вводе валидных данных появляется результат конвертации'):
                    assert driver.find_element_by_xpath("//div[@class='converter-result' and @data-reactid='.0.$1.$1']"), 'Конвертация не осуществлена.' #подтверждаем, что появился блок с результатом конвертации

                    time.sleep(1)
                    num1 = driver.find_element_by_xpath("//span[@data-reactid='.0.$1.$1.1.0']").text #сумма 1 (отображается в результатах)
                    val1 = driver.find_element_by_xpath("//span[@data-reactid='.0.$1.$1.1.1']").text #валюта 1 (отображается в результатах)
                    #option = option + ',00' #добавляем десятичную часть, чтобы можно было сравнить с выводимым текстовым результатом (убеждаемся, что это не сумма по умолчанию)
                    if ',' not in option: #если нет дробной части в варианте (точки), то добавляем ее, чтобы можно было сравнить с информацией в результате
                        option = option + ',00'

                    with allure.step('Сравниваем введенную сумму с отображаемой в резульате'):
                        assert option == num1, 'Суммы не совпадают.'


(Maxim Zaitsev) #15

Основные ошибки:

  1. Имя класса должно начинаться на Test
  2. setup_method и teardown_method - эти методы вызываются pytest автоматически. Не нужно их дополнительно вызывать в теле самого теста
  3. Инициализация тестового класса и запуск его методов происходит также автоматически. Нет нужды прописывать это вручную (последние две строчки)

(Natalia Abakumova) #16

Спасибо! Я попробовала ваш код у себя с запуском в Хроме, больше ничего не делала, но не работает(


(Natalia Abakumova) #17

Что-то у меня не вяжется с этими setup и teardown. Я переписала код следующим образом:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
import pytest
import allure
import time

driver = webdriver.Chrome()

def setup_method(self, method):
    driver.maximize_window()
    driver.get('http://www.sberbank.ru/ru/quotes/converter')
    assert 'Калькулятор иностранных валют' in driver.title
    driver.implicitly_wait(15)

def teardown_method(self, method):
    driver.quit()

def get_text(xpath_get_text):
    global var_get_text
    var_get_text = driver.find_element_by_xpath(xpath_get_text).text
    
def click(var_click, xpath_click):
    var_click = driver.find_element_by_xpath(xpath_click)
    var_click.click()

def clear_field(var_field, xpath_field):
    var_field = driver.find_element_by_xpath(xpath_field)
    var_field.clear()

def input_data(var_input, xpath_input, keys):
    var_input = driver.find_element_by_xpath(xpath_input)
    var_input.send_keys(keys)
    
    

def test_input_amount(self):
    amount = ['1', '1 250', '999 999 999 999', '3 600,57', '666 745,95']
    setup_method()
    click('field', "//input[@data-reactid='.0.$1.$0.0.1.0.0.0']")
    for option in amount:
        clear_field('field', "//input[@data-reactid='.0.$1.$0.0.1.0.0.0']")
        input_data('summa', "//input[@data-reactid='.0.$1.$0.0.1.0.0.0']", option)
        click('convert-result', "//button[@data-reactid='.0.$1.$0.6.0']")
        assert driver.find_element_by_xpath("//div[@class='converter-result' and @data-reactid='.0.$1.$1']"), 'Конвертация не осуществлена.'
        time.sleep(1)
        get_text("//span[@data-reactid='.0.$1.$1.1.0']")
        if ',' not in option:
            option = option + ',00'
        assert option == var_get_text, 'Суммы не равны.'
    teardown_method()

test_input_amount()

Я убирала сетап, тирдаун и последнюю строчку из кода, но тогда ничего не работает. Плюс при записи setup_method(self, method) и teardown_method(self, method) - ругается: TypeError: setup_method() missing 2 required positional arguments: ‘self’ and ‘method’. Если убираю аргументы и оставляю пустые скобки - все работает.
Дальше - если заменяю на setup_module(module), то ругается потом, что не находит элемент на странице (ибо страницу не открыл, а значит модуль не сработал, собственно, но на сам модуль уже не ругается). Никак не могу понять, как правильно нужно их использовать.
Ну и без последней строчки тоже… может я неправильно запускаю вообще тест? Редактирую код в Python Shellб запускаю там же.


(Maxim Zaitsev) #18

Давайте пока остановимся на моем варианте. У меня он точно работает. Какая у вас ошибка возникает?


(Natalia Abakumova) #19

Ошибок не пишет, открывает браузер и все, страницу не загружает. Попробовала как в Хроме, так и Мозилле.
Для верности еще раз скопировала ваш код, только мне к Мозилле вот такую шляпу приходится писать:
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
binary = FirefoxBinary(r’C:\Program Files (x86)\Mozilla Firefox\firefox.exe’)
driver = webdriver.Firefox(firefox_binary=binary)

Но это рабочий код, проверенный.


(Maxim Zaitsev) #20

Похоже на проблему совместимости версий браузера и селениума. Попробуйте обновить пакеты:
1)

pip install selenium --upgrade
  1. Свежий драйвер хрома:
    https://sites.google.com/a/chromium.org/chromedriver/downloads