Skip to content

Commit

Permalink
[Core] Add StepDefinedEvent (#1634)
Browse files Browse the repository at this point in the history
Adds a `StepDefinedEvent` to replace the `StepDefinitionReporter` plugin interface.

## Details

Publish an event from `Glue.addStepDefinition`, as `Runner.reportStepDefinitions` is called before step definition classes are instantiated, which fails to pick up on lambda based steps.

## Motivation and Context

Provide an event to listen for steps being registered, so all steps registrations are available, instead of only the annotation based step definitions.
#1633
  • Loading branch information
timtebeek authored and mpkorstanje committed May 30, 2019
1 parent 6469d70 commit f172c4f
Show file tree
Hide file tree
Showing 14 changed files with 245 additions and 37 deletions.
5 changes: 5 additions & 0 deletions core/src/main/java/cucumber/api/StepDefinitionReporter.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package cucumber.api;

import cucumber.api.event.StepDefinedEvent;
import cucumber.runtime.StepDefinition;

/**
* @deprecated in favor of {@link StepDefinedEvent}, as Lambda Step Definitions are not reported through this class.
*/
@Deprecated
public interface StepDefinitionReporter extends Plugin {
/**
* Called when a step definition is defined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ private static final class FixedEventOrderComparator implements Comparator<Event
TestRunStarted.class,
TestSourceRead.class,
SnippetsSuggestedEvent.class,
StepDefinedEvent.class,
TestCaseEvent.class,
TestRunFinished.class
);
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/cucumber/api/event/EventPublisher.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public interface EventPublisher {
* <li>{@link TestRunStarted} - the first event sent.
* <li>{@link TestSourceRead} - sent for each feature file read, contains the feature file source.
* <li>{@link SnippetsSuggestedEvent} - sent for each step that could not be matched to a step definition, contains the raw snippets for the step.
* <li>{@link StepDefinedEvent} - sent for each step definition as it is loaded, contains the StepDefinition
* <li>{@link TestCaseStarted} - sent before starting the execution of a Test Case(/Pickle/Scenario), contains the Test Case
* <li>{@link TestStepStarted} - sent before starting the execution of a Test Step, contains the Test Step
* <li>{@link EmbedEvent} - calling scenario.embed in a hook triggers this event.
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/cucumber/api/event/StepDefinedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cucumber.api.event;

import cucumber.runtime.StepDefinition;

public class StepDefinedEvent extends TimeStampedEvent {
public final StepDefinition stepDefinition;

public StepDefinedEvent(Long time, Long timeMillis, StepDefinition stepDefinition) {
super(time, timeMillis);
this.stepDefinition = stepDefinition;
}

}
17 changes: 17 additions & 0 deletions core/src/main/java/cucumber/runner/Glue.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import cucumber.runtime.DuplicateStepDefinitionException;
import cucumber.runtime.HookDefinition;
import cucumber.runtime.ScenarioScoped;
import cucumber.runtime.StepDefinition;
import io.cucumber.stepexpression.Argument;
import cucumber.api.StepDefinitionReporter;
import cucumber.api.event.StepDefinedEvent;
import gherkin.pickles.PickleStep;

import java.util.ArrayList;
Expand All @@ -23,13 +25,20 @@ final class Glue implements cucumber.runtime.Glue {
final List<HookDefinition> afterHooks = new ArrayList<>();
final List<HookDefinition> afterStepHooks = new ArrayList<>();

private final EventBus bus;

public Glue(EventBus bus) {
this.bus = bus;
}

@Override
public void addStepDefinition(StepDefinition stepDefinition) {
StepDefinition previous = stepDefinitionsByPattern.get(stepDefinition.getPattern());
if (previous != null) {
throw new DuplicateStepDefinitionException(previous, stepDefinition);
}
stepDefinitionsByPattern.put(stepDefinition.getPattern(), stepDefinition);
bus.send(new StepDefinedEvent(bus.getTime(), bus.getTimeMillis(), stepDefinition));
}

@Override
Expand Down Expand Up @@ -130,6 +139,10 @@ private void removeScenarioScopedHooks(List<HookDefinition> beforeHooks) {
Iterator<HookDefinition> hookIterator = beforeHooks.iterator();
while (hookIterator.hasNext()) {
HookDefinition hook = hookIterator.next();
if (hook instanceof ScenarioScoped) {
ScenarioScoped scenarioScopedHookDefinition = (ScenarioScoped) hook;
scenarioScopedHookDefinition.disposeScenarioScope();
}
if (hook.isScenarioScoped()) {
hookIterator.remove();
}
Expand All @@ -140,6 +153,10 @@ private void removeScenariosScopedStepDefinitions(Map<String, StepDefinition> st
Iterator<Map.Entry<String, StepDefinition>> stepDefinitionIterator = stepDefinitions.entrySet().iterator();
while(stepDefinitionIterator.hasNext()){
StepDefinition stepDefinition = stepDefinitionIterator.next().getValue();
if (stepDefinition instanceof ScenarioScoped) {
ScenarioScoped scenarioScopedStepDefinition = (ScenarioScoped) stepDefinition;
scenarioScopedStepDefinition.disposeScenarioScope();
}
if(stepDefinition.isScenarioScoped()){
stepDefinitionIterator.remove();
}
Expand Down
10 changes: 6 additions & 4 deletions core/src/main/java/cucumber/runner/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import cucumber.runtime.Backend;
import cucumber.runtime.HookDefinition;
import cucumber.util.FixJava;
import io.cucumber.core.logging.Logger;
import io.cucumber.core.logging.LoggerFactory;
import io.cucumber.core.options.RunnerOptions;
import gherkin.events.PickleEvent;
import gherkin.pickles.PickleStep;
import gherkin.pickles.PickleTag;
import io.cucumber.core.logging.Logger;
import io.cucumber.core.logging.LoggerFactory;
import io.cucumber.core.options.RunnerOptions;

import java.net.URI;
import java.util.ArrayList;
Expand All @@ -22,13 +22,14 @@ public final class Runner {

private static final Logger log = LoggerFactory.getLogger(Runner.class);

private final Glue glue = new Glue();
private final Glue glue;
private final EventBus bus;
private final Collection<? extends Backend> backends;
private final RunnerOptions runnerOptions;

public Runner(EventBus bus, Collection<? extends Backend> backends, RunnerOptions runnerOptions) {
this.bus = bus;
this.glue = new Glue(bus);
this.runnerOptions = runnerOptions;
this.backends = backends;
List<URI> gluePaths = runnerOptions.getGlue();
Expand Down Expand Up @@ -134,5 +135,6 @@ private void disposeBackendWorlds() {
for (Backend backend : backends) {
backend.disposeWorld();
}
glue.removeScenarioScopedGlue();
}
}
2 changes: 2 additions & 0 deletions core/src/main/java/cucumber/runtime/HookDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public interface HookDefinition {
int getOrder();

/**
* @deprecated replaced with {@link ScenarioScoped}
* @return true if this instance is scoped to a single scenario, or false if it can be reused across scenarios.
*/
@Deprecated
boolean isScenarioScoped();
}
8 changes: 8 additions & 0 deletions core/src/main/java/cucumber/runtime/ScenarioScoped.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cucumber.runtime;

public interface ScenarioScoped {
/**
* Dispose references to Runtime world to allow garbage collection to run.
*/
void disposeScenarioScope();
}
2 changes: 2 additions & 0 deletions core/src/main/java/cucumber/runtime/StepDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public interface StepDefinition {
String getPattern();

/**
* @deprecated replaced with {@link ScenarioScoped}
* @return true if this instance is scoped to a single scenario, or false if it can be reused across scenarios.
*/
@Deprecated
boolean isScenarioScoped();
}
4 changes: 2 additions & 2 deletions core/src/test/java/cucumber/runner/GlueTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public class GlueTest {

@Before
public void setUp() {
glue = new Glue();
glue = new Glue(mock(EventBus.class));
}

@Test
public void throws_duplicate_error_on_dupe_stepdefs() {
Glue glue = new Glue();
Glue glue = new Glue(mock(EventBus.class));

StepDefinition a = mock(StepDefinition.class);
when(a.getPattern()).thenReturn("hello");
Expand Down
Loading

0 comments on commit f172c4f

Please sign in to comment.