(Очень) небольшой модульного тестирования строго для какао/основе типов в C


Это был мой первый раз когда я пишу платформы модульного тестирования и только 2-й месяц я был на самом деле обучения и использование C на регулярной основе. Итак, есть несколько ключевых вещей, я ищу, чтобы знать:

  • Управление памятью: я должным образом к alloc/свободной памяти?
  • Условные обозначения: мои функции/переменные правильно назвал?
  • Управление потоком: нет ли дублирования в мой код? Если это так, что я мог сделать, чтобы сделать их лучше?
  • ОО: функции были разделены должным образом? -Что глобальной переменной: можно ли нуждаются в моем конкретном случае?

UnitTester.С

#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <objc/objc-runtime.h>
#include "CFTest.h"

#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define RESET "\x1B[0m"

void CF_ASSERT(CFTypeRef test, CFTypeRef should){
    Boolean equal = CFEqual(test, should);
    if (!equal) {
        g_test_passed = false;
    } else {
        g_test_passed = true;
    }
}

void NS_ASSERT(id test, id should) {
    Boolean equal = (Boolean)objc_msgSend(test, sel_registerName("isEqual:"), should);
    if(!equal) {
        g_test_passed = false;
    } else {
        g_test_passed = true;
    }
}

void CF_add_test(CF_TEST_SUITE *test_suite, char *name, void (*test)()){
    test();
    CF_TEST *new_test = malloc(sizeof(CF_TEST));
    new_test->name = name;
    new_test->pass = g_test_passed;

    test_suite->all_tests = realloc(test_suite->all_tests, sizeof(CF_TEST) * (test_suite->test_count +1));
    test_suite->all_tests[test_suite->test_count] = (CF_TEST *)malloc(sizeof(CF_TEST));
    test_suite->all_tests[test_suite->test_count] = new_test;

    test_suite->test_count++;
}

CF_TEST_SUITE * CF_new_suite(char *name) {
    CF_TEST_SUITE *test_suite = malloc(sizeof(CF_TEST_SUITE));
    test_suite->name = name;
    test_suite->test_count = 0;
    test_suite->all_tests = malloc(sizeof(CF_TEST));
    return test_suite;  
}

void print_results(CF_TEST **all_tests, uintptr_t test_count) {
    uintptr_t i;
    for(i = 0; i < test_count; i++) {
        printf("- %s: ", all_tests[i]->name);
        if(all_tests[i]->pass) {
            printf(KGRN "Passed\n" RESET);
        } else {
            printf(KRED "Failed\n" RESET);
            break;
        }
    }
    printf("-----------------------------------------------\n");
}

void RUN_SUITE(CF_TEST_SUITE *test_suite) {
    printf(KYEL "%s:\n" RESET, test_suite->name);
    print_results(test_suite->all_tests, test_suite->test_count);
    free(test_suite);
}    

UnitTester.Ч

#ifndef CFTEST_H
#define CFTEST_H

typedef struct cftest {
    char *name;
    _Bool pass;
}CF_TEST;

typedef struct cftestsuite {
    char *name;
    uintptr_t test_count;
    CF_TEST **all_tests;
}CF_TEST_SUITE;

_Bool g_test_passed;

void CF_add_test(CF_TEST_SUITE *test_suite, char *name, void (*test)());
void CF_ASSERT(CFTypeRef test, CFTypeRef should);
void NS_ASSERT(id test, id should);
CF_TEST_SUITE * CF_new_suite(char *name);
void RUN_SUITE(CF_TEST_SUITE *test_suite);
#endif    

Пример.С

#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <objc/objc-runtime.h>    
#include "CFTest.h"

void cfstringref_test1() {
    //Initial setup
    char *cstr = "test";
    CFStringRef should_ret = CFSTR("test");

    //Should pass
    CF_ASSERT(c_to_cfstr(cstr), should_ret);

    //Teardown
    CFRelease(should_ret);
}

void cfstringref_test2(){
    char *cstr = "this is a test";
    CFStringRef should_ret = CFSTR("this is a test");
    CF_ASSERT(c_to_cfstr(cstr), should_ret);
    CFRelease(should_ret);
}

void nsusernotification_test() {
     id notif = objc_msgSend((id)objc_getClass("NSUserNotification"),
                            sel_registerName("alloc"),
                            sel_registerName("init"));

     NS_ASSERT(get_user_notification(), notif);

     objc_msgSend(notif, sel_registerName("release"));
}

int main(void) {
    CF_TEST_SUITE * cfstring_suite = CF_new_suite("C string to CFStringRef Suite");
    CF_add_test(cfstring_suite, "Single word Test",  &cfstringref_test1);
    CF_add_test(cfstring_suite, "Multi-word Test",  &cfstringref_test2);
    RUN_SUITE(cfstring_suite);

    CF_TEST_SUITE * nsnotif_suite = CF_new_suite("NSUserNotification Suite");
    CF_add_test(nsnotif_suite, "NSUserNotification does create",  &nsusernotification_test);
    RUN_SUITE(nsnotif_suite);
}    


Комментарии