feat: Add template system to weevil new command
Implements template-based project creation allowing teams to start with
professional example code instead of empty projects.
Features:
- Two templates: 'basic' (minimal) and 'testing' (45-test showcase)
- Template variable substitution ({{PROJECT_NAME}}, etc.)
- Template validation with helpful error messages
- `weevil new --list-templates` command
- Template files embedded in binary at compile time
Technical details:
- Templates stored in templates/basic/ and templates/testing/
- Files ending in .template have variables replaced
- Uses include_dir! macro to embed templates in binary
- Returns file count for user feedback
Testing template includes:
- 3 complete subsystems (MotorCycler, WallApproach, TurnController)
- Hardware abstraction layer with mock implementations
- 45 comprehensive tests (unit, integration, system)
- Professional documentation (DESIGN_AND_TEST_PLAN.md, etc.)
Usage:
weevil new my-robot # basic template
weevil new my-robot --template testing # testing showcase
weevil new --list-templates # show available templates
This enables FTC teams to learn from working code and best practices
rather than starting from scratch.
This commit is contained in:
126
templates/testing/SOLUTION.md
Normal file
126
templates/testing/SOLUTION.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user