Debugging in Erlang

Mustafa
6 min readMar 20, 2019

--

An inside look on how to perform debugging in Erlang.

Now on the third part of Erlang in 2019 which you can read the first two parts from here

Part 1

Part 2

Moving now on an important part of any programming language, which is DEBUGGING

1 — Debugging and testing support

Now that we are familiar with erlang and able to create a module, we can start looking into erlangs debugger. The monitor window will display when you call,

debugger:start().

In the erlang terminal. Then select

Module > Interpret… and select the appropriate module.

To view the contents of the source file you select

Module > module to be interpreted > View

Now you can set breakpoints in the source code. The breakpoints can only be set at an executable line. A blank line, line containing comment, function head, or pattern in a case or receive statement is not executable. The trigger action allows you to enable, disable, or delete breakpoints. You can set a line break, conditional break, or a function break.

Line Breakpoint:

A line break can be set by selecting,

Break > Line Break…

A popup menu will appear allowing you to select the module, enter the breakpoint line number, and selecting the trigger action.

Conditional Breakpoint:

A conditonal breakpoint can be set by selecting,

Break > Conditional Break…

A popup menu will appear allowing you to select the module, breakpoint line number, specifying the CModule and CFunction, and trigger action. The condition is specified as a module name CModule and function name CFunction. When the process reaches the breakpoint, CModule:CFunction(Binding) is evaluated. If the function returns true the process stops and if the function returns false the breakpoint is ignored. Binding is a list of variable bindings and the variable can be retrieved by using the fuction int:get_binding(Variable, Bindings).

Function Breakpoint:

To set a function breakpoint select,

Break > Function Break…

The popup menu will appear allowing you select the module and function. A function breakpoint is a set of line breakpoints, one at the first line of the specified function.

2 — Demonstration of debugger

3 — Unit testing framework

EUnit — a Lightweight Unit Testing Framework for Erlang

Being able to test small portions or ‘units’ of your program is extremely useful in optimizing your code, and the time you spend writing it. EUnit is the Erlang specific unit testing framework which builds on other object-oriented language unit testing frameworks. We will give you an introduction to EUnit and some examples of its use.

Getting Started with EUnit:

To use EUnit in your module, simply add the header

in your module directly after its declaration. This will create an exported function test(), cause all functions whose names match …_test()(test function) or …_test_() (test generator function) to be automatically exported from the module, and makes all the preprocessor macros of EUnit available to help in writing tests.

Writing Test Functions:

A simple test function recognized by EUnit is anyone with a name ending in …_test() which takes no arguments and when executed it will either succeed or throw an exception. And example of what this code might look like would be

Which one might use test that the function function_to_test() does not crash when given the input function_input.

We can write more complicated tests which will do more than simply show us that a function won’t crash. We can use pattern match to throw a ‘badmatch’ error, an example of this would be

This updated example will cause the program to crash and thrown an exception if function_to_test(function_input) does not return []. This is extremely useful if you know the expected output of the function you are testing for the specified input.

We can also go a step further and use Boolean operators by using the assert macro. An example of this is

This will also test that the function will return a certain expected value and assert will either return ok if the test evaluates to true or throw an exception if it does not give the expected return value.

Running EUnit

All you need to do to run the tests you’ve defined on your module which includes the EUnit header is to compile the module, and then run

Which will run all tests defined in your module.

Test Generating Functions

Test generating functions in EUnit return a representation of a set of tests to be executed, this allows you to bypass the need for writing separate test functions with separate names for each test case. EUnit will put all the tests generated by this function into a list and run them one-by-one. Test generated functions have a name ending with …_test_() and adding an underscore in front of the macro which will be used for the test will signal that that macro is a test object. An example of this is

Which when run will test that each of these three inputs to the function to be tested will have the same expected output. Not the underscore in front of the assert macro which signals that this is a test object.

source: : http://erlang.org/doc/apps/eunit/chapter.html

Common Test Basics

The Common Test framework is a tool that supports implementation and automated execution of test cases to any types of target systems. Common Test is the main tool being used in all testing- and verification activities that are part of Erlang/OTP system development and maintenance.

  • Common Test is also a very useful tool for white-box testing Erlang code for example (module testing), as the test programs can call exported Erlang functions directly

The Common Test server requires that the test suite defines and exports the following mandatory or optional callback functions:

  • all(): Returns a list of all test cases and groups in the suite. (Mandatory)
  • suite(): Information function used to return properties for the suite. (Optional)
  • groups(): For declaring test case groups. (Optional)
  • init_per_suite(Config): Suite level configuration function, executed before the first test case. (Optional)
  • end_per_suite(Config): Suite level configuration function, executed after the last test case. (Optional)
  • group(GroupName): Information function used to return properties for a test case group. (Optional)
  • init_per_group(GroupName, Config): Configuration function for a group, executed before the first test case. (Optional)
  • end_per_group(GroupName, Config): Configuration function for a group, executed after the last test case. (Optional)
  • init_per_testcase(TestCase, Config): Configuration function for a testcase, executed before each test case. (Optional)
  • end_per_testcase(TestCase, Config): Configuration function for a testcase, executed after each test case. (Optional)

For each test case, the Common Test test server expects the following functions:

  • Testcasename(): Information function that returns a list of test case properties. (Optional)
  • Testcasename(Config): The test case function.

Source: http://erlang.org/documentation/doc-6.3/lib/common_test 1.9/doc/html/basics_chapter.html

--

--