← Code Compare

Testing

Every BEAM language ships (or borrows) a unit-testing story, and the shared task is the smallest one possible: assert that add(2, 3) equals 5. Notice how the assertion macro shapes each style - Erlang's EUnit recognises any function named *_test, Elixir's ExUnit wraps cases in test "..." blocks, Gleam's gleeunit auto-discovers *_test functions and uses a should pipeline, and LFE reuses EUnit through (deftest ...). Lua (Luerl) has no test framework on board, so a test is just an assert call you write yourself.

Show: ErlangElixirGleamLFELuerl
Erlang
-module(math_tests).
-include_lib("eunit/include/eunit.hrl").

add(A, B) -> A + B.

%% EUnit auto-discovers any zero-arity function whose name
%% ends in _test; ?assertEqual reports Expected vs Actual on failure.
add_test() ->
    ?assertEqual(5, add(2, 3)).

%% Run with: eunit:test(math_tests).
%%   Test passed.

EUnit is part of Erlang/OTP: including eunit.hrl turns every name_test/0 function into a test case, and the ?assertEqual(Expected, Actual) macro prints both sides when they differ.

Elixir
defmodule MathTest do
  use ExUnit.Case

  defp add(a, b), do: a + b

  # `test` defines a case; `assert` introspects the expression
  # so a failure shows the actual left/right values.
  test "add/2 sums its arguments" do
    assert add(2, 3) == 5
  end
end

# Run with: mix test
#   1 test, 0 failures

ExUnit ships with Elixir: use ExUnit.Case brings in the test "..." macro and a single magic assert, which rewrites the == expression to report both operands on failure.

Gleam
import gleeunit
import gleeunit/should

pub fn main() {
  gleeunit.main()
}

fn add(a: Int, b: Int) -> Int {
  a + b
}

// gleeunit discovers every public *_test function in the module.
pub fn add_test() {
  add(2, 3)
  |> should.equal(5)
}

// Run with: gleam test
//   1 tests, 0 failures

gleeunit wraps EUnit for Gleam: gleeunit.main() auto-discovers each pub fn *_test, and the should.equal helper is piped onto the value under test, staying fully type-checked with no exceptions.

LFE
(defmodule math-tests
  (behaviour ltest-unit)
  (export all))

(include-lib "ltest/include/ltest-macros.lfe")

(defun add (a b) (+ a b))

;; (deftest name ...) expands to an EUnit name_test function;
;; (is-equal Expected Actual) is the LFE wrapper over ?assertEqual.
(deftest add
  (is-equal 5 (add 2 3)))

;; Run with: (eunit:test 'math-tests)
;;   Test passed.

LFE rides on Erlang's EUnit through the ltest library: after (include-lib "ltest/include/ltest-macros.lfe"), the (deftest add ...) macro generates the add_test/0 function EUnit looks for, and (is-equal ...) is the Lisp-friendly form of ?assertEqual.

Luerl
-- Lua has no built-in test runner, so a unit test is just
-- a function that calls assert() and reports its own result.
local function add(a, b)
  return a + b
end

local function test_add()
  -- assert(condition, message): raises with the message when false.
  assert(add(2, 3) == 5, "add(2, 3) should equal 5")
  print("ok - add")
end

test_add()
-- prints: ok - add
-- (a failing assert would raise the message and abort the run)

Plain Lua leans on the standard assert(condition, message), which throws the message when the condition is false; a "test" is simply a function that asserts and prints, with no framework involved.