Nim: [unittest] test fail messages don't go to stderr

Created on 31 May 2018  Â·  13Comments  Â·  Source: nim-lang/Nim

Ref:

When a test fails, unittest sets the exit code to 1 (fail).

But whether the test passes or fails, the corresponding messages always go to stdout (errors don't go to stderr).

Stdlib

Most helpful comment

Using both streams can cause confusion to some users who try to redirect the output in a naive way.

File streams are a very basic concept. It's important to understand the difference between stdout and stderr. The naive users should see the bash redirection basics of 1> and 2>.

All 13 comments

Because unittest uses styledEcho from the terminal module and styledEcho writes only to stdout.

Try with NIMTEST_NO_COLOR env var.

I tried that.

The envvar works as expected i.e. the messages don't have color any more. But the errors still come on stdout.

Here's how I confirm in Bash:

export NIMTEST_NO_COLOR=yes
# running compiled binary
./unitest_fail_test 1> stdout.txt
./unitest_fail_test 2> stderr.txt

The stderr.txt stays empty.


Here's the nim code for testing:

type
  Card = object
    rank: Rank
    suit: Suit
  Rank = enum
    crSeven
    crEight
    crNine
    crTen
    crJack
    crQueen
    crKing
    crAce
  Suit = enum
    csClubs = "â™§"
    csDiamonds = "♢"
    csHearts = "♡"
    csSpades = "♤"
proc `<`(a,b: Card): bool = a.rank < b.rank
when isMainModule:
  import unittest
  suite "test card relations":

    setup:
      let
        aceDiamonds = Card(rank: crAce, suit: csDiamonds)
        kingClubs = Card(rank: crKing, suit: csClubs)
        aceClubs = Card(rank: crAce, suit: csClubs)

    test "greater than":
      check:
        aceDiamonds > kingClubs
        aceClubs > kingClubs
    test "equal to":
      check aceDiamonds == aceClubs

I also think that fails should be output to stderr, but let's wait other opinions.

I think the reported test failures is an essential output of the test program. It's not an error message (the test program didn't fail to complete its duties). Using both streams can cause confusion to some users who try to redirect the output in a naive way.

If it's "not an error message", it shouldn't return an exit code of 1.

While setting exit code of 1, keeping stderr empty confuses the tool I am using.

Output to stdout if exit code is 0. Output to stderr if exit code is 1.

You need to output something to stderr in the case of an error, it could be even a simple message summarizing the errors.

Using both streams can cause confusion to some users who try to redirect the output in a naive way.

File streams are a very basic concept. It's important to understand the difference between stdout and stderr. The naive users should see the bash redirection basics of 1> and 2>.

No, it's just harmful friction, so now for every output statement I have to answer the question "should this go to stderr or stdout" and it doesn't solve anything because Unix's core assumption is that you can use line based parsing/filtering tools to connect programs together. Which never worked reliably and never will, but that's besides the point, stderr vs stdout is against Unix's core ideas.

No, it's just harmful friction, so now for every output statement I have to answer the question "should this go to stderr or stdout"

No. You can send all error messages to the stdout. But when ending the unittest, just send a summary error message to stderr saying that one or more of the tests in that unittest run failed. The issue is that while unittest exits with a code of 1, it creates no activity on stderr.

As I suggested earlier:

You need to output something to stderr in the case of an error, it could be even a simple message summarizing the errors.

@Araq

I have to answer the question "should this go to stderr or stdout"

Maybe, for unittests we could make exclusion.
Probably, it can be used for the tester: output only results with fails.

Or to add support for something like NIMTEST_FAILS_TO_STDERR env var.

No. You can send all error messages to the stdout. But when ending the unittest, just send a summary error message to stderr saying that one or more of the tests in that unittest run failed. The issue is that while unittest exits with a code of 1, it creates no activity on stderr.

I agree that's quite a nice solution for unittest, thanks for this idea.

(But in general stdout vs stderr is just another design bug in Unix, deal with it. ;-) )

unittest provides a structured output on stdout and the output of successful and failed tests should go in there to be readable and consistent.
Stderr is meant to be captured independently of stdout.
It should contain at least a 1-line summary in case of failure. IMO it should list the failed tests and, optionally, provide parsable output that can be easily displayed in CI.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alaviss picture alaviss  Â·  3Comments

awr1 picture awr1  Â·  3Comments

juancarlospaco picture juancarlospaco  Â·  3Comments

kobi2187 picture kobi2187  Â·  4Comments

hlaaftana picture hlaaftana  Â·  3Comments