Спасибо, за наводку. Даж когда-то читал эту тему xD. В этом варианте мне придется каждый тест(или класс) отметить фикстурой. Неплохо. Но хочется лучше.
Selene так и так делает скриншот. Всего-то нужно изменить подход: вместо сохранения в папку, прикреплять к отчету. Может у разработчиков есть планы по реализации такого функционала через конфиг ? @Ayia @Sergey_Pirogov
Не вместо, а просто крепить к отчету. В selene есть метод get_latest_screenshot
Да, метод такой есть. И я так понимаю, возможный вариант его использования следующий:
в базовый класс тестов в teardown_method я прописываю функцию, которая будет проверять, есть ли последний скриншот, и если есть, то прикреплять его к отчету.
Безусловно, это вариант будет лучше, чем прописывать фикстуры для каждого класса. Но отчет будет выглядеть коряво: файл со скриншот прикрепится в самый конец (а в не шаге с ошибкой) + будет информация о скриншоте, сохраненным на диск (а этот файл скорее всего не будет доступен пользователю). Ну и сам скриншот будет занимать места на харде в два раза больше.
Все верно?
Не верно. Посмотрите на форуме уже рассказывали как на экстеншин поставить вызов скриншота и прикрепить к отчету
Добрый день, подскажите. Как вы реализовали добавления скриншота к отчету. Спасибо
Пока остановился на варианте с хуком pytest_exception_interact
Скриншот прикрепляется к отчету, но и дублируется в папку, указанную в конфиге selene.
Наверное глупый вопрос, но где мне найти этот файл conftest.py ? Использую virtualenv мне непосредственно там надо найти и прописать pytest_exception_interact в conftest.py?
Файл conftest.py создается вручную и размещается в папке с тестами. Например, в такой структуре:
project_folder
- tests
-- conftest.py
-- test_something.py
-- test_something_2.py
Структуру понял, спасибо.
Добавил файл в conftest.py.
Вот такого он формата:
#!/usr/bin/env python
# -- coding: utf-8 --
# coding: utf8
import allure
def pytest_exception_interact(node, call, report):
** driver = node.instance.driver**
** allure.attach(**
** name=‘Скриншот’,**
** contents=driver.get_screenshot_as_png(),**
** type=allure.constants.AttachmentType.PNG,**
** )**
Но при запуске такое выводит:
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/main.py”, line 110, in wrap_session
INTERNALERROR> session.exitstatus = doit(config, session) or 0
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/main.py”, line 146, in _main
INTERNALERROR> config.hook.pytest_runtestloop(session=session)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 745, in call
INTERNALERROR> return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 339, in _hookexec
INTERNALERROR> return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 334, in
INTERNALERROR> _MultiCall(methods, kwargs, hook.spec_opts).execute()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 614, in execute
INTERNALERROR> res = hook_impl.function(*args)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/main.py”, line 169, in pytest_runtestloop
INTERNALERROR> item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 745, in call
INTERNALERROR> return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 339, in _hookexec
INTERNALERROR> return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 334, in
INTERNALERROR> _MultiCall(methods, kwargs, hook.spec_opts).execute()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 613, in execute
INTERNALERROR> return _wrapped_call(hook_impl.function(*args), self.execute)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 254, in _wrapped_call
INTERNALERROR> return call_outcome.get_result()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 280, in get_result
INTERNALERROR> _reraise(*ex) # noqa
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 265, in init
INTERNALERROR> self.result = func()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 613, in execute
INTERNALERROR> return _wrapped_call(hook_impl.function(*args), self.execute)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 254, in _wrapped_call
INTERNALERROR> return call_outcome.get_result()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 280, in get_result
INTERNALERROR> _reraise(*ex) # noqa
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 265, in init
INTERNALERROR> self.result = func()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 613, in execute
INTERNALERROR> return _wrapped_call(hook_impl.function(*args), self.execute)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 254, in _wrapped_call
INTERNALERROR> return call_outcome.get_result()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 280, in get_result
INTERNALERROR> _reraise(*ex) # noqa
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 265, in init
INTERNALERROR> self.result = func()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 614, in execute
INTERNALERROR> res = hook_impl.function(*args)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/runner.py”, line 68, in pytest_runtest_protocol
INTERNALERROR> runtestprotocol(item, nextitem=nextitem)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/runner.py”, line 82, in runtestprotocol
INTERNALERROR> reports.append(call_and_report(item, “call”, log))
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/runner.py”, line 168, in call_and_report
INTERNALERROR> hook.pytest_exception_interact(node=item, call=call, report=report)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 745, in call
INTERNALERROR> return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 339, in _hookexec
INTERNALERROR> return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 334, in
INTERNALERROR> _MultiCall(methods, kwargs, hook.spec_opts).execute()
INTERNALERROR> File “/Users/user/Desktop/autotesting2/config/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py”, line 614, in execute
INTERNALERROR> res = hook_impl.function(*args)
INTERNALERROR> File “/Users/user/Desktop/autotesting2/conftest.py”, line 9, in pytest_exception_interact
INTERNALERROR> driver = node.instance.driver
INTERNALERROR> AttributeError: TestSomeCase instance has no attribute ‘driver’
Или файл надо положить в virtualenv ?
Конечно, pytest traceback’i , бывают непонятными, но в данном случае, все очевидно.
В объекте класса TestSomeCase нет свойства ‘driver’
Каким образом у тебя драйвер попадает в тестовый класс ?
Использую Selene, при импорте его, как я понимаю и подтягивается драйвер.
Или його явно надо объявить ?
значит попробуй его импортнуть в этот хук напрямую:
def pytest_exception_interact(node, call, report):
from selene.browser import driver
# ...
allure.attach(
name='Скриншот',
contents=driver().get_screenshot_as_png(),
type=allure.constants.AttachmentType.PNG,
)
# ...
Данный хук работает, вот как выглядит финальный файл для селена
def pytest_exception_interact(node, call, report):
driver = node.instance.driver
# …
allure.attach(
name=‘Скриншот’,
body=browser.driver().get_screenshot_as_png(),
attachment_type=allure.attachment_type.PNG,
)
# …
- надо явно указать драйвер перед кейсами (для селена это так driver = browser.driver())
тесты запускал в PyCharm? из консоли ошибка та же? INTERNALERROR может быть от самого PyCharm
Перенес тесты на сервер. Теперь при “фэйле” тестов ошибка в файле conftest.py в котором лежит мой хук
INTERNALERROR> File “/home/autotesting2/conftest.py”, line 20, in pytest_exception_interact
INTERNALERROR> attachment_type=allure.attachment_type.PNG,
INTERNALERROR> AttributeError: ‘module’ object has no attribute ‘attachment_type’
Как я понимаю что какой-то модуль не установлен, может подскажите какой ?
Я полагаю, что дело не в модуле. Как-то криво код написан. Насколько я вижу по коду allure там нет свойства attachment_type.
Попробуй, как в моем примере:
Так и не смог найти информацию про то как работает driver = node.instance.driver.
Я так понимаю он пытается взять у класса driver. В самом классе у меня driver не прописывается, я его прописываю в функцию:
def test_check_price(self, driver, number_product, additionally__to_website)
Сам драйвер прописывается в conftest:
class ChromeDriverManager(object):
def __init__(self):
self._instance = None
def start(self, type='ff'):
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=1920x1080")
self._instance = webdriver.Chrome()
# self._instance = webdriver.Chrome(chrome_options=chrome_options)
return self._instance
@property
def instance(self):
if not self._instance:
self.start()
return self._instance
def stop(self):
self._instance.quit()
self._instance = None
Я не в полной мере понимаю как это все отрабатывает. Все работает - это главное.
Мне как то надо прописать в классе драйвер? Или в хук закинуть драйвер другим способом?
У меня ошибка аналогичная:
INTERNALERROR> AttributeError: TestSomeCase instance has no attribute ‘driver’
Я вставляю скрины, когда тест фейлится. Pytest + appium+allure.
Делаю это через хук pytest_runtest_makereport:
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
setattr(item, "rep_" + rep.when, rep)
return rep
@pytest.fixture(autouse=True, scope='session')
def driver(request, _device):
import allure
from appium import webdriver
from config.devices import devices
opt = _device
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=devices[opt]
)
driver.set_page_load_timeout(7)
yield driver
if request.node.rep_call.failed:
# Make the screen-shot if test failed:
try:
allure.attach(
driver.get_screenshot_as_png(),
name=request.function.__name__,
attachment_type=allure.attachment_type.PNG
)
except:
pass
driver.close_app()
А что так сложно? Можно просто заманкипатчить в рантайме метод снятия скриншота в selene, повесив декоратор в котором аттачить скриншот
Спасибо! Получилось таким способом, все работает )