Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Never create pull requests or push git branches without explicit confirmation fr

## Test Work

Use [Allure Test Agent](docs/allure-test-agent.md) for test-related work in this repository.
Use [Allure Agent Mode](docs/allure-agent-mode.md) for test-related work in this repository.

- Read `docs/allure-test-agent.md` before designing, writing, reviewing, validating, debugging, or enriching tests.
- Use the `$allure-test-agent` skill as the durable behavior guide when it is installed; this project file contains local commands and conventions.
- Read `docs/allure-agent-mode.md` before designing, writing, reviewing, validating, debugging, or enriching tests.
- Use the `$allure-agent-mode` skill as the durable behavior guide when it is installed; this project file contains local commands and conventions.
- If a command executes tests and its result will be used for smoke checking, reasoning, review, coverage analysis, debugging, or a user-facing conclusion, run it through `allure agent`.
- Use agent-mode execution for smoke checks too, even when the change is small or mechanical.
- If agent output is missing or incomplete, debug that first and treat console-only conclusions as provisional.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,6 @@
@Aspect
public class AllureAspectJ {

private static InheritableThreadLocal<AllureLifecycle> lifecycle = new InheritableThreadLocal<AllureLifecycle>() {
@Override
protected AllureLifecycle initialValue() {
return Allure.getLifecycle();
}
};

private static final ThreadLocal<AssertJRecorder> RECORDER = ThreadLocal.withInitial(AssertJRecorder::new);

private static final ThreadLocal<Boolean> RECORDING_MUTED = ThreadLocal.withInitial(() -> false);
Expand Down Expand Up @@ -158,27 +151,18 @@ public void softAssertionFailed(final AssertionError error) {
getRecorder().softAssertionFailed(error);
}

/**
* For tests only.
*
* @param allure allure lifecycle to set.
*/
public static void setLifecycle(final AllureLifecycle allure) {
lifecycle.set(allure);
clearContext();
}

/**
* Returns the lifecycle.
*
* @return the Allure lifecycle used by this integration
*/
public static AllureLifecycle getLifecycle() {
return lifecycle.get();
return Allure.getLifecycle();
}

/**
* Handles the clear context callback.
* Drops the calling thread's recorder state. Invoked by {@link AssertJLifecycleListener} at test boundaries so
* chain bookkeeping never accumulates across tests.
*/
public static void clearContext() {
RECORDER.remove();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
*/
package io.qameta.allure.assertj;

import io.qameta.allure.AllureExternalKey;
import io.qameta.allure.model.Stage;
import io.qameta.allure.model.Status;
import io.qameta.allure.model.StatusDetails;
import io.qameta.allure.model.StepResult;
import org.assertj.core.api.AbstractAssert;

import java.util.Optional;
import java.util.UUID;

/**
* Parent Allure step for one AssertJ assertion chain.
Expand Down Expand Up @@ -69,14 +69,14 @@ final class AssertJChain {

private static final String ASSERTJ_STEP_PREFIX = "assert ";

private final String uuid;
private final AllureExternalKey key;

private final AbstractAssert<?, ?> assertion;

private final StepResult step;

AssertJChain(final AbstractAssert<?, ?> assertion, final String subject) {
this.uuid = UUID.randomUUID().toString();
this.key = AllureExternalKey.random(AllureAspectJ.class);
this.assertion = assertion;
this.step = new StepResult()
.setName(chainName(subject))
Expand All @@ -86,8 +86,8 @@ final class AssertJChain {
.setStop(System.currentTimeMillis());
}

String getUuid() {
return uuid;
AllureExternalKey getKey() {
return key;
}

AbstractAssert<?, ?> getAssertion() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,10 @@ private void attachChain(final AllureLifecycle lifecycle,
final AssertJChain chain,
final AssertJOperation parentOperation) {
if (parentOperation == null) {
lifecycle.startStep(chain.getUuid(), chain.getStep());
lifecycle.stopStep(chain.getUuid());
lifecycle.getCurrentExecutableKey().ifPresent(parent -> {
lifecycle.startStep(parent, chain.getKey(), chain.getStep());
lifecycle.stopStep(chain.getKey());
});
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.qameta.allure.model.TestResult;
import io.qameta.allure.test.AllureFeatures;
import io.qameta.allure.test.AllureResults;
import io.qameta.allure.test.IsolatedLifecycle;
import org.assertj.core.api.AbstractStringAssert;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.assertj.core.api.SoftAssertions;
Expand All @@ -36,6 +37,7 @@
import static io.qameta.allure.test.RunUtils.runWithinTestContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
@IsolatedLifecycle
class AllureAspectJTest {

@AllureFeatures.Steps
Expand All @@ -44,7 +46,7 @@ void shouldCreateSemanticChainForScalarAssert() {
final AllureResults results = runWithinTestContext(() -> {
assertThat("Data")
.hasSize(4);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -67,7 +69,7 @@ void shouldUseAssertDescriptionAsChainName() {
assertThat((Object) null)
.as("Nullable object")
.isNull();
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -87,7 +89,7 @@ void shouldRenderByteArraysWithoutPayload() {
assertThat(value.getBytes(StandardCharsets.UTF_8))
.as("Byte array object")
.isEqualTo(value.getBytes(StandardCharsets.UTF_8));
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -105,7 +107,7 @@ void shouldRenderCollectionsAsSubjectsAndExpectedValuesAsValues() {
final AllureResults results = runWithinTestContext(() -> {
assertThat(Arrays.asList("a", "b"))
.containsExactly("a", "b");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -130,7 +132,7 @@ void shouldRenderSmallArraysAsValues() {

assertThat(new String[]{"alpha", "bravo"})
.containsExactly("alpha", "bravo");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -156,7 +158,7 @@ void shouldRenderTuplesAsValues() {
tuple("first", Status.PASSED),
tuple("second", Status.FAILED)
);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -178,7 +180,7 @@ void shouldRenderNullValuesInContainsExactlyInAnyOrder() {
final AllureResults results = runWithinTestContext(() -> {
assertThat(Arrays.asList(null, "a", "b"))
.containsExactlyInAnyOrder(null, "a", "b");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -203,7 +205,7 @@ void shouldRenderNullValuesAfterExtractingAndKeepLambdaVarargs() {
assertThat(model)
.extracting(TestResult::getDescription, TestResult::getDescriptionHtml)
.containsExactly(null, null);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -231,7 +233,7 @@ void shouldRenderFieldOrPropertyValueAssertions() {
final AllureResults results = runWithinTestContext(() -> {
assertThat(details)
.hasFieldOrPropertyWithValue("message", "Make the test failed");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -255,7 +257,7 @@ void shouldTruncateLongStepNamesAndAddOnlyTruncatedValuesAsParameters() {
final AllureResults results = runWithinTestContext(() -> {
assertThat(value)
.isEqualTo(value);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -294,7 +296,7 @@ void shouldCreateSeparateChainsForMultipleAssertThatCalls() {
assertThat(Arrays.asList("a", "b"))
.hasSize(2)
.contains("a");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -328,7 +330,7 @@ void shouldAttachOperationsToStoredAssertionInstances() {

a.isEqualTo("alpha");
b.isEqualTo("bravo");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -361,7 +363,7 @@ void shouldAvoidVerboseModelToStringPayloads() {
assertThat(Collections.singletonList(model))
.hasSize(1)
.containsExactly(model);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -408,7 +410,7 @@ void shouldKeepNavigationInsideTheSameChain() {
assertThat(Collections.singletonList(Collections.singletonList("delta")))
.flatExtracting(value -> value)
.containsExactly("delta");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -440,7 +442,7 @@ void shouldRenderSerializedLambdaMethodReferences() {
assertThat(Collections.singletonList(model))
.extracting((Function<TestResult, String> & Serializable) TestResult::getFullName)
.containsExactly("my.company.Test.testOne");
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand All @@ -458,7 +460,7 @@ void shouldMarkTheFailedHardAssertionOperation() {
final AllureResults results = runWithinTestContext(() -> {
assertThat("Data")
.hasSize(5);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -486,7 +488,7 @@ void shouldMarkTheFailedSoftAssertionOperationBeforeAssertAll() {
.as("Age")
.isEqualTo(26);
soft.assertAll();
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down Expand Up @@ -518,7 +520,7 @@ void shouldAttachNestedAssertionsUnderCallbackOperations() {
.startsWith("al")
.endsWith("ha")
);
}, AllureAspectJ::setLifecycle);
});

final TestResult result = assertOnlyOneResult(results);
assertThat(result.getSteps())
Expand Down
Loading
Loading