Skip to content

Commit 70e1659

Browse files
jukziakurtakov
authored andcommitted
How to use junit.jupiter Extensions in OSGi and plain java
logs start, stop, duration, error for all tests executed
1 parent 7bc2aa7 commit 70e1659

File tree

8 files changed

+256
-2
lines changed

8 files changed

+256
-2
lines changed

eclipse.platform.releng/bundles/org.eclipse.test/META-INF/MANIFEST.MF

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ Require-Bundle: org.apache.ant,
1111
org.eclipse.core.runtime,
1212
org.eclipse.ui.ide.application,
1313
org.eclipse.equinox.app,
14-
org.junit
14+
org.apache.aries.spifly.dynamic.bundle,
15+
junit-jupiter-api,
16+
org.junit
1517
Import-Package: org.junit.jupiter.api,
1618
org.junit.platform.engine,
1719
org.junit.platform.engine.discovery,
@@ -24,5 +26,6 @@ Import-Package: org.junit.jupiter.api,
2426
org.junit.jupiter.engine
2527
Bundle-ActivationPolicy: lazy
2628
Bundle-RequiredExecutionEnvironment: JavaSE-17
27-
Export-Package: org.eclipse.test
29+
Export-Package: org.eclipse.test,
30+
org.eclipse.test.services
2831
Automatic-Module-Name: org.eclipse.test
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.eclipse.test.services.LoggingTestExtension
2+
org.eclipse.test.services.SwtLeakTestExtension
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
junit.jupiter.extensions.autodetection.enabled=true
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Joerg Kubitz and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Joerg Kubitz - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.test.services;
15+
16+
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
17+
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
18+
import org.junit.jupiter.api.extension.ExtensionContext;
19+
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
20+
import org.junit.jupiter.api.extension.ExtensionContext.Store;
21+
22+
/** logs start, stop, duration, error for all tests executed **/
23+
public class LoggingTestExtension implements AfterTestExecutionCallback, BeforeTestExecutionCallback {
24+
public static String BEFORE_TEST_START = "Test Before: ";
25+
public static String AFTER_TEST_PASSED = "Test Passed: ";
26+
public static String AFTER_TEST_FAILED = "Test Failed: ";
27+
28+
public LoggingTestExtension() {
29+
System.out.println("LoggingTestService");
30+
}
31+
@Override
32+
public void beforeTestExecution(ExtensionContext context) throws Exception {
33+
long n0 = System.nanoTime();
34+
getStore(context).put("TIME", n0);
35+
System.out.println(BEFORE_TEST_START + context.getDisplayName());
36+
}
37+
38+
@Override
39+
public void afterTestExecution(ExtensionContext context) throws Exception {
40+
long t1 = System.nanoTime();
41+
long t0 = getStore(context).remove("TIME", long.class);
42+
String took = " after: " + (t1 - t0) / 1_000_000 + "ms";
43+
Throwable t = context.getExecutionException().orElse(null);
44+
if (t == null) {
45+
System.out.println(AFTER_TEST_PASSED + context.getDisplayName() + took);
46+
} else {
47+
System.out.println(AFTER_TEST_FAILED + context.getDisplayName() + took);
48+
t.printStackTrace(System.out);
49+
}
50+
}
51+
52+
private Store getStore(ExtensionContext context) {
53+
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
54+
}
55+
56+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Joerg Kubitz and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Joerg Kubitz - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.test.services;
15+
16+
import static org.junit.Assert.assertTrue;
17+
18+
import java.io.ByteArrayOutputStream;
19+
import java.io.PrintStream;
20+
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.BeforeAll;
23+
import org.junit.jupiter.api.Test;
24+
25+
/** verifies the Extension is used **/
26+
public class LoggingTestExtensionTest {
27+
private static final String SOMETHING = "something";
28+
private static final ByteArrayOutputStream OUT = new ByteArrayOutputStream();
29+
private static PrintStream oldStdOut;
30+
31+
@BeforeAll
32+
public static void beforeAll() {
33+
oldStdOut = System.out;
34+
System.setOut(new PrintStream(OUT));
35+
}
36+
@Test
37+
public void testWritten() {
38+
System.out.println(SOMETHING);
39+
}
40+
41+
@AfterAll
42+
public static void afterAll() {
43+
String output = new String(OUT.toByteArray());
44+
System.setOut(oldStdOut);
45+
assertTrue(output, output.contains("testWritten"));
46+
assertTrue(output, output.contains(SOMETHING));
47+
assertTrue(output, output.contains(org.eclipse.test.services.LoggingTestExtension.BEFORE_TEST_START));
48+
assertTrue(output, output.contains(org.eclipse.test.services.LoggingTestExtension.AFTER_TEST_PASSED));
49+
}
50+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Joerg Kubitz and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Joerg Kubitz - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.test.services;
15+
16+
import org.junit.jupiter.api.Test;
17+
18+
// Manual demonstration:
19+
public class LoggingTestExtensionTest2 {
20+
21+
@Test
22+
public void testWritten() {
23+
System.out.println("real");
24+
}
25+
26+
@Test
27+
public void testWritten2() {
28+
throw new RuntimeException("intended");
29+
}
30+
31+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Joerg Kubitz and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Joerg Kubitz - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.test.services;
15+
16+
import static org.junit.Assert.assertEquals;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.Set;
21+
22+
import org.eclipse.swt.widgets.Shell;
23+
import org.eclipse.ui.IWorkbench;
24+
import org.eclipse.ui.PlatformUI;
25+
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
26+
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
27+
import org.junit.jupiter.api.extension.ExtensionContext;
28+
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
29+
import org.junit.jupiter.api.extension.ExtensionContext.Store;
30+
31+
/** logs start, stop, duration, error for all tests executed **/
32+
public class SwtLeakTestExtension implements AfterTestExecutionCallback, BeforeTestExecutionCallback {
33+
@Override
34+
public void beforeTestExecution(ExtensionContext context) throws Exception {
35+
IWorkbench workbench = PlatformUI.getWorkbench();
36+
Set<Shell> preExistingShells = Set.of(workbench.getDisplay().getShells());
37+
38+
getStore(context).put("workbench", workbench);
39+
getStore(context).put("preExistingShells", preExistingShells);
40+
}
41+
42+
@Override
43+
public void afterTestExecution(ExtensionContext context) throws Exception {
44+
IWorkbench workbench = getStore(context).remove("workbench", IWorkbench.class);
45+
Set<Shell> preExistingShells = getStore(context).remove("preExistingShells", Set.class);
46+
// Check for shell leak.
47+
List<String> leakedModalShellTitles = new ArrayList<>();
48+
Shell[] shells = workbench.getDisplay().getShells();
49+
for (Shell shell : shells) {
50+
if (!shell.isDisposed() && !preExistingShells.contains(shell)) {
51+
leakedModalShellTitles.add(shell.getText());
52+
shell.close();
53+
}
54+
}
55+
assertEquals("Test leaked modal shell: [" + String.join(", ", leakedModalShellTitles) + "]", 0,
56+
leakedModalShellTitles.size());
57+
}
58+
59+
private Store getStore(ExtensionContext context) {
60+
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
61+
}
62+
63+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Joerg Kubitz and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Joerg Kubitz - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.test.services;
15+
16+
import org.eclipse.swt.widgets.Display;
17+
import org.eclipse.swt.widgets.Shell;
18+
import org.eclipse.ui.IWorkbench;
19+
import org.eclipse.ui.PlatformUI;
20+
import org.junit.jupiter.api.AfterAll;
21+
import org.junit.jupiter.api.Test;
22+
23+
// Manual demonstration:
24+
public class SwtLeakTestExtensionTest {
25+
static Shell leakedShell;
26+
@Test
27+
public void testNoLeak() {
28+
System.out.println("noleak");
29+
IWorkbench workbench = PlatformUI.getWorkbench();
30+
Display display = workbench.getDisplay();
31+
Shell shell = new Shell(display);
32+
shell.dispose();
33+
}
34+
35+
@Test
36+
public void testLeak() { // fails
37+
System.out.println("leak");
38+
IWorkbench workbench = PlatformUI.getWorkbench();
39+
Display display = workbench.getDisplay();
40+
leakedShell = new Shell(display);
41+
}
42+
43+
@AfterAll
44+
public static void afterAll() {
45+
leakedShell.dispose();
46+
}
47+
48+
}

0 commit comments

Comments
 (0)