Загальний огляд
CUnit – це фреймворк для написання, адміністрування та виконання модульних тестів на мові С. Він розроблений, як статична бібліотека, яка зв’язана з кодом користувача.
Сunit включає великий набір перевірок для простих типів даних. Додаткова в ньому є ще кілька інших інтерфейсів для виконання тестів і перегляду результатів тестування. Вони включають автоматизовані інтерфейси для тестування коду і перегляду результатів, а також інтерактивні інтерфейси, які дозволяють користувачу запускати тести і переглядати результати динамічно.
Типи даних і функції потрібні користувачу знаходяться в заголовочних файлах ( табл.1 )
Таблиця 1. Файли потрібні для роботи з CUnit.
Заголовочний файл
Опис
1
#include <CUnit/CUnit.h>
Містить Assert-макроси для тест-кейсів, і включає інші заготовочні файли фреймворку
2
#include <CUnit/CUError.h>
Функії перехоплення помилок. Включається в проект автоматично в CUnit.h.
3
#include <CUnit/TestDB.h>
Типи даних і функції для роботи з регістром тестів, набором тестів і самими тестами. Включається в проект автоматично в CUnit.h.
4
#include <CUnit/TestRun.h>
Оголошення типів даних і функцій для виконання тестів і отримання результатів. Включається в проект автоматично в CUnit.h.
5
#include <CUnit/Automated.h>
Автоматичний інтерфейс виводу в xml.
6
#include <CUnit/Basic.h>
Базовий інтерфейс з не інтерактивним виводом в stdout.
7
#include <CUnit/Console.h>
Інтерактивний інтерфейс виводу на консоль.
8
#include <CUnit/CUCurses.h>
Інтерактивний інтерфейс виводу на консоль. (*nix).
9
#include <CUnit/Win.h>
Інтерфейс Windows. (ще не реалізований)
CUnit – це комбінація кросплатформенного фреймворку і різноманітних інтерфейсів користувача. Кросплатформенний фреймворк забезпечує базову підтримку керування тестовим регістром, наборами тестів і тестами. Інтерфейс користувача забезпечує взаємодію з фреймворком, запуск тестів і перегляд результатів.
Рис 1. Структура CUnit.
Індивідуальні тести складають набори тестів, з яких в свою чергу складений активний регістр тестів. Набори тестів можуть мати опції, і викликати певні функції перед і після виконання наборів тестів. Всі набори тестів/тести можна запустити єдиним викликом функції, або можна вибирати певні набори тестів чи окремі тести для запуску.
Послідовність дій для початку використання CUnit
Написати функції для тестування (ініціалізації, завершення виконання набору тестів, якщо необхідно)
Ініціалізувати реєстр тестів CU_initialize_registry()
Додати набір тестів в регістр CU_add_suite()
Додати тести в набір CU_add_test()
Виконати тести використовуючи пропрієтарний інтерфейс CU_console_run_test()
Очистити регістр тестів CU_cleanup_registry().
Всі публічні імена в CUnit починаються з префіксу CU_. Це допомагає зменшити появу помилки в коді користувача. Раніші версії CUnit використовували імена без цього префіксу і досі підтримуються в CUnit, але треба використовувати макрос USE_DEPRECATED_CUNIT_NAMES.
Написання тестів
CUnit тест – це С-функція з сигнатурою void test_func(void). Немає ніяких обмежень на вміст тестової функції окрім того, що вона не повиння модифікувати сам фреймворк (тобто додавати тести, набори тестів чи запускати тести на виконання). Вона може викликати іншу функцію яка також не повинна модифікувати фреймворк. Додавання тесту в тесті спричинить виконання його функції для тестування при виконанні самого тесту.
Приклад тестування функції яка повертає максимальне з двох чисел:
int maxi(int i1, int i2)
{
return (i1 > i2) ? i1 : i2;
}
void test_maxi(void)
{
CU_ASSERT(maxi(0,2) == 2);
CU_ASSERT(maxi(0,-2) == 0);
CU_ASSERT(maxi(2,2) == 2);
}
СUnit містить ряд перевірок для тестування логічних умов. Успішне чи неуспішне виконання перевірок відстежується фреймворком, і результати роботи можна побачити після виконання тесту. Кожна така перевірка тестує одну логічну умову і виконання її неуспішне, якщо умова рівна FALSE.У випадку не проходження перевірки функція продовжує виконання, хіба що користувач задав ’xxx_FATAL’ версію перевірки. В цьому випадку тест-функція завершує виконання. FATAL версія перевірки повинна використовуватися обачно, адже тест-функція не буде мати змоги завершитися коректно, наприклад не зможе закрити файл. Проте це не впливає на функцію завершення набору тестів.
Також існують спеціальні функції які реєструють проходження чи не проходження тесту без будь-яких додаткових параметрів. Вони використовуються для тестування гілок виконання чи інших випадків, які не підходять для чітких логічних перевірок.
void test_longjmp(void)
{
jmp_buf buf;
int i;
i = setjmp(buf);
if (i == 0) {
run_other_func();
CU_PASS("run_other_func() succeeded.");
}
else
CU_FAIL("run_other_func() issued longjmp.");
}
Інші функції можуть вільно використовувати перевірки CUnit. Вони будуть прелічені для викликаючої функції. Також вони можуть використовувати FATAL версії перевірок. Непрохождження перевірки призведе до виходу з усіх функції по ланцюгу викликів і з базової функції.
Таблиця 2. Список перевірок CUnit.
Функція
Опис
CU_ASSERT(int expression)CU_ASSERT_FATAL(int expression)CU_TEST(int expression)CU_TEST_FATAL(int expression)
Перевіряє чи expression є TRUE (не нуль)
Еxpression - вираз
CU_ASSERT_TRUE(value)CU_ASSERT_TRUE_FATAL(value)
Перевіряє чи value є TRUE (не нуль)
Value - значення
CU_ASSERT_FALSE(value)CU_ASSERT_FALSE_FATAL(value)
Перевіряє чи value є FALSE (zero)
CU_ASSERT_EQUAL(actual, expected)CU_ASSERT_EQUAL_FATAL(actual, expected)
Перевіряє чи actual = = expected
actual – те що дане
expected – те що очікуване
CU_ASSERT_NOT_EQUAL(actual, expected))CU_ASSERT_NOT_EQUAL_FATAL(actual, expected)
Перевіряє чи actual != expected
CU_ASSERT_PTR_EQUAL(actual, expected)CU_ASSERT_PTR_EQUAL_FATAL(actual, expected)
Перевіряє чи вказівники actual = = expected
CU_ASSERT_PTR_NOT_EQUAL(actual, expected)CU_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected)
Перевіряє чи вказівники actual != expected
CU_ASSERT_PTR_NULL(value)CU_ASSERT_PTR_NULL_FATAL(value)
Перевіряє чи вказівник value == NULL
CU_ASSERT_PTR_NOT_NULL(value)CU_ASSERT_PTR_NOT_NULL_FATAL(value)
Перевіряє чи вказівник value != NULL
CU_ASSERT_STRING_EQUAL(actual, expected)CU_ASSERT_STRING_EQUAL_FATAL(actual, expected)
Перевіояє чи стрічки actual і expected є еквівалентні
CU_ASSERT_STRING_NOT_EQUAL(actual, expected)CU_ASSERT_STRING_NOT_EQUAL_FATAL(actual, expected)
Перевіояє чи стрічки actual і expected є різні
CU_ASSERT_NSTRING_EQUAL(actual, expected, count)CU_ASSERT_NSTRING_EQUAL_FATAL(actual, expected, count)
Перевіояє чи перші count символів стрічки actual і expected є такі ж самі
CU_ASSERT_NSTRING_NOT_EQUAL(actual, expected, count)CU_ASSERT_NSTRING_NOT_EQUAL_FATAL(actual, expected, count)
Перевіояє чи перші count символів стрічки actual і expected не є такі ж самі
CU_ASSERT_DOUBLE_EQUAL(actual, expected, granularity)CU_ASSERT_DOUBLE_EQUAL_FATAL(actual, expected, granularity)
Перевіряє чи |actual - expected| <= |granularity|Треба підключити math.h
CU_ASSERT_DOUBLE_NOT_EQUAL(actual, expected, granularity)CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL(actual, expected, granularity)
Перевіряє чи |actual - expected| > |granularity|Треба підключити math.h
CU_PASS(message)
Реєструє проходження перевірки.
Message - повідомлення
CU_FAIL(message)CU_FAIL_FATAL(message)
Реєструє непроходження перевірки.
Таблиця 3. Список старих версій функцій CUnit
Старі імена
Нові імена
ASSERT
CU_ASSERT_FATAL
ASSERT_TRUE
CU_ASSERT_TRUE_FATAL
ASSERT_FALSE
CU_ASSERT_FALSE_FATAL
ASSERT_EQUAL
CU_ASSERT_EQUAL_FATAL
ASSERT_NOT_EQUAL
CU_ASSERT_NOT_EQUAL_FATAL
ASSERT_PTR_EQUAL
CU_ASSERT_PTR_EQUAL_FATAL
ASSERT_PTR_NOT_EQUAL
CU_ASSERT_PTR_NOT_EQUAL_FATAL
ASSERT_PTR_NULL
CU_ASSERT_PTR_NULL_FATAL
ASSERT_PTR_NOT_NULL
CU_ASSERT_PTR_NOT_NULL_FATAL
ASSERT_STRING_EQUAL
CU_ASSERT_STRING_EQUAL_FATAL
ASSERT_STRING_NOT_EQUAL
CU_ASSERT_STRING_NOT_EQUAL_FATAL
ASSERT_NSTRING_EQUAL
CU_ASSERT_NSTRING_EQUAL_FATAL
ASSERT_NSTRING_NOT_EQUAL
CU_ASSERT_NSTRING_NOT_EQUAL_FATAL
ASSERT_DOUBLE_EQUAL
CU_ASSERT_DOUBLE_EQUAL_FATAL
ASSERT_DOUBLE_NOT_EQUAL
CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL
Реєстр тестів
Реєстр тестів – це репозиторій наборів тестів і самих тестів. CUnit підтримує активний тестовий реєстр, який оновлюється коли користувач додає новий тест. Реєстр тестів CUnit в коді – це структура даних CU_TestRegistry. Вона включає поля для зберігання загальної кількості наборів тестів і окремих тестів в реєстрі, а також вказівник на початок зв’язного списку зареєстрованих наборів
typedef struct CU_TestRegistry
{
unsigned int uiNumberOfSuites;
unsigned int uiNumberOfTests;
CU_pSuite pSuite;
} CU_TestRegistry;
typedef CU_TestRegistry* CU_pTestRegistry;
Зазвичай користувачу необхідно лиш ініціалізувати реєстр тестів а потім завершити роботу реєстру. Проте є і інші функції для роботи з реєстром, якщо це необхідно.
Основні функції та структури реєстру тестів:
typedef struct CU_TestRegistry
typedef CU_TestRegistry* CU_pTestRegistry
CU_ErrorCode CU_initialize_registry(void)
Void CU_cleanup_registry(void)
CU_pTestRegistry CU_get_registry(void)
CU_pTestRegistry CU_set_registry(CU_pTestRegistry pTestRegistry)
CU_pTestRegistry CU_create_new_registry(void)
Void CU_destroy_existing_registry(CU_pTestRegistry* ppRegistry)
Коли тестування завершене необхідно викликати функцію для завершення роботи реєстру void CU_cleanup_registry(void). Вона звільняє п’янять, яку використовує фреймворк. Вона повинна бути останньою функцією, яка викликається при тестуванні.(крім функції установки тестового реєстру CU_initialize_registry() або CU_set_registry()).
Невдале виконання цієї функції призведе до витоку пам’яті. Це функція знищує всі набори тестів і окремі тести в реєстрі, тому вказівники на ці дані не можна буде розіменувати після завершення роботи реєстру.
Виклик CU_cleanup_registry(void) вплине тільки на внутрішній реєстр тестів CU_TestRegistry, який підтримується фреймворком. Знищення будь-якого іншого тестового реєстру користувачем є справою користувача. Це можна зробити явно викликом CU_destroy_existing_registry(), або неявно роблячи реєстр активним викликом CU_set_registry(), а потім знащити його викликом CU_cleanup_registry() знову.
Також в реєстрі є деякі інші функції для забезпечення потреб тестування і внутрішнього використання, проте користувачі мають про них знати для глибшого розуміння фреймворку і можливо практичного використання.
CU_pTestRegistry CU_get_registry(void)
Повертає вказівник на активний тестовий реєстр. Реєстр це змінна типу CU_TestRegistry. Пряма маніпуляція з тестовим реєстром не рекомендована для цього використовуються API. Так як фреймворк керує реєстром, то вказівник буде недісним при завершенні роботи реєстру.
CU_pTestRegistry CU_set_registry(CU_pTestRegistry pTestRegistry)
Замінює активний реєстр на вказаний. Повертається вказівник на попередній реєстр. Завершення роботи попереднього реєстру – справа користувача. Це можна зробити явно викликавши CU_destroy_existing_registry() для цього вказівника, або неявно викликавши CU_set_registry() а потім CU_cleanup_registry(). Слід проявляти обережність, щоб не знищити реєстру, який встановлюється в якості активного. Це може призвести до багаторазового звільнення тієї ж пам’яті і помилки програми.
CU_pTestRegistry CU_create_new_registry(void)
Створює новий реєстр і встановлює на нього вказівник. Новий реєстр не містить ніяких наборів тестів чи окремих тестів. Завершувати роботу реєстру є відповідальністю користувача.
void CU_destroy_existing_registry(CU_pTestRegistry* ppRegistry)
Знищує і звільняє всю пам'ять зайняту певним реєстром включаючи будь-які зареєстровані набори тестів чи тести. Цю функцію не слід викликати для активного реєстру. Це призведе до багаторазового звільнення тієї ж пам’яті і помилки програми. Виклик функції з параметром NULL нічого не виконує.
Таблиця 4. Список старих версій функцій CUnit для роботи з реєстром
Старі імена
Нові імена
_TestRegistry
CU_TestRegistry
_TestRegistry.uiNumberOfGroupsPTestRegistry->uiNumberOfGroups
CU_TestRegistry.uiNumberOfSuitesCU_pTestRegistry->uiNumberOfSuites
_TestRegistry.pGroupPTestRegistry->pGroup
CU_TestRegistry.pSuiteCU_pTestRegistry->pSuite
PTestRegistry
CU_pTestRegistry
initialize_registry()
CU_initialize_registry()
cleanup_registry()
CU_cleanup_registry()
get_registry()
CU_get_registry()
set_registry()
CU_set_registry()
Керування тестами і наборами тестів
Для того, щоб запустити тести CUnit треба додати тести в спеціальну колекцію тестів(набір), який розміщений в реєстрі тестів.
typedef struct CU_Suite
typedef CU_Suite* CU_pSuite
typedef struct CU_Test
typedef CU_Test* CU_pTest
typedef void (*CU_TestFunc)(void)
typedef int (*CU_InitializeFunc)(void)
typedef int (*CU_CleanupFunc)(void)
CU_pSuite CU_add_suite(const char* strName,
CU_InitializeFunc pInit,
CU_CleanupFunc pClean);
CU_pTest CU_add_test(CU_pSuite pSuite,
const char* strName,
CU_TestFunc pTestFunc);
typedef struct CU_TestInfo
typedef struct CU_SuiteInfo
CU_ErrorCode CU_register_suites(CU_SuiteInfo suite_info[]);
CU_ErrorCode CU_register_nsuites(int suite_count, ...);
Щоб додати нібір тестів в реєстр необхідно використовувати функцію:
CU_pSuite CU_add_suite(const char* strName, CU_InitializeFunc pInit, CU_CleanupFunc pClean)
Вона створює нову колекцію(набір) тестів з певним ім’ям, функцією ініціалізації і функцією завершення. Новий набір тестів знаходиться в реєстрі тестів, тому він повинен бути ініціалізований перед додаванням тестів. Дана реалізація CUnit не підтримує створення наборів тестів без реєстру тестів.
Ім’я набору повинно бути унікальне для всі наборів реєстру. Функції ініціалізації і завершення є необов’язковими і передаються у вигляді вказівників на функції, які будуть виконані до і після тестів в наборі тестів. Вони не приймають параметрів і не повертають значення 0 при успішному завершенні (при неуспішному завершенні – інше значення). Якщо цих функції не потрібно в наборі, то функції додавання набору CU_add_suite() треба передати аргументи NULL на їх місці.
Функція повертає вказівник на новий набір тестів, який потрібен функції додавання тестів. При помилці повертається NULL і код помилки фреймворку приймає одне з наступних значень.
Таблиця 5. Коди помилок встановлені функцією CU_add_suite()
CUE_SUCCESS
створення набору тестів успішне
CUE_NOREGISTRY
реєстр не був ініціалізований
CUE_NO_SUITENAME
немає імені набору
CUE_DUP_SUITE
ім’я не унікальне
CUE_NOMEMORY
помилка виділення пам’яті
Щоб додати тест в набір тестів існує функція
CU_pTest CU_add_test(CU_pSuite pSuite, const char* strName, CU_TestFunc pTestFunc)
Вона створює новий тест який має ім’я і тестову функцію, яку реєструє в певному наборі тестів. Набір тестів повинен бути створеним функцією CU_add_suite(). Ім’я тесту повинно бути унікальне в наборі тестів. Вказівник на тестову функцію повинен бути ненульовий і вказувати на функцію яка викличеться при виконанні тесту. Тестові функції не мають параметрів і не повертають значень.
Функція повертає вказівник на новий тест.При помилці повертається NULL і код помилки фреймворку приймає одне з наступних значень.
Таблиця 6. Коди помилок встановлені функцією CU_add_test()
CUE_SUCCESS
створення тесту успішне
CUE_NOSUITE
Набір тестів не існує
CUE_NO_TESTNAME
ім’я тесту не задано
CUE_NO_TEST
Тестова функція не існує чи неправильна
CUE_DUP_TEST
ім’я тесту не унікальне
CUE_NOMEMORY
помилка виділення пам’яті
#define CU_ADD_TEST(suite, test) (CU_add_test(suite, #test, (CU_TestFunc)test))
Цей макрос автоматично створює унікальне імя, яке базується на імені тестової функції і додає її в певний набір тестів. Результат роботи повинен бути перевірений користувачем, щоб запобігти помилкам
CU_ErrorCode CU_register_suites(CU_SuiteInfo suite_info[])CU_ErrorCode CU_register_nsuites(int suite_count, ...)
Для великих тестових структур з багатьма тестами і наборами тестів, управління тестами/наборами тестів і їх реєстрацією є стомлююче і в процесі можна допустити помилки. CUnit забезпечує спеціальну систему реєстрації для допомоги в управлінні тестами і наборами тестів. Вся суть цієї системи забезпечити централізацію реєстрації тестів і наборів тестів А також зменшити об’єм коду перевірки на помилки, який має писати користувач.
Тести згруповані в масиви змінних структури CU_TestInfo
CU_TestInfo test_array1[] = {
{ "testname1", test_func1 },
{ "testname2", test_func2 },
{ "testname3", test_func3 },
CU_TEST_INFO_NULL,
};
Кожен елемент масиву включає ім’я (унікальне) і тестову функцію для одного тесту. Масив має закінчуватись елементом з NULL значеннями, який оголошений макросом CU_TEST_INFO_NULL. Тести включені в єдиний масив CU_TestInfo формують єдину множину тестів, які будуть зареєстровані в одному наборів тестів.
Інформація про набори тестів знаходиться в одному чи більше масивах елементів CU_SuiteInfo
CU_SuiteInfo suites[] = {
{ "suitename1", suite1_init-func, suite1_cleanup_func, test_array1 },
{ "suitename2", suite2_init-func, suite2_cleanup_func, test_array2 },
CU_SUITE_INFO_NULL,
};
Кожен з цих елементів масиву включає (унікальне) ім’я, функцію ініціалізаці набору тестів і функцію завершення набору тестів а також масив CU_TestInfo для кожного конкретного набору тестів. Якщо функцій ініціалізації чи завершення не потрібно, тоді вказується NULL. Масив повинен закінчуватися елементом з NULL значеннями, який оголошений макросом CU_SUITE_INFO_NULL.
Всі набори тестів оголошені в CU_SuiteInfo масиві можна зареєструвати єдиним рядком.
CU_ErrorCode error = CU_register_suites(suites);
При виникненні помилки при реєстрації набору тестів чи тесту повертається код помилки. Код помилки такий самий, яки при виконання функцій CU_add_test() і CU_add_suit().
Функція CU_register_nsuites() призначена для ситуацій коли користувач хоче зареєструвати багато CU_SuiteInfo масивів одним рядком коду
CU_ErrorCode error = CU_register_nsuites(2, suites1, suites2);
Функція приймає кількість масивів для реєстрації і самі масиви. Перший параметр – це кількість масивів.
Таблиця 7. Старі версії функцій
Старі імена
Нові імена
TestFunc
CU_TestFunc
InitializeFunc
CU_InitializeFunc
CleanupFunc
CU_CleanupFunc
_TestCase
CU_Test
PTestCase
CU_pTest
_TestGroup
CU_Suite
PTestGroup
CU_pSuite
add_test_group()
CU_add_suite()
add_test_case()
CU_add_test()
ADD_TEST_TO_GROUP()
CU_ADD_TEST()
test_case_t
CU_TestInfo
test_group_t
CU_SuiteInfo
test_suite_t
no equivalent - use CU_SuiteInfo
TEST_CASE_NULL
CU_TEST_INFO_NULL
TEST_GROUP_NULL
CU_SUITE_INFO_NULL
test_group_register
CU_register_suites()
test_suite_register
no equivalent - use CU_register_suites()
Виконання тестів
Cunit забезпечує виконання всіх тестів в усіх зареєстрованих наборах тестів, але також можна виконувати і окремі тести. Протягом кожного запуску фреймворк зберігає стан кожного набору тестів, запущені тести, пройдені тести і не пройдені тести. Треба мати на увазі, що результати очищуються кожного разу, коли тести запускаються(навіть непройдені).
Тоді як Cunit забезпечує виконання примітивних функцій для запуску тестів і наборів тестів, користувач хоче використовувати один з мпрощених інтерфейсів користувача. Вони скривають деталі взаємодії з фреймворком і забезпечують вивід деталей виконання тестів і результати для користувача. В CUnit є наступні інтерфейси
Таблиця 8. Список інтерфейсів користувача
Інтерфейс
Платформа
Опис
Automated
all
Не інтерактивний з виводом xml файлів
Basic
all
Не інтерактивний з виводом в stdout
Console
all
Інтерактивний консольний режим під контролем користувача
Curses
Linux/Unix
Інтерактивний режим з контролем користувача
Якщо цих інтерфейсів недостатньо, користувачі можуть також використовувати примітивні API фреймворку. Для взаємодії з фреймворком потрібно читати його документацію.
Атоматичні інтерфейси не інтерактивні. Клієнт запускає тести і результати виводяться в xml файл. Лістин зареєстрованих тестів і наборів тестів також можна знайти в xml файлі.
Наступна функція включає автоматичний інтерфейс АРІ:
void CU_automated_run_tests(void)
Виконує всі тести в усіх заєрестрованих наборах тестів. Результат тестів виводиться в файл ROOT-Results.xml. Ім’я ROOT може бути задано функцією CU_set_output_filename(). Якщо ім’я файлу не задано перед кожним запуском результат файлу буде перезаписано.
CU_ErrorCode CU_list_tests_to_file(void)
Записує список зареєстрованих наборів тестів і тестів в файл. Файл називається ROOT-Listing.xml. Файл з лістингом не генерується при виконання тестів. Клієнський код повинен явно вказати це функцією CU_automated_run_tests(). Ім’я ROOT може бути задано функцією CU_set_output_filename(). Якщо ім’я файлу не задано перед кожним запуском результат файлу буде перезаписано.
void CU_set_output_filename(const char* szFilenameRoot)
Встановлює імена файлів для виводу результатів тестування і лістингу. szFilenameRoot використовується для для побудови імен додаючи до них Results.xml і -Listing.xml, відповідно.
Базовий інтерфейс також не інтерактивний. Результати зписуються в stdout. Інтерфейс забезпечує виконання окремих наборів тестів і тестів і дозволяє клієнтському коду контролювати тип виводу на кожному виконанні тесту. Він забезпечує значну гнучкість для клієнтів, які хочуть простий доступ до Cunit API.
Він забезпечується наступними функціями:
CU_ErrorCode CU_basic_run_tests(void)
Виконує тести в усіх зареєстрованих наборах тестів. Повертає код першої помилки яка виникає при виконанні тесту. Тип виводу контролюється типом виконання, який встановлюється функцією CU_basic_set_mode().
CU_ErrorCode CU_basic_run_suite(CU_pSuite pSuite)
Виконує всі тести з певного набору тестів. Повертає код першої помилки яка виникає при виконанні тесту. Тип виводу контролюється типом виконання, який встановлюється функцією CU_basic_set_mode().
CU_ErrorCode CU_basic_run_test(CU_pSuite pSuite, CU_pTest pTest)
Виконує певний тест з певного набору тестів. Повертає код першої помилки яка виникає при виконанні тесту. Тип виводу контролюється типом виконання, який встановлюється функцією CU_basic_set_mode().
void CU_basic_set_mode(CU_BasicRunMode mode)
Встановлює базовий режим виконання, який контролює вивід протягом виконання тестів
CU_BRM_NORMAL
Невдалі тести і результати
CU_BRM_SILENT
Не виводиться нічог окрім помилок виконання
CU_BRM_VERBOSE
Виводиться все
CU_BasicRunMode CU_basic_get_mode(void)
Отримати поточний режим виводу.
void CU_basic_show_failures(CU_pFailureRecord pFailure)
Виводить результати провалених тестів в stdout. Не залежить від режиму виконання.
Консольний режим є інтерактивний. Все що потрібно зробити користувачу – це ініціалізувати сесію консолі, і користувач може інтерактивно керувати виконанням тестів. А сасе він керує зареєстрованими наборами тестів і тестами і отримує результати тестів. Щоб запусти консольний режим треба виконати функцію
void CU_console_run_tests(void)
Інтерактивний режим для Linux. Користувачу слід запустити сесію і контролювати тестування інтерактивно. Можна вибирати і виконувати тести і набори тестів і переглядати їх результати тестів. Використання цього інтерфейсу потребує зв’язування бібліотеки з програмою. Щоб запустити сесію слід використати:
void CU_curses_run_tests(void)
Інтерфейси представляють результати виконання тестів, але клієнтський код має безпосередньо доступитися до результату. Він включає різні результати виконання включаючи провалені тести з результатами виконанн. Результати перезаписуються кожен раз при виконанні тестів чи при ініціалізації завершенні роботи реєстру.
Функції доступу до результатів тестів:
unsigned int CU_get_number_of_suites_run(void)unsigned int CU_get_number_of_suites_failed(void)unsigned int CU_get_number_of_tests_run(void)unsigned int CU_get_number_of_tests_failed(void)unsigned int CU_get_number_of_asserts(void)unsigned int CU_get_number_of_successes(void)unsigned int CU_get_number_of_failures(void)
Ці функції забезпечують вивід кількості наборів тестів, тестів і перевірок, які були виконані чи провалились при виконанні. Набір тестів вважається не пройденим, якшо функція ініціалізації чи завершення повертає не нульове значення. Тест непрройдени, якщо хоч одна перевірка не пройдена. Останні 3 функції всі пов’язані з власними перевірками.
Щоб визначити загальне число зареєстрованих наборів тестів слід використовувати CU_get_registry()−>uiNumberOfSuites і CU_get_registry()−>uiNumberOfTests.
const CU_pRunSummary CU_get_run_summary(void)
Визначає всі результати тестів. Результат виконання вказівник на структуру яка включає ці результати
typedef struct CU_RunSummary
{
unsigned int nSuitesRun;
unsigned int nSuitesFailed;
unsigned int nTestsRun;
unsigned int nTestsFailed;
unsigned int nAsserts;
unsigned int nAssertsFailed;
unsigned int nFailureRecords;
} CU_RunSummary;
typedef CU_Runsummary* CU_pRunSummary;
Змінна цієї структури належить фреймворку, тому користувач не повинен завершувати його виконання чи іншим чином змінювати його. Вказівник може стати недійсним коли запущено інший набір тестів.
const CU_pFailureRecord CU_get_failure_list(void)
Функція повертає зв’язний список з записаними помилками, які виникли при виконанні (NULL якщо не було помилок). Кожен запис помилки включає інформацію про положення і природу помилки
typedef struct CU_FailureRecord
{
unsigned int uiLineNumber;
char* strFileName;
char* strCondition;
CU_pTest pTest;
CU_pSuite pSuite;
struct CU_FailureRecord* pNext;
struct CU_FailureRecord* pPrev;
} CU_FailureRecord;
typedef CU_FailureRecord* CU_pFailureRecord;
Змінна цієї структури належить фреймворку, тому користувач не повинен завершувати його виконання чи іншим чином змінювати його. Вказівник може стати недійсним коли запущено інший набір тестів.
unsigned int CU_get_number_of_failure_records(void)
Повертає кількість CU_FailureRecords в зв’язному списку помилок отриманих функцією CU_get_failure_list().
Таблиця 9. Список старих імен функцій
Старі імена
Нові імена
automated_run_tests()
CU_automated_run_tests() plusCU_list_tests_to_file()
set_output_filename()
CU_set_output_filename()
console_run_tests()
CU_console_run_tests()
curses_run_tests()
CU_curses_run_tests()
Обробка помилок
Більшість функцій CUnit встановлюють код помилки який означає статус помилки фреймворку. Деякі повертають код помилки, а деякі встановлюють код в змінній фреймворку і повертають інше значення. Функції дл перевірки статусу фреймворку:
CU_ErrorCode CU_get_error(void)const char* CU_get_error_msg(void)
Перша функція повертає код помилки, в той час як інша повертає повідомлення,яке описує помилку. Код помилки це тип перелічення CU_ErrorCode. Існують наступні значення цього перелічення:
Таблиця 10. Список кодів помилок
Значення коду помилки
Опис коду помилки
CUE_SUCCESS
Немає помилки
CUE_NOMEMORY
Невдалося виділити пам’ять
CUE_NOREGISTRY
Реєст не ініціалізовано
CUE_REGISTRY_EXISTS
Спроба встановити новий реєстр тестів не завершивши старий
CUE_NOSUITE
Набору тестів не існує (вказівник рівний NULL)
CUE_NO_SUITENAME
Немає імені для набору тестів
CUE_SINIT_FAILED
Ініціалізація набору тестів не вдалась
CUE_SCLEAN_FAILED
Завершення набору тестів не вдалося
CUE_DUP_SUITE
Ім’я набору тестів вже існує
CUE_NOTEST
Тесту не існує (вказівник рівний NULL)
CUE_NO_TESTNAME
Немає імені для тесту
CUE_DUP_TEST
Ім’я тесту вже існує
CUE_TEST_NOT_IN_SUITE
Тест не зареєстровано в наборі тестів
CUE_FOPEN_FAILED
Помилка відкриття файлу
CUE_FCLOSE_FAILED
Помилка закриття файлу
CUE_BAD_FILENAME
Неправмльне ім’я файлу (NULL, породній, не існує, і т. д.)
CUE_WRITE_ERROR
Помилка запису в файл
Поведінка фреймворку по замовчуванню при виникненні помилок така: встановлюється код помилки і виконання продовжується. Але користувачі бажають, щоб виконання тесту припинялося при помилці, або навіть завершувалась тестова програма. Ця поведінка може бути задана користувачем за допомогою функцій
void CU_set_error_action(CU_ErrorAction action)CU_ErrorAction CU_get_error_action(void)
CU_ErrorAction – це перелічення з кодами поведінки при помилках
Таблиця 11. Список кодів поведінки при помилках
Імя
Опис
CUEA_IGNORE
Виконання продовжується при помилці
CUEA_FAIL
Виконання тесту зупиняється при помилці
CUEA_ABORT
При помилці зупиняється виконання цілої програми
Таблиця 12. Список кодів поведінки при помилках старіша версія
Старі імена
Нові імена
get_error()
CU_get_error_msg()
error_code
Немає вже. Використовувати CU_get_error()