Adds several more tests to the PID Test Class

Adds Logger output to tests when they fail to allow the rest of the tests to run while you can follow the failure stack trace. This allows you to begin working on fixing the failure before the remainder of the tests have run.

Change-Id: I84adfad0b31b166f027d0bf9797a23856dd02f97
This commit is contained in:
Jonathan Leitschuh
2014-06-13 15:03:38 -04:00
parent fdfc33a380
commit aa3b24092a
20 changed files with 237 additions and 42 deletions

View File

@@ -9,6 +9,7 @@ package edu.wpi.first.wpilibj;
import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.logging.Logger;
import org.junit.AfterClass;
import org.junit.Before;
@@ -31,10 +32,15 @@ import edu.wpi.first.wpilibj.test.TestBench;
@RunWith(Parameterized.class)
public class CounterTest extends AbstractComsSetup {
private static FakeCounterFixture counter = null;
private static final Logger logger = Logger.getLogger(CounterTest.class.getName());
Integer input;
Integer output;
protected Logger getClassLogger(){
return logger;
}
/**
* Constructs a Counter Test with the given inputs
* @param input The input Port

View File

@@ -10,6 +10,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
@@ -31,8 +32,13 @@ import edu.wpi.first.wpilibj.test.TestBench;
*/
@RunWith(Parameterized.class)
public class DIOCrossConnectTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(DIOCrossConnectTest.class.getName());
private static DIOCrossConnectFixture dio = null;
protected Logger getClassLogger(){
return logger;
}
/**
* Default constructor for the DIOCrossConnectTest

View File

@@ -9,6 +9,7 @@ package edu.wpi.first.wpilibj;
import static org.junit.Assert.*;
import java.util.Collection;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
@@ -33,7 +34,7 @@ import edu.wpi.first.wpilibj.test.TestBench;
*/
@RunWith(Parameterized.class)
public class EncoderTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(EncoderTest.class.getName());
private static FakeEncoderFixture encoder = null;
private final boolean flip; //Does this test need to flip the inputs
@@ -42,6 +43,10 @@ public class EncoderTest extends AbstractComsSetup {
private final int outputA;
private final int outputB;
protected Logger getClassLogger(){
return logger;
}
/**
* Test data generator. This method is called the the JUnit
* parameterized test runner and returns a Collection of Arrays. For each

View File

@@ -35,6 +35,10 @@ public class MotorEncoderTest extends AbstractComsSetup {
//private static final List<MotorEncoderFixture> pairs = new ArrayList<MotorEncoderFixture>();
private static MotorEncoderFixture me = null;
protected Logger getClassLogger(){
return logger;
}
public MotorEncoderTest(MotorEncoderFixture mef){
logger.fine("Constructor with: " + mef.getType());
if(me != null && !me.equals(mef)) me.teardown();

View File

@@ -7,6 +7,7 @@
package edu.wpi.first.wpilibj;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,6 +29,7 @@ import org.junit.runners.Parameterized.Parameters;
import edu.wpi.first.wpilibj.PIDSource.PIDSourceParameter;
import edu.wpi.first.wpilibj.fixtures.MotorEncoderFixture;
import edu.wpi.first.wpilibj.networktables.NetworkTable;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
import edu.wpi.first.wpilibj.test.TestBench;
@@ -41,41 +43,40 @@ import edu.wpi.first.wpilibj.test.TestBench;
@RunWith(Parameterized.class)
public class PIDTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(PIDTest.class.getName());
private NetworkTable table;
private static final double absoluteTollerance = 20;
private static final double outputRange = 0.19;
private PIDController controller = null;
private static MotorEncoderFixture me = null;
private final Double p;
private final Double i;
private final Double d;
private final Double k_p, k_i, k_d;
@Rule
public TestWatcher testWatcher = new TestWatcher() {
protected void failed(Throwable e, Description description) {
System.out.println();
logger.severe("" + description.getDisplayName() + " failed " + e.getMessage());
super.failed(e, description);
}
};
protected Logger getClassLogger(){
return logger;
}
public PIDTest(Double p, Double i, Double d, MotorEncoderFixture mef){
logger.fine("Constructor with: " + mef.getType());
if(PIDTest.me != null && !PIDTest.me.equals(mef)) PIDTest.me.teardown();
PIDTest.me = mef;
this.p = p;
this.i = i;
this.d = d;
this.k_p = p;
this.k_i = i;
this.k_d = d;
}
@Parameters
public static Collection<Object[]> generateData(){
//logger.fine("Loading the MotorList");
Collection<Object[]> data = new ArrayList<Object[]>();
double kp = 0.0035;
double ki = 0.001;
double kp = 0.003;
double ki = 0.0015;
double kd = 0.0;
for(int i = 0; i < 10; i++){
for(int i = 0; i < 5; i++){
data.addAll(Arrays.asList(new Object[][]{
{kp, ki, kd, TestBench.getInstance().getTalonPair()},
{kp, ki, kd, TestBench.getInstance().getVictorPair()},
@@ -107,9 +108,9 @@ public class PIDTest extends AbstractComsSetup {
public void setUp() throws Exception {
logger.fine("Setup: " + me.getType());
me.setup();
controller = new PIDController(p, i, d, me.getEncoder(), me.getMotor());
controller.setAbsoluteTolerance(15);
controller.setOutputRange(-0.2, 0.2);
table = NetworkTable.getTable("TEST_PID");
controller = new PIDController(k_p, k_i, k_d, me.getEncoder(), me.getMotor());
controller.initTable(table);
}
/**
@@ -124,14 +125,49 @@ public class PIDTest extends AbstractComsSetup {
me.reset();
}
private void setupAbsoluteTollerance(){
controller.setAbsoluteTolerance(absoluteTollerance);
}
private void setupOutputRange(){
controller.setOutputRange(-outputRange, outputRange);
}
@Test
public void testInitialSettings(){
controller.disable();
assertTrue("PID did not start at 0", controller.getError() == 0);
setupAbsoluteTollerance();
setupOutputRange();
double setpoint = 2500.0;
controller.setSetpoint(setpoint);
assertFalse("PID did not begin disabled", controller.isEnable());
assertEquals("PID.getError() did not start at " + setpoint, setpoint, controller.getError(), 0);
assertEquals(k_p, table.getNumber("p"), 0);
assertEquals(k_i, table.getNumber("i"), 0);
assertEquals(k_d, table.getNumber("d"), 0);
assertEquals(setpoint, table.getNumber("setpoint"), 0);
assertFalse(table.getBoolean("enabled"));
}
@Test
public void testRestartAfterEnable(){
setupAbsoluteTollerance();
setupOutputRange();
double setpoint = 2500.0;
controller.setSetpoint(setpoint);
controller.enable();
Timer.delay(.5);
assertTrue(table.getBoolean("enabled"));
assertTrue(controller.isEnable());
assertThat(0.0, is(not(me.getMotor().get())));
controller.reset();
assertFalse(table.getBoolean("enabled"));
assertFalse(controller.isEnable());
assertEquals(0, me.getMotor().get(), 0);
}
@Test
public void testSetSetpoint(){
setupAbsoluteTollerance();
setupOutputRange();
Double setpoint = 2500.0;
controller.disable();
controller.setSetpoint(setpoint);
@@ -141,6 +177,8 @@ public class PIDTest extends AbstractComsSetup {
@Test (timeout = 6000)
public void testRotateToTarget() {
setupAbsoluteTollerance();
setupOutputRange();
double setpoint = 2500.0;
assertEquals(pidData() + "did not start at 0", 0, controller.get(), 0);
controller.setSetpoint(setpoint);
@@ -155,4 +193,10 @@ public class PIDTest extends AbstractComsSetup {
return me.getType() + " PID {P:" +controller.getP() + " I:" + controller.getI() + " D:" + controller.getD() +"} ";
}
@Test(expected = RuntimeException.class)
public void testOnTargetNoTolleranceSet(){
setupOutputRange();
controller.onTarget();
}
}

View File

@@ -12,6 +12,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
@@ -27,11 +28,16 @@ import edu.wpi.first.wpilibj.networktables.NetworkTable;
*
*/
public class PrefrencesTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(PrefrencesTest.class.getName());
private NetworkTable prefTable;
private Preferences pref;
private long check;
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception
*/

View File

@@ -8,6 +8,8 @@ package edu.wpi.first.wpilibj;
import static org.junit.Assert.assertTrue;
import java.util.logging.Logger;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -26,10 +28,12 @@ import edu.wpi.first.wpilibj.test.AbstractComsSetup;
* @author Fredric Silberberg
*/
public class SampleTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(SampleTest.class.getName());
static SampleFixture fixture = new SampleFixture();
public SampleTest() {
protected Logger getClassLogger(){
return logger;
}
@BeforeClass

View File

@@ -28,6 +28,11 @@ public class TiltPanCameraTest extends AbstractComsSetup {
private static TiltPanCameraFixture tpcam;
protected Logger getClassLogger(){
return logger;
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
logger.fine("Setup: TiltPan camera");
@@ -42,7 +47,10 @@ public class TiltPanCameraTest extends AbstractComsSetup {
@Before
public void setUp() throws Exception {
tpcam.reset();
boolean setupSucsess = tpcam.setup();
assertTrue(tpcam.getSetupError(), setupSucsess);
double resetTime = tpcam.getLastResetTimeGyro();
assertEquals("The Gyroscoe reset time was " + resetTime + " seconds", 0, resetTime, .03);
}
@After
@@ -53,7 +61,7 @@ public class TiltPanCameraTest extends AbstractComsSetup {
@Test
public void testInitial(){
double angle = tpcam.getGyro().getAngle();
assertEquals(errorMessage(angle, 0), 0, angle, .5);
assertEquals(errorMessage(angle, 0), 0, angle, .5);
}
/**
@@ -78,6 +86,15 @@ public class TiltPanCameraTest extends AbstractComsSetup {
assertEquals(errorMessage(diff, TEST_ANGLE), TEST_ANGLE, angle, 8);
}
@Test
public void testDeviationOverTime(){
double angle = tpcam.getGyro().getAngle();
assertEquals(errorMessage(angle, 0), 0, angle, .5);
Timer.delay(5);
angle = tpcam.getGyro().getAngle();
assertEquals(errorMessage(angle, 0), 0, angle, .5);
}
private String errorMessage(double difference, double target){
return "Gryo angle skewed " + difference + " deg away from target " + target;
}

View File

@@ -9,6 +9,8 @@ package edu.wpi.first.wpilibj;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.logging.Logger;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -18,10 +20,15 @@ import edu.wpi.first.wpilibj.test.AbstractComsSetup;
public class TimerTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(TimerTest.class.getName());
private static final long TIMER_TOLARANCE = 5 * 1000;
private static final long TIMER_RUNTIME = 5 * 1000000;
protected Logger getClassLogger(){
return logger;
}
@BeforeClass
public static void classSetup() {
}

View File

@@ -6,6 +6,8 @@
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -22,10 +24,15 @@ import edu.wpi.first.wpilibj.mocks.MockCommand;
*
*/
public class ButtonTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(ButtonTest.class.getName());
private InternalButton button1;
private InternalButton button2;
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception
*/

View File

@@ -8,6 +8,8 @@ package edu.wpi.first.wpilibj.command;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -23,6 +25,11 @@ import edu.wpi.first.wpilibj.test.AbstractComsSetup;
* @author Jonathan Leitschuh
*/
public class CommandParallelGroupTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(CommandParallelGroupTest.class.getName());
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception

View File

@@ -8,6 +8,8 @@ package edu.wpi.first.wpilibj.command;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -22,6 +24,11 @@ import edu.wpi.first.wpilibj.mocks.MockCommand;
* @author Jonathan Leitschuh
*/
public class CommandScheduleTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(CommandScheduleTest.class.getName());
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception

View File

@@ -23,9 +23,12 @@ import edu.wpi.first.wpilibj.mocks.MockCommand;
* @author Jonathan Leitschuh
*/
public class CommandSequentialGroupTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(CommandSequentialGroupTest.class.getName());
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception
*/

View File

@@ -6,6 +6,8 @@
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -21,6 +23,11 @@ import edu.wpi.first.wpilibj.mocks.MockCommand;
* @author Jonathan Leitschuh
*/
public class CommandSupersedeTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(CommandSupersedeTest.class.getName());
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception

View File

@@ -8,6 +8,8 @@ package edu.wpi.first.wpilibj.command;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -21,6 +23,11 @@ import edu.wpi.first.wpilibj.mocks.MockCommand;
*
*/
public class CommandTimeoutTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(CommandTimeoutTest.class.getName());
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception

View File

@@ -8,6 +8,8 @@ package edu.wpi.first.wpilibj.command;
import static org.junit.Assert.*;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -21,6 +23,11 @@ import edu.wpi.first.wpilibj.mocks.MockCommand;
*
*/
public class DefaultCommandTest extends AbstractCommandTest {
private static final Logger logger = Logger.getLogger(DefaultCommandTest.class.getName());
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception

View File

@@ -25,6 +25,8 @@ public class TiltPanCameraFixture implements ITestFixture {
private final Servo tilt;
private final Servo pan;
private double lastResetTimeGyro = 0;
/**
* Constructs the TiltPanCamera
* @param tilt
@@ -37,26 +39,50 @@ public class TiltPanCameraFixture implements ITestFixture {
this.tilt = tilt;
this.pan = pan;
this.gyro = gyro;
}
@Override
public boolean setup() {
return reset();
boolean wasSetup = true;
pan.set(0.0);
tilt.set(0.0);
Timer.delay(RESET_TIME);
gyro.reset();
double startTime = Timer.getFPGATimestamp();
while(Math.abs(gyro.getAngle()) > 0.1){
Timer.delay(.0001);
}
double endTime = Timer.getFPGATimestamp();
lastResetTimeGyro = endTime - startTime;
//System.out.println("Gyro reset in " + lastResetTimeGyro + " seconds");
wasSetup = wasSetup && Math.abs(pan.get()) < 0.01;
wasSetup = wasSetup && Math.abs(tilt.get()) < 0.01;
wasSetup = wasSetup && Math.abs(gyro.getAngle()) < .2;
return wasSetup;
}
/**
* When resetting the gyroscope the reset time is stored as a variable that can be retrieved with this method
* @return The last time that it took to reset the gyroscope
*/
public double getLastResetTimeGyro() {
return lastResetTimeGyro;
}
public String getSetupError(){
StringBuilder error = new StringBuilder("SETUP ERROR: ");
if(Math.abs(pan.get()) >= 0.01) error.append("Pan " + pan.get() + ", ");
if(Math.abs(tilt.get()) >= 0.01) error.append("Tilt " + tilt.get() + ", ");
if(Math.abs(gyro.getAngle()) >= 0.2) error.append("Gyro " + gyro.getAngle() + ", ");
error.delete(error.length()-2, error.length());
return error.toString();
}
@Override
public boolean reset(){
boolean wasReset = true;
pan.setAngle(0);
tilt.set(0);
Timer.delay(RESET_TIME);
gyro.reset();
wasReset &= pan.get() == 0;
wasReset &= tilt.get() == 0;
wasReset &= gyro.getAngle() == 0;
return wasReset;
return true;
}
public Servo getTilt() {
@@ -73,8 +99,7 @@ public class TiltPanCameraFixture implements ITestFixture {
@Override
public boolean teardown() {
reset();
setup();
tilt.free();
pan.free();
gyro.free();

View File

@@ -8,6 +8,8 @@ package edu.wpi.first.wpilibj.smartdashboard;
import static org.junit.Assert.assertEquals;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -24,8 +26,13 @@ import edu.wpi.first.wpilibj.test.AbstractComsSetup;
*
*/
public class SmartDashboardTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(SmartDashboardTest.class.getName());
private static final NetworkTable table = NetworkTable.getTable("SmartDashboard");
protected Logger getClassLogger(){
return logger;
}
/**
* @throws java.lang.Exception
*/

View File

@@ -6,7 +6,12 @@
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.test;
import java.util.logging.Logger;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary;
@@ -55,5 +60,19 @@ public abstract class AbstractComsSetup {
System.out.println("Running!");
}
}
protected abstract Logger getClassLogger();
/** This causes a stack trace to be printed as the test is running as well as at the end */
@Rule
public TestWatcher testWatcher = new TestWatcher() {
protected void failed(Throwable e, Description description) {
System.out.println();
getClassLogger().severe("" + description.getDisplayName() + " failed " + e.getMessage());
e.printStackTrace();
super.failed(e, description);
}
};
}