= The Problem =
The code uses an enumeration (or other magic integer constants) as a return value.  When these are used in tests, the CPPUNIT macros compare them as integers, and the output is not very clear.

= Example =
This enumeration is used to determine the time of day given the current time:
{{{#!cplusplus
/* Here is the enumeration definition, from the header file */
enum TIME_OF_DAY {
  TOD_NIGHT,
  TOD_DAWN,
  TOD_DAY,
  TOD_DUSK,
  TOD_LAST    // This and higher are invalid values
};

/* Here is a function that returns the enumeration, from another source file */
TIME_OF_DAY get_time_of_day();

/* Here is a test for that function, from a different source file */
void TimeTests::testTimeOfDay()
{
  CPPUNIT_ASSERT_EQUAL(TOD_DAY, get_time_of_day());
}
}}}

When the test fails, the text output is:
{{{
Test name: TimeTests::testTimeOfDay
equality assertion failed
- Expected: 2
- Actual  : 0
}}}
Without going back to enumeration definition, it is hard to tell what "2" and "0" refer to.

= Solution =
Create a function that converts the enumeration to a string.  For example:
{{{#!cplusplus
/* This function can be declared in the same header as the enumeration */
#include <string>
const std::string TIME_OF_DAY_Name(const TIME_OF_DAY tod);

/* Here is a test of the new function */
void TimeTests::testTimeOfDayName()
{
  CPPUNIT_ASSERT(std::string("Night"),TIME_OF_DAY_Name(TOD_NIGHT));
  CPPUNIT_ASSERT_EQUAL(std::string("Day"), TIME_OF_DAY_Name(TOD_DAY));
  CPPUNIT_ASSERT_EQUAL(std::string("Night"), TIME_OF_DAY_Name(TOD_NIGHT));
  CPPUNIT_ASSERT_EQUAL(std::string("Dusk"), TIME_OF_DAY_Name(TOD_DUSK));
  CPPUNIT_ASSERT_EQUAL(std::string("Dawn"), TIME_OF_DAY_Name(TOD_DAWN));
  CPPUNIT_ASSERT_EQUAL(std::string("INVALID"), TIME_OF_DAY_Name(TOD_LAST));
  CPPUNIT_ASSERT_EQUAL(
    std::string("INVALID"),
    TIME_OF_DAY_Name(TIME_OF_DAY(TOD_LAST+1)));
}

/* Here is a re-written version of the failing test */
void TimeTests::testTimeOfDay()
{
  CPPUNIT_ASSERT_EQUAL(
    TIME_OF_DAY_Name(TOD_DAY),
    TIME_OF_DAY_Name(get_time_of_day()));
}
}}}

Here is the new (clearer) output for the failing test:
{{{
Test name: UtilTests::testTimeOfDayName
equality assertion failed
- Expected: Night
- Actual  : Day
}}}

Here are three possible implementations of that function.  This first one uses a switch statement, so it works best if the number of enumeration values are small:{{{#!cplusplus
const std::string TIME_OF_DAY_Name(const TIME_OF_DAY tod)
{
  switch (tod) {
    case TOD_NIGHT: return std::string("Night");
    case TOD_DAWN:  return std::string("Dawn");
    case TOD_DAY:   return std::string("Day");
    case TOD_DUSK:  return std::string("Dusk");
    default:        return std::string("INVALID");
  }
}
}}}

This implementation works well for large enumerations without gaps:{{{#!cplusplus
const std::string TIME_OF_DAY_Name(const TIME_OF_DAY tod) 
{
  const std::string invalid_name = "INVALID";
  const std::string Names[] = {
    "Night", 
    "Dawn",
    "Day",
    "Dusk",
    invalid_name
  };
  if (tod < TOD_LAST) return Names[tod];
  else return invalid_name;
}
}}}

This implementation works for large enumerations with gaps:{{{#!cplusplus
#include <map>
const std::string TIME_OF_DAY_Name(const TIME_OF_DAY tod) 
{
  typedef std::map<TIME_OF_DAY, std::string> MapType;
  static MapType *the_map = 0;

  if (!the_map) {
    the_map = new MapType;
    *the_map[TOD_NIGHT] = "Night";
    *the_map[TOD_DAY] = "Day";
    *the_map[TOD_DAWN] = "Dawn";
    *the_map[TOD_DUSK] = "Dusk";
  }

  std::string name = *the_map[tod];
  if (name.empty()) return "INVALID";
  else return name;
} 
}}}

This function will also be useful for any debug output using the TIME_OF_DAY enumeration.

----
CategoryTips
