Skip to main content

moonbit-extract-spec-test

Extract formal spec and comprehensive test suites from existing MoonBit implementations. Use when asked to "extract spec from implementation", "generate tests from code", or "create spec-driven tests for existing package". Analyzes existing code to produce spec.mbt with `declare` keyword stubs and organized test files (valid/invalid).

설치로 이동

소스 정보

저장소
moonbitlang/skills
최근 소스 활동
2026년 4월 27일 11:57
감지된 SKILL.md 언어
영어
스타
31
포크
5

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
moonbit-extract-spec-test
description
Extract formal spec and comprehensive test suites from existing MoonBit implementations. Use when asked to "extract spec from implementation", "generate tests from code", or "create spec-driven tests for existing package". Analyzes existing code to produce spec.mbt with `declare` keyword stubs and organized test files (valid/invalid).
# MoonBit Extract Spec & Test ## Overview Reverse-engineer a formal API contract (`<pkg>_spec.mbt`) and comprehensive test suites from an existing MoonBit implementation. This enables spec-driven testing for already-written code. ## When to Use - User asks to "extract spec from existing implementation" - User wants to "generate spec-driven tests for a package" - User requests "create formal API specification from code" - Converting legacy code to spec-driven development workflow - Need to document and test existing public API surface ## Workflow ### 1. Analyze the Existing Implementation **Identify public API surface:** - List all `pub` and `pub(all)` types, functions, traits - Note error types (suberrors) and their variants - Document method signatures and trait implementations - Identify key entry points and core functionality **Examine test patterns (if tests exist):** - Look for existing test files (`*_test.mbt`, `*_wbtest.mbt`) - Identify test coverage gaps - Note common test scenarios ### 2. Generate the Spec File (`<pkg>_spec.mbt`) **Create formal API contract:** - Use the `declare` keyword for all public functions/types - Preserve exact type signatures from implementation - Include error types with `derive(Show, Eq, ToJson)` for testability - Add documentation comments from original code - Declarations with `declare` do not have a body - Use `pub(all)` for types that need construction in tests - Keep `pub` for opaque types **Example spec structure:** ```mbt ///| /// Error type for parsing operations pub(all) suberror ParseError { InvalidFormat(String) UnexpectedEof } derive(Show, Eq, ToJson) ///| /// Main data type declare pub(all) type Toml ///| /// Convert to test JSON format declare pub fn Toml::to_test_json(self : Toml) -> Json ///| /// Parse TOML from string declare pub fn parse(input : StringView) -> Result[Toml, ParseError] ``` ### 3. Extract and Organize Test Cases **Categorize tests by validity (happy path vs error path):** **Valid tests** (`<pkg>_valid_test.mbt`): - Happy path: valid inputs that exercise core features - Edge cases: boundary sizes, empty inputs, maximum nesting - Compatibility: behaviors that match real-world data or dominant implementations - Regression: bugs fixed in prior work or known pitfalls **Invalid tests** (`<pkg>_invalid_test.mbt`): - Error path: invalid inputs and required error behavior - Ambiguities: inputs where the spec allows multiple interpretations (tests pin down chosen interpretation) - Malformed inputs: syntax errors, type mismatches, constraint violations ### 4. Write Spec-Driven Tests **For valid input tests:** ```mbt ///| test "valid/category/test-name" { let toml_text = #|key = "value" #| let toml = match @pkg.parse(toml_text) { Ok(toml) => toml Err(error) => fail("Failed to parse: " + error.to_string()) } json_inspect(toml.to_test_json(), content={ "key": { "type": "string", "value": "value" } }) } ``` **For invalid input tests:** ```mbt ///| test "invalid/category/test-name" { let toml_text = #|invalid syntax here #| match @pkg.parse(toml_text) { Ok(toml) => { let json = toml.to_test_json() fail("Expected parse to fail, got \{json.stringify(indent=2)}") } Err(_) => () } } ``` ### 5. Validate **Type-check the spec:** ```bash moon check ``` **Run the tests:** ```bash moon test # Run all tests moon test -u # Update snapshot tests ``` **Verify coverage:** - Ensure all public API functions have tests - Check for untested error paths - Confirm edge cases are covered ## Key Principles ### Spec File Rules 1. **Declaration-only stubs**: All public API uses `declare` keyword (no body needed) 2. **Exact signatures**: Match the implementation's type signatures precisely 3. **Error handling**: Include all error types with proper derives 4. **Documentation**: Preserve or add doc comments for clarity 5. **Test helpers**: Include conversion functions like `to_test_json()` for inspection ### Test Organization 1. **Black-box testing**: Tests use only public API (call via `@pkg.function`) 2. **Snapshot testing**: Prefer `json_inspect()` for complex values 3. **Clear naming**: Use descriptive test names like "valid/arrays/nested" or "invalid/keys/empty" 4. **Categorization**: Organize by validity (`<pkg>_valid_test.mbt` for happy path, `<pkg>_invalid_test.mbt` for error path) 5. **Block separation**: Use `///|` to delimit test blocks ### Test Coverage Goals - **Positive cases**: Valid inputs producing expected outputs - **Negative cases**: Invalid inputs producing appropriate errors - **Edge cases**: Boundaries, empty inputs, special values - **Integration**: Features working together - **Aim for 80-90% API coverage** ## Example Extraction ### From Implementation ```mbt pub type Config pub fn Config::parse(text : String) -> Result[Config, String] { // implementation } pub fn Config::get_value(self : Config, key : String) -> String? { // implementation } ``` ### To Spec ```mbt ///| declare pub type Config ///| declare pub fn Config::parse(text : String) -> Result[Config, String] ///| declare pub fn Config::get_value(self : Config, key : String) -> String? ``` ### To Tests ```mbt ///| test "parse valid config" { let result = try? Config::parse("key=value") match result { Ok(cfg) => { inspect(cfg.get_value("key"), content="Some(\"value\")") } Err(e) => fail("Parse failed: \{e}") } } ///| test "parse invalid config returns error" { let result = try? Config::parse("invalid") match result { Ok(_) => fail("Should have failed to parse") Err(_) => () } } ``` ## Tips - **Start simple**: Begin with core functionality, add complexity incrementally - **Use existing tests**: If tests exist, migrate and enhance them - **Iterate**: Run `moon check` frequently to catch type errors early - **Update snapshots**: Use `moon test -u` when output format changes - **Document reasoning**: Add comments explaining non-obvious test cases ## Common Patterns ### Testing with Result types ```mbt let result : Result[T, Error] = try? function_call(...) match result { Ok(value) => inspect(value, content="...") Err(e) => fail("Unexpected error: \{e}") } ``` ### Testing expected failures ```mbt match try? function_call(...) { Ok(v) => fail("Expected error, got \{v}") Err(_) => () // Success - error was expected } ``` ### Using test JSON format ```mbt json_inspect(value.to_test_json(), content={ "field": { "type": "integer", "value": "42" } }) ```
GitHub에서 보기