Current section

Files

Jump to
testament src testament.gleam
Raw

src/testament.gleam

import argv
import envoy
import filepath
import gleam/dict
import gleam/io
import gleam/list
import gleam/result
import gleam/string
import platform
import shellout
import simplifile
import testament/conf
import testament/internal/util
const help = "📖 Testament
Doc tests for gleam! ✨
- `clean`: delete doc test files
- `clean all`: delete all doc test files (useful after code reorgs) 'test/**/*_doc_test.gleam'
- `help`: prints this help message
-----------------------
Usage:
Write some beautiful gleam code with Doc Comments
```gleam
////Example Module
////```gleam
////: assert 1 + 1 == 2
////```
///adds two Ints
///```gleam
///: assert example.add(1, 2) == 3
///: assert example.add(1, -1) == 0
/// ```
pub fn add(a: Int, b: Int) -> Int {
a + b
}
```
Add testament to your test's main function
```gleam
import gleeunit
import testament
pub fn main() -> Nil {
testament.test_main(gleeunit.main)
}
```
Enjoy
```bash
gleam test
Compiling example
Compiled in 0.44s
Running example_test.main
.
1 tests, no failures
```
"
pub fn main() -> Nil {
case argv.load().arguments {
["clean"] -> {
let _ = util.clean_doc_tests()
Nil
}
["clean", "all"] -> {
let _ = util.clean_doc_tests()
let _ = simplifile.delete(filepath.join("test", "testament"))
Nil
}
["-h"] | ["h"] | ["--help"] | ["help"] -> io.println(help)
_ -> {
io.print_error("Unknown command")
shellout.exit(1)
}
}
}
const docs_env_var = "TESTAMENT_WITH_DOCS"
const js_args = ["javascript", "--runtime"]
///Add testament to your test's main function and you're good to go!
///You can use gleeunit or any other testing framework
/// ```gleam
/// import gleeunit
/// import testament
///
/// pub fn main() -> Nil {
/// testament.test_main(gleeunit.main)
/// }
/// ```
pub fn test_main(run_tests: fn() -> Nil) -> Nil {
test_main_with_opts(run_tests, [])
}
///Add testament to your test's main function and you're good to go!
///You can use gleeunit or any other testing framework
/// ```gleam
/// import gleeunit
/// import testament
/// import testament/conf
///
/// pub fn main() -> Nil {
/// testament.test_main_with_opts(gleeunit.main, [conf.IgnoreFiles(["src/example.gleam"])])
/// }
/// ```
pub fn test_main_with_opts(run_tests: fn() -> Nil, opts: List(conf.Conf)) -> Nil {
let cfg = util.combine_conf_values(opts)
case envoy.get(docs_env_var) {
Ok(_) -> run_tests()
Error(_) -> {
util.verbose_log(cfg.verbose, "reading src directory")
let assert Ok(files) = simplifile.get_files("src")
as "could not read 'src' directory"
let files =
list.filter(files, fn(f) {
string.ends_with(f, ".gleam") && !list.contains(cfg.ignore_files, f)
})
let assert Ok(Nil) =
list.try_each(files, fn(file) {
util.verbose_log(cfg.verbose, "creating doc tests for: " <> file)
let imports =
dict.get(cfg.extra_imports, file)
|> result.unwrap([])
|> list.prepend(util.import_from_file_name(file))
util.create_tests_for_file(file, imports)
})
as "failed to read source files"
util.verbose_log(cfg.verbose, "compiling doc tests")
let args = case platform.runtime() {
platform.Erlang -> ["erlang"]
platform.Bun -> list.append(js_args, ["bun"])
platform.Deno -> list.append(js_args, ["deno"])
platform.Node -> list.append(js_args, ["node"])
_ -> panic as "testament: invalid runtime or target"
}
util.verbose_log(
cfg.verbose,
"running '"
<> string.join(["gleam", "test", "--target", ..args], " ")
<> "'",
)
let res =
shellout.command("gleam", ["test", "--target", ..args], ".", [
shellout.LetBeStderr,
shellout.LetBeStdout,
shellout.SetEnvironment([#(docs_env_var, "1")]),
])
case cfg.preserve_files {
False -> {
util.verbose_log(cfg.verbose, "deleting generated doc tests")
let assert Ok(Nil) = util.clean_doc_tests()
as "failed to clean doc test"
let assert Ok(Nil) =
simplifile.delete(filepath.join("test", "testament"))
as "failed to clean doc test"
Nil
}
_ -> Nil
}
case res {
Error(#(code, _)) -> shellout.exit(code)
Ok(_) -> Nil
}
}
}
}