Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,17 @@ public AllureLifecycle() {
* @param writer the results writer.
*/
public AllureLifecycle(final AllureResultsWriter writer) {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
this.notifier = new LifecycleNotifier(
load(ContainerLifecycleListener.class, classLoader),
load(TestLifecycleListener.class, classLoader),
load(FixtureLifecycleListener.class, classLoader),
load(StepLifecycleListener.class, classLoader)
);
this(writer, getDefaultNotifier());
}

/**
* Creates a new lifecycle instance with specified {@link AllureResultsWriter}
* and {@link LifecycleNotifier}.
*
* @param writer the results writer.
*/
AllureLifecycle(final AllureResultsWriter writer, final LifecycleNotifier lifecycleNotifier) {
this.notifier = lifecycleNotifier;
this.writer = writer;
this.storage = new AllureStorage();
this.threadContext = new AllureThreadContext();
Expand Down Expand Up @@ -141,14 +145,16 @@ public void stopTestContainer(final String uuid) {
* @param uuid the uuid of container.
*/
public void writeTestContainer(final String uuid) {
final Optional<TestResultContainer> found = storage.removeContainer(uuid);
final Optional<TestResultContainer> found = storage.getContainer(uuid);
if (!found.isPresent()) {
LOGGER.error("Could not write test container: container with uuid {} not found", uuid);
return;
}
final TestResultContainer container = found.get();
notifier.beforeContainerWrite(container);
writer.write(container);

storage.remove(uuid);
notifier.afterContainerWrite(container);
}

Expand Down Expand Up @@ -243,7 +249,7 @@ public void updateFixture(final String uuid, final Consumer<FixtureResult> updat
* @param uuid the uuid of fixture.
*/
public void stopFixture(final String uuid) {
final Optional<FixtureResult> found = storage.removeFixture(uuid);
final Optional<FixtureResult> found = storage.getFixture(uuid);
if (!found.isPresent()) {
LOGGER.error("Could not stop test fixture: test fixture with uuid {} not found", uuid);
return;
Expand All @@ -253,7 +259,10 @@ public void stopFixture(final String uuid) {
notifier.beforeFixtureStop(fixture);
fixture.setStage(Stage.FINISHED);
fixture.setStop(System.currentTimeMillis());

storage.remove(uuid);
threadContext.clear();

notifier.afterFixtureStop(fixture);
}

Expand Down Expand Up @@ -298,7 +307,7 @@ public void scheduleTestCase(final String containerUuid, final TestResult result
public void scheduleTestCase(final TestResult result) {
notifier.beforeTestSchedule(result);
result.setStage(Stage.SCHEDULED);
storage.addTestResult(result);
storage.put(result.getUuid(), result);
notifier.afterTestSchedule(result);
}

Expand Down Expand Up @@ -389,7 +398,7 @@ public void stopTestCase(final String uuid) {
* @param uuid the uuid of test case to write.
*/
public void writeTestCase(final String uuid) {
final Optional<TestResult> found = storage.removeTestResult(uuid);
final Optional<TestResult> found = storage.getTestResult(uuid);
if (!found.isPresent()) {
LOGGER.error("Could not write test case: test case with uuid {} not found", uuid);
return;
Expand All @@ -398,6 +407,7 @@ public void writeTestCase(final String uuid) {
final TestResult testResult = found.get();
notifier.beforeTestWrite(testResult);
writer.write(testResult);
storage.remove(uuid);
notifier.afterTestWrite(testResult);
}

Expand Down Expand Up @@ -499,18 +509,21 @@ public void stopStep() {
* @param uuid the uuid of step to stop.
*/
public void stopStep(final String uuid) {
final Optional<StepResult> found = storage.removeStep(uuid);
final Optional<StepResult> found = storage.getStep(uuid);
if (!found.isPresent()) {
LOGGER.error("Could not stop step: step with uuid {} not found", uuid);
return;
}

final StepResult step = found.get();

notifier.beforeStepStop(step);

step.setStage(Stage.FINISHED);
step.setStop(System.currentTimeMillis());

storage.remove(uuid);
threadContext.stop();

notifier.afterStepStop(step);
}

Expand Down Expand Up @@ -597,4 +610,14 @@ private static FileSystemResultsWriter getDefaultWriter() {
final String path = properties.getProperty("allure.results.directory", "allure-results");
return new FileSystemResultsWriter(Paths.get(path));
}

private static LifecycleNotifier getDefaultNotifier() {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return new LifecycleNotifier(
load(ContainerLifecycleListener.class, classLoader),
load(TestLifecycleListener.class, classLoader),
load(FixtureLifecycleListener.class, classLoader),
load(StepLifecycleListener.class, classLoader)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,18 @@ public Optional<TestResultContainer> getContainer(final String uuid) {
return get(uuid, TestResultContainer.class);
}

public Optional<TestResultContainer> removeContainer(final String uuid) {
return remove(uuid, TestResultContainer.class);
}

public void addTestResult(final TestResult testResult) {
put(testResult.getUuid(), testResult);
}

public Optional<TestResult> getTestResult(final String uuid) {
return get(uuid, TestResult.class);
}

public Optional<TestResult> removeTestResult(final String uuid) {
return remove(uuid, TestResult.class);
}

public Optional<FixtureResult> getFixture(final String uuid) {
return get(uuid, FixtureResult.class);
}

public Optional<FixtureResult> removeFixture(final String uuid) {
return remove(uuid, FixtureResult.class);
}

public Optional<StepResult> getStep(final String uuid) {
return get(uuid, StepResult.class);
}

public Optional<StepResult> removeStep(final String uuid) {
return remove(uuid, StepResult.class);
}

public <T> Optional<T> get(final String uuid, final Class<T> clazz) {
lock.readLock().lock();
try {
Expand All @@ -82,13 +62,11 @@ public <T> T put(final String uuid, final T item) {
}
}

public <T> Optional<T> remove(final String uuid, final Class<T> clazz) {
public void remove(final String uuid) {
lock.writeLock().lock();
try {
Objects.requireNonNull(uuid, "Can't remove item from storage: uuid can't be null");
return Optional.ofNullable(storage.remove(uuid))
.filter(clazz::isInstance)
.map(clazz::cast);
storage.remove(uuid);
} finally {
lock.writeLock().unlock();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package io.qameta.allure;

import io.qameta.allure.aspects.StepsAspects;
import io.qameta.allure.listener.LifecycleNotifier;
import io.qameta.allure.listener.StepLifecycleListener;
import io.qameta.allure.model.Attachment;
import io.qameta.allure.model.ExecutableItem;
import io.qameta.allure.model.Status;
import io.qameta.allure.model.StepResult;
import io.qameta.allure.model.TestResult;
import io.qameta.allure.test.AllureResults;
import io.qameta.allure.test.AllureResultsWriterStub;
import org.junit.jupiter.api.Test;

import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

import static io.qameta.allure.util.ResultsUtils.getStatus;
import static io.qameta.allure.util.ResultsUtils.getStatusDetails;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;

/**
* @author charlie (Dmitry Baev).
*/
class StepLifecycleListenerTest {

@Test
void shouldExecuteBeforeStepStart() {
final AtomicInteger executionCount = new AtomicInteger();
final StepLifecycleListener listener = new StepLifecycleListener() {
@Override
public void beforeStepStart(final StepResult result) {
executionCount.incrementAndGet();
}
};
final AllureResults run = run(listener, "first", "second");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.extracting(StepResult::getName)
.containsExactly("first", "second");

assertThat(executionCount.get())
.isEqualTo(2);
}

@Test
void shouldExecuteAfterStepStart() {
final AtomicInteger executionCount = new AtomicInteger();
final StepLifecycleListener listener = new StepLifecycleListener() {
@Override
public void afterStepStart(final StepResult result) {
executionCount.incrementAndGet();
Allure.addAttachment("inner " + result.getName(), "some");
}
};
final AllureResults run = run(listener, "first", "second");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.extracting(StepResult::getName)
.containsExactly("first", "second");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.filteredOn("name", "first")
.flatExtracting(StepResult::getAttachments)
.extracting(Attachment::getName)
.containsExactly("inner first");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.filteredOn("name", "second")
.flatExtracting(StepResult::getAttachments)
.extracting(Attachment::getName)
.containsExactly("inner second");

assertThat(executionCount.get())
.isEqualTo(2);
}

@Issue("177")
@Test
void shouldExecuteBeforeStepStop() {
final AtomicInteger executionCount = new AtomicInteger();
final StepLifecycleListener listener = new StepLifecycleListener() {
@Override
public void beforeStepStop(final StepResult result) {
executionCount.incrementAndGet();
Allure.addAttachment("inner " + result.getName(), "some");
}
};
final AllureResults run = run(listener, "first", "second");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.extracting(StepResult::getName)
.containsExactly("first", "second");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.filteredOn("name", "first")
.flatExtracting(StepResult::getAttachments)
.extracting(Attachment::getName)
.containsExactly("inner first");

assertThat(run.getTestResults())
.flatExtracting(TestResult::getSteps)
.filteredOn("name", "second")
.flatExtracting(StepResult::getAttachments)
.extracting(Attachment::getName)
.containsExactly("inner second");

assertThat(executionCount.get())
.isEqualTo(2);
}

protected AllureResults run(final StepLifecycleListener listener, final String... steps) {
final AllureResultsWriterStub writer = new AllureResultsWriterStub();
final LifecycleNotifier notifier = new LifecycleNotifier(
emptyList(),
emptyList(),
emptyList(),
singletonList(listener)
);
final AllureLifecycle lifecycle = new AllureLifecycle(writer, notifier);

final String uuid = UUID.randomUUID().toString();
final TestResult result = new TestResult().setUuid(uuid);

final AllureLifecycle cached = Allure.getLifecycle();
try {
Allure.setLifecycle(lifecycle);
StepsAspects.setLifecycle(lifecycle);

lifecycle.scheduleTestCase(result);
lifecycle.startTestCase(uuid);

Stream.of(steps).forEach(step -> {
final String stepUuid = UUID.randomUUID().toString();
lifecycle.startStep(stepUuid, new StepResult().setName(step).setStatus(Status.PASSED));
lifecycle.stopStep(stepUuid);
});
} catch (Throwable e) {
lifecycle.updateTestCase(uuid, testResult -> {
getStatus(e).ifPresent(testResult::setStatus);
getStatusDetails(e).ifPresent(testResult::setStatusDetails);

});
} finally {
lifecycle.stopTestCase(uuid);
lifecycle.writeTestCase(uuid);

Allure.setLifecycle(cached);
StepsAspects.setLifecycle(cached);
}

return writer;
}
}