Menu

CUTE reporter

2008-12-14
2012-12-11
  • Thomas Nilsson

    Thomas Nilsson - 2008-12-14

    This is an excerpt from a mail I sent to Marcus, but thinking about it decided that it would probably be of use to a more general audience.

    ---------------

    I am getting very fond of CGreen, so I looked at possibilities to integrate it with the unit test frameworks in Eclipse. After some research I found a C++ unit testing framework CUTE (by IFS in Germany) which offers a plugin for Eclipse.

    I managed to figure out the protocol between the C++ unit test framework and the CUTE plugin (wasn't that hard really). It is based on console output, so I thought it would be easy to create a new CGreen reporter, based on the existing text_reporter, to hook them together.

    JUnit, and CUTE, assumes that a test fails early by aborting on a failing assert, and that the normal exit from a method without any failure is a pass. So the CUTE protocol is:

        suite = "#beginning" <suite> <nl> { suite | test } "#ending" <test> <nl>

        test = "#starting" <name> <nl> [ success | failure ]

        success = "#success" <name> OK <nl>

        failure = "#failure <name> <position> <message> <nl>

    (<nl> is newline)

    This does not fit right in with CGreens reporter interface but after some experimenting I managed to comply to the CUTE protocol.

    I had to separate reporter->start() into reporter->start() & reporter->start_test() for suites and tests respectively, likewise with finish, to get a hook on the call to test functions as opposed to starting suites, changing some calls in unit.c to reflect this split. A suggestion would be to rename the reporter->start() to start_suite(), likewise with finish().

    I'm attaching the source for my cute_reporter for your peruse. Or maybe I should join the project and do them on the development branch.

    Usage is fairly simple. Install the CUTE plugin in your Eclipse. Create a CUTE Run Configuration. Call create_cute_reporter() in your main() instead of whatever reporter you are using. Run your Run Configuration and admire the CUTE Results view. (Minor hickups so far is that the CUTE Results view doesn't popup. I would also want it to fold suites with all passing tests, like the JUnit view does, but that is up to the CUTE guys...) It does not seem to calculate the number of tests, failures and errors correctly. But that could be because it doesn't know the total number of test. This is an extension that would be needed in the reporter, namely to send the number of tests in the suite as a parameter to reporter->start().

    /Thomas

    ------------- cute_reporter.c ------------------------------
    #include <cgreen/cute_reporter.h>
    #include <cgreen/reporter.h>
    #include <cgreen/breadcrumb.h>
    #include <stdlib.h>
    #include <stdio.h>

    static void cute_reporter_start_suite(TestReporter *reporter, const char *name);
    static void cute_reporter_start_test(TestReporter *reporter, const char *name);
    static void assert_failed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
    static void assert_passed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
    static void test_failed_to_complete(TestReporter *reporter, const char *name);
    static void assert_true(TestReporter *reporter, const char *file, int line, int result, const char *message, ...);
    static void cute_reporter_finish_test(TestReporter *reporter, const char *name);
    static void cute_reporter_finish_suite(TestReporter *reporter, const char *name);

    static void print_breadcrumb(TestReporter *reporter);
    static void show_breadcrumb(const char *name, void *memo);

    TestReporter *create_cute_reporter() {
        TestReporter *reporter = create_reporter();
        reporter->start = &cute_reporter_start_suite;
        reporter->start_test = &cute_reporter_start_test;
        reporter->show_fail = &assert_failed;
        reporter->show_pass = &assert_passed;
        reporter->show_incomplete = &test_failed_to_complete;
        reporter->finish_test = &cute_reporter_finish_test;
        reporter->finish = &cute_reporter_finish_suite;
        return reporter;
    }

    static void cute_reporter_start_suite(TestReporter *reporter, const char *name) {
        // TODO Send number of tests as a parameter
        int number_of_tests = 4;
        reporter_start(reporter, name);
        printf("#beginning %s %d\n", name, number_of_tests);
    }

    static int error_count;
    static void cute_reporter_start_test(TestReporter *reporter, const char *name) {
        error_count = reporter->exceptions + reporter->failures;
        reporter_start(reporter, name);
        printf("#starting %s\n", name);
    }

    static void cute_reporter_finish_test(TestReporter *reporter, const char *name) {
        reporter_finish(reporter, name);
        if (error_count == reporter->exceptions + reporter->failures) {
            printf("#success %s OK\n", name);
        }
    }

    static void cute_reporter_finish_suite(TestReporter *reporter, const char *name) {
        reporter_finish(reporter, name);
        printf("#ending %s", name);
        if (get_breadcrumb_depth((CgreenBreadcrumb *)reporter->breadcrumb) == 0) {
            printf(
                    ": %d pass%s, %d failure%s, %d exception%s.\n",
                    reporter->passes,
                    reporter->passes == 1 ? "" : "es",
                    reporter->failures,
                    reporter->failures == 1 ? "" : "s",
                    reporter->exceptions,
                    reporter->exceptions == 1 ? "" : "s");
        } else
            printf("\n");
    }

    static int previous_errors = 0;
    static void assert_failed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
        if (!previous_errors) {
            printf("#failure %s", get_current_from_breadcrumb((CgreenBreadcrumb *)reporter->breadcrumb));
            printf(" %s:%d ", file, line);
            vprintf((message == NULL ? "Problem" : message), arguments);
            printf("\n");
            previous_errors = 1;
        }
    }

    static void assert_passed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
    }

    static void test_failed_to_complete(TestReporter *reporter, const char *name) {
        printf("#error %s failed to complete\n", name);
    }

    ------------- cute_reporter.h ------------------------------
    #ifndef CUTE_REPORTER_HEADER
    #define CUTE_REPORTER_HEADER

    #include <cgreen/reporter.h>

    TestReporter *create_cute_reporter();

    #endif

     
    • João Henrique F. de Freitas

      Hello,

      I will try it now.