3.5. SRunner output

The function to run tests in an SRunner is defined as follows:

void srunner_run_all(SRunner *sr, enum print_output print_mode);

This function does two things:

  1. Runs all of the unit tests for all of the test cases defined for all of the suites in the SRunner, and collects the results in the SRunner

  2. Prints the results according to the print mode specified

For SRunners that have already been run, there is also a separate printing function defined as follows:

void srunner_print(SRunner *sr, enum print_output print_mode);

The enumeration values defined in Check to control print output are as follows:

CK_SILENT

Specifies that no output is to be generated. If you use this flag, you either need to programmatically examine the SRunner object, print separately, or use test logging (described below: Test Logging).

CK_MINIMAL

Only a summary of the test run will be printed (number run, passed, failed, errors).

CK_NORMAL

Prints the summary of the run, and prints one message per failed tests.

CK_VERBOSE

Prints the summary, and one message per test (passed or failed)

CK_ENV

Gets the print mode from the environment variable CK_VERBOSITY, which can have the values "silent", "minimal", "normal, "verbose". If the variable is not found or the value is not recognized, the print mode is set to CK_NORMAL.

With the CK_NORMAL flag specified, let's rerun make check now. We get the following satisfying output:

Running suite(s): Money 
0%: Checks: 1, Failures: 1, Errors: 0 
check_money.c:9:F:Core:test_create: Amount not set correctly on creation

The first number in the summary line tells us that 0% of our tests passed, and the rest of the line tells us that there was one check, and one failure. The next line tells us exactly where that failure occurred, what kind of failure it was (P for pass, F for failure, E for error).

Let's implement the money_amount function, so that it will pass its tests. We first have to create a Money structure to hold the amount:

struct Money { 
  int amount; 
};

Then we will implement the money_amount function to return the correct amount:

int money_amount(Money *m) 
{ 
  return m->amount;
}

We will now rerun make check and... What's this? The output is now as follows:

Running suite(s): Money 
0%: Checks: 1, Failures: 0, Errors: 1 
check_money.c:5:E:Core:test_create: (after this point) Received signal 11

What does this mean? Note that we now have an error, rather than a failure. This means that our unit test either exited early, or was signaled. Next note that the failure message says “after this point” This means that somewhere after the point noted (check_money.c, line 5) there was a problem: signal 11 (AKA segmentation fault). The last point reached is set on entry to the unit test, and after every call to fail_unless, fail, or the special function mark_point. E.g., if we wrote some test code as follows:

stuff_that_works();
mark_point();
stuff_that_dies();

then the point returned will be that marked by mark_point.

The reason our test failed so horribly is that we haven't implemented money_create to create any money. Go ahead and implement that, and money_currency, to make the unit tests pass.