Skip to content

Commit

Permalink
Fixed a defect related to Screenplay Facts, where the teardown() meth…
Browse files Browse the repository at this point in the history
…od was called more than once in some circumstances
  • Loading branch information
wakaleo committed Nov 6, 2020
1 parent b2fe607 commit a5a314c
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 14 deletions.
@@ -0,0 +1,3 @@
package net.thucydides.core.steps;

public interface Droppable {}
Expand Up @@ -13,9 +13,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

import static net.thucydides.core.ThucydidesSystemProperty.SERENITY_ENABLE_WEBDRIVER_IN_FIXTURE_METHODS;

Expand Down Expand Up @@ -270,6 +272,7 @@ public void clear() {
webdriverSuspensions.clear();

Broadcaster.unregisterAllListeners();
dropClosableListeners();
}

private boolean clearSessionForEachTest() {
Expand Down Expand Up @@ -480,6 +483,10 @@ public void dropListener(final StepListener stepListener) {
registeredListeners.remove(stepListener);
}

private void dropClosableListeners() {
registeredListeners = registeredListeners.stream().filter( stepListener -> (!(stepListener instanceof Droppable))).collect(Collectors.toList());
}

public void dropAllListeners() {
registeredListeners.clear();
}
Expand Down
Expand Up @@ -14,6 +14,7 @@
import net.thucydides.core.guice.Injectors;
import net.thucydides.core.steps.ExecutedStepDescription;
import net.thucydides.core.steps.StepEventBus;
import net.thucydides.core.steps.StepListener;
import net.thucydides.core.util.EnvironmentVariables;
import org.openqa.selenium.Keys;

Expand Down Expand Up @@ -145,12 +146,16 @@ public final void has(Performable... todos) {
attemptsTo(todos);
}

private List<FactLifecycleListener> factListeners = new ArrayList<>();

public final void has(Fact... facts) {
Arrays.stream(facts).forEach(
fact -> {
fact.setup(this);
eventBusInterface.assignFactToActor(this, fact.toString());
StepEventBus.getEventBus().registerListener(new FactLifecycleListener(this, fact));
FactLifecycleListener listener = new FactLifecycleListener(this, fact);
factListeners.add(listener);
StepEventBus.getEventBus().registerListener(listener);
}
);
}
Expand Down Expand Up @@ -421,4 +426,12 @@ private boolean manualTaskInstrumentation() {
EnvironmentVariables environmentVariables = Injectors.getInjector().getInstance(EnvironmentVariables.class);
return (MANUAL_TASK_INSTRUMENTATION.booleanFrom(environmentVariables, false));
}

public void wrapUp() {
getTeardowns().forEach(HasTeardown::tearDown);
factListeners.forEach(
factLifecycleListener -> StepEventBus.getEventBus().dropListener(factLifecycleListener)
);

}
}
Expand Up @@ -75,19 +75,10 @@ public List<Actor> getActors() {
}

public void dismissAll() {
runTeardowns();
actors.clear();
}

/**
* Run the teardown for any {@link Ability} that implements one.
*/
private void runTeardowns() {
for (Actor a : actors.values()) {
for (HasTeardown ability : a.getTeardowns()) {
ability.tearDown();
}
for (Actor actor : actors.values()) {
actor.wrapUp();
}
actors.clear();
}

protected void assignGeneralAbilitiesTo(Actor newActor) {
Expand Down
Expand Up @@ -4,13 +4,14 @@
import net.thucydides.core.model.DataTable;
import net.thucydides.core.model.Story;
import net.thucydides.core.model.TestOutcome;
import net.thucydides.core.steps.Droppable;
import net.thucydides.core.steps.ExecutedStepDescription;
import net.thucydides.core.steps.StepFailure;
import net.thucydides.core.steps.StepListener;

import java.util.Map;

public class FactLifecycleListener implements StepListener {
public class FactLifecycleListener implements StepListener, Droppable {
private final Actor actor;
private final Fact fact;

Expand Down
Expand Up @@ -104,6 +104,19 @@ public void facts_let_us_setup_and_teardown_test_data() {
assertThat(existingSavingsAccounts).doesNotContain("Savings-123456");
}

@Test
public void fact_setup_and_teardown_methods_are_only_called_once_per_test() {

Actor tim = Actor.named("Tim");

tim.has(ASavingsAccount.numbered("Savings-123456"));

StepEventBus.getEventBus().testFinished();

assertThat(knownAccounts).contains("Savings-123456");
assertThat(existingSavingsAccounts).doesNotContain("Savings-123456");
}

@Test(expected = TestCompromisedException.class)
public void facts_can_throw_exceptions() {
Actor tim = Actor.named("Tim");
Expand Down

0 comments on commit a5a314c

Please sign in to comment.