Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions testing/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ version = '1.0.0-alpha.1'
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
maven {
// WPI
url 'https://frcmaven.wpi.edu/artifactory/release/'
}
}

dependencies {
implementation wpi.java.deps.wpilib()
implementation wpi.java.vendor.java()
implementation 'com.google.truth:truth:1.4.4'
implementation(platform('org.junit:junit-bom:5.13.1'))
implementation('org.junit.jupiter:junit-jupiter')

nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
Expand All @@ -22,8 +28,7 @@ dependencies {
nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
simulationRelease wpi.sim.enableRelease()
testImplementation(platform('org.junit:junit-bom:5.13.1'))
testImplementation('org.junit.jupiter:junit-jupiter')

testRuntimeOnly('org.junit.platform:junit-platform-launcher')
}

Expand All @@ -45,15 +50,6 @@ javadoc {
]
}

// Generates Javadocs for test libraries under /build/docs/testjavadoc
// https://discuss.gradle.org/t/how-configure-gradle-to-generate-javadoc-for-testing-classes-junit/12764/6
task testJavadoc(type: Javadoc) {
source = sourceSets.test.allJava
classpath = sourceSets.test.compileClasspath
destinationDir = file("${buildDir}/docs/testjavadoc")
println (title == null ? '<null>' : title)
}

task sourceJar(type: Jar) {
from sourceSets.main.allJava
archiveClassifier = 'sources'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.team2813.lib2813.testing.junit.jupiter;

import edu.wpi.first.wpilibj2.command.Command;

/**
* Allows tests to run commands.
*
* <p>Tests can get an instance by using {@link WPILibExtension}.
*/
public interface CommandTester {

/** Schedules the provided command and runs it until it completes. */
void runUntilComplete(Command command);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.team2813.lib2813.testing.junit.jupiter;

import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
import edu.wpi.first.wpilibj2.command.CommandScheduler;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;

/**
* JUnit Jupiter extension for testing code that depends on WPILib.
*
* <p>Also provides a {@link CommandTester} for tests.
*
* <p>Example use:
*
* <pre>{@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();
* }
* }
* }</pre>
*/
public final class WPILibExtension
implements Extension,
AfterAllCallback,
AfterEachCallback,
BeforeAllCallback,
ParameterResolver {

@Override
public void beforeAll(ExtensionContext context) {
// See https://www.chiefdelphi.com/t/driverstation-getalliance-in-gradle-test/
HAL.initialize(500, 0);
DriverStationSim.setEnabled(true);
DriverStationSim.notifyNewData();
CommandScheduler.getInstance().enable();
CommandScheduler.getInstance().cancelAll();
CommandScheduler.getInstance().unregisterAllSubsystems();
Comment thread
kcooney marked this conversation as resolved.
}

@Override
public void afterEach(ExtensionContext context) {
CommandScheduler.getInstance().cancelAll();
CommandScheduler.getInstance().unregisterAllSubsystems();
}

@Override
public void afterAll(ExtensionContext context) {
CommandScheduler.getInstance().cancelAll();
CommandScheduler.getInstance().unregisterAllSubsystems();
CommandScheduler.getInstance().disable();
DriverStationSim.setEnabled(false);
DriverStationSim.notifyNewData();
}

@Override
public boolean supportsParameter(
ParameterContext parameterContext, ExtensionContext extensionContext)
throws ParameterResolutionException {
return CommandTester.class.equals(parameterContext.getParameter().getType());
}

@Override
public CommandTester resolveParameter(
ParameterContext parameterContext, ExtensionContext extensionContext) {
return command -> {
CommandScheduler scheduler = CommandScheduler.getInstance();
command.schedule();
do {
scheduler.run();
} while (scheduler.isScheduled(command));
};
}
}
38 changes: 38 additions & 0 deletions testing/vendordeps/WPILibNewCommands.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"fileName": "WPILibNewCommands.json",
"name": "WPILib-New-Commands",
"version": "1.0.0",
"uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266",
"frcYear": "2025",
"mavenUrls": [],
"jsonUrl": "",
"javaDependencies": [
{
"groupId": "edu.wpi.first.wpilibNewCommands",
"artifactId": "wpilibNewCommands-java",
"version": "wpilib"
}
],
"jniDependencies": [],
"cppDependencies": [
{
"groupId": "edu.wpi.first.wpilibNewCommands",
"artifactId": "wpilibNewCommands-cpp",
"version": "wpilib",
"libName": "wpilibNewCommands",
"headerClassifier": "headers",
"sourcesClassifier": "sources",
"sharedLibrary": true,
"skipInvalidPlatforms": true,
"binaryPlatforms": [
"linuxathena",
"linuxarm32",
"linuxarm64",
"windowsx86-64",
"windowsx86",
"linuxx86-64",
"osxuniversal"
]
}
]
}
Loading