[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"vUornF0GZR":3},"# LeanTest\n\n[![CI](https://github.com/tim-br/LeanTest/workflows/CI/badge.svg)](https://github.com/tim-br/LeanTest/actions)\n\nA unit testing framework for Lean 4. LeanTest provides an expressive, easy-to-use testing interface for writing and running tests in Lean.\n\n## Features\n\n- **Fluent API**: Clean, readable test definition syntax using pipe operators\n- **Rich Assertions**: Comprehensive set of assertion functions including:\n  - Basic assertions (equality, boolean, Option, collections)\n  - Range checking (`assertInRange`)\n  - Error handling (`assertError`, `assertOk` for `Except` types)\n  - IO testing (`assertThrows`, `assertSucceeds` for IO operations)\n- **Colorized Output**: Clear, colorful test results in the terminal\n- **Test Organization**: Group tests into test suites for better organization\n- **Custom Messages**: Add custom error messages to all assertions\n- **CI/CD Ready**: Proper exit codes for continuous integration\n\n## Installation\n\nAdd LeanTest as a dependency to your project's `lakefile.toml`:\n\n```toml\n[[require]]\nname = \"LeanTest\"\ngit = \"https://github.com/tim-br/LeanTest\"\nrev = \"main\"\n```\n\nThen run:\n```bash\nlake update\nlake build\n```\n\n## Quick Start\n\nHere's a simple example:\n\n```lean\nimport LeanTest\n\nopen LeanTest\n\n/-- Define a test suite -/\ndef myTests : TestSuite :=\n  (TestSuite.empty \"My First Tests\")\n  |>.addTest \"addition works\" (do\n      return assertEqual 4 (2 + 2))\n  |>.addTest \"strings concatenate\" (do\n      return assertEqual \"hello world\" (\"hello\" ++ \" \" ++ \"world\"))\n  |>.addTest \"boolean assertion\" (do\n      return assertTrue true)\n\n/-- Run the tests -/\ndef main : IO UInt32 := do\n  runTestSuitesWithExitCode [myTests]\n```\n\n## API Reference\n\n### Assertions\n\nLeanTest provides the following assertion functions:\n\n#### `assert`\nAssert that a boolean condition is true.\n```lean\nassert (5 > 3)\nassert (x == y) \"x and y should be equal\"\n```\n\n#### `assertEqual`\nAssert that two values are equal.\n```lean\nassertEqual 10 (5 + 5)\nassertEqual \"hello\" myString \"Should greet with hello\"\n```\n\n#### `assertNotEqual`\nAssert that two values are not equal.\n```lean\nassertNotEqual 5 10\nassertNotEqual \"foo\" \"bar\"\n```\n\n#### `refute`\nRefute that a condition is true (assert it's false).\n```lean\nrefute (5 \u003C 3)\nrefute isEmpty \"List should not be empty\"\n```\n\n#### `assertTrue` / `assertFalse`\nAssert that a boolean value is true or false.\n```lean\nassertTrue (isEven 4)\nassertFalse (isOdd 4)\n```\n\n#### `assertSome` / `assertNone`\nAssert that an Option is Some or None.\n```lean\nassertSome (some 42)\nassertNone (none : Option Nat)\n```\n\n#### `assertEmpty`\nAssert that a list is empty.\n```lean\nassertEmpty ([] : List Nat)\n```\n\n#### `assertContains`\nAssert that a list contains an element.\n```lean\nassertContains [1, 2, 3, 4] 3\n```\n\n#### `assertInRange`\nAssert that a value is within a range (inclusive).\n```lean\nassertInRange 5 1 10  -- checks if 5 is in [1, 10]\nassertInRange 3.14 0.0 5.0  -- works with floats\nassertInRange (-5) (-10) 0  -- works with negative ranges\n```\n\n#### `assertError` / `assertOk`\nAssert the result of an Except type.\n```lean\n-- Assert that result is an error\nlet result : Except String Nat := .error \"failed\"\nassertError result\n\n-- Assert that result is ok\nlet result : Except String Nat := .ok 42\nassertOk result\n```\n\n#### `assertThrows` / `assertSucceeds`\nAssert whether an IO action throws an error. **Note:** These return `IO AssertionResult`.\n```lean\n-- Assert that IO action throws\nassertThrows (IO.FS.readFile \"/nonexistent/file.txt\")\n\n-- Assert that IO action succeeds\nassertSucceeds (pure ())\n```\n\n### Test Organization\n\n#### Creating Test Suites\n```lean\ndef myTestSuite : TestSuite :=\n  (TestSuite.empty \"Suite Name\")\n  |>.addTest \"test description 1\" (do\n      return assertEqual expected actual)\n  |>.addTest \"test description 2\" (do\n      return assertTrue condition)\n```\n\n#### Running Tests\n\n**For CI/CD (recommended):**\n```lean\ndef main : IO UInt32 := do\n  -- Returns exit code: 0 if all tests pass, 1 if any fail\n  runTestSuitesWithExitCode [suite1, suite2, suite3]\n```\n\n**For interactive use:**\n```lean\ndef main : IO Unit := do\n  -- Always exits with code 0\n  runTestSuites [suite1, suite2, suite3]\n```\n\n## Examples\n\nThe `examples/` directory contains several example test files:\n\n### BasicTest.lean\nDemonstrates basic assertions with arithmetic, boolean, and string tests.\n\n**Run it:**\n```bash\nlake env lean examples/BasicTest.lean\n```\n\n### CollectionTest.lean\nShows how to test lists, options, and custom data structures.\n\n**Run it:**\n```bash\nlake env lean examples/CollectionTest.lean\n```\n\n### CustomMessageTest.lean\nExamples of custom error messages and function testing.\n\n**Run it:**\n```bash\nlake env lean examples/CustomMessageTest.lean\n```\n\n### StackTest.lean\n**Real-world example** testing a complete Stack data structure implementation. Demonstrates:\n- Testing stateful operations (push, pop, peek)\n- Testing edge cases (empty stack, full sequences)\n- Testing invariants (LIFO ordering, size consistency)\n- Testing with different types (Nat, String)\n- 22 comprehensive tests covering all operations\n\n**Run it:**\n```bash\nlake env lean --run examples/StackTest.lean\n```\n\n### AdvancedAssertionsTest.lean\nTests for advanced assertions including range checking, error handling, and IO operations. Demonstrates:\n- Range assertions (`assertInRange`)\n- Error handling with `Except` types (`assertError`, `assertOk`)\n- IO error testing (`assertThrows`, `assertSucceeds`)\n- Real-world validation example (config parsing)\n- 28 tests covering edge cases and error scenarios\n\n**Run it:**\n```bash\nlake env lean --run examples/AdvancedAssertionsTest.lean\n```\n\n## Output Format\n\nLeanTest provides colorized terminal output:\n\n```\nArithmetic Tests\n  ✓ addition works correctly\n  ✓ subtraction works correctly\n  ✓ multiplication works correctly\n\nBoolean Tests\n  ✓ assert true condition\n  ✗ this test failed\n    Expected: true\n    Actual: false\n\nTest Summary:\n  Total:  5\n  Passed: 4\n  Failed: 1\n\nFAILED\n```\n\n## Writing Your Own Tests\n\n1. Create a new `.lean` file in your project\n2. Import LeanTest: `import LeanTest`\n3. Open the namespace: `open LeanTest`\n4. Define your test suites using `TestSuite.empty` and `.addTest`\n5. Create a `main` function that calls `runTestSuitesWithExitCode` (for CI) or `runTestSuites` (for interactive use)\n6. Run with: `lake env lean --run your_test_file.lean`\n\n### Exit Codes for CI/CD\n\nWhen using `runTestSuitesWithExitCode`, your test executable will:\n- Return **exit code 0** if all tests pass\n- Return **exit code 1** if any tests fail\n\nThis makes it easy to integrate with CI/CD pipelines:\n\n```bash\nlake env lean --run tests/MyTests.lean\n# Exit code will be non-zero if tests fail, failing the CI build\n```\n\n## Advanced Usage\n\n### Custom Data Types\n\nYou can test custom data types as long as they derive `BEq` and `Repr`:\n\n```lean\nstructure Point where\n  x : Int\n  y : Int\n  deriving Repr, BEq\n\ndef pointTests : TestSuite :=\n  (TestSuite.empty \"Point Tests\")\n  |>.addTest \"points are equal\" (do\n      return assertEqual (Point.mk 1 2) (Point.mk 1 2))\n```\n\n### Testing Functions\n\n```lean\ndef fibonacci : Nat → Nat\n  | 0 => 0\n  | 1 => 1\n  | n + 2 => fibonacci n + fibonacci (n + 1)\n\ndef fibTests : TestSuite :=\n  (TestSuite.empty \"Fibonacci Tests\")\n  |>.addTest \"fib(0) = 0\" (do\n      return assertEqual 0 (fibonacci 0))\n  |>.addTest \"fib(5) = 5\" (do\n      return assertEqual 5 (fibonacci 5))\n```\n\n## Running All Tests\n\nTo run all example tests at once:\n\n```bash\n./run_all_tests.sh\n```\n\nThis script:\n- Builds the LeanTest framework\n- Runs all example test suites (BasicTest, CollectionTest, CustomMessageTest, StackTest, AdvancedAssertionsTest)\n- Reports a summary of passed/failed test suites\n- Returns exit code 0 if all pass, 1 if any fail\n\n## Continuous Integration\n\nLeanTest uses GitHub Actions to automatically run all tests on every push and pull request. The CI pipeline:\n- Tests on both Ubuntu and macOS\n- Verifies all examples pass\n- Ensures the framework dogfoods its own testing capabilities\n\nSee [`.github/workflows/ci.yml`](.github/workflows/ci.yml) for the full configuration.\n\n## Contributing\n\nContributions are welcome! Feel free to:\n- Add new assertion types\n- Improve error messages\n- Add more examples\n- Enhance the test runner\n\nPlease ensure all tests pass before submitting a PR:\n```bash\n./run_all_tests.sh\n```\n\n## License\n\nApache License 2.0 - See [LICENSE](LICENSE) file for details",1782661972136]