CUnit-基于C语言单元测试框架

本文是对《CUnit Programmer Guide》进行翻译以及加入了一些自己的理解。
原文链接:CUnit Programmer Guide

1.简介

1.1 概述

CUnit是一个用于编写,管理和运行C语言单元测试的系统。

CUnit使用一个简单的框架来构建测试结构,并提供了一组丰富的断言来测试常见的数据类型。此外,还提供了几种不同的界面来运行测试和报告结果。这些功能包括用于代码控制的测试和报告的自动界面,以及允许用户动态运行测试和查看结果的交互式界面。

在以下头文件中声明了对典型用户有用的数据类型和函数:

#include <CUnit/CUnit.h>		ASSERT宏,用于测试用例,并包括其他框架头
#include <CUnit/CUError.h>		错误处理功能和数据类型,由CUnit.h自动包含
#include <CUnit/TestDB.h>		测试注册表,套件和测试的数据类型定义和操作功能,由CUnit.h自动包含
#include <CUnit/TestRun.h>		用于运行测试和检索结果的数据类型定义和函数,由CUnit.h自动包含
#include <CUnit/Automated.h>    具有xml输出的自动接口
#include <CUnit/Basic.h>		基本接口,具有向stdout的非交互式输出
#include <CUnit/Console.h>		交互式控制台界面
#include <CUnit/CUCurses.h>		交互式控制台界面(* nix)
#include <CUnit/Win.h>	        Windows界面(尚未实现)
1.2 结构

CUnit还是独立于平台框架与各种用户界面的组合。核心框架为管理测试注册表,套件和测试提供了基本支持。用户界面促进了与框架的交互,以运行测试和查看结果。

CUnit的组织方式类似于常规的单元测试框架:

                  Test Registry
                        |
         ------------------------------
         |                            |
      Suite '1'      . . . .       Suite 'N'
         |                            |
   ---------------             ---------------
   |             |             |             |
Test '11' ... Test '1M'     Test 'N1' ... Test 'NM'

各个测试注册到套件(Suite)中,并在活动的测试注册表中注册。套件可以具有设置(setup)和拆卸(teardown)功能,可以在运行套件的测试之前和结束之后自动调用它们。注册表中的所有套件/测试都可以使用单个函数调用来运行,或者也可以运行选定的套件或测试。

1.3 基本用法

使用CUnit框架的典型步骤序列为:

  1. 编写测试功能方法(并在必要时进行套件(Suite)初始化/清除)
  2. 初始化测试注册表:CU_initialize_registry()
  3. 将套件添加到测试注册表:CU_add_suite(),可以调用多次添加多个测试套件
  4. 将测试添加到套件:CU_add_test(),每个测试套件都可以调用多次添加多个测试
  5. 使用适当的界面运行测试,例如:CU_console_run_tests或者CU_automated_run_tests
  6. 清理测试注册表:CU_cleanup_registry

2.编写测试用例

2.1 测试功能

CUnit对测试功能的内容没有任何限制,只是它不应修改CUnit的框架(例如,添加套件或测试,修改测试注册表或启动测试运行)。测试功能可以调用其他功能函数(也不能修改CUnit的框架)。
下面是返回两个int型数值中最大值的函数测试用例:

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);
}
2.2 断言

CUnit提供了一组用于测试逻辑条件的断言。这些断言的成功或失败由框架跟踪,并且可以在测试运行完成时查看。
每个断言都会测试一个逻辑条件,如果条件的计算结果为FALSE,则会失败。失败时,除非用户选择xxx_FATAL版本的断言,否则测试程序不会停止。
如果选择使用xxx_FATAL断言,测试程序将立即中止并返回。xxx_FATAL版本的断言应谨慎使用! 因为一旦xxx_FATAL断言失败,测试函数最后便不会执行套件的清除函数(cleanup/teardown)。

还有一些特殊的“断言”,用于在不执行逻辑测试的情况下向框架标注为通过或失败。这些对于测试控制流或其他不需要逻辑测试的条件还是非常有用的,如下:

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的断言,这些断言也会记录在这个测试函数的report中,当然也可以用FATAL版本的断言,但是如果FATAL断言失败,这将会abort这个测试函数和他的整个调用链。

CUnit定义的断言是:
#include <CUnit/CUnit.h>

assertcomments
CU_ASSERT(int expression)
CU_ASSERT_FATAL(int expression)
CU_TEST(int expression)
CU_TEST_FATAL(int expression)
Assert that expression is TRUE (non-zero)
CU_ASSERT_TRUE(value)
CU_ASSERT_TRUE_FATAL(value)
Assert that value is TRUE (non-zero)
CU_ASSERT_FALSE(value)
CU_ASSERT_FALSE_FATAL(value)
Assert that value is FALSE (zero)
CU_ASSERT_EQUAL(actual, expected)
CU_ASSERT_EQUAL_FATAL(actual, expected)
Assert that actual = = expected
CU_ASSERT_NOT_EQUAL(actual, expected))
CU_ASSERT_NOT_EQUAL_FATAL(actual, expected)
Assert that actual != expected
CU_ASSERT_PTR_EQUAL(actual, expected)
CU_ASSERT_PTR_EQUAL_FATAL(actual, expected)
Assert that pointers actual = = expected
CU_ASSERT_PTR_NOT_EQUAL(actual, expected)
CU_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected)
Assert that pointers actual != expected
CU_ASSERT_PTR_NULL(value)
CU_ASSERT_PTR_NULL_FATAL(value)
Assert that pointer value == NULL
CU_ASSERT_PTR_NOT_NULL(value)
CU_ASSERT_PTR_NOT_NULL_FATAL(value)
Assert that pointer value != NULL
CU_ASSERT_STRING_EQUAL(actual, expected)
CU_ASSERT_STRING_EQUAL_FATAL(actual, expected)
Assert that strings actual and expected are equivalent
CU_ASSERT_STRING_NOT_EQUAL(actual, expected)
CU_ASSERT_STRING_NOT_EQUAL_FATAL(actual, expected)
Assert that strings actual and expected differ
CU_ASSERT_NSTRING_EQUAL(actual, expected, count)
CU_ASSERT_NSTRING_EQUAL_FATAL(actual, expected, count)
Assert that 1st count chars of actual and expected are the same
CU_ASSERT_NSTRING_NOT_EQUAL(actual, expected, count)
CU_ASSERT_NSTRING_NOT_EQUAL_FATAL(actual, expected, count)
Assert that 1st count chars of actual and expected differ
CU_ASSERT_DOUBLE_EQUAL(actual, expected, granularity)
CU_ASSERT_DOUBLE_EQUAL_FATAL(actual, expected, granularity)
Assert that ‘actual - expected’ <= 'granularity’
Math library must be linked in for this assertion.
CU_ASSERT_DOUBLE_NOT_EQUAL(actual, expected, granularity)
CU_ASSERT_DOUBLE_NOT_EQUAL_FATAL(actual, expected, granularity)
Assert that ‘actual - expected’ > 'granularity’
Math library must be linked in for this assertion.
CU_PASS(message)Register a passing assertion with the specified message. No logical test is performed.
CU_FAIL(message)
CU_FAIL_FATAL(message)
Register a failed assertion with the specified message. No logical test is performed.

3.测试注册表

3.1 概要

CUnit的注册表主要是用于管理测试套件和测试用例的一个功能集合。主要有一个结构体和若干个函数:

#include <CUnit/TestDB.h> (included automatically by <CUnit/CUnit.h>)

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)
3.2 内部结构

测试注册表是套件和套件相关测试用例的存储库。CUnit维护一个活动的测试注册表,该注册表在用户添加套件或测试时更新。当用户选择运行所有测试时,将在此活动注册表中运行套件。
CUnit测试注册表是 在<CUnit/TestDB.h>中声明的数据结构CU_TestRegistry。它包括存储在注册表中的套件和测试总数的字段,以及指向已经注册的套件链表头部的指针。

typedef struct CU_TestRegistry
{
    unsigned int uiNumberOfSuites;
    unsigned int uiNumberOfTests;
    CU_pSuite    pSuite;
}CU_TestRegistry;

typedef CU_TestRegistry* CU_pTestRegistry;

用户通常需要在使用前初始化注册表,和使用后销毁注册表。同时也提供了其他功能来操纵注册表。

3.3 初始化注册表
CU_ErrorCode CU_initialize_registry(void)
  • 一个活动的CUnit测试注册表必须在使用之前进行初始化。用户应在调用任何其他CUnit函数之前先调用CU_initialize_registry(),否则可能会导致崩溃。
  • 返回错误状态代码:
      CUE_SUCCESS     初始化成功。
      CUE_NOMEMORY    初始化时内存申请失败。
    
3.4 销毁注册表
void CU_cleanup_registry(void)
  • 测试完成后,用户应调用此函数以销毁注册表和释放框架申请的内存。这应该是最后一个调用的CUnit函数(使用CU_initialize_registry()或 CU_set_registry()恢复测试注册表除外)。

  • 函数CU_cleanup_registry()未调用或者执行失败都会导致内存泄漏。该函数是可以多次调用的,用户应多次调用以确保执行成功。需要注意的是,此功能将销毁注册表中的所有套件(及其相关的测试)。销毁注册表后,指向这些注册套件和测试的指针不应该继续使用。

  • 调用CU_cleanup_registry()仅会影响内部由CUnit框架维护的CU_TestRegistry。销毁用户拥有的任何其他测试注册表是用户的责任。可以通过调用CU_destroy_existing_registry()显式完成此操作,也可以通过调用CU_set_registry()使注册表处于活动状态,然后再调用CU_cleanup_registry()将该注册表销毁。

3.5 其他注册表功能

其他注册表功能主要用于内部和测试目的。但是,对于一般用户这些功能可能会对他们有用,所以也应该了解熟悉它们。

CU_pTestRegistry CU_get_registry(void)
  • 返回指向活动测试注册表的指针。注册表是数据类型CU_TestRegistry的指针变量。不建议直接操作内部测试注册表,应该使用API​​函数。该框架维护注册表的所有权,因此返回的指针在调用CU_cleanup_registry()或CU_initialize_registry()之后将变得无效。
CU_pTestRegistry CU_set_registry(CU_pTestRegistry pTestRegistry)
  • 用指定的注册表替换当前活动注册表。返回指向先前活动注册表的指针。调用者负责销毁旧注册表,通过为返回的指针调用CU_destroy_existing_registry()可以直接销毁旧注册表。或者可以使用CU_set_registry()使注册表处于活动状态,然后调用CU_cleanup_registry()时隐式销毁注册表 。注意不要显式销毁(CU_destroy_existing_registry())设置为活动注册表。这可能导致同一内存多次释放,并可能导致崩溃。
CU_pTestRegistry CU_create_new_registry(void)
  • 创建一个新的注册表并返回一个指向它的指针。新的注册表将不包含任何套件或测试。调用者负责通过上述机制之一销毁新的注册表。
void CU_destroy_existing_registry(CU_pTestRegistry* ppRegistry)
  • 销毁并释放指定测试注册表的所有内存,包括所有已注册的套件和测试。对于设置为活动的测试注册表(例如,使用CU_get_registry()检索到的CU_pTestRegistry指针),不应调用此函数。当调用CU_cleanup_registry()时,这将导致多个空闲空间释放相同的内存。如果调用此函数传入NULL将无效。

4.套件和测试的管理

为了使CUnit运行测试,必须将其添加到已在注册表中的套件(Suite)中。

4.1 概要
#include <CUnit/TestDB.h> (included automatically by <CUnit/CUnit.h>)

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, ...);
4.2 添加套件到注册表
CU_pSuite CU_add_suite(const char* strName, CU_InitializeFunc pInit, CU_CleanupFunc pClean)
  • 创建一个具有指定名称,初始化函数和清除函数的新测试集合(Suite)。新套件将被添加到测试注册表中(并由其拥有),因此必须在添加任何套件之前初始化注册表。当前的实现不支持独立于测试注册表的套件的创建。

  • 套件的名称在注册表所有套件中必须是唯一的。初始化和清除函数是可选的,需要传递的是初始化和清除函数的函数指针,在运行套件中包含的测试之前和之后调用它们。这允许套件设置和拆除临时固定装置以支持运行测试。这些函数不带参数,如果成功完成,则应返回零(否则为非零)。如果套件不需要这两个功能之一或全部,可以传递NULL给CU_add_suite()。

  • 返回指向新套件的指针,向套件中添加测试时必需要用该指针。如果发生错误,则返回NULL,并将框架ERROR_CODE(CUError.h)设置为以下之一:

      CUE_SUCCESS         套件创建成功。
      CUE_NOREGISTRY      注册表尚未初始化。
      CUE_NO_SUITENAME    strName是NULL。
      CUE_DUP_SUITE       套件的名字不是唯一的。
      CUE_NOMEMORY        内存申请失败。
    
4.3 添加测试到套件
CU_pTest CU_add_test(CU_pSuite pSuite, const char* strName, CU_TestFunc pTestFunc)
  • 创建具有指定名称和测试功能的新测试,并将其注册到指定套件中。该套件必须已经使用CU_add_suite()创建。当前实现不支持独立于注册套件的测试的创建。

  • 在添加到单个套件的所有测试中,测试的名称必须唯一。测试函数不能为NULL,它是指向运行测试时要调用的函数。测试函数既没有参数也没有返回值。

  • 返回指向新测试的指针。如果在创建测试期间发生错误,则返回NULL,并将框架ERROR_CODE(CUError.h)设置为以下之一:

      CUE_SUCCESS         套件创建成功。
      CUE_NOSUITE         指定的套件是NULL或无效的。
      CUE_NO_TESTNAME     strName是NULL。
      CUE_NO_TEST         pTestFunc是NULL或无效的。
      CUE_DUP_TEST        测试的名称不是唯一的。
      CUE_NOMEMORY        内存申请失败。
    
4.4 快捷方法添加套件和测试
#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提供了一种特殊的注册系统来帮助管理套件和测试。它的主要好处是集中套件和相关测试的注册,并最大程度地减少用户需要编写的错误检查代码的数量。

  • 首先将同一个Suite组的测试用例定义在CU_TestInfo实例数组中(在<CUnit/TestDB.h>中定义):

     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实例数组中定义套件信息(在<CUnit/TestDB.h>中定义):

     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_register_nsuites()用于用户希望在单个语句中注册多个CU_SuiteInfo数组的情况:

      CU_ErrorCode error = CU_register_nsuites(2,suites1,suites2);
    
  • 该函数接受可变数量的CU_SuiteInfo数组。第一个参数指示要传递的实际数组个数。

5. 执行测试

5.1 概要

#include <CUnit/Automated.h>

  void         CU_automated_run_tests(void)
  CU_ErrorCode CU_list_tests_to_file(void)
  void         CU_set_output_filename(const char* szFilenameRoot)

#include <CUnit/Basic.h>

  typedef enum    CU_BasicRunMode
  CU_ErrorCode    CU_basic_run_tests(void)
  CU_ErrorCode    CU_basic_run_suite(CU_pSuite pSuite)
  CU_ErrorCode    CU_basic_run_test(CU_pSuite pSuite, CU_pTest pTest)
  void            CU_basic_set_mode(CU_BasicRunMode mode)
  CU_BasicRunMode CU_basic_get_mode(void)
  void            CU_basic_show_failures(CU_pFailureRecord pFailure)

#include <CUnit/Console.h>

  void CU_console_run_tests(void)

#include <CUnit/CUCurses.h>

  void CU_curses_run_tests(void)

#include <CUnit/TestRun.h> (included automatically by <CUnit/CUnit.h>)

  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)

  typedef struct CU_RunSummary
  typedef CU_Runsummary* CU_pRunSummary
  const CU_pRunSummary CU_get_run_summary(void)

  typedef struct CU_FailureRecord
  typedef CU_FailureRecord*  CU_pFailureRecord
  const CU_pFailureRecord CU_get_failure_list(void)
  unsigned int CU_get_number_of_failure_records(void)
5.2 执行测试

CUnit支持在所有注册的套件中运行所有测试,但是也可以运行单个测试或套件。在每次运行期间,框架都会跟踪运行,通过和失败的套件,测试和断言的数量。请注意,每次启动测试运行时都会清除结果(即使失败)。
尽管CUnit为运行套件和测试提供了原始功能,但大多数用户将希望使用简化的用户界面之一。这些界面处理与框架交互的详细信息,并为用户提供测试详细信息和结果的输出。

CUnit库中包含以下测试模式:

测试模式平台描述
Automatedall非交互模式,测试报告输出到XML文件
Basicall非交互模式,测试报告输出stdout
Consoleall控制台下的交互模式
CursesLinux/Unixcurses的交互模式

如果这些界面还不满足,则客户端也可以使用在<CUnit/TestRun.h>中定义的原始框架API。有关如何直接与原始API进行交互的示例,请参见各种接口的源代码。

5.3 Automated Mode

自动界面是非交互式的。客户端启动测试运行,并将结果输出到XML文件。还可以将已注册测试和套件的列表也输出在XML中。
以下函数就是启动自动测试的接口:

void CU_automated_run_tests(void)
  • 运行所有已注册套件中的所有测试。测试结果将输出到名为ROOT-Results.xml的文件中。可以使用CU_set_output_filename()设置文件名ROOT,或者使用默认的CUnitAutomated-Results.xml。请注意,如果在每次运行之前未设置一个新的文件名ROOT,则之前相同文件名的结果文件将被覆盖。测试报告文档的文件类型还可以设置为(CUnit-Run.dtd)和XSL样式表(CUnit-Run.xsl)。这些在源树和安装树的“共享”子目录中提供。
CU_ErrorCode CU_list_tests_to_file(void)
  • 列出已注册的套件和相关测试到测试清单文件中。文件名为ROOT-Listing.xml。 可以使用CU_set_output_filename()设置文件名ROOT,否则将使用默认的CUnitAutomated。请注意,如果 在每次运行之前未设置文件名ROOT,则之前同名的清单文件将被覆盖。清单文件的文件类型还可以定义为(CUnit-List.dtd)和XSL样式表(CUnit-List.xsl)。这些在源树和安装树的“共享”子目录中提供。 另请注意,在执行CU_automated_run_tests()时清单文件自动生成。客户代码中必须显示调用该函数生成。
void CU_set_output_filename(const char* szFilenameRoot)
  • 设置结果和列表文件的输出文件名。 szFilenameRoot分别用于附加构造的文件名-Results.xml和-Listing.xml。
5.4 Basic Mode
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。不取决于运行模式。
5.5 Interactive Console Mode

控制台界面是交互式的。客户端所需要做的就是启动控制台会话,并且用户以交互方式控制测试的运行。这包括选择和运行已注册的套件和测试,以及查看测试结果。要启动控制台会话,请使用

void CU_console_run_tests(void)
5.6 Interactive Curses Mode

curses界面是交互式的。客户端所需要做的就是启动curses会话,并且用户以交互方式控制测试运行。这包括选择和运行已注册的套件和测试,以及查看测试结果。使用此接口需要将ncurses库链接到应用程序。要启动curses会话,请使用

void CU_curses_run_tests(void)
5.7 Getting Test Results

这些接口提供了测试运行的结果,但是有时客户端代码可能需要直接访问测试结果。这些结果包括各种运行计数,以及包含故障详细信息的故障记录链表。请注意,每次启动新的测试运行时,或者初始化或清理注册表时,测试结果都会被覆盖。
获取测试结果信息的函数是:

  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)
  • 这些函数报告在上次运行期间运行或失败的套件,测试和断言的数量。如果套件的初始化或清除函数返回非零,则该套件被视为失败。如果测试的任何断言失败,则测试也认为是失败的。后三个函数均与单个断言相关。

  • 要获取已注册套件和测试的总数,请分别使用CU_get_registry()->uiNumberOfSuites和CU_get_registry()-> uiNumberOfTests。

const CU_pRunSummary CU_get_run_summary(void)
  • 一次获取所有测试结果总数。返回值是指向已保存的测试结果的结构体指针。此数据类型在<CUnit/TestRun.h>中定义(由<CUnit/CUnit.h>自动包含):
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表示没有任何错误)。返回值的数据类型在<CUnit/TestRun.h>中声明(由<CUnit/CUnit.h>自动包含)。每个故障记录都包含有故障的位置和性质的信息:
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_get_failure_list()返回的失败链表中CU_FailureRecords的数量。请注意,由于包含套件初始化和清除失败,因此这可能比失败的断言数量还要多。

6. 错误处理

6.1 概要
#include <CUnit/CUError.h> (included automatically by <CUnit/CUnit.h>)
typedef enum   CU_ErrorCode
CU_ErrorCode   CU_get_error(void);
const char*    CU_get_error_msg(void);

typedef enum   CU_ErrorAction
void           CU_set_error_action(CU_ErrorAction action);
CU_ErrorAction CU_get_error_action(void);
6.2 CUnit错误处理

大多数CUnit函数都设置一个错误代码,指示框架错误状态。一些函数返回代码,而另一些函数只是设置代码并返回其他值。提供了一下两个函数来检查框架错误状态:

CU_ErrorCode CU_get_error(void)
const char* CU_get_error_msg(void)

第一个返回错误代码本身,而第二个返回描述错误状态的消息。错误代码是<CUnit/CUError.h>中定义的CU_ErrorCodeenum枚举类型。定义了以下错误代码值:

Error ValueDescription
CUE_SUCCENo error condition.
CUE_NOMEMORYMemory allocation failed.
CUE_NOREGISTRYTest registry not initialized.
CUE_REGISTRY_EXISTSAttempt to CU_set_registry() without CU_cleanup_registry().
CUE_NOSUITEA required CU_pSuite pointer was NULL.
CUE_NO_SUITENAMERequired CU_Suite name not provided.
CUE_SINIT_FAILEDSuite initialization failed.
CUE_SCLEAN_FAILEDSuite cleanup failed.
CUE_DUP_SUITEDuplicate suite name not allowed.
CUE_NOTESTA required CU_pTest pointer was NULL.
CUE_NO_TESTNAMERequired CU_Test name not provided.
CUE_DUP_TESTDuplicate test case name not allowed.
CUE_TEST_NOT_IN_SUITETest is not registered in the specified suite.
CUE_FOPEN_FAILEDAn error occurred opening a file.
CUE_FCLOSE_FAILEDAn error occurred closing a file.
CUE_BAD_FILENAMEA bad filename was requested (NULL, empty, nonexistent, etc.).
CUE_WRITE_ERRORAn error occurred during a write to a file.
6.3 框架错误时的行为

遇到错误情况时的默认行为是设置错误代码并继续执行。有些客户可能希望出现错误时停止测试运行,甚至希望测试应用程序退出。可以由用户设置此行为,为此提供了以下功能函数:

void CU_set_error_action(CU_ErrorAction action)
CU_ErrorAction CU_get_error_action(void)

错误操作代码是<CUnit/CUError.h>中定义的CU_ErrorAction枚举类型。定义了以下错误操作代码:

Error ValueDescription
CUEA_IGNORE测试继续执行当有错误发生时 (默认行为)
CUEA_FAIL测试停止执行当有错误发生时
CUEA_ABORT测试程序退出当有错误发生时
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值