Skip to content

Commit a026b72

Browse files
committed
testing JUnit 5 equivalent of XpectRunner
1 parent e27f2f2 commit a026b72

File tree

5 files changed

+529
-0
lines changed

5 files changed

+529
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.eclipse.xpect.dynamic;
2+
3+
import java.util.stream.Stream;
4+
5+
import org.eclipse.xpect.XpectImport;
6+
import org.eclipse.xpect.runner.TestTitleProvider;
7+
import org.junit.jupiter.api.DynamicContainer;
8+
import org.junit.jupiter.api.TestFactory;
9+
10+
@XpectImport(TestTitleProvider.class)
11+
public interface IXpectDynamicTestFactory {
12+
13+
@TestFactory
14+
default Stream<DynamicContainer> generateTests() {
15+
return XpectDynamicTestFactory.xpectTests(getClass());
16+
}
17+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.eclipse.xpect.dynamic;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
5+
import org.eclipse.xpect.XjmTestMethod;
6+
import org.eclipse.xpect.runner.ValidatingSetup;
7+
import org.eclipse.xpect.runner.XpectTestGlobalState;
8+
import org.eclipse.xpect.setup.ThisTestObject;
9+
import org.eclipse.xpect.state.Creates;
10+
import org.eclipse.xpect.state.StateContainer;
11+
import org.junit.jupiter.api.DynamicTest;
12+
13+
import com.google.common.base.Preconditions;
14+
15+
public class XpectDynamicTest {
16+
17+
private final String className;
18+
private XjmTestMethod method;
19+
private final StateContainer state;
20+
21+
public XpectDynamicTest(StateContainer state, XjmTestMethod method) {
22+
Preconditions.checkNotNull(method);
23+
this.className = XpectTestGlobalState.INSTANCE.testClass().getName();
24+
this.method = method;
25+
this.state = state;
26+
}
27+
28+
@Creates
29+
public XpectDynamicTest create() {
30+
return this;
31+
}
32+
33+
public XjmTestMethod getMethod() {
34+
return method;
35+
}
36+
37+
public StateContainer getState() {
38+
return state;
39+
}
40+
41+
public DynamicTest test() {
42+
String testName = getName();
43+
return DynamicTest.dynamicTest(testName, () -> runInternal());
44+
}
45+
46+
public String getName() {
47+
String testName = formatDisplayName(method.getName(), className);
48+
return testName;
49+
}
50+
51+
protected void runInternal() throws Throwable {
52+
Object test = state.get(Object.class, ThisTestObject.class).get();
53+
try {
54+
method.getJavaMethod().invoke(test);
55+
} catch (InvocationTargetException e) {
56+
throw e.getCause();
57+
}
58+
}
59+
60+
private static String formatDisplayName(String name, String className) {
61+
return String.format("%s(%s)", name, className);
62+
}
63+
64+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package org.eclipse.xpect.dynamic;
2+
3+
import static org.eclipse.xpect.runner.DescriptionFactory.*;
4+
5+
import java.util.Arrays;
6+
import java.util.List;
7+
import java.util.stream.Stream;
8+
9+
import org.eclipse.emf.common.util.URI;
10+
import org.eclipse.xpect.XjmMethod;
11+
import org.eclipse.xpect.XjmTestMethod;
12+
import org.eclipse.xpect.XpectFile;
13+
import org.eclipse.xpect.XpectInvocation;
14+
import org.eclipse.xpect.XpectJavaModel;
15+
import org.eclipse.xpect.runner.IXpectURIProvider;
16+
import org.eclipse.xpect.runner.TestExecutor;
17+
import org.eclipse.xpect.runner.TestRunner;
18+
import org.eclipse.xpect.runner.ValidatingSetup;
19+
import org.eclipse.xpect.runner.XpectTestRunner;
20+
import org.eclipse.xpect.setup.ThisRootTestClass;
21+
import org.eclipse.xpect.state.Creates;
22+
import org.eclipse.xpect.state.StateContainer;
23+
import org.junit.jupiter.api.DynamicContainer;
24+
import org.junit.jupiter.api.DynamicTest;
25+
import org.junit.runner.Description;
26+
import org.junit.runner.Runner;
27+
import org.junit.runner.notification.Failure;
28+
import org.junit.runner.notification.RunNotifier;
29+
30+
import com.google.common.collect.Lists;
31+
32+
public class XpectDynamicTestCase {
33+
private Stream<DynamicTest> children;
34+
private Description description;
35+
private final StateContainer state;
36+
private final XpectFile xpectFile;
37+
38+
public XpectDynamicTestCase(StateContainer state, XpectFile file) {
39+
this.xpectFile = file;
40+
this.state = state;
41+
}
42+
43+
@Creates
44+
public XpectDynamicTestCase create() {
45+
return this;
46+
}
47+
48+
/**
49+
* <p>
50+
* To run code before an Xpect test begins, extend this class and annotate the extending class with:
51+
* {@code @org.eclipse.xpect.XpectReplace(org.eclipse.xpect.dynamic.XpectDynamicTestCase)}
52+
* </p>
53+
* <p>
54+
* The extended class must then be included in the values of the annotation of the test case:
55+
* {@code @org.eclipse.xpect.XpectImport({...class})}
56+
* </p>
57+
*/
58+
public void setUp() throws Throwable {
59+
// nothing to set up
60+
}
61+
62+
/**
63+
* <p>
64+
* To run code after an Xpect test finishes, extend this class and annotate the extending class with:
65+
* {@code @org.eclipse.xpect.XpectReplace(org.eclipse.xpect.dynamic.XpectDynamicTestCase)}
66+
* </p>
67+
* <p>
68+
* The extended class must then be included in the values of the annotation of the test case:
69+
* {@code @org.eclipse.xpect.XpectImport({...class})}
70+
* </p>
71+
*/
72+
public void tearDown() throws Throwable {
73+
// nothing to tear down
74+
}
75+
76+
public DynamicContainer dynamicContainer() {
77+
return DynamicContainer.dynamicContainer(getName(), getChildren());
78+
}
79+
80+
protected Stream<DynamicTest> createChildren() {
81+
List<DynamicTest> children = Lists.newArrayList();
82+
if (xpectFile != null) {
83+
XpectJavaModel xjm = xpectFile.getJavaModel();
84+
for (XjmMethod method : xjm.getMethods().values())
85+
if (method instanceof XjmTestMethod) {
86+
DynamicTest test = createDynamicTest((XjmTestMethod) method);
87+
if (test != null)
88+
children.add(test);
89+
}
90+
for (XpectInvocation inv : xpectFile.getInvocations()) {
91+
DynamicTest test = createDynamicTest(inv);
92+
if (test != null)
93+
children.add(test);
94+
}
95+
}
96+
return children.stream().map(test -> wrapTest(test));
97+
}
98+
99+
protected DynamicTest createDynamicTest(XjmTestMethod method) {
100+
StateContainer childState = TestExecutor.createState(state, TestExecutor.createTestConfiguration(method));
101+
return childState.get(XpectDynamicTest.class).get().test();
102+
}
103+
104+
protected DynamicTest createDynamicTest(XpectInvocation invocation) {
105+
StateContainer childState = TestExecutor.createState(state, TestExecutor.createXpectConfiguration(invocation));
106+
DynamicTest test = childState.get(XpectInvocationDynamicTest.class).get().test();
107+
return wrapTest(test);
108+
}
109+
110+
protected DynamicTest wrapTest(DynamicTest test) {
111+
return DynamicTest.dynamicTest(test.getDisplayName(), () -> {
112+
setUp();
113+
try {
114+
try {
115+
state.get(ValidatingSetup.class).get().validate();
116+
} catch (Throwable e) {
117+
throw new AssertionError("Setup validation failed: ", e);
118+
}
119+
test.getExecutable().execute();
120+
} finally {
121+
try {
122+
state.invalidate();
123+
} finally {
124+
tearDown();
125+
}
126+
}
127+
});
128+
}
129+
130+
protected Stream<DynamicTest> getChildren() {
131+
if (children == null)
132+
children = createChildren();
133+
return children;
134+
}
135+
136+
public Class<?> getJavaTestClass() {
137+
return state.get(Class.class, ThisRootTestClass.class).get();
138+
}
139+
140+
public IXpectURIProvider getURIProvider() {
141+
return state.get(IXpectURIProvider.class).get();
142+
}
143+
144+
public StateContainer getState() {
145+
return state;
146+
}
147+
148+
public URI getUri() {
149+
return xpectFile.eResource().getURI();
150+
}
151+
152+
public XpectFile getXpectFile() {
153+
return xpectFile;
154+
}
155+
156+
public String getName() {
157+
IXpectURIProvider uriProvider = getURIProvider();
158+
URI uri = getUri();
159+
URI deresolved = uriProvider.deresolveToProject(uri);
160+
String pathInProject = deresolved.trimSegments(1).toString();
161+
String fileName = deresolved.lastSegment();
162+
return fileName + ": " + pathInProject;
163+
}
164+
}

0 commit comments

Comments
 (0)