Testing And Benchmarking in Erlang

Here’s the translation of the Go testing and benchmarking example to Erlang:

-module(int_min).
-export([int_min/2]).
-include_lib("eunit/include/eunit.hrl").

%% Unit testing is an important part of writing principled Erlang programs.
%% The EUnit framework provides the tools we need to write unit tests,
%% and the `rebar3 eunit` command runs tests.

%% We'll be testing this simple implementation of an integer minimum.
int_min(A, B) when A < B -> A;
int_min(_, B) -> B.

%% A test is created by writing a function with a name ending with "_test".
int_min_basic_test() ->
    ?assertEqual(-2, int_min(2, -2)).

%% Writing tests can be repetitive, so it's idiomatic to use a table-driven style,
%% where test inputs and expected outputs are listed in a list and a single function
%% walks over them and performs the test logic.
int_min_table_test_() ->
    Tests = [
        {0, 1, 0},
        {1, 0, 0},
        {2, -2, -2},
        {0, -1, -1},
        {-1, 0, -1}
    ],
    [?_assertEqual(Want, int_min(A, B)) || {A, B, Want} <- Tests].

%% Benchmark tests in Erlang are typically created using the `timer:tc/3` function
%% to measure execution time. Here's a simple benchmark function:
benchmark_int_min() ->
    {Time, _} = timer:tc(fun() ->
        lists:foreach(fun(_) ->
            int_min(1, 2)
        end, lists:seq(1, 1000000))
    end),
    io:format("Benchmark: ~p microseconds~n", [Time]).

To run the tests, you would typically use rebar3 eunit or the Erlang shell:

1> c(int_min).
{ok,int_min}
2> eunit:test(int_min).
  All 6 tests passed.
ok
3> int_min:benchmark_int_min().
Benchmark: 223407 microseconds
ok

In this Erlang version:

  1. We define the module and export the int_min/2 function.
  2. We include the EUnit header file for testing macros.
  3. The int_min/2 function is implemented using pattern matching and guards.
  4. We create a basic test function int_min_basic_test/0.
  5. We implement a table-driven test using a list comprehension and the ?_assertEqual macro.
  6. For benchmarking, we create a benchmark_int_min/0 function that uses timer:tc/3 to measure execution time.

Note that Erlang’s approach to testing and benchmarking is quite different from Go’s:

  • Erlang uses the EUnit framework for unit testing, which is included in OTP.
  • Test functions typically end with _test or _test_.
  • Erlang doesn’t have a built-in benchmarking tool like Go’s testing package, so we implement a simple benchmark using timer:tc/3.
  • The output format and running process are different from Go’s testing package.

Despite these differences, the core concepts of unit testing and benchmarking are still applied in this Erlang example.

查看推荐产品