diff --git a/lib/src/test/java/com/team2813/lib2813/preferences/IsolatedPreferences.java b/lib/src/test/java/com/team2813/lib2813/preferences/IsolatedPreferences.java index cb6ed91b..d183769f 100644 --- a/lib/src/test/java/com/team2813/lib2813/preferences/IsolatedPreferences.java +++ b/lib/src/test/java/com/team2813/lib2813/preferences/IsolatedPreferences.java @@ -40,6 +40,7 @@ protected void before() { prevInstance = Preferences.getNetworkTable().getInstance(); tempInstance = NetworkTableInstance.create(); Preferences.setNetworkTableInstance(tempInstance); + tempInstance.waitForListenerQueue(1); removePreferencesListener(); } @@ -52,7 +53,7 @@ protected void after() { // This works around a race condition in WPILib where a listener registered by Preferences can // be called after the NetworkTableInstance was closed (see // https://github.com/wpilibsuite/allwpilib/issues/8215). - if (!tempInstance.waitForListenerQueue(4)) { + if (!tempInstance.waitForListenerQueue(.4)) { System.err.println( "Timed out waiting for the NetworkTableInstance listener queue to empty (waited 400ms);" + " will not close temporary NetworkTableInstance"); @@ -74,7 +75,7 @@ private static void removePreferencesListener() { NetworkTableListener listener = (NetworkTableListener) listnerField.get(null); listnerField.set(null, null); listener.close(); - } catch (NoSuchFieldException | IllegalAccessException e) { + } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) { } } } diff --git a/lib/src/test/java/com/team2813/lib2813/subsystems/ParameterizedIntakeSubsystemTest.java b/lib/src/test/java/com/team2813/lib2813/subsystems/ParameterizedIntakeSubsystemTest.java index 6da2a7fc..a14ebc9d 100644 --- a/lib/src/test/java/com/team2813/lib2813/subsystems/ParameterizedIntakeSubsystemTest.java +++ b/lib/src/test/java/com/team2813/lib2813/subsystems/ParameterizedIntakeSubsystemTest.java @@ -1,5 +1,5 @@ /* -Copyright 2025 Prospect Robotics SWENext Club +Copyright 2025-2026 Prospect Robotics SWENext Club Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,16 +22,15 @@ import com.team2813.lib2813.control.Motor; import com.team2813.lib2813.testing.FakeMotor; import com.team2813.lib2813.testing.junit.jupiter.CommandTester; -import com.team2813.lib2813.testing.junit.jupiter.WPILibExtension; +import com.team2813.lib2813.testing.junit.jupiter.InitWPILib; import edu.wpi.first.wpilibj2.command.Command; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.provider.EnumSource; @ParameterizedClass @EnumSource(ControlMode.class) -@ExtendWith(WPILibExtension.class) +@InitWPILib public final class ParameterizedIntakeSubsystemTest { private static class ConcreteParameterizedIntakeSubsystem extends ParameterizedIntakeSubsystem { diff --git a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/CommandTester.java b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/CommandTester.java index 6fbdd517..7eabcf92 100644 --- a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/CommandTester.java +++ b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/CommandTester.java @@ -20,7 +20,7 @@ /** * Allows tests to run commands. * - *
Tests can get an instance by using {@link WPILibExtension}. + *
Tests can get an instance by using {@link InitWPILib}. * * @since 2.0.0 */ diff --git a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/InitWPILib.java b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/InitWPILib.java new file mode 100644 index 00000000..8ac614fc --- /dev/null +++ b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/InitWPILib.java @@ -0,0 +1,59 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.testing.junit.jupiter; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ExtendWith; + +/** + * JUnit Jupiter annotation used to signal tests that depends on WPILib. + * + *
Also provides a {@link CommandTester} for tests. + * + *
Example use: + * + *
{@code
+ * @InitWPILib
+ * public final class FlightSubsystemTest {
+ *
+ * @Test
+ * public void initiallyNotInAir() {
+ * var flight = new FlightSubsystem();
+ *
+ * assertThat(flight.inAir()).isFalse();
+ * }
+ *
+ * @Test
+ * public void takesFlight(CommandTester commandTester) {
+ * var flight = new FlightSubsystem();
+ * Command takeOff = flight.createTakeOffCommandCommand();
+ *
+ * commandTester.runUntilComplete(takeOff);
+ *
+ * assertThat(flight.inAir()).isTrue();
+ * }
+ * }
+ * }
+ *
+ * @since 2.0.0
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(InitWPILibExtension.class)
+public @interface InitWPILib {}
diff --git a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/WPILibExtension.java b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/InitWPILibExtension.java
similarity index 82%
rename from testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/WPILibExtension.java
rename to testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/InitWPILibExtension.java
index 085d27a1..d3f9bcc0 100644
--- a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/WPILibExtension.java
+++ b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/InitWPILibExtension.java
@@ -30,39 +30,8 @@
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;
-/**
- * JUnit Jupiter extension for testing code that depends on WPILib.
- *
- * Also provides a {@link CommandTester} for tests. - * - *
Example use: - * - *
{@code
- * @ExtendWith(WPILibExtension.class)
- * public final class FlightSubsystemTest {
- *
- * @Test
- * public void initiallyNotInAir() {
- * var flight = new FlightSubsystem();
- *
- * assertThat(flight.inAir()).isFalse();
- * }
- *
- * @Test
- * public void takesFlight(CommandTester commandTester) {
- * var flight = new FlightSubsystem();
- * Command takeOff = flight.createTakeOffCommandCommand();
- *
- * commandTester.runUntilComplete(takeOff);
- *
- * assertThat(flight.inAir()).isTrue();
- * }
- * }
- * }
- *
- * @since 2.0.0
- */
-public final class WPILibExtension
+/** JUnit Jupiter extension for testing code that depends on WPILib. */
+final class InitWPILibExtension
implements Extension,
AfterAllCallback,
AfterEachCallback,
diff --git a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/ProvideUniqueNetworkTableInstance.java b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/ProvideUniqueNetworkTableInstance.java
new file mode 100644
index 00000000..96e3e186
--- /dev/null
+++ b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/ProvideUniqueNetworkTableInstance.java
@@ -0,0 +1,59 @@
+/*
+Copyright 2026 Prospect Robotics SWENext Club
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package com.team2813.lib2813.testing.junit.jupiter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ * JUnit Jupiter annotation used to signal tests that need an isolated NetworkTableInstance.
+ *
+ * Example use: + * + *
{@code
+ * @ProvideUniqueNetworkTableInstance
+ * public final class IntakeTest {
+ *
+ * @Test
+ * public void intakeCoral(NetworkTableInstance ntInstance) {
+ * // Do something with ntInstance
+ * }
+ * }
+ * }
+ *
+ * @since 2.0.0
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(ProvideUniqueNetworkTableInstanceExtension.class)
+public @interface ProvideUniqueNetworkTableInstance {
+
+ /**
+ * How long to wait for the listener queue to empty before destroying the temporary network table
+ * instance.
+ */
+ double waitForListenerQueueSeconds() default 0.6;
+
+ /**
+ * Whether to call {@link
+ * edu.wpi.first.wpilibj.Preferences#setNetworkTableInstance(edu.wpi.first.networktables.NetworkTableInstance)}
+ * with the temporary network table instance before starting each test.
+ */
+ boolean replacePreferencesNetworkTable() default false;
+}
diff --git a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/IsolatedNetworkTablesExtension.java b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/ProvideUniqueNetworkTableInstanceExtension.java
similarity index 64%
rename from testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/IsolatedNetworkTablesExtension.java
rename to testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/ProvideUniqueNetworkTableInstanceExtension.java
index fde01441..222e4d22 100644
--- a/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/IsolatedNetworkTablesExtension.java
+++ b/testing/src/main/java/com/team2813/lib2813/testing/junit/jupiter/ProvideUniqueNetworkTableInstanceExtension.java
@@ -20,6 +20,7 @@
import edu.wpi.first.wpilibj.Preferences;
import java.lang.reflect.Field;
import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
@@ -28,37 +29,39 @@
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;
+import org.junit.platform.commons.support.AnnotationSupport;
-/**
- * JUnit Jupiter extension for providing an isolated NetworkTableInstance to tests.
- *
- * Example use: - * - *
{@code
- * @ExtendWith(IsolatedNetworkTablesExtension.class)
- * public final class IntakeTest {
- *
- * @Test
- * public void intakeCoral(NetworkTableInstance ntInstance) {
- * // Do something with ntInstance
- * }
- * }
- * }
- *
- * @since 2.0.0
- */
-public final class IsolatedNetworkTablesExtension
- implements Extension, BeforeEachCallback, AfterEachCallback, ParameterResolver {
- private static final Namespace NAMESPACE = Namespace.create(IsolatedNetworkTablesExtension.class);
+/** JUnit Jupiter extension for providing an isolated NetworkTableInstance to tests. */
+final class ProvideUniqueNetworkTableInstanceExtension
+ implements Extension,
+ BeforeAllCallback,
+ BeforeEachCallback,
+ AfterEachCallback,
+ ParameterResolver {
+ private static final Namespace NAMESPACE =
+ Namespace.create(ProvideUniqueNetworkTableInstanceExtension.class);
private static final StoreKey DATA_KEY = StoreKey.of(Data.class);
+ private static final StoreKey