Cutter

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

Synopsis

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

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

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.


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


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.


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


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_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_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.

context :

... :


cut_set_attributes()

#define             cut_set_attributes(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_get_current_test_context()

#define             cut_get_current_test_context()

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_set_current_test_context()

#define             cut_set_current_test_context(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_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()

#define             cut_message(...)

Specifies optional assertion message.

e.g.:

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

... :

the parameters to insert into the format string.

Since 1.1.0

See Also

Assertions