## Cutter Cutter — An Unit Testing Framework for C. |

## Synopsis

    void                setup                               (void);
    void                teardown                            (void);
    void                startup                             (void);
    void                shutdown                            (void);
    #define             cut_add_data                        (first_data_name, ...)
    #define             cut_set_attributes                  (first_attribute_name, ...)
    #define             cut_get_current_test_context        ()
    #define             cut_set_current_test_context        (test_context)

## Description

Cutter is a Unit Testing Framework for 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);

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

### teardown ()

    void                teardown                            (void);

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.

### startup ()

    void                startup                             (void);

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

Since 0.8

### shutdown ()

    void                shutdown                            (void);

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

Since 0.8

### 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);
    }

    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.

Since 1.0.3

### 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");
    }

    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.

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

## See Also

Assertions