GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — AllureSelenide attaches Screenshot and Page source once per nesting level of SelenideLogger.step · Issue #1453 · allure-framework/allure-java

AllureSelenide attaches Screenshot and Page source once per nesting level of SelenideLogger.step #1453

New issue
Copy link
New issue
Copy link
Open
Bug
#1505
Open
AllureSelenide attaches Screenshot and Page source once per nesting level of SelenideLogger.step#1453
Bug
#1505
Copy link

Description

@mikashee
mikashee
opened on Oct 9, 2026
Issue body actions

What happened?

Summary

AllureSelenide.afterEvent attaches Screenshot and Page source on every SelenideLogger
event with status FAIL. It never checks whether the same failure was already captured, so a
single failure inside nested steps produces one pair of attachments per nesting level.

Why it happens

afterEvent captures unconditionally on FAIL:

public void afterEvent(final LogEvent event) {
    if (event.getStatus().equals(LogEvent.EventStatus.FAIL)) {
        lifecycle.getCurrentExecutableKey().ifPresent(owner -> {
            if (saveScreenshots) { ... addAttachment(owner, "Screenshot", ...) }
            if (savePageHtml)   { ... addAttachment(owner, "Page source", ...) }

SelenideLogger.step(...) is itself a SelenideLogger event, and SelenideLogger.wrap()
commits it as FAIL again while the exception propagates outwards:

catch (RuntimeException | Error e) {
    SelenideLogger.commitStep(log, e);   // -> afterEvent(FAIL) -> another screenshot
    throw e;
}

So the number of attachment pairs is (number of enclosing SelenideLogger.step calls) + 1.

How to reproduce

SelenideLogger.addListener("allure", new AllureSelenide().screenshots(true));
SelenideLogger.step("outer step", () -> SelenideLogger.step("inner step", () -> $("#missing").shouldBe(visible)));

Actual

Three Screenshot + Page source pairs for one failure:

  • [failed] $("outer step") <- Screenshot, Page source
    • [failed] $("inner step") <- Screenshot, Page source
      • [failed] $("#missing") should be(visible) <- Screenshot, Page source

Expected

One Screenshot and one Page source, attached to the innermost step where the failure
actually happened.

Impact

The duplicates are not copies — each one is a separate getScreenshotAs + getPageSource
round trip to the driver. On a mobile/Appium setup that costs seconds per failure, and the
later screenshots are taken after the Selenide timeout has already elapsed, so they show a
different (less useful) state than the one that caused the failure. The report also becomes
noticeably harder to read: the reader has to figure out which of the identical-looking
attachments is the relevant one.

Reproduces on 2.24.0 as well — the body of afterEvent is unchanged between 2.24.0 and
3.0.0, only the lifecycle API around it has moved.

Note on the obvious workaround

Skipping attachments for step wrappers (for example when event.getSubject() is empty) is
not sufficient. When non-Selenide code fails inside a step() — an assertion, an NPE, an API
or messaging error — the wrapper's FAIL event is the only one, and that is exactly the case
where a screenshot is most valuable. Deduplicating by the Throwable instead handles both
cases, because SelenideLogger.wrap() rethrows the same instance (walking the getCause()
chain also covers failures that get wrapped on the way out).

I have a working implementation of this as a subclass in our own project, with tests for all
four cases (Selenide failure through a wrapper, wrapped-in-cause failure, assertion failure
inside a wrapper, two distinct failures in one test).

Question before I send a PR

Which direction would you prefer?

  1. Fix the default — one attachment pair per failure, no new API. Cleaner, but changes
    behaviour for everyone on upgrade.
  2. Add an opt-in deduplicateAttachments(boolean), default false. Safe, but users have
    to discover it.

I'm ready to send a PR with unit tests for either — just let me know which one you'd accept.

Related: #1439 / #1440 touch getScreenshotBytes() in the same method, so there may be a
small conflict; happy to rebase on top of that PR.

What Allure Integration are you using?

allure-selenide

What version of Allure Integration you are using?

3.0.0

What version of Allure Report you are using?

2.19.0

Code of Conduct

  • I agree to follow this project's Code of Conduct
Reacted by USSQA

Activity

  1. mikashee
    added the
    Bug
    issue type on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Bug

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.