Cutter

Cutter — A Unit Testing Framework for C and C++.

Synopsis

#define             CUT_EXPORT
#define             cut_add_data                        (first_data_name,
                                                         ...)
#define             cut_add_data_backward_compatibility (context,
                                                         ...)
CutTestContext *    cut_get_current_test_context        (void);
void                cut_keep_message                    (void);
void                cut_message                         (const char *format,
                                                         ...);
void                cut_set_attributes                  (const char *first_attribute_name,
                                                         ...);
void                cut_set_current_test_context        (CutTestContext *test_context);
void                cut_set_message                     (const char *format,
                                                         ...);
void                cut_set_message_va_list             (const char *format,
                                                         va_list args);
void                cut_setup                           (void);
void                cut_shutdown                        (void);
void                cut_startup                         (void);
void                cut_teardown                        (void);
void                setup                               (void);
void                teardown                            (void);

Description

Cutter is a Unit Testing Framework for C and C++ and has the following features:

  • Easy to use. Cutter doesn't introduce any magic macros like CUTTER_DEFINE_TEST_START and CUTTER_DEFINE_TEST_END into your test program. You can write your test program like normal program. You only use cut_assert_XXX() to check that your program works as you expect.

    #include <cutter.h>
    #include "my-stack.h"
    
    void
    test_my_stack (void)
    {
        MyStack *stack = my_stack_new();
    
        cut_assert_not_null(stack);
        cut_assert(my_stack_is_empty(stack));
        cut_assert_equal_int(0, my_stack_get_size(stack));
    
        my_stack_push(stack, 10);
        cut_assert(!my_stack_is_empty(stack));
        cut_assert_equal_int(1, my_stack_get_size(stack));
    
        my_stack_push(stack, 20);
        cut_assert_equal_int(2, my_stack_get_size(stack));
    
        cut_assert_equal(20, my_stack_pop(stack));
        cut_assert(!my_stack_is_empty(stack));
        cut_assert_equal_int(1, my_stack_get_size(stack));
    
        cut_assert_equal(10, my_stack_pop(stack));
        cut_assert(my_stack_is_empty(stack));
        cut_assert_equal_int(0, my_stack_get_size(stack));
    }
    

  • Simple but useful output. Cutter works quietly if tests are running without any problems by default. The following is an output of self test:

    ...........................................................
    
    Finished in 0.213021 seconds
    
    59 test(s), 246 assertion(s), 0 failure(s), 0 error(s), 0 pending(s), 0 notification(s)
    

    Cutter just outputs "." for a passed test and a summary at the end. Cutter doesn't output each test name, how many assertions are used for a test and so because we don't need the information on success.

    Cutter outputs many information on failure:

    .....................F.....................................
    
    1) Failure: test_error
    <"Strange" == cut_test_result_get_test_name(result)>
    expected: <Strange!!!>
     but was: <dummy-error-test>
    test/test-cut-assertions.c:240: cut_assert_test_result()
    
    Finished in 0.223657 seconds
    
    59 test(s), 242 assertion(s), 1 failure(s), 0 error(s), 0 pending(s), 0 notification(s)
    

    The above result is happened because I add a strange expected staring in Cutter's self test:

    cut_assert_equal_string("Strange!!!", cut_test_result_get_test_name(result));
    

    The strange assertion is written in the 240th line in test/test-cut-assertions.c and the line is in the cut_assert_test_result() function. The function is called in test_error test. We expected cut_test_result_get_test_name(result) should return "Strange!!!" but got "dummy-error-name". We can get the above information from Cutter output. This will help your debug.

    Cutter's output format is pragmatic. ' but was:' is indented and aligned with the above 'expected:'. This helps that you find difference between expected value and actual value by your eyes easily. The problem line is formated as 'FILENAME:LINE: FUNCTION' to integrate Emacs. In Emacs's compilation-mode, if the format is appeared in *compilation* buffer, we can jump to FILENAME at LINE with next-error command. (C-x `) This helps that you find the problem line rapidly.

    Cutter supports not only easy test writing but also easy debugging.

Details

CUT_EXPORT

#  define CUT_EXPORT __declspec(dllexport)

Marks a function as a exported function. This is needed for just Windows environment. If you want to run your tests on Windows, you need to use this. Otherwise, you don't need to use this.

e.g.:

CUT_EXPORT void
test_add (void)
{
  ...
}

Since 1.1.2


cut_add_data()

#define             cut_add_data(first_data_name, ...)

Adds data to use data driven test.

e.g.:

#include <cutter.h>

void data_translate (void);
void test_translate (const void *data);

static const char*
translate (int input)
{
   switch(input) {
   case 1:
       return "first";
   case 111:
       return "a hundred eleven";
   default:
       return "unsupported";
   }
}

typedef struct _TranslateTestData
{
    char *translated;
    int input;
} TranslateTestData;

static TranslateTestData *
translate_test_data_new (char *translated, int input)
{
    TranslateTestData *data;

    data = malloc(sizeof(TranslateTestData));
    data->translated = strdup(translated);
    data->input = input;

    return data;
}

static void
translate_test_data_free (TranslateTestData *data)
{
    free(data->translated);
    free(data);
}

void
data_translate(void)
{
    cut_add_data("simple data",
                 translate_test_data_new("first", 1),
                 translate_test_data_free,
                 "complex data",
                 translate_test_data_new("a hundred eleven", 111),
                 translate_test_data_free,
                 NULL);
}

void
test_translate(const void *data)
{
     const TranslateTestData *test_data = data;

     cut_assert_equal_string(test_data->translated,
                             translate(test_data->input));
}

first_data_name :

The first data name.

... :

The data and destroy function of the first data, followed optionally by more name/data/destroy_function(CutDestroyFunction) triples. The variable arguments should be terminated by NULL since 1.0.6.

Since 1.0.3


cut_add_data_backward_compatibility()

#define             cut_add_data_backward_compatibility(context, ...)

Warning

cut_add_data_backward_compatibility is deprecated and should not be used in newly-written code.


cut_get_current_test_context ()

CutTestContext *    cut_get_current_test_context        (void);

Returns the current test context. The current test context is a thread local object. It means that you don't need to care this if you don't create a new thread in your test. This is only needed to care if you create a new thread. You need to pass the current test context in your test thread to the current test context in a created thread.

e.g.:

int
your_thread_function(void *data)
{
    CutTestContext *test_context = data;
    cut_set_current_test_context(test_context);
    ...
}

void
run_your_thread(void)
{
    int result;
    pthread_t your_thread;

    result = pthread_create(&your_thread, NULL,
                            your_thread_function,
                            cut_get_current_test_context());
    ...
}

Returns :

a CutTestContext.

Since 1.0.4


cut_keep_message ()

void                cut_keep_message                    (void);

Warning

cut_keep_message has been deprecated since version 1.1.0 and should not be used in newly-written code. Use cut_message() instead.

Keeps the current message set by cut_set_message() or cut_set_message_va_list() after the next assertion.

Since 1.0.6


cut_message ()

void                cut_message                         (const char *format,
                                                         ...);

Specifies optional assertion message.

e.g.:

cut_assert_equal_string("abc", "def",
                        cut_message("should fail!"));

format :

the message format. See the printf() documentation.

... :

the parameters to insert into the format string.

Since 1.1.0


cut_set_attributes ()

void                cut_set_attributes                  (const char *first_attribute_name,
                                                         ...);

Sets attributes of the test.

e.g.:

#include <cutter.h>

void attributes_repeat (void);
void test_repeat (void);

void
attributes_repeat(void)
{
    cut_set_attributes("description", "a test for repeat function",
                       "bug", "111",
                       "priority", "high",
                       NULL);
}

void
test_repeat(void)
{
     cut_assert_equal_string_with_free("XXX", repeat("X", 3));
}

first_attribute_name :

The first attribute name.

... :

The value of the first attribute, followed optionally by more name/value pairs. NULL-terminate is required since 1.0.7.

Since 1.0.4


cut_set_current_test_context ()

void                cut_set_current_test_context        (CutTestContext *test_context);

Set test_context as the current test context. See cut_get_current_test_context() for more details.

test_context :

the CutTestContext to be the current test context.

Since 1.0.4


cut_set_message ()

void                cut_set_message                     (const char *format,
                                                         ...);

Warning

cut_set_message has been deprecated since version 1.1.0 and should not be used in newly-written code. Use cut_message() instead.

Sets a message to be used by the next assertion.

format :

the message format. See the printf() documentation.

... :

the parameters to insert into the format string.

Since 1.0.6


cut_set_message_va_list ()

void                cut_set_message_va_list             (const char *format,
                                                         va_list args);

Warning

cut_set_message_va_list has been deprecated since version 1.1.0 and should not be used in newly-written code. Use cut_message() instead.

Sets a message to be used by the next assertion.

format :

the message format. See the printf() documentation.

args :

the parameters to insert into the format string.

Since 1.0.6


cut_setup ()

void                cut_setup                           (void);

If you define cut_setup() in your test program, cutter will call your cut_setup() before each your test is run. cut_setup() has priority over setup().

Since 1.0.6


cut_shutdown ()

void                cut_shutdown                        (void);

If you define shutdown() in your test program, cutter will call your shutdown() after each your test case is run. cut_shutdown() has priority over shutdown().

Since 1.0.6


cut_startup ()

void                cut_startup                         (void);

If you define cut_startup() in your test program, cutter will call your cut_startup() before each your test case is run. cut_startup() has priority over startup().

Since 1.0.6


cut_teardown ()

void                cut_teardown                        (void);

If you define cut_teardown() in your test program, cutter will call your cut_teardown() after each your test is run even if a test is failed. cut_teardown() has priority over teardown().

Since 1.0.6


setup ()

void                setup                               (void);

Warning

setup has been deprecated since version 1.0.7 and should not be used in newly-written code. Use cut_setup() instead.

If you define setup() in your test program, cutter will call your setup() before each your test is run. If you define cut_setup(), setup() is ignored.


teardown ()

void                teardown                            (void);

Warning

teardown has been deprecated since version 1.0.7 and should not be used in newly-written code. Use cut_teardown() instead.

If you define teardown() in your test program, cutter will call your teardown() after each your test is run even if a test is failed. If you define cut_teardown(), teardown() is ignored.

See Also

Assertions