# Solution: Testing FTC Code Without Hardware ## The Problem When you run `gradlew test`, it tries to compile ALL your code including FTC-dependent files: ``` FtcMotorController.java → needs com.qualcomm.robotcore.hardware.DcMotor MotorCycleOpMode.java → needs com.qualcomm.robotcore.eventloop.opmode.OpMode ``` These classes don't exist on Windows → compilation fails → no tests. ## The Solution (One Line) **Exclude FTC-dependent files from test compilation:** ```kotlin // build.gradle.kts sourceSets { main { java { exclude( "robot/hardware/FtcMotorController.java", "robot/opmodes/**/*.java" ) } } } ``` Done. That's it. ## What Happens Now ### When You Run `gradlew test`: - ✅ Compiles: MotorController.java (interface, no FTC deps) - ✅ Compiles: MotorCycler.java (pure Java logic) - ✅ Compiles: MockMotorController.java (test mock) - ✅ Compiles: MotorCyclerTest.java (tests) - ❌ Skips: FtcMotorController.java (EXCLUDED - has FTC deps) - ❌ Skips: MotorCycleOpMode.java (EXCLUDED - has FTC deps) Tests run on Windows in seconds! ### When You Run `build.bat`: - Copies ALL files to FTC SDK TeamCode directory - FTC SDK's Gradle compiles everything (it has the FTC SDK jars) - Creates APK with all your code ## The Architecture Pattern ``` Interface (no FTC) → Logic uses interface → Test with mock ↓ FTC Implementation (excluded from tests) ``` ### Example: Motor ```java // 1. Interface (compiles for tests) public interface MotorController { void setPower(double power); } // 2. FTC implementation (excluded from tests) public class FtcMotorController implements MotorController { private final DcMotor motor; // FTC SDK class public void setPower(double p) { motor.setPower(p); } } // 3. Mock (test only) public class MockMotorController implements MotorController { private double power; public void setPower(double p) { this.power = p; } } // 4. Logic (pure Java - testable!) public class MotorCycler { private final MotorController motor; // Uses interface! // ... no FTC dependencies ... } // 5. Test @Test void test() { MockMotorController mock = new MockMotorController(); MotorCycler cycler = new MotorCycler(mock, 100, 50); cycler.update(60); assertEquals(0.5, mock.getPower()); } ``` ## Applies to Any Hardware Same pattern for everything: - **Motors** → MotorController interface + Ftc + Mock - **Servos** → ServoController interface + Ftc + Mock - **Sensors** (I2C, SPI, USB, etc.) → SensorInterface + Ftc + Mock - **Gyros** → GyroSensor interface + Ftc + Mock The FTC implementation is always just a thin wrapper. All your logic uses interfaces and is fully testable. ## Why This Works **Test compilation:** - Only compiles files WITHOUT FTC dependencies - Pure Java logic + interfaces + mocks - Runs on Windows JRE **Robot compilation:** - ALL files copied to TeamCode - Compiled by FTC SDK (which has FTC jars) - Creates APK with everything Same logic runs in both places - no special test-only code! ## Quick Start 1. Create interface (no FTC deps) 2. Create FTC implementation (add to exclude list) 3. Create mock for testing 4. Write pure Java logic using interface 5. Test instantly on PC 6. Deploy to robot - everything works See TESTING_GUIDE.md for detailed examples.