Glacier · Gleam Incremental Interactive Unit Testing

Hex Package Hex Docs Licence

Glacier brings incremental interactive unit testing to Gleam. It is meant as a drop-in replacement for Gleeunit and depends on a fork of it.

Glacier Logo
Glacier: «A persistent body of dense ice that is constantly moving under its own weight.»

Quick start

  1. Open gleam.toml and remove gleeunit from the dependencies.

  2. Run gleam add glacier --dev.

  3. Open gleam.toml and remove:

    [dev-dependencies]
    gleeunit = ...
    
  4. Run gleam clean.

  5. Open ./test/YOUR_PROJECT.gleam and replace import gleeunit with import glacier and gleeunit.main() with glacier.main().

  6. If you want to run on Deno 1.35+ open gleam.toml and add:

    [javascript.deno]
    allow_read = ["./"]
    allow_net = ["deno.land"]
    allow_run = ["gleam"]
    
  7. Run gleam test --target erlang -- --glacier or gleam test --target javascript --runtime deno -- --glacier or gleam test --target javascript --runtime node -- --glacier.

  8. Save a src or test module and watch associated tests to re-run.

Notice: On Linux inotify must be installed.

Upgrading Glacier

Make sure to run gleam clean after upgrading Glacier as a dependency.

Introduction

Glacier differs from Gleeunit insofar, that it let’s you:

  1. Pass in the glacier flag like so: gleam test -- --glacier, save a module and only related tests will rerun.
  2. Or Pass in a specific unit test modules to rerun gleam test -- test/my_module_test.gleam.
  3. If gleam test is passed without any ---arguments it behaves the same as Gleeunit.
  4. You can still pass in --target erlang or --target javascript like so gleam test --target erlang -- --glacier, or like gleam test --target javascript -- test/my_module_test.gleam.

To enable this behavior, all you have to do is add Glacier as a dev dependency, aka gleam add glacier --dev, open ./test/YOUR_PROJECT.gleam and replace gleeunit.main() with glacier.main().

Note: gleam test must only be executed from the base project directory!

Testing against Erlang, NodeJS and Deno simultaneously

Run these in 3 terminals side by side:

Caveats, Requirements & Installation

Caveats

Requirements

Requires Gleam 0.30 or later.

Target specific requirements

Target Erlang

Development and testing only happens on very recent stable Erlang/OTP versions, and thus may or may not run on previous versions.

Depends on fs:

Target JavaScript/NodeJS/Deno

Development and testing only happens on very recent NodeJS LTS versions, and thus may or may not run on previous versions.

Depends on NodeJS:fsPromises.watch or Deno.watchFs:

Installation

This package is available on hex.pm can be added to your Gleam project:

  1. Open .gleam.toml and remove the gleeunit dependency because Glacier will fetch its own gleeunit fork.
  2. Run gleam add glacier --dev.

If you are using Deno you will need to add this to your projects’s gleam.toml file:

[javascript.deno]
allow_read = ["./"]
allow_net = ["deno.land"]
allow_run = ["gleam"]

Usage

  1. Open ./test/YOUR_PROJECT.gleam and replace import gleeunit with import glacier and gleeunit.main() with glacier.main().
  2. Run gleam test -- --glacier, then:
    • Save any test module (within ./test) file to re-run that single test
    • Save any src module (within ./src) to run all associated tests. Associated tests are test modules where the module is imported or where any of the module’s imports and their import’s imports (import chain) are imported into.
  3. Optional: You may find and replace all import gleeunit/should with import glacier/should and remove gleeunit from your dependencies in gleam.toml.

Documentation

Documentation can be found at https://hexdocs.pm/glacier.

How does it work?

  1. gleam test passes through glacier.main() and simply executes gleeunit.main() as if Gleeunit was used directly.
  2. gleam test -- test_module_a test_module_b passes through glacier.main() and executes gleeunit.test_modules(modules_list) where modules_list is ["foo", "bar"]. The given modules are checked if they exist as either .gleam or .erl test module files and then Gleeunit runs these test modules.
  3. gleam test -- --glacier enters glacier.main() and starts a file watcher: Upon changes in module files in ./test it just passes those through as gleam test -- changed_test_module(so re-saving test files executes the single test), and if a module file in ./src got changed it parses that changed module file for any imported modules and puts the module and all chained imported modules in a distinct list of modules that should be tested. Then all test module files are read and imports of those are gathered one by one and cross matched against that list. The result is a list of test modules that need to be run, which then gets done by executing a shell call similar to gleam test -- detected_test_module_a detected_test_module_b detected_test_module_c etc, aka jump to step 2.

Developing Glacier

git clone https://github.com/inoas/glacier.git
cd glacier

See all open issues on GitHub if you want to help out.

Demo for target Erlang

# Traditional test runs
gleam test --target erlang
gleam test --target erlang -- test/glacier_demo/glacier_demo_module_a_test.gleam

# Incremental interactive test
gleam test --target erlang -- --glacier
# Re-save ./src/glacier_demo/glacier_demo_module_a.gleam

Demo for target JavaScript/NodeJS

# Traditional test runs
gleam test --target javascript --runtime node
gleam test --target javascript --runtime node -- test/glacier_demo/glacier_demo_module_a_test.gleam

# Incremental interactive test
gleam test --target javascript --runtime node -- --glacier
# Re-save ./src/glacier_demo/glacier_demo_module_a.gleam

Notice: You may omit --runtime node as it is currently set as the default runtime for target javascript.

Demo for target JavaScript/Deno

# Traditional test runs
gleam test --target javascript --runtime deno
gleam test --target javascript --runtime deno -- test/glacier_demo/glacier_demo_module_a_test.gleam

# Incremental interactive test
gleam test --target javascript --runtime deno -- --glacier
# Re-save ./src/glacier_demo/glacier_demo_module_a.gleam

Deno Privileges

Do not forget to edit gleam.toml to add deno privileges:

[javascript.deno]
allow_read = ["./"]
allow_net = ["deno.land"]
allow_run = ["gleam"]

License

Apache 2.0

Search Document