Skip to content

Commit 2f4e9da

Browse files
committed
[Java] Add BeforeAll and AfterAll hooks
Work in progress to fix #515. TODO: - [ ] How to deal with failure? - [ ] Test with JUnit4 - [ ] Test with JUnit5 - [ ] Test with TestNG - [ ] Test with CLI - [ ] Invoke around semantics? - [ ] How to report execution results? - [ ] TeamCity Plugin - [ ] Pretty formatter - [ ] Messages/Events
1 parent 218dcae commit 2f4e9da

File tree

17 files changed

+205
-9
lines changed

17 files changed

+205
-9
lines changed

core/src/main/java/io/cucumber/core/backend/Glue.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
@API(status = API.Status.STABLE)
66
public interface Glue {
77

8+
void addBeforeAllHook(StaticHookDefinition beforeAllHook);
9+
10+
void addAfterAllHook(StaticHookDefinition afterAllHook);
11+
812
void addStepDefinition(StepDefinition stepDefinition);
913

1014
void addBeforeHook(HookDefinition beforeHook);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.cucumber.core.backend;
2+
3+
import org.apiguardian.api.API;
4+
5+
@API(status = API.Status.STABLE)
6+
public interface StaticHookDefinition extends Located {
7+
8+
void execute();
9+
10+
int getOrder();
11+
}

core/src/main/java/io/cucumber/core/runner/CachingGlue.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.cucumber.core.backend.HookDefinition;
1010
import io.cucumber.core.backend.ParameterTypeDefinition;
1111
import io.cucumber.core.backend.ScenarioScoped;
12+
import io.cucumber.core.backend.StaticHookDefinition;
1213
import io.cucumber.core.backend.StepDefinition;
1314
import io.cucumber.core.eventbus.EventBus;
1415
import io.cucumber.core.gherkin.Step;
@@ -45,11 +46,13 @@ final class CachingGlue implements Glue {
4546
private final List<DefaultDataTableCellTransformerDefinition> defaultDataTableCellTransformers = new ArrayList<>();
4647
private final List<DocStringTypeDefinition> docStringTypeDefinitions = new ArrayList<>();
4748

49+
private final List<StaticHookDefinition> beforeAllHooks = new ArrayList<>();
4850
private final List<CoreHookDefinition> beforeHooks = new ArrayList<>();
4951
private final List<CoreHookDefinition> beforeStepHooks = new ArrayList<>();
5052
private final List<StepDefinition> stepDefinitions = new ArrayList<>();
5153
private final List<CoreHookDefinition> afterStepHooks = new ArrayList<>();
5254
private final List<CoreHookDefinition> afterHooks = new ArrayList<>();
55+
private final List<StaticHookDefinition> afterAllHooks = new ArrayList<>();
5356

5457
/*
5558
* Storing the pattern that matches the step text allows us to cache the rather slow
@@ -67,6 +70,17 @@ final class CachingGlue implements Glue {
6770
this.bus = bus;
6871
}
6972

73+
@Override
74+
public void addBeforeAllHook(StaticHookDefinition beforeAllHook) {
75+
beforeAllHooks.add(beforeAllHook);
76+
77+
}
78+
79+
@Override
80+
public void addAfterAllHook(StaticHookDefinition afterAllHook) {
81+
afterAllHooks.add(afterAllHook);
82+
}
83+
7084
@Override
7185
public void addStepDefinition(StepDefinition stepDefinition) {
7286
stepDefinitions.add(stepDefinition);
@@ -126,6 +140,10 @@ public void addDocStringType(DocStringTypeDefinition docStringType) {
126140
docStringTypeDefinitions.add(docStringType);
127141
}
128142

143+
List<StaticHookDefinition> getBeforeAllHooks() {
144+
return new ArrayList<>(beforeAllHooks);
145+
}
146+
129147
Collection<CoreHookDefinition> getBeforeHooks() {
130148
return new ArrayList<>(beforeHooks);
131149
}
@@ -146,6 +164,10 @@ Collection<CoreHookDefinition> getAfterStepHooks() {
146164
return hooks;
147165
}
148166

167+
List<StaticHookDefinition> getAfterAllHooks() {
168+
return new ArrayList<>(afterAllHooks);
169+
}
170+
149171
Collection<ParameterTypeDefinition> getParameterTypeDefinitions() {
150172
return parameterTypeDefinitions;
151173
}

core/src/main/java/io/cucumber/core/runner/Runner.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.cucumber.core.api.TypeRegistryConfigurer;
44
import io.cucumber.core.backend.Backend;
55
import io.cucumber.core.backend.ObjectFactory;
6+
import io.cucumber.core.backend.StaticHookDefinition;
67
import io.cucumber.core.eventbus.EventBus;
78
import io.cucumber.core.gherkin.Pickle;
89
import io.cucumber.core.gherkin.Step;
@@ -70,6 +71,14 @@ public void runPickle(Pickle pickle) {
7071
}
7172
}
7273

74+
public void runBeforeAllHooks(){
75+
glue.getBeforeAllHooks().forEach(StaticHookDefinition::execute);
76+
}
77+
78+
public void runAfterAllHooks(){
79+
glue.getAfterAllHooks().forEach(StaticHookDefinition::execute);
80+
}
81+
7382
private List<SnippetGenerator> createSnippetGeneratorsForPickle(StepTypeRegistry stepTypeRegistry) {
7483
return backends.stream()
7584
.map(Backend::getSnippet)

core/src/main/java/io/cucumber/core/runtime/Runtime.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public void run() {
9090
for (Feature feature : features) {
9191
bus.send(new TestSourceRead(bus.getInstant(), feature.getUri(), feature.getSource()));
9292
}
93+
runnerSupplier.get().runBeforeAllHooks();
9394

9495
final List<Future<?>> executingPickles = features.stream()
9596
.flatMap(feature -> feature.getPickles().stream())
@@ -119,7 +120,7 @@ public void run() {
119120
} else if (thrown.size() > 1) {
120121
throw new CompositeCucumberException(thrown);
121122
}
122-
123+
runnerSupplier.get().runAfterAllHooks();
123124
bus.send(new TestRunFinished(bus.getInstant()));
124125
}
125126

examples/java-calculator/src/test/java/io/cucumber/examples/java/RpnCalculatorSteps.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.cucumber.examples.java;
22

33
import io.cucumber.java.After;
4+
import io.cucumber.java.AfterAll;
45
import io.cucumber.java.Before;
6+
import io.cucumber.java.BeforeAll;
57
import io.cucumber.java.Scenario;
68
import io.cucumber.java.en.Given;
79
import io.cucumber.java.en.Then;
@@ -14,6 +16,16 @@
1416
public class RpnCalculatorSteps {
1517
private RpnCalculator calc;
1618

19+
@BeforeAll
20+
public static void enable_super_math_engine(){
21+
// System.enableSuperMaths()
22+
}
23+
24+
@AfterAll
25+
public static void disable_super_math_engine(){
26+
// System.disableSuperMaths()
27+
}
28+
1729
@Given("a calculator I just turned on")
1830
public void a_calculator_I_just_turned_on() {
1931
calc = new RpnCalculator();

java/src/main/java/io/cucumber/java/After.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
String value() default "";
2424

2525
/**
26-
* @return the order in which this hook should run. Higher numbers are run first.
26+
* The order in which this hook should run. Higher numbers are run first.
2727
* The default order is 10000.
28+
*
29+
* @return the order in which this hook should run.
2830
*/
2931
int order() default 10000;
3032
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.cucumber.java;
2+
3+
import org.apiguardian.api.API;
4+
5+
import java.lang.annotation.ElementType;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Executes a method before all scenarios
12+
*/
13+
@Retention(RetentionPolicy.RUNTIME)
14+
@Target(ElementType.METHOD)
15+
@API(status = API.Status.STABLE)
16+
public @interface AfterAll {
17+
18+
/**
19+
* The order in which this hook should run. Higher numbers are run first.
20+
* The default order is 10000.
21+
*
22+
* @return the order in which this hook should run.
23+
*/
24+
int order() default 10000;
25+
}

java/src/main/java/io/cucumber/java/Before.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
String value() default "";
2424

2525
/**
26-
* @return the order in which this hook should run. Lower numbers are run first.
26+
* The order in which this hook should run. Lower numbers are run first.
2727
* The default order is 10000.
28+
*
29+
* @return the order in which this hook should run.
2830
*/
2931
int order() default 10000;
3032
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.cucumber.java;
2+
3+
import org.apiguardian.api.API;
4+
5+
import java.lang.annotation.ElementType;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Executes a method after all scenarios
12+
*/
13+
@Retention(RetentionPolicy.RUNTIME)
14+
@Target(ElementType.METHOD)
15+
@API(status = API.Status.STABLE)
16+
public @interface BeforeAll {
17+
18+
/**
19+
* The order in which this hook should run. Lower numbers are run first.
20+
* The default order is 10000.
21+
*
22+
* @return the order in which this hook should run.
23+
*/
24+
int order() default 10000;
25+
}

0 commit comments

Comments
 (0)