Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Allow attaching screenshot and video into Allure report #77

Open
YusukeIwaki opened this issue Sep 24, 2021 · 4 comments
Open

Comments

@YusukeIwaki
Copy link

YusukeIwaki commented Sep 24, 2021

I usually use Allure report with PyTest+Playwright.

Test code (intented to fail)

from playwright.sync_api import Page


def test_github_search(page: Page):
    page.goto('https://github.com/')
    page.focus('input[name="q"]')
    page.keyboard.type('playwright')
    with page.expect_navigation():
        page.keyboard.press('Enter')
    first_item = page.query_selector_all('.repo-list-item')[0]
    assert 'Playwright' in first_item.text_content()

Motivation

I want to store the video for failed tests.
I don't want to keep sitting at the laptop for observing flaky test failure :)

So I used to attach video into Allure report.
https://zenn.dev/yusukeiwaki/articles/cfda648dc170e5#%E3%83%86%E3%82%B9%E3%83%88%E5%A4%B1%E6%95%97%E6%99%82%E3%81%AE%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AB%E5%8B%95%E7%94%BB%E3%82%92%E6%B7%BB%E4%BB%98%E3%81%99%E3%82%8B (Sorry in Japanese)

image

When we handle a lot of test cases, it is useful to put screenshot and video into Allure report (not in test-report directory), because it is really hard to find the video file from a list of many files for each failure.

Problem

#70 brought very useful feature. Thank you :)

However it doesn't put video and screenshots into Allure report as attachments.
For putting them into Allure report, we still have to write the script like below.

from playwright.sync_api import Page
import pytest
import allure
from slugify import slugify


def pytest_runtest_makereport(item, call) -> None:
    if call.when == "call":
        if call.excinfo is not None and "page" in item.funcargs:
            page: Page = item.funcargs["page"]

            # ref: https://stackoverflow.com/q/29929244
            allure.attach(
                page.screenshot(type='png'),
                name=f"{slugify(item.nodeid)}.png",
                attachment_type=allure.attachment_type.PNG
            )

            video_path = page.video.path()
            page.context.close()  # ensure video saved
            allure.attach(
                open(video_path, 'rb').read(),
                name=f"{slugify(item.nodeid)}.webm",
                attachment_type=allure.attachment_type.WEBM
            )


@pytest.fixture()
def browser_context_args(browser_context_args, tmpdir_factory: pytest.TempdirFactory):
    return {
        **browser_context_args,
        "record_video_dir": tmpdir_factory.mktemp('videos')
    }

Feature Request

Attach screenshot and videos into Allure report when --alluredir is specified (of cource only when --video=on/retain-on-failure or --screenshot=on/retain-on-failure is specified)

@ksdaftari
Copy link

ksdaftari commented Mar 21, 2022

@YusukeIwaki curious did you get similar code to work for trace zip file to attach to allure report? and just so understand your code does this only attach video/screenshot on failure? or this actually integrating with --video=on option? from testing think just on failure (is getting to run all as simple as changing if call.excinfo is not None and "page" in item.funcargs to instead be if "page" in item.funcargs ?

@ksdaftari
Copy link

ksdaftari commented Mar 21, 2022

One thing (and perhaps this question best serviced and asked https://github.com/microsoft/playwright-python) but was thinking that would be nice in general for screenshot/videos/trace if had option to get file so could and just use allure.attach. would have similar code when using selenium that would something like below

allure.attach(driver.get_screenshot_as_png(), name=description, attachment_type=allure.attachment_type.PNG)

@CB-KevinChow
Copy link

Hello, it's a kind follow-up if this feature request will be worked on. Thanks!

@Romarionijim
Copy link

Romarionijim commented Mar 24, 2024

@YusukeIwaki I saw your article and I like your solution and it does attach screenshot and videos on test failure, however with my current setup in addition to your makereport function, I seem to have a slight conflicting problem.
the problem is because it is a session scoped fixture, if one test fails - it disables the rest of the tests in the same file resulting in an error that the target context is already closed,
and if I don't closed the context manually like you did in the fixture, the video does not actually get attached, do you have a workaround maybe for this issue?

my current setup:

import os

import allure
import pytest
from playwright.sync_api import Page
from slugify import slugify
import json

@pytest.fixture(scope='function', autouse=True)
def goto(page, request):
base_url = request.config.getoption("--base-url")
print("Base URL:", base_url)
page.goto(base_url)

@pytest.fixture(scope="session")
def playwright_launch_args():
launch_options = {}
if os.environ.get('CI'):
launch_options['headless'] = True
else:
launch_options['headless'] = False
launch_options['slow_mo'] = 500
return launch_options

@pytest.fixture(scope="session")
def playwright_context_args():
return {
"viewport": {"width": 1400, "height": 900},
}

@pytest.fixture(scope="session")
def browser_type(playwright, request):
specified_browser = request.config.getoption("--custom-browser")
return playwright[specified_browser]

@pytest.fixture(scope="session")
def page_context(browser_type, playwright_launch_args, playwright_context_args):
browser = browser_type.launch(**playwright_launch_args)
context = browser.new_context(**playwright_context_args, record_video_dir="videos/")
yield context
context.close()
browser.close()

@pytest.fixture(scope="function", autouse=True)
def page(page_context):
page: Page = page_context.new_page()
yield page
page.close()

def pytest_runtest_makereport(item, call) -> None:
if call.when == "call":
if call.excinfo is not None and "page" in item.funcargs:
page: Page = item.funcargs["page"]
allure.attach(
page.screenshot(type='png'),
name=f"{slugify(item.nodeid)}.png",
attachment_type=allure.attachment_type.PNG
)
video_path = page.video.path()
page.context.close() # ensure video saved
allure.attach(
open(video_path, 'rb').read(),
name=f"{slugify(item.nodeid)}.webm",
attachment_type=allure.attachment_type.WEBM
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants