-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
started adding unit tests, which will be used on to test the self che…
…ck feature outside main robot code
- Loading branch information
Showing
5 changed files
with
199 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package frc.lib; | ||
|
||
import static edu.wpi.first.units.Units.Seconds; | ||
|
||
import edu.wpi.first.hal.HAL; | ||
import edu.wpi.first.units.measure.Time; | ||
import edu.wpi.first.wpilibj.simulation.DriverStationSim; | ||
import edu.wpi.first.wpilibj.simulation.SimHooks; | ||
import edu.wpi.first.wpilibj2.command.Command; | ||
import edu.wpi.first.wpilibj2.command.CommandScheduler; | ||
|
||
// (from team 1155) | ||
|
||
/** Provides helper methods that run a command when performing unit tests. */ | ||
public class UnitTestingUtil { | ||
public static final Time TICK_RATE = Seconds.of(0.02); | ||
|
||
/** Sets up DS and initializes HAL with default values and asserts that it doesn't fail. */ | ||
public static void setupTests() { | ||
assert HAL.initialize(500, 0); | ||
DriverStationSim.setEnabled(true); | ||
DriverStationSim.setTest(true); | ||
DriverStationSim.notifyNewData(); | ||
FaultLogger.clear(); | ||
FaultLogger.unregisterAll(); | ||
} | ||
|
||
/** | ||
* Resets CommandScheduler and closes all subsystems. Please call in an @AfterEach method! | ||
* | ||
* @param subsystems All subsystems that need to be closed. | ||
*/ | ||
public static void reset(AutoCloseable... subsystems) throws Exception { | ||
CommandScheduler.getInstance().unregisterAllSubsystems(); | ||
CommandScheduler.getInstance().cancelAll(); | ||
|
||
for (AutoCloseable subsystem : subsystems) { | ||
subsystem.close(); | ||
} | ||
} | ||
|
||
/** | ||
* Runs CommandScheduler and updates timer repeatedly to fast forward subsystems and run commands. | ||
* | ||
* @param ticks The number of times CommandScheduler is run. | ||
*/ | ||
public static void fastForward(int ticks) { | ||
for (int i = 0; i < ticks; i++) { | ||
CommandScheduler.getInstance().run(); | ||
SimHooks.stepTiming(TICK_RATE.in(Seconds)); | ||
} | ||
} | ||
|
||
/** | ||
* Fasts forward in time by running CommandScheduler and updating timer. | ||
* | ||
* @param time | ||
*/ | ||
public static void fastForward(Time time) { | ||
fastForward((int) (time.in(Seconds) / TICK_RATE.in(Seconds))); | ||
} | ||
|
||
/** | ||
* Runs CommandScheduler and updates timer to fast forward subsystems by 4 seconds and run | ||
* commands. | ||
*/ | ||
public static void fastForward() { | ||
fastForward(Seconds.of(4)); | ||
} | ||
|
||
/** | ||
* Schedules and runs a command. | ||
* | ||
* @param command The command to run. | ||
*/ | ||
public static void run(Command command) { | ||
command.schedule(); | ||
CommandScheduler.getInstance().run(); | ||
} | ||
|
||
/** | ||
* Schedules and runs a command. | ||
* | ||
* @param command The command to run. | ||
* @param runs The number of times CommandScheduler is run. | ||
*/ | ||
public static void run(Command command, int runs) { | ||
command.schedule(); | ||
fastForward(runs); | ||
} | ||
|
||
/** | ||
* Schedules a command and runs it until it ends. Be careful -- if the command you give never | ||
* ends, this will be an infinate loop! | ||
* | ||
* @param command | ||
*/ | ||
public static void runToCompletion(Command command) { | ||
command.schedule(); | ||
fastForward(1); | ||
while (command.isScheduled()) { | ||
fastForward(1); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// Copyright (c) FIRST and other WPILib contributors. | ||
// Open Source Software; you can modify and/or share it under the terms of | ||
// the WPILib BSD license file in the root directory of this project. | ||
|
||
package frc.lib; | ||
|
||
import static frc.lib.UnitTestingUtil.*; | ||
|
||
import edu.wpi.first.wpilibj2.command.Command; | ||
import edu.wpi.first.wpilibj2.command.Commands; | ||
import frc.lib.FaultsTable.FaultType; | ||
import java.util.function.BiConsumer; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
public class AdvancedSubsystemTest { | ||
static final double DELTA = 1e-2; // acceptable deviation range | ||
|
||
private TestImpl sub = new TestImpl(); | ||
|
||
@BeforeEach | ||
public void setup() { | ||
setupTests(); | ||
} | ||
|
||
@AfterEach | ||
public void close() throws Exception { | ||
reset(sub); | ||
} | ||
|
||
@Test | ||
public void subsystemSelfCheck() { | ||
// TODO | ||
} | ||
|
||
public class TestImpl extends AdvancedSubsystem { | ||
private final BaseIO _io = new TestIO(); | ||
|
||
private interface BaseIO extends SelfChecked { | ||
public double getEncoderSpeed(); | ||
} | ||
|
||
// irl this would be for example "TalonIO" (handles real/sim) or "NoneIO" (handles no subsystem) | ||
private class TestIO implements BaseIO { | ||
private final boolean _fault1 = true; | ||
private final boolean _fault2 = true; | ||
private final boolean _fault3 = false; | ||
|
||
@Override | ||
public double getEncoderSpeed() { | ||
return 1.0; | ||
} | ||
|
||
@Override | ||
public Command selfCheck(BiConsumer<String, FaultType> faultAdder) { | ||
return Commands.sequence( | ||
Commands.runOnce( | ||
() -> { | ||
if (_fault1) faultAdder.accept("FAULT 1", FaultType.ERROR); | ||
}), | ||
Commands.runOnce( | ||
() -> { | ||
if (_fault2) faultAdder.accept("FAULT 2", FaultType.ERROR); | ||
}), | ||
Commands.runOnce( | ||
() -> { | ||
if (_fault3) faultAdder.accept("FAULT 3", FaultType.WARNING); | ||
})); | ||
} | ||
} | ||
|
||
// uses the io | ||
public double speed() { | ||
return _io.getEncoderSpeed(); | ||
} | ||
|
||
@Override | ||
public Command selfCheck(BiConsumer<String, FaultType> faultAdder) { | ||
return Commands.sequence( | ||
_io.selfCheck(faultAdder), // self check io devices first | ||
runOnce( | ||
() -> { | ||
if (speed() < 2) faultAdder.accept("TOO SLOW", FaultType.WARNING); | ||
}) // then check the whole subsystem | ||
); | ||
} | ||
} | ||
} |