Programowanie · Nauka i wyjaśnianie
testing
/testing
Opisuje strategie testów bibliotek OCaml: strukturę testów, alcotest, mocki eio i rozwój oparty na testach.
Dla kogo
- Autor
- avsm ↗
- Repozytorium
- ocaml-claude-marketplace ↗
- Licencja
- ISC
- Ostatnia zmiana repozytorium
- 02.09.2026
Ocena i bezpieczeństwo
100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
- Pliki w paczce
- 3
- Skrypty
- 0
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 0
Przestarzałość
Brak sygnałów. Repozytorium zmienione 02.09.2026, bez odwołań do wycofanych modeli i API.
Licencja
ISC, otwarta.
Co robi i kiedy
Opisuje strategie testów bibliotek OCaml: strukturę testów, alcotest, mocki eio i rozwój oparty na testach.
Oryginalny opis (EN)
Testing strategies for OCaml libraries. Use when discussing tests, alcotest, eio mocks, test structure, or test-driven development in OCaml projects.
Jak działa
- Test Directory Structure
- Dune Configuration
- Main Runner Pattern (test.ml)
- Module Test File Pattern (testx.ml)
- Lazy State for Module-Level Values
- Alcotest Patterns
- Initialization Order
- Test Logging
- Core Philosophy
- Naming Conventions
Sekcje z nagłówków SKILL.md, w oryginale · 228 linii, 837 słów
Podgląd SKILL.md
---
name: testing
description: Testing strategies for OCaml libraries. Use when discussing tests, alcotest, eio mocks, test structure, or test-driven development in OCaml projects.
---
# OCaml Testing
## Test Directory Structure
Use `test/` directory with:
- `test.ml` - Main runner controlling initialization order
- `test_x.ml` - One file per module `x.ml` being tested, exports `suite`
```
lib/
├── foo.ml
└── bar.ml
test/
├── dune
├── test.ml # Main runner
├── test_foo.ml # suite : (string * unit Alcotest.test_case list) list
└── test_bar.ml
```
For single-module libraries, a single `test_foo.ml` as runner is acceptable.
## Dune Configuration
```dune
(test
(name test)
(libraries mylib alcotest logs logs.fmt fmt.tty))
```
## Main Runner Pattern (test.ml)
The main `test.ml` controls initialization order for side effects:
```ocaml
(* 1. Initialize RNG before any test module is loaded *)
let () = Crypto_rng_unix.use_default ()
(* 2. Set up logging *)
let () = Fmt_tty.setup_std_outputs ()
let () = Logs.set_reporter (Logs_fmt.reporter ())
let () = Logs.set_level (Some Logs.Debug)
(* 3. Run all test suites *)
let () = Alcotest.run "mylib" Test_foo.suite
```
For multiple modules:
```ocaml
let () = Crypto_rng_unix.use_default ()
let () = Alcotest.run "mylib" (Test_foo.suite @ Test_bar.suite)
```
## Module Test File Pattern (test_x.ml)
Each module exports a `suite` value. **Do not initialize RNG or run Alcotest here.**
```ocaml
(** Tests for Foo module. *)
let test_basic () =
let result = Foo.process "input" in
Alcotest.(check string) "expected output" "output" result
let test_empty () =
let result = Foo.process "" in
Alcotest.(check string) "empty input" "" result
let suite =
[
( "process",
[
Alcotest.test_case "basic" `Quick test_basic;
Alcotest.test_case "empty" `Quick test_empty;
] );
]
```
## Lazy State for Module-Level Values
If a test module needs RNG at load time, use lazy evaluation:
```ocaml
let key = lazy (Crypto_rng.generate 32)
let key () = Lazy.force key
let test_encrypt () =
let ciphertext = Foo.encrypt ~key:(key ()) plaintext in
...
```
This defers RNG use until tests actually run, after `test.ml` initializes the RNG.
## Alcotest Patterns
### Custom Testables
```ocaml
let result_testable ok_t =
Alcotest.result ok_t Alcotest.string
let my_type_testable =
Alcotest.testable My_type.pp My_type.equal
```
### Common Checks
```ocaml
Alcotest.(check int) "count" 42 actual
Alcotest.(check string) "name" expected actual
Alcotest.(check bool) "flag" true actual
Alcotest.(check (list int)) "items" [1;2;3] actual
Alcotest.(check (option string)) "maybe" (Some "x") actual
Alcotest.(check (result int string)) "result" (Ok 42) actual
```
### Testing Exceptions
```ocaml
let test_raises () =
Alcotest.check_raises "should fail" (Invalid_argument "bad")
(fun () -> Foo.parse "bad")
```
## Initialization Order
Always initialize in `test.ml` before `Alcotest.run`:
1. **RNG** - `Crypto_rng_unix.use_default ()` or `Mirage_crypto_rng_unix.use_default ()`
2. **Logging** - `Logs.set_reporter` and `Logs.set_level`
3. **Other global state** - Environment setup, temp directories
This ensures deterministic test ordering and proper side-effect sequencing.
## Test Logging
Set up logging in tests using the standard `Logs` library:
```ocaml
let () = Fmt_tty.setup_std_outputs ()
let () = Logs.set_reporter (Logs_fmt.reporter ())
let () = Logs.set_level (Some Logs.Debug)
```
**Default behaviour**: Logs at Debug level. Alcotest captures output to a file by default, so verbose logging doesn't clutter the terminal. Output is shown only when tests fail.
### Per-Source Overrides
For per-source control, set levels after the reporter:
```ocaml
let () = Logs.Src.set_level Conpool.src (Some Logs.Debug)
let () = Logs.Src.set_level Requests.src (Some Logs.Warning)
```
### Why Default to Debug?
1. **Alcotest captures output**: Verbose logs don't clutter terminal
2. **Shown on failure**: When a test fails, you see all the debug info
3. **No re-running needed**: Debug output is already captured
## Core Philosophy
1. **Unit Tests First**: Prioritize unit tests for individual modules and functions.
2. **1:1 Test Coverage**: Every module in `lib/` should have a corresponding test module in `test/`.
3. **Isolated Tests**: Each test should be independent and not rely on external state.
4. **Clear Test Names**: Test names should describe what they test, not how.
5. **Test Inclusion**: All test suites must be included in the main test runner.
## Naming Conventions
- **Test suite names**: lowercase, single words (e.g., `"users"`, `"commands"`, `"process"`)
- **Test case names**: lowercase with underscores, concise but descriptive (e.g., `"basic"`, `"empty_input"`, `"parse_error"`)
## Writing Good Tests
**Function Coverage**: Test all public functions exposed in `.mli` files, including success, error, and edge cases.
**Test Data**: Use helper functions to create test data:
```ocaml
let make_user ?(name = "test") ?(id = 1) () = User.v ~name ~id
```
**Property-Based Testing**: For complex logic, consider property-based testing with QCheck:
```ocaml
let test_roundtrip =
QCheck.Test.make ~count:1000
~name:"encode then decode is identity"
QCheck.string
(fun s -> Codec.decode (Codec.encode s) = s)
```
## End-to-End Testing with Cram
Cram tests verify CLI executable behavior.
**Use Cram Directories**: Every Cram test should be a directory ending in `.t` (e.g., `my_feature.t/`).
**Create Actual Test Files**: Avoid embedding code within `run.t` using heredocs. Create real source files within the test directory.
```
test/
└── my_feature.t/
├── run.t # The cram test script
├── input.txt # Test input file
└── expected.json # Expected output
```
## Running Tests
```bash
# Run all tests
dune test
# Run tests and watch for changes
dune test -w
# Run a specific test
dune exec test/test.exe -- test "suite_name"
# Run tests with coverage
dune test --instrument-with bisect_ppx
bisect-ppx-report summary
```
Pliki w paczce (3)
- SKILL.md 6 KB
- templates/test_eio_mock.ml 2 KB
- templates/test_template.ml 1 KB
Wersje
| Repozytorium | Wynik | Licencja |
|---|---|---|
| Ta strona · avsm/ocaml-claude-marketplace | 100 | ISC |
| wrongstack/wrongstack | 100 | MIT |
| langwatch/langwatch | 100 | Apache-2.0 |
| mcouthon/agents | 100 | MIT |
| nteract/nteract | 100 | BSD-3-Clause |
| kettleofketchup/DraftForge | 100 | GPL-3.0 |
| TheBeardedBearSAS/claude-craft | 100 | MIT |
| fastrepl/anarlog | 100 | MIT |
| nvidia/nvcf | 100 | Apache-2.0 |
Migawka bazy z 28.10.2026 · wersja paczki 5bd7ebbb82e9 (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 95eio
Pomaga pisać współbieżny kod OCaml w Eio: operacje sieciowe z cohttp-eio, zarządzanie zasobami, limity i testy. - 100ocaml
Prowadzi rozwój w OCaml: nowoczesne praktyki, interfejsy modułów .mli, obsługa błędów typem result, system budowania dune oraz biblioteki eio, fmt, logs, cmdliner, yojson i cohttp-eio. - 100test-conventions
Opisuje konwencje pisania testów w dowolnym kodzie: mocki, helpery, fixtury i strategię testów dla nowych funkcji. - 100testing-strategy
Opisuje strategie testowania testów jednostkowych, integracyjnych i end-to-end: piramida testów, strategie mockowania i wytyczne dotyczące pokrycia. - 100testing-best-practices
Opisuje zasady testów jednostkowych, integracyjnych i test-driven development przy pisaniu testów, przeglądzie kodu testowego, zwiększaniu pokrycia i ustalaniu strategii testowania. - 91python-testing-patterns
Wdraża strategie testowania w Pythonie z pytest, fixtures, mockowaniem i TDD przy pisaniu testów i konfiguracji zestawów testów.