{"id":50557595,"url":"https://github.com/llbbl/lisunit","last_synced_at":"2026-06-04T08:30:56.246Z","repository":{"id":358831575,"uuid":"1202943792","full_name":"llbbl/lisunit","owner":"llbbl","description":"A small unit-testing library for the Lisette programming language, in the spirit of JUnit / pytest.","archived":false,"fork":false,"pushed_at":"2026-04-06T15:04:34.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T10:16:52.441Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/llbbl.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-06T15:04:20.000Z","updated_at":"2026-04-06T15:04:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/llbbl/lisunit","commit_stats":null,"previous_names":["llbbl/lisunit"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/llbbl/lisunit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llbbl%2Flisunit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llbbl%2Flisunit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llbbl%2Flisunit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llbbl%2Flisunit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/llbbl","download_url":"https://codeload.github.com/llbbl/lisunit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llbbl%2Flisunit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33897568,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-04T08:30:56.178Z","updated_at":"2026-06-04T08:30:56.233Z","avatar_url":"https://github.com/llbbl.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# lisunit\n\nA small unit-testing library for the [Lisette](https://lisette.run) programming language, in the spirit of JUnit / PHPUnit / pytest.\n\n\u003e **Status:** experimental. Tested against **lisette 0.1.2**.\n\n## Why a library?\n\nLisette doesn't yet ship a built-in test runner (it's on the [roadmap](https://github.com/ivov/lisette/blob/main/docs/intro/roadmap.md)), and the language has no macros or attributes today for test discovery. `lisunit` takes the library-based approach — you register test cases as closures on a `Suite` and call `run()`.\n\nWhen Lisette eventually ships a core `lis test` command, the runner/discovery parts of this library will likely become obsolete — but the assertion and matcher helpers should remain useful on top of it.\n\n## Install\n\nLisette does not have a package manager yet, so installation is copy-paste:\n\n1. Copy the `src/lisunit/` directory from this repo into your project's `src/` directory.\n2. Add `import \"lisunit\"` in files that need it.\n\nThat's it. When Lisette gets a package manager, this README will be updated with the proper dependency declaration.\n\n## Quickstart\n\n```lis\nimport \"lisunit\"\n\nfn add(a: int, b: int) -\u003e int {\n  a + b\n}\n\nfn main() {\n  lisunit.Suite.new(\"math\")\n    .case(\"add produces sum\", || {\n      lisunit.assert_eq_int(add(2, 3), 5)?\n      Ok(())\n    })\n    .case(\"add is commutative\", || {\n      lisunit.assert_eq_int(add(2, 3), add(3, 2))?\n      Ok(())\n    })\n    .run()\n}\n```\n\nRunning with `lis run` will produce colored output and exit non-zero if any tests fail.\n\n## API\n\n### `Suite`\n\nBuilder for a named collection of test cases.\n\n```lis\nlisunit.Suite.new(name: string) -\u003e Suite\n  .case(name: string, body: fn() -\u003e Result\u003c(), string\u003e) -\u003e Suite\n  .run()                            // prints results, exits non-zero on failure\n  .run_silent() -\u003e SuiteResult      // returns result without printing (for programmatic use)\n```\n\n### `run_all`\n\nRun multiple suites in order with a combined summary.\n\n```lis\nlisunit.run_all(suites: Slice\u003cSuite\u003e)\n```\n\n### Assertions\n\nAll assertions return `Result\u003c(), string\u003e` so they compose with the `?` operator.\n\n```lis\nlisunit.assert_true(cond: bool, msg: string) -\u003e Result\u003c(), string\u003e\nlisunit.assert_false(cond: bool, msg: string) -\u003e Result\u003c(), string\u003e\nlisunit.assert_eq_int(actual: int, expected: int) -\u003e Result\u003c(), string\u003e\nlisunit.assert_eq_string(actual: string, expected: string) -\u003e Result\u003c(), string\u003e\nlisunit.assert_eq_bool(actual: bool, expected: bool) -\u003e Result\u003c(), string\u003e\nlisunit.fail(msg: string) -\u003e Result\u003c(), string\u003e\n```\n\nA test case body returns `Result\u003c(), string\u003e`. Return `Ok(())` to pass, `Err(msg)` to fail — or just use `?` on assertions and let them propagate:\n\n```lis\n.case(\"a complex test\", || {\n  let result = do_something()\n  lisunit.assert_true(result.is_valid(), \"should be valid\")?\n  lisunit.assert_eq_int(result.count, 3)?\n  Ok(())\n})\n```\n\n## Running the self-demo\n\nThis repo is itself a runnable Lisette project that demonstrates the library testing a few trivial functions:\n\n```bash\ngit clone https://github.com/llbbl/lisunit\ncd lisunit\nlis run\n```\n\nExpected output: 8 green checks across two suites.\n\n## Design notes\n\n- **Manual registration.** Lisette has no `#[test]` attribute or reflection; every test case is registered explicitly via `.case(...)`. This is closer to JUnit/Jest/PHPUnit than to Rust/Go's built-in test runners.\n- **`Result\u003c(), string\u003e` as the test return type.** Asserts return `Result`, so `?` propagates the first failure to the runner, which catches it via `match` to isolate failures between tests.\n- **Test isolation via `match`.** The runner's per-case loop uses a `match` (not `?`) so one failing test does not stop subsequent tests in the suite.\n- **Colored output via ANSI escapes.** Go's stdlib has no color helper, so `lisunit` hard-codes a small set of ANSI codes. If your terminal doesn't support them, they'll render as literal escape sequences.\n- **No panic recovery yet.** A panic inside a test body (e.g. an unwrap of `None`) will currently kill the whole suite. Future versions may use Go's `recover()` if/when Lisette exposes it.\n- **No `main`-free test discovery.** Because there's no `lis test` command, your `main()` must call the runner. A dedicated test-only binary isn't possible today.\n\n## Roadmap\n\nLikely short-term additions:\n\n- More assertions: `assert_contains`, `assert_empty`, `assert_ok` / `assert_err` on `Result`\n- Setup / teardown hooks (`before_each`, `after_each`)\n- Name filtering: `lis run -- --filter \"arithmetic\"` runs only matching cases\n- Per-test progress output (print each PASS/FAIL as it happens)\n- Panic recovery once the mechanism is clear\n\nWhen Lisette's core `lis test` ships, `lisunit` will pivot to being a higher-level matcher/helper library layered on top, similar to how Hamcrest layers on JUnit.\n\n## Contributing\n\nIssues and PRs welcome. Please file suggestions for assertions you'd like to see, or design thoughts for when this library and a future core `lis test` command should meet.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllbbl%2Flisunit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fllbbl%2Flisunit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllbbl%2Flisunit/lists"}