# How to add trace output to unit tests?

**URL:** <https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098>\
**Category:** Help!\
**Tags:** how-to\
**Created:** [January 16, 2023, 12:36am UTC](https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098 "2023-01-16T00:36:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [January 16, 2023, 12:36am UTC](https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098/1 "2023-01-16T00:36:25Z")

</div>

Is there a way to have a successful test output a message?

This unit test:

```prolog
test(foo1) :-
    format(user_error, '>>>I am here>>>~n', []).

```

outputs nothing.

But these tests output the message:

```prolog
test(foo2, fail) :-
    format(user_error, '>>>I am here>>>~n', []).
test(foo3) :-
    format(user_error, '>>>I am here>>>~n', []),
    fail.

```

(Why am I doing this? Because - until plunit is improved (there’s a separate thread on this) - it’s useful for me to output some tracing messages from my tests to isolate which test is crashing.)

A related question: I noticed that `plunit.pl` has this:

```prolog
with_output_to(string(Output), Goal,
                       [capture([user_output, user_error])])

```

but the `capture` option doesn’t seem to be described in the documentation for with\_output\_to/2.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 16, 2023, 8:58am UTC](https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098/2 "2023-01-16T08:58:04Z")

</div>

> [@peter.ludemann](#):
>
> (Why am I doing this? Because - until plunit is improved (there’s a separate thread on this) - it’s useful for me to output some tracing messages from my tests to isolate which test is crashing.)

That is one of the things the next iteration must address. You can hack this on older versions by hooking e.g.

```
print_message(silent, plunit(begin(Unit:Test, File:Line, STO)))

```

> [@peter.ludemann](#):
>
> but the `capture` option doesn’t seem to be described

Because it calls `with_output_to/3` 🙂 That is not picked up by the doc system yet, but is in library(streams). Before you try, this does not work for C(++) `stdout` output, only for Prolog I/O and foreign I/O that uses the `SWI-Stream.h` I/O functions.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [January 16, 2023, 9:19am UTC](https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098/3 "2023-01-16T09:19:13Z")

</div>

> [@peter.ludemann](#):
>
> to isolate which test is crashing.

In the other [thread](https://swi-prolog.discourse.group/t/improving-unit-tests/6091/5) where I noted the GUI test runners, they show each test run and typically change color of the test to green if the test succeeds and color the test red if the test fails.

![image](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/0/08939f415ed44873253ad008235c54cb82a29df0.png)

(Image from Wikipedia [CsUnit](https://en.wikipedia.org/wiki/CsUnit)).

Most GUI test runners include the console output of the test run as some test cases will create a stack trace that is sent to the console instead of being captured for the test.

Another nice feature that many of the GUI test runners have is the ability to run subsets of the test, e.g. only failed test. The really nice ones will not only show failed test but by clicking on the failed test will start the build environment and then take you to the line of code in the editor.

As I noted I only used one of these GUI test runners extensively with F# so don’t know how many of these features were hard coded to work with F# and Visual Studio, not to be confused with Visual Studio Code.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [January 16, 2023, 4:45pm UTC](https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098/4 "2023-01-16T16:45:15Z")

</div>

> [@jan](#):
>
> this does not work for C(++) `stdout` output, only for Prolog I/O and foreign I/O that uses the `SWI-Stream.h` I/O functions.

Another workaround is to use `Sdprintf()` in a trivial foreign predicate.

```prolog
/* ffi_term_chars must be called inside a PL_STRINGS_{MARK,RELEASE} */
static
const char *ffi_term_chars(term_t t)
{ char *s;
  int nchars_rc;
  if ( !t )
    return "<null-term>";
  nchars_rc = PL_get_nchars(t, NULL, &s, CVT_ALL|CVT_WRITEQ|BUF_STACK|CVT_EXCEPTION);
  if ( nchars_rc )
    return s;
  { static char s_x[100]; /* TODO: this is non-reentrant */
    sprintf(s_x, "<unknown term: %lu>", (unsigned long)t);
    return s_x;
  }
}

static foreign_t
sdprintf_(term_t t)
{ PL_STRINGS_MARK();
    Sdprintf("%s", ffi_term_chars(t));
  PL_STRINGS_RELEASE();
  return TRUE;
}

```

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [January 17, 2023, 9:04am UTC](https://swi-prolog.discourse.group/t/how-to-add-trace-output-to-unit-tests/6098/5 "2023-01-17T09:04:04Z")

</div>

> [@peter.ludemann](#):
>
> Another workaround is to use `Sdprintf()` in a trivial foreign predicate.

We also have PL\_write\_term(). I see it was not documented. Added (simple) documentation. It is a bit easier though:

```
PL_write_term(Serror, t, 1200, PL_WRT_QUOTED);

```

There are a _lot_ of flags, covering most of what write\_term/2 supports.
