Current section

10 Versions

Jump to

Compare versions

34 files changed
+2342 additions
-372 deletions
  @@ -58,12 +58,27 @@ Summary: 3 run, 0 failed, 3 passed in 2ms
58 58
59 59 ---
60 60
61 + ## Contents
62 +
63 + - [Installation](#installation)
64 + - [Why Dream Test?](#why-dream-test)
65 + - [Quick Start](#quick-start)
66 + - [The Assertion Pattern](#the-assertion-pattern)
67 + - [Lifecycle Hooks](#lifecycle-hooks)
68 + - [Snapshot Testing](#snapshot-testing)
69 + - [Gherkin / BDD Testing](#gherkin--bdd-testing)
70 + - [BEAM-Powered Test Isolation](#beam-powered-test-isolation)
71 + - [Tagging, CI & Reporters](#tagging-ci--reporters)
72 + - [How It Works](#how-it-works)
73 +
74 + ---
75 +
61 76 ## Installation
62 77
63 78 ```toml
64 79 # gleam.toml
65 80 [dev-dependencies]
66 - dream_test = "~> 1.1"
81 + dream_test = "~> 1.2"
67 82 ```
68 83
69 84 ---
  @@ -77,6 +92,7 @@ dream_test = "~> 1.1"
77 92 | **Crash-proof** | Each test runs in an isolated BEAM process; one crash doesn't kill the suite |
78 93 | **Timeout-protected** | Hanging tests get killed automatically; no more stuck CI pipelines |
79 94 | **Lifecycle hooks** | `before_all`, `before_each`, `after_each`, `after_all` for setup/teardown |
95 + | **Snapshot testing** | Compare output against golden files; auto-create on first run |
80 96 | **Tagging & filtering** | Tag tests and run subsets with custom filter predicates |
81 97 | **Gleam-native** | Pipe-first assertions that feel natural; no macros, no reflection, no magic |
82 98 | **Multiple reporters** | BDD-style human output or JSON for CI/tooling integration |
  @@ -188,6 +204,7 @@ Ok("success")
188 204 | **Collections** | `contain`, `not_contain`, `have_length`, `be_empty` |
189 205 | **Comparison** | `be_greater_than`, `be_less_than`, `be_at_least`, `be_at_most`, `be_between`, `be_in_range` |
190 206 | **String** | `start_with`, `end_with`, `contain_string` |
207 + | **Snapshot** | `match_snapshot`, `match_snapshot_inspect` |
191 208
192 209 ### Custom matchers
193 210
  @@ -272,109 +289,203 @@ The test body is preserved but not executed—just change `skip` back to `it` wh
272 289
273 290 <sub>🧪 [Tested source](examples/snippets/test/skipping_tests.gleam)</sub>
274 291
275 - ### Tagging and filtering
292 + ---
276 293
277 - Add tags to tests for selective execution:
294 + ## Lifecycle Hooks
295 +
296 + Setup and teardown logic for your tests. Dream_test supports four lifecycle hooks
297 + that let you run code before and after tests.
278 298
279 299 ```gleam
280 - import dream_test/unit.{describe, it, with_tags}
300 + import dream_test/unit.{describe, it, before_each, after_each, before_all, after_all}
301 + import dream_test/assertions/should.{succeed}
281 302
282 - describe("Calculator", [
283 - it("adds numbers", fn() { ... })
284 - |> with_tags(["unit", "fast"]),
285 - it("complex calculation", fn() { ... })
286 - |> with_tags(["integration", "slow"]),
303 + describe("Database tests", [
304 + before_all(fn() {
305 + start_database()
306 + succeed()
307 + }),
308 +
309 + before_each(fn() {
310 + begin_transaction()
311 + succeed()
312 + }),
313 +
314 + it("creates a user", fn() { ... }),
315 + it("deletes a user", fn() { ... }),
316 +
317 + after_each(fn() {
318 + rollback_transaction()
319 + succeed()
320 + }),
321 +
322 + after_all(fn() {
323 + stop_database()
324 + succeed()
325 + }),
287 326 ])
288 327 ```
289 328
290 - Filter which tests run via `RunnerConfig.test_filter`:
329 + <sub>🧪 [Tested source](examples/snippets/test/lifecycle_hooks.gleam)</sub>
330 +
331 + ### Hook Types
332 +
333 + | Hook | Runs | Use case |
334 + | ------------- | --------------------------------- | --------------------------------- |
335 + | `before_all` | Once before all tests in group | Start services, create temp files |
336 + | `before_each` | Before each test | Reset state, begin transaction |
337 + | `after_each` | After each test (even on failure) | Rollback, cleanup temp data |
338 + | `after_all` | Once after all tests in group | Stop services, remove temp files |
339 +
340 + ### Two Execution Modes
341 +
342 + Choose the mode based on which hooks you need:
343 +
344 + | Mode | Function | Hooks supported |
345 + | ----- | ----------------------------- | --------------------------- |
346 + | Flat | `to_test_cases``run_all` | `before_each`, `after_each` |
347 + | Suite | `to_test_suite``run_suite` | All four hooks |
348 +
349 + **Flat mode** — simpler, faster; use when you only need per-test setup:
291 350
292 351 ```gleam
293 - import dream_test/runner.{RunnerConfig, run_all_with_config}
294 - import gleam/list
352 + import dream_test/unit.{describe, it, before_each, to_test_cases}
353 + import dream_test/runner.{run_all}
295 354
296 - let config = RunnerConfig(
297 - max_concurrency: 4,
298 - default_timeout_ms: 5000,
299 - test_filter: Some(fn(c) { list.contains(c.tags, "unit") }),
300 - )
301 -
302 - test_cases |> run_all_with_config(config)
355 + to_test_cases("my_test", tests())
356 + |> run_all()
357 + |> report(io.print)
303 358 ```
304 359
305 - The filter is a predicate function receiving `SingleTestConfig`, so you can filter by tags, name, or any other field. You control how to populate the filter—from environment variables, CLI args, or hardcoded for debugging.
306 -
307 - | Use case | Filter example |
308 - | ------------------ | ------------------------------------------ |
309 - | Run tagged "unit" | `fn(c) { list.contains(c.tags, "unit") }` |
310 - | Exclude "slow" | `fn(c) { !list.contains(c.tags, "slow") }` |
311 - | Match name pattern | `fn(c) { string.contains(c.name, "add") }` |
312 - | Run all (default) | `None` |
313 -
314 - For Gherkin scenarios, use `dream_test/gherkin/feature.with_tags` instead.
315 -
316 - ### CI integration
317 -
318 - Use `exit_on_failure` to ensure your CI pipeline fails when tests fail:
360 + **Suite mode** — preserves group structure; use when you need once-per-group setup:
319 361
320 362 ```gleam
321 - import dream_test/runner.{exit_on_failure, run_all}
363 + import dream_test/unit.{describe, it, before_all, after_all, to_test_suite}
364 + import dream_test/runner.{run_suite}
322 365
323 - pub fn main() {
324 - to_test_cases("my_test", tests())
325 - |> run_all()
326 - |> report(io.print)
327 - |> exit_on_failure() // Exits with code 1 if any tests failed
328 - }
366 + to_test_suite("my_test", tests())
367 + |> run_suite()
368 + |> report(io.print)
329 369 ```
330 370
331 - | Result | Exit Code |
332 - | ------------------------------------------------ | --------- |
333 - | All tests passed | 0 |
334 - | Any test failed, timed out, or had setup failure | 1 |
371 + <sub>🧪 [Tested source](examples/snippets/test/execution_modes.gleam)</sub>
335 372
336 - <sub>🧪 [Tested source](examples/snippets/test/quick_start.gleam)</sub>
373 + ### Hook Inheritance
337 374
338 - ### JSON reporter
339 -
340 - Output test results as JSON for CI/CD integration, test aggregation, or tooling:
375 + Nested `describe` blocks inherit parent hooks. Hooks run outer-to-inner for
376 + setup, inner-to-outer for teardown:
341 377
342 378 ```gleam
343 - import dream_test/reporter/json
344 - import dream_test/reporter/bdd.{report}
345 -
346 - pub fn main() {
347 - to_test_cases("my_test", tests())
348 - |> run_all()
349 - |> report(io.print) // Human-readable to stdout
350 - |> json.report(write_to_file) // JSON to file
351 - |> exit_on_failure()
352 - }
379 + describe("Outer", [
380 + before_each(fn() {
381 + io.println("1. outer setup")
382 + succeed()
383 + }),
384 + after_each(fn() {
385 + io.println("4. outer teardown")
386 + succeed()
387 + }),
388 + describe("Inner", [
389 + before_each(fn() {
390 + io.println("2. inner setup")
391 + succeed()
392 + }),
393 + after_each(fn() {
394 + io.println("3. inner teardown")
395 + succeed()
396 + }),
397 + it("test", fn() {
398 + io.println("(test)")
399 + succeed()
400 + }),
401 + ]),
402 + ])
403 + // Output: 1. outer setup → 2. inner setup → (test) → 3. inner teardown → 4. outer teardown
353 404 ```
354 405
355 - The JSON output includes system info, timing, and detailed failure data:
406 + <sub>🧪 [Tested source](examples/snippets/test/hook_inheritance.gleam)</sub>
356 407
357 - ```json
358 - {
359 - "version": "1.0",
360 - "timestamp_ms": 1733151045123,
361 - "duration_ms": 315,
362 - "system": { "os": "darwin", "otp_version": "27", "gleam_version": "0.67.0" },
363 - "summary": { "total": 3, "passed": 2, "failed": 1, ... },
364 - "tests": [
365 - {
366 - "name": "adds numbers",
367 - "full_name": ["Calculator", "add", "adds numbers"],
368 - "status": "passed",
369 - "duration_ms": 2,
370 - "kind": "unit",
371 - "failures": []
408 + ### Hook Failure Behavior
409 +
410 + If a hook fails, Dream Test handles it gracefully:
411 +
412 + | Failure in | Result |
413 + | ------------- | ------------------------------------------------- |
414 + | `before_all` | All tests in group marked `SetupFailed`, skipped |
415 + | `before_each` | That test marked `SetupFailed`, skipped |
416 + | `after_each` | Test result preserved; hook failure recorded |
417 + | `after_all` | Hook failure recorded; all test results preserved |
418 +
419 + ```gleam
420 + describe("Handles failures", [
421 + before_all(fn() {
422 + case connect_to_database() {
423 + Ok(_) -> succeed()
424 + Error(e) -> fail_with("Database connection failed: " <> e)
372 425 }
373 - ]
374 - }
426 + }),
427 + // If before_all fails, these tests are marked SetupFailed (not run)
428 + it("test1", fn() { succeed() }),
429 + it("test2", fn() { succeed() }),
430 + ])
375 431 ```
376 432
377 - <sub>🧪 [Tested source](examples/snippets/test/json_reporter.gleam)</sub>
433 + <sub>🧪 [Tested source](examples/snippets/test/hook_failure.gleam)</sub>
434 +
435 + ---
436 +
437 + ## Snapshot Testing
438 +
439 + Snapshot tests compare output against stored "golden" files. On first run, the snapshot is created automatically. On subsequent runs, any difference is a failure.
440 +
441 + ```gleam
442 + import dream_test/assertions/should.{should, match_snapshot, or_fail_with}
443 +
444 + it("renders user profile", fn() {
445 + render_profile(user)
446 + |> should()
447 + |> match_snapshot("./test/snapshots/user_profile.snap")
448 + |> or_fail_with("Profile should match snapshot")
449 + })
450 + ```
451 +
452 + | Scenario | Behavior |
453 + | ---------------- | --------------------------- |
454 + | Snapshot missing | Creates it, test **passes** |
455 + | Snapshot matches | Test **passes** |
456 + | Snapshot differs | Test **fails** with diff |
457 +
458 + **Updating snapshots** — delete the file and re-run the test:
459 +
460 + ```sh
461 + rm ./test/snapshots/user_profile.snap
462 + gleam test
463 + ```
464 +
465 + **Testing non-strings** — use `match_snapshot_inspect` for complex data:
466 +
467 + ```gleam
468 + build_config()
469 + |> should()
470 + |> match_snapshot_inspect("./test/snapshots/config.snap")
471 + |> or_fail_with("Config should match snapshot")
472 + ```
473 +
474 + This serializes values using `string.inspect`, so you can snapshot records, lists, tuples, etc.
475 +
476 + **Clearing snapshots programmatically:**
477 +
478 + ```gleam
479 + import dream_test/matchers/snapshot
480 +
481 + // Clear one snapshot
482 + let _ = snapshot.clear_snapshot("./test/snapshots/old.snap")
483 +
484 + // Clear all .snap files in a directory
485 + let _ = snapshot.clear_snapshots_in_directory("./test/snapshots")
486 + ```
487 +
488 + <sub>🧪 [Tested source](examples/snippets/test/snapshot_testing.gleam)</sub>
378 489
379 490 ---
380 491
  @@ -580,149 +691,6 @@ See [examples/shopping_cart](examples/shopping_cart) for a complete Gherkin BDD
580 691
581 692 ---
582 693
583 - ## Lifecycle Hooks
584 -
585 - Setup and teardown logic for your tests. Dream_test supports four lifecycle hooks
586 - that let you run code before and after tests.
587 -
588 - ```gleam
589 - import dream_test/unit.{describe, it, before_each, after_each, before_all, after_all}
590 - import dream_test/assertions/should.{succeed}
591 -
592 - describe("Database tests", [
593 - before_all(fn() {
594 - start_database()
595 - succeed()
596 - }),
597 -
598 - before_each(fn() {
599 - begin_transaction()
600 - succeed()
601 - }),
602 -
603 - it("creates a user", fn() { ... }),
604 - it("deletes a user", fn() { ... }),
605 -
606 - after_each(fn() {
607 - rollback_transaction()
608 - succeed()
609 - }),
610 -
611 - after_all(fn() {
612 - stop_database()
613 - succeed()
614 - }),
615 - ])
616 - ```
617 -
618 - <sub>🧪 [Tested source](examples/snippets/test/lifecycle_hooks.gleam)</sub>
619 -
620 - ### Hook Types
621 -
622 - | Hook | Runs | Use case |
623 - | ------------- | --------------------------------- | --------------------------------- |
624 - | `before_all` | Once before all tests in group | Start services, create temp files |
625 - | `before_each` | Before each test | Reset state, begin transaction |
626 - | `after_each` | After each test (even on failure) | Rollback, cleanup temp data |
627 - | `after_all` | Once after all tests in group | Stop services, remove temp files |
628 -
629 - ### Two Execution Modes
630 -
631 - Choose the mode based on which hooks you need:
632 -
633 - | Mode | Function | Hooks supported |
634 - | ----- | ----------------------------- | --------------------------- |
635 - | Flat | `to_test_cases``run_all` | `before_each`, `after_each` |
636 - | Suite | `to_test_suite``run_suite` | All four hooks |
637 -
638 - **Flat mode** — simpler, faster; use when you only need per-test setup:
639 -
640 - ```gleam
641 - import dream_test/unit.{describe, it, before_each, to_test_cases}
642 - import dream_test/runner.{run_all}
643 -
644 - to_test_cases("my_test", tests())
645 - |> run_all()
646 - |> report(io.print)
647 - ```
648 -
649 - **Suite mode** — preserves group structure; use when you need once-per-group setup:
650 -
651 - ```gleam
652 - import dream_test/unit.{describe, it, before_all, after_all, to_test_suite}
653 - import dream_test/runner.{run_suite}
654 -
655 - to_test_suite("my_test", tests())
656 - |> run_suite()
657 - |> report(io.print)
658 - ```
659 -
660 - <sub>🧪 [Tested source](examples/snippets/test/execution_modes.gleam)</sub>
661 -
662 - ### Hook Inheritance
663 -
664 - Nested `describe` blocks inherit parent hooks. Hooks run outer-to-inner for
665 - setup, inner-to-outer for teardown:
666 -
667 - ```gleam
668 - describe("Outer", [
669 - before_each(fn() {
670 - io.println("1. outer setup")
671 - succeed()
672 - }),
673 - after_each(fn() {
674 - io.println("4. outer teardown")
675 - succeed()
676 - }),
677 - describe("Inner", [
678 - before_each(fn() {
679 - io.println("2. inner setup")
680 - succeed()
681 - }),
682 - after_each(fn() {
683 - io.println("3. inner teardown")
684 - succeed()
685 - }),
686 - it("test", fn() {
687 - io.println("(test)")
688 - succeed()
689 - }),
690 - ]),
691 - ])
692 - // Output: 1. outer setup → 2. inner setup → (test) → 3. inner teardown → 4. outer teardown
693 - ```
694 -
695 - <sub>🧪 [Tested source](examples/snippets/test/hook_inheritance.gleam)</sub>
696 -
697 - ### Hook Failure Behavior
698 -
699 - If a hook fails, Dream Test handles it gracefully:
700 -
701 - | Failure in | Result |
702 - | ------------- | ------------------------------------------------- |
703 - | `before_all` | All tests in group marked `SetupFailed`, skipped |
704 - | `before_each` | That test marked `SetupFailed`, skipped |
705 - | `after_each` | Test result preserved; hook failure recorded |
706 - | `after_all` | Hook failure recorded; all test results preserved |
707 -
708 - ```gleam
709 - describe("Handles failures", [
710 - before_all(fn() {
711 - case connect_to_database() {
712 - Ok(_) -> succeed()
713 - Error(e) -> fail_with("Database connection failed: " <> e)
714 - }
715 - }),
716 - // If before_all fails, these tests are marked SetupFailed (not run)
717 - it("test1", fn() { succeed() }),
718 - it("test2", fn() { succeed() }),
719 - ])
720 - ```
721 -
722 - <sub>🧪 [Tested source](examples/snippets/test/hook_failure.gleam)</sub>
723 -
724 - ---
725 -
726 694 ## BEAM-Powered Test Isolation
727 695
728 696 Every test runs in its own lightweight BEAM process—this is what makes Dream Test fast:
  @@ -783,6 +751,114 @@ run_all_with_config(config, test_cases)
783 751
784 752 ---
785 753
754 + ## Tagging, CI & Reporters
755 +
756 + ### Tagging and filtering
757 +
758 + Add tags to tests for selective execution:
759 +
760 + ```gleam
761 + import dream_test/unit.{describe, it, with_tags}
762 +
763 + describe("Calculator", [
764 + it("adds numbers", fn() { ... })
765 + |> with_tags(["unit", "fast"]),
766 + it("complex calculation", fn() { ... })
767 + |> with_tags(["integration", "slow"]),
768 + ])
769 + ```
770 +
771 + Filter which tests run via `RunnerConfig.test_filter`:
772 +
773 + ```gleam
774 + import dream_test/runner.{RunnerConfig, run_all_with_config}
775 + import gleam/list
776 +
777 + let config = RunnerConfig(
778 + max_concurrency: 4,
779 + default_timeout_ms: 5000,
780 + test_filter: Some(fn(c) { list.contains(c.tags, "unit") }),
781 + )
782 +
783 + test_cases |> run_all_with_config(config)
784 + ```
785 +
786 + The filter is a predicate function receiving `SingleTestConfig`, so you can filter by tags, name, or any other field. You control how to populate the filter—from environment variables, CLI args, or hardcoded for debugging.
787 +
788 + | Use case | Filter example |
789 + | ------------------ | ------------------------------------------ |
790 + | Run tagged "unit" | `fn(c) { list.contains(c.tags, "unit") }` |
791 + | Exclude "slow" | `fn(c) { !list.contains(c.tags, "slow") }` |
792 + | Match name pattern | `fn(c) { string.contains(c.name, "add") }` |
793 + | Run all (default) | `None` |
794 +
795 + For Gherkin scenarios, use `dream_test/gherkin/feature.with_tags` instead.
796 +
797 + ### CI integration
798 +
799 + Use `exit_on_failure` to ensure your CI pipeline fails when tests fail:
800 +
801 + ```gleam
802 + import dream_test/runner.{exit_on_failure, run_all}
803 +
804 + pub fn main() {
805 + to_test_cases("my_test", tests())
806 + |> run_all()
807 + |> report(io.print)
808 + |> exit_on_failure() // Exits with code 1 if any tests failed
809 + }
810 + ```
811 +
812 + | Result | Exit Code |
813 + | ------------------------------------------------ | --------- |
814 + | All tests passed | 0 |
815 + | Any test failed, timed out, or had setup failure | 1 |
816 +
817 + <sub>🧪 [Tested source](examples/snippets/test/quick_start.gleam)</sub>
818 +
819 + ### JSON reporter
820 +
821 + Output test results as JSON for CI/CD integration, test aggregation, or tooling:
822 +
823 + ```gleam
824 + import dream_test/reporter/json
825 + import dream_test/reporter/bdd.{report}
826 +
827 + pub fn main() {
828 + to_test_cases("my_test", tests())
829 + |> run_all()
830 + |> report(io.print) // Human-readable to stdout
831 + |> json.report(write_to_file) // JSON to file
832 + |> exit_on_failure()
833 + }
834 + ```
835 +
836 + The JSON output includes system info, timing, and detailed failure data:
837 +
838 + ```json
839 + {
840 + "version": "1.0",
841 + "timestamp_ms": 1733151045123,
842 + "duration_ms": 315,
843 + "system": { "os": "darwin", "otp_version": "27", "gleam_version": "0.67.0" },
844 + "summary": { "total": 3, "passed": 2, "failed": 1, ... },
845 + "tests": [
846 + {
847 + "name": "adds numbers",
848 + "full_name": ["Calculator", "add", "adds numbers"],
849 + "status": "passed",
850 + "duration_ms": 2,
851 + "kind": "unit",
852 + "failures": []
853 + }
854 + ]
855 + }
856 + ```
857 +
858 + <sub>🧪 [Tested source](examples/snippets/test/json_reporter.gleam)</sub>
859 +
860 + ---
861 +
786 862 ## How It Works
787 863
788 864 Dream_test uses an explicit pipeline—no hidden globals, no magic test discovery.
  @@ -846,13 +922,14 @@ Benefits:
846 922
847 923 ## Status
848 924
849 - **Stable** — v1.1 release. API is stable and ready for production use.
925 + **Stable** — v1.2 release. API is stable and ready for production use.
850 926
851 927 | Feature | Status |
852 928 | --------------------------------- | --------- |
853 929 | Core DSL (`describe`/`it`/`skip`) | ✅ Stable |
854 930 | Lifecycle hooks | ✅ Stable |
855 931 | Assertions (`should.*`) | ✅ Stable |
932 + | Snapshot testing | ✅ Stable |
856 933 | BDD Reporter | ✅ Stable |
857 934 | JSON Reporter | ✅ Stable |
858 935 | Parallel execution | ✅ Stable |
  @@ -1,5 +1,5 @@
1 1 name = "dream_test"
2 - version = "1.1.0"
2 + version = "1.2.0"
3 3 description = "A testing framework for Gleam that gets out of your way"
4 4 licences = ["MIT"]
5 5 repository = { type = "github", user = "TrustBound", repo = "dream_test" }
  @@ -1,6 +1,6 @@
1 1 {<<"name">>, <<"dream_test">>}.
2 2 {<<"app">>, <<"dream_test">>}.
3 - {<<"version">>, <<"1.1.0">>}.
3 + {<<"version">>, <<"1.2.0">>}.
4 4 {<<"description">>, <<"A testing framework for Gleam that gets out of your way"/utf8>>}.
5 5 {<<"licenses">>, [<<"MIT">>]}.
6 6 {<<"build_tools">>, [<<"gleam">>]}.
  @@ -40,6 +40,11 @@
40 40 <<"README.md">>,
41 41 <<"gleam.toml">>,
42 42 <<"include/dream_test@context_TestContext.hrl">>,
43 + <<"include/dream_test@file_FileSystemError.hrl">>,
44 + <<"include/dream_test@file_IsDirectory.hrl">>,
45 + <<"include/dream_test@file_NoSpace.hrl">>,
46 + <<"include/dream_test@file_NotFound.hrl">>,
47 + <<"include/dream_test@file_PermissionDenied.hrl">>,
43 48 <<"include/dream_test@gherkin@discover_FeatureDiscovery.hrl">>,
44 49 <<"include/dream_test@gherkin@discover_LoadResult.hrl">>,
45 50 <<"include/dream_test@gherkin@feature_FeatureConfig.hrl">>,
  @@ -75,6 +80,7 @@
75 80 <<"include/dream_test@types_OptionFailure.hrl">>,
76 81 <<"include/dream_test@types_ResultFailure.hrl">>,
77 82 <<"include/dream_test@types_SingleTestConfig.hrl">>,
83 + <<"include/dream_test@types_SnapshotFailure.hrl">>,
78 84 <<"include/dream_test@types_StringMatchFailure.hrl">>,
79 85 <<"include/dream_test@types_TestResult.hrl">>,
80 86 <<"include/dream_test@types_TestSuite.hrl">>,
  @@ -87,6 +93,7 @@
87 93 <<"src/dream_test.app.src">>,
88 94 <<"src/dream_test/assertions/should.gleam">>,
89 95 <<"src/dream_test/context.gleam">>,
96 + <<"src/dream_test/file.gleam">>,
90 97 <<"src/dream_test/gherkin/discover.gleam">>,
91 98 <<"src/dream_test/gherkin/feature.gleam">>,
92 99 <<"src/dream_test/gherkin/parser.gleam">>,
  @@ -100,6 +107,7 @@
100 107 <<"src/dream_test/matchers/equality.gleam">>,
101 108 <<"src/dream_test/matchers/option.gleam">>,
102 109 <<"src/dream_test/matchers/result.gleam">>,
110 + <<"src/dream_test/matchers/snapshot.gleam">>,
103 111 <<"src/dream_test/matchers/string.gleam">>,
104 112 <<"src/dream_test/parallel.gleam">>,
105 113 <<"src/dream_test/process.gleam">>,
  @@ -113,6 +121,7 @@
113 121 <<"src/dream_test/unit.gleam">>,
114 122 <<"src/dream_test@assertions@should.erl">>,
115 123 <<"src/dream_test@context.erl">>,
124 + <<"src/dream_test@file.erl">>,
116 125 <<"src/dream_test@gherkin@discover.erl">>,
117 126 <<"src/dream_test@gherkin@feature.erl">>,
118 127 <<"src/dream_test@gherkin@parser.erl">>,
  @@ -126,6 +135,7 @@
126 135 <<"src/dream_test@matchers@equality.erl">>,
127 136 <<"src/dream_test@matchers@option.erl">>,
128 137 <<"src/dream_test@matchers@result.erl">>,
138 + <<"src/dream_test@matchers@snapshot.erl">>,
129 139 <<"src/dream_test@matchers@string.erl">>,
130 140 <<"src/dream_test@parallel.erl">>,
131 141 <<"src/dream_test@process.erl">>,
  @@ -137,8 +147,8 @@
137 147 <<"src/dream_test@timing.erl">>,
138 148 <<"src/dream_test@types.erl">>,
139 149 <<"src/dream_test@unit.erl">>,
150 + <<"src/dream_test_file_ffi.erl">>,
140 151 <<"src/dream_test_gherkin_discover_ffi.erl">>,
141 - <<"src/dream_test_gherkin_parser_ffi.erl">>,
142 152 <<"src/dream_test_gherkin_world_ffi.erl">>,
143 153 <<"src/dream_test_reporter_json_ffi.erl">>,
144 154 <<"src/dream_test_timing_ffi.erl">>
  @@ -0,0 +1 @@
1 + -record(file_system_error, {path :: binary(), reason :: binary()}).
  @@ -0,0 +1 @@
1 + -record(is_directory, {path :: binary()}).
Loading more files…