一键导入
starsector-testing
Guidelines for JUnit, jqwik property-based testing, SpotBugs static analysis, and verification rules.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Guidelines for JUnit, jqwik property-based testing, SpotBugs static analysis, and verification rules.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Core guidelines, coordinate transformation mathematics, high-performance drawing techniques, and state recovery patterns for OpenGL rendering in Starsector Ship Editor.
Core system architecture including EventBus, Undo/Redo, Layer System, Threading Model, and Startup Sequence.
Guidelines for Jackson configuration, JSON pre-processing, CSV serialization rules, and entity ID extraction in Starsector Ship Editor.
SQLite database design, indexing engine, transaction strategies, and query service in Starsector Ship Editor.
Information about the required technology stack, environment JVM flags, and build plugins.
| name | starsector-testing |
| description | Guidelines for JUnit, jqwik property-based testing, SpotBugs static analysis, and verification rules. |
This skill is organized as follows:
SKILL.md: Main instructions (this file).resources/: Configurations and templates.
examples/: Code references.
scripts/: Automation.
| Framework | Version | Scope | Purpose |
|---|---|---|---|
| JUnit Jupiter | 5.10.3 | test | Standard test runner and assertions |
| jqwik | 1.9.0 | test | Property-based testing with random input generation |
Both are executed via maven-surefire-plugin (3.2.5).
The test suite is focused on mathematical correctness of utility functions that underpin coordinate transformations and data display. Two test files exist:
UtilityPropertiesTestUtilityPropertiesTest.java — Property-based tests for core mathematical utilities.
| Property | What It Validates |
|---|---|
testParseIntegerOrDefault | Utility.parseIntegerOrDefault() returns parsed int for valid strings, default for invalid/empty |
testParseDoubleOrDefault | Utility.parseDoubleOrDefault() returns parsed double for valid strings, default for invalid/empty |
testClampAngleWithRounding | Result is always in [0, 360) for any input in [-1e9, 1e9] |
testFlipAngle | Flipping twice returns the normalized original (within 0.0001 delta) |
testRound | Utility.round(value, decimalPlaces) produces a result for all finite values |
testTransformAngle | Utility.transformAngle() output is always in [-90, 270) |
Why jqwik here: These functions are called thousands of times per frame for coordinate display and point placement. A single edge case (e.g., NaN, negative zero, very large values) would corrupt the viewport or produce nonsensical coordinates. Property-based testing with random inputs catches edge cases that handwritten examples miss.
CoordinatesFormatterPropertiesTestCoordinatesFormatterPropertiesTest.java — Property-based tests for coordinate rounding.
| Property | What It Validates |
|---|---|
testRoundMaintainsValue | CoordinatesFormatter.round() produces results within 0.005 of input for normal values, handles NaN and Infinity correctly, and doesn't overflow for very large values |
testRoundPointMaintainsValue | CoordinatesFormatter.roundPoint() preserves NaN propagation for both X and Y |
Quirk — Overflow Guard: The test explicitly handles the case where Math.abs(value) >= Long.MAX_VALUE / 1000.0, because the rounding implementation internally converts to long for fixed-point math. For values exceeding this threshold, the test relaxes the precision requirement to 1% of the input value.
There are no automated Swing/AWT UI tests. The PrimaryViewer, PaintOrderController, and all painter classes require:
These are impractical in CI environments. Visual verification is done manually.
The JsonProcessor.straightenMalformed() pipeline is not unit-tested. This is a gap — the complex regex and character-by-character state machine are prime candidates for property-based testing with fuzzed Starsector JSON inputs.
DatabaseManager and DatabaseQueryService are not tested in isolation. The schema, PRAGMAs, and query correctness are validated implicitly by the full-application launch test.
Plugin: spotbugs-maven-plugin 4.8.3.1
Configuration: effort=Max, threshold=Low, xmlOutput=true
This is the strictest possible SpotBugs configuration. It catches:
The spotbugs-annotations dependency (4.8.3) provides @NonNull, @Nullable, @SuppressFBWarnings, etc.
Deliberate Suppressions (Quirks):
@SuppressFBWarnings({"EI_EXPOSE_REP", "EI_EXPOSE_REP2", "MS_EXPOSE_REP"}) is used extensively on PrimaryViewer, PaintOrderController, UndoOverseer, and DrawUtilities. These classes intentionally expose mutable internal state for performance. SpotBugs would flag every getter that returns a mutable list or map.The command mvn clean package acts as the primary validation gate. It executes:
If the Log4j2PluginCacheFileTransformer is missing or misconfigured, the shaded JAR will start but Log4j2 will silently fall back to NullAppender, producing zero log output. This is a silent failure — the application appears to work but cannot be debugged. The transformer merges Log4j2Plugins.dat cache files from all dependencies.
Similarly, if ServicesResourceTransformer is missing, JDBC driver auto-discovery fails and DatabaseManager.getConnection() throws ClassNotFoundException for org.sqlite.JDBC (which is why the explicit Class.forName() fallback exists).
The editor is launched via:
mvn exec:exec
or directly:
java -Xmx512m -XX:+UseG1GC -XX:+UseStringDeduplication \
-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 \
-cp <classpath> shipeditor.Main
Verification checklist:
On Linux with multiple GPUs (e.g., integrated + discrete), the editor must use the correct GPU. The DRI_PRIME=1 environment variable or explicit /dev/dri/card0 mapping may be needed to target the discrete GPU for adequate OpenGL 3.3 support.
.jqwik-databaseA .jqwik-database file exists in the project root. This is jqwik's internal database for tracking which random seeds have been tested and which have found failures. It enables shrinking (finding minimal failing inputs) and replay (re-running previously failing seeds). The file is currently 4 bytes, indicating minimal or no persisted failure history.
When writing and refactoring Java code, adhere to these conventions to keep the build completely warning-free:
Avoid saving state to a boolean variable before performing null checks. Static analyzers (like Eclipse/ECJ) fail to link the boolean state to the null state of the original object.
boolean present = selected != null && selected.getPainter() != null;
if (!present) return;
selected.getPainter().doSomething(); // Compiler warning: potential null pointer access
if (selected == null || selected.getPainter() == null) return;
selected.getPainter().doSomething(); // Safe
When passing method references to generic containers/spinners that expect wrapper types (e.g. Consumer<Integer> or Consumer<Boolean>), do not use method references targeting primitives (e.g. void setFluxVents(int)). This triggers "Null type safety" warnings under strict ECJ compilation. Use lambdas with explicit null-safe defaults instead.
ventsSpinner.enableSpinner(layer, variant.getFluxVents(), maxVents, variant::setFluxVents);
ventsSpinner.enableSpinner(layer, variant.getFluxVents(), maxVents, val -> variant.setFluxVents(val != null ? val : 0));
Avoid leaving @SuppressWarnings("unused") or similar compiler overrides on classes/methods unless there is a specific, active reason to silence a compiler error. Redundant suppressions cause ECJ warnings about unused annotations.