|
| 1 | +# Testing Guide |
| 2 | + |
| 3 | +This document provides comprehensive information about the testing infrastructure and practices in the AntiRedstoneClock-Remastered project. |
| 4 | + |
| 5 | +## Testing Infrastructure |
| 6 | + |
| 7 | +### Framework Stack |
| 8 | +- **JUnit 5.10.1**: Modern testing framework with advanced features |
| 9 | +- **Mockito 5.7.0**: Mocking framework for creating test doubles |
| 10 | +- **AssertJ 3.24.2**: Fluent assertion library for readable test assertions |
| 11 | +- **MockBukkit 3.128.0**: Bukkit server simulation for integration testing |
| 12 | + |
| 13 | +### Test Configuration |
| 14 | +- **Parallel Execution**: Disabled for MockBukkit compatibility |
| 15 | +- **Test Reports**: JUnit XML and HTML reports generated |
| 16 | +- **Coverage Reports**: Jacoco coverage analysis integrated |
| 17 | + |
| 18 | +## Test Categories |
| 19 | + |
| 20 | +### Unit Tests |
| 21 | +Test individual components in isolation with mocked dependencies. |
| 22 | + |
| 23 | +**Examples:** |
| 24 | +- `DisplayActiveClocksCommandTest`: Tests command dependency injection and execution |
| 25 | +- `DependencyInjectionIntegrationTest`: Tests DI framework integration |
| 26 | +- `DIValidationTest`: Tests module structure and architectural patterns |
| 27 | + |
| 28 | +### Integration Tests |
| 29 | +Test complete workflows with MockBukkit server simulation. |
| 30 | + |
| 31 | +**Features Tested:** |
| 32 | +- Dependency injection framework integration |
| 33 | +- Service layer architecture validation |
| 34 | +- Command and listener dependency resolution |
| 35 | + |
| 36 | +## Running Tests |
| 37 | + |
| 38 | +### Command Line |
| 39 | +```bash |
| 40 | +# Run all tests |
| 41 | +./gradlew test |
| 42 | + |
| 43 | +# Run tests with coverage |
| 44 | +./gradlew test jacocoTestReport |
| 45 | + |
| 46 | +# Run specific test class |
| 47 | +./gradlew test --tests "DisplayActiveClocksCommandTest" |
| 48 | + |
| 49 | +# Run with detailed logging |
| 50 | +./gradlew test --info |
| 51 | +``` |
| 52 | + |
| 53 | +### IDE Integration |
| 54 | +All tests are compatible with IntelliJ IDEA and Eclipse JUnit runners. |
| 55 | + |
| 56 | +## Test Reports |
| 57 | + |
| 58 | +### Location |
| 59 | +- **HTML Reports**: `build/reports/tests/test/index.html` |
| 60 | +- **JUnit XML**: `build/test-results/test/TEST-*.xml` |
| 61 | +- **Coverage Reports**: `build/reports/jacoco/test/html/index.html` |
| 62 | + |
| 63 | +### CI/CD Integration |
| 64 | +- Test results automatically published in GitHub Actions |
| 65 | +- Coverage reports uploaded as artifacts |
| 66 | +- Test failures cause build failures |
| 67 | + |
| 68 | +## Writing Tests |
| 69 | + |
| 70 | +### Test Structure |
| 71 | +```java |
| 72 | +@ExtendWith(MockitoExtension.class) |
| 73 | +class ExampleServiceTest { |
| 74 | + |
| 75 | + @Mock |
| 76 | + private Dependency mockDependency; |
| 77 | + |
| 78 | + @InjectMocks |
| 79 | + private ExampleService service; |
| 80 | + |
| 81 | + @Test |
| 82 | + @DisplayName("Should perform expected behavior") |
| 83 | + void shouldPerformExpectedBehavior() { |
| 84 | + // Given |
| 85 | + when(mockDependency.someMethod()).thenReturn(expectedValue); |
| 86 | + |
| 87 | + // When |
| 88 | + Result result = service.performAction(); |
| 89 | + |
| 90 | + // Then |
| 91 | + assertThat(result).isNotNull() |
| 92 | + .satisfies(r -> { |
| 93 | + assertThat(r.getValue()).isEqualTo(expectedValue); |
| 94 | + assertThat(r.isValid()).isTrue(); |
| 95 | + }); |
| 96 | + |
| 97 | + verify(mockDependency).someMethod(); |
| 98 | + } |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +### Best Practices |
| 103 | + |
| 104 | +#### Naming Conventions |
| 105 | +- Test classes: `<ClassUnderTest>Test` |
| 106 | +- Test methods: `should<ExpectedBehavior>When<Condition>` |
| 107 | +- Display names: Descriptive sentences explaining the test |
| 108 | + |
| 109 | +#### Test Organization |
| 110 | +- **Given-When-Then**: Structure tests with clear sections |
| 111 | +- **One Assertion Per Test**: Focus each test on a single behavior |
| 112 | +- **Descriptive Assertions**: Use AssertJ for readable assertions |
| 113 | + |
| 114 | +#### Mocking Guidelines |
| 115 | +- **Mock External Dependencies**: Use `@Mock` for external dependencies |
| 116 | +- **Spy Real Objects**: Use `@Spy` when testing partial behavior |
| 117 | +- **Verify Interactions**: Always verify important method calls |
| 118 | + |
| 119 | +## Dependency Injection Testing |
| 120 | + |
| 121 | +### Testing DI Components |
| 122 | +```java |
| 123 | +@Test |
| 124 | +void shouldInjectDependenciesCorrectly() { |
| 125 | + // Create injector with test modules |
| 126 | + Injector injector = Guice.createInjector( |
| 127 | + new TestServiceModule(), |
| 128 | + new TestListenerModule() |
| 129 | + ); |
| 130 | + |
| 131 | + // Verify singleton behavior |
| 132 | + Service instance1 = injector.getInstance(Service.class); |
| 133 | + Service instance2 = injector.getInstance(Service.class); |
| 134 | + |
| 135 | + assertThat(instance1).isSameAs(instance2); |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +### Mocking in DI Context |
| 140 | +- Create test modules with mocked dependencies |
| 141 | +- Use `@TestConfiguration` equivalents for Spring-style testing |
| 142 | +- Verify dependency injection eliminates service locator pattern |
| 143 | + |
| 144 | +## MockBukkit Integration |
| 145 | + |
| 146 | +### Server Setup |
| 147 | +```java |
| 148 | +@BeforeEach |
| 149 | +void setUp() { |
| 150 | + server = MockBukkit.mock(); |
| 151 | + // Note: We don't load the actual plugin due to final class limitations |
| 152 | + // Instead, we mock the plugin and test components in isolation |
| 153 | +} |
| 154 | + |
| 155 | +@AfterEach |
| 156 | +void tearDown() { |
| 157 | + MockBukkit.unmock(); |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +### Testing Bukkit Components |
| 162 | +- Mock Bukkit API calls for consistent behavior |
| 163 | +- Test event handling and command execution |
| 164 | +- Validate plugin configuration and permissions |
| 165 | + |
| 166 | +## Continuous Integration |
| 167 | + |
| 168 | +### GitHub Actions Integration |
| 169 | +- Tests run on multiple OS platforms (Ubuntu, Windows, macOS) |
| 170 | +- Test results published with detailed reporting |
| 171 | +- Coverage reports generated and archived |
| 172 | +- Build fails on test failures |
| 173 | + |
| 174 | +### Test Metrics |
| 175 | +- **Coverage Threshold**: Maintain high code coverage |
| 176 | +- **Test Execution Time**: Monitor test performance |
| 177 | +- **Flaky Test Detection**: Identify and fix unstable tests |
| 178 | + |
| 179 | +## Troubleshooting |
| 180 | + |
| 181 | +### Common Issues |
| 182 | + |
| 183 | +#### MockBukkit Plugin Loading |
| 184 | +``` |
| 185 | +java.io.FileNotFoundException: Could not find file plugin.yml |
| 186 | +``` |
| 187 | +**Solution**: Use mocked dependencies instead of loading the actual plugin class. |
| 188 | + |
| 189 | +#### Parallel Test Execution |
| 190 | +``` |
| 191 | +Tests failing intermittently in parallel execution |
| 192 | +``` |
| 193 | +**Solution**: MockBukkit requires sequential execution (`maxParallelForks = 1`). |
| 194 | + |
| 195 | +#### Dependency Injection Conflicts |
| 196 | +``` |
| 197 | +Guice injection errors in tests |
| 198 | +``` |
| 199 | +**Solution**: Create test-specific modules with mocked dependencies. |
| 200 | + |
| 201 | +## Future Enhancements |
| 202 | + |
| 203 | +### Planned Improvements |
| 204 | +- **Performance Testing**: Add JMH benchmarks for critical paths |
| 205 | +- **Property-Based Testing**: Integrate QuickCheck-style testing |
| 206 | +- **Contract Testing**: Add consumer-driven contract tests |
| 207 | +- **Mutation Testing**: Implement PIT mutation testing |
| 208 | + |
| 209 | +### Tool Integration |
| 210 | +- **SonarQube**: Code quality analysis |
| 211 | +- **TestContainers**: Real server testing |
| 212 | +- **Testcontainers**: Database integration testing |
| 213 | + |
| 214 | +This testing infrastructure ensures the dependency injection refactoring maintains high quality and reliability while enabling future enhancements like Folia compatibility. |
0 commit comments