Skip to content

Commit

Permalink
How to use junit.jupiter Extensions in OSGi and plain java
Browse files Browse the repository at this point in the history
logs start, stop, duration, error for all tests executed
  • Loading branch information
EcljpseB0T committed Dec 11, 2024
1 parent da040ac commit 30cf747
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Require-Bundle: org.apache.ant,
org.eclipse.core.runtime,
org.eclipse.ui.ide.application,
org.eclipse.equinox.app,
org.junit
org.apache.aries.spifly.dynamic.bundle,
junit-jupiter-api,
org.junit
Import-Package: org.junit.jupiter.api,
org.junit.platform.engine,
org.junit.platform.engine.discovery,
Expand All @@ -24,5 +26,6 @@ Import-Package: org.junit.jupiter.api,
org.junit.jupiter.engine
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Export-Package: org.eclipse.test
Export-Package: org.eclipse.test,
org.eclipse.test.services
Automatic-Module-Name: org.eclipse.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.eclipse.test.services.LoggingTestExtension
org.eclipse.test.services.SwtLeakTestExtension
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
junit.jupiter.extensions.autodetection.enabled=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2024 Joerg Kubitz and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Joerg Kubitz - initial API and implementation
*******************************************************************************/
package org.eclipse.test.services;

import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;

/** logs start, stop, duration, error for all tests executed **/
public class LoggingTestExtension implements AfterTestExecutionCallback, BeforeTestExecutionCallback {
public static String BEFORE_TEST_START = "Test Before: ";
public static String AFTER_TEST_PASSED = "Test Passed: ";
public static String AFTER_TEST_FAILED = "Test Failed: ";

public LoggingTestExtension() {
System.out.println("LoggingTestService");
}
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
long n0 = System.nanoTime();
getStore(context).put("TIME", n0);
System.out.println(BEFORE_TEST_START + context.getDisplayName());
}

@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
long t1 = System.nanoTime();
long t0 = getStore(context).remove("TIME", long.class);
String took = " after: " + (t1 - t0) / 1_000_000 + "ms";
Throwable t = context.getExecutionException().orElse(null);
if (t == null) {
System.out.println(AFTER_TEST_PASSED + context.getDisplayName() + took);
} else {
System.out.println(AFTER_TEST_FAILED + context.getDisplayName() + took);
t.printStackTrace(System.out);
}
}

private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2024 Joerg Kubitz and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Joerg Kubitz - initial API and implementation
*******************************************************************************/
package org.eclipse.test.services;

import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

/** verifies the Extension is used **/
public class LoggingTestExtensionTest {
private static final String SOMETHING = "something";
private static final ByteArrayOutputStream OUT = new ByteArrayOutputStream();
private static PrintStream oldStdOut;

@BeforeAll
public static void beforeAll() {
oldStdOut = System.out;
System.setOut(new PrintStream(OUT));
}
@Test
public void testWritten() {
System.out.println(SOMETHING);
}

@AfterAll
public static void afterAll() {
String output = new String(OUT.toByteArray());
System.setOut(oldStdOut);
assertTrue(output, output.contains("testWritten"));
assertTrue(output, output.contains(SOMETHING));
assertTrue(output, output.contains(org.eclipse.test.services.LoggingTestExtension.BEFORE_TEST_START));
assertTrue(output, output.contains(org.eclipse.test.services.LoggingTestExtension.AFTER_TEST_PASSED));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2024 Joerg Kubitz and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Joerg Kubitz - initial API and implementation
*******************************************************************************/
package org.eclipse.test.services;

import org.junit.jupiter.api.Test;

// Manual demonstration:
public class LoggingTestExtensionTest2 {

@Test
public void testWritten() {
System.out.println("real");
}

@Test
public void testWritten2() {
throw new RuntimeException("intended");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2024 Joerg Kubitz and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Joerg Kubitz - initial API and implementation
*******************************************************************************/
package org.eclipse.test.services;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;

/** logs start, stop, duration, error for all tests executed **/
public class SwtLeakTestExtension implements AfterTestExecutionCallback, BeforeTestExecutionCallback {
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
IWorkbench workbench = PlatformUI.getWorkbench();
Set<Shell> preExistingShells = Set.of(workbench.getDisplay().getShells());

getStore(context).put("workbench", workbench);
getStore(context).put("preExistingShells", preExistingShells);
}

@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
IWorkbench workbench = getStore(context).remove("workbench", IWorkbench.class);
Set<Shell> preExistingShells = getStore(context).remove("preExistingShells", Set.class);
// Check for shell leak.
List<String> leakedModalShellTitles = new ArrayList<>();
Shell[] shells = workbench.getDisplay().getShells();
for (Shell shell : shells) {
if (!shell.isDisposed() && !preExistingShells.contains(shell)) {
leakedModalShellTitles.add(shell.getText());
shell.close();
}
}
assertEquals("Test leaked modal shell: [" + String.join(", ", leakedModalShellTitles) + "]", 0,
leakedModalShellTitles.size());
}

private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2024 Joerg Kubitz and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Joerg Kubitz - initial API and implementation
*******************************************************************************/
package org.eclipse.test.services;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;

// Manual demonstration:
public class SwtLeakTestExtensionTest {
static Shell leakedShell;
@Test
public void testNoLeak() {
System.out.println("noleak");
IWorkbench workbench = PlatformUI.getWorkbench();
Display display = workbench.getDisplay();
Shell shell = new Shell(display);
shell.dispose();
}

@Test
public void testLeak() { // fails
System.out.println("leak");
IWorkbench workbench = PlatformUI.getWorkbench();
Display display = workbench.getDisplay();
leakedShell = new Shell(display);
}

@AfterAll
public static void afterAll() {
leakedShell.dispose();
}

}

0 comments on commit 30cf747

Please sign in to comment.