本主题说明测试期间如何使用预定义或自动生成的数据源值。 在不同的数据集上运行测试的能力使您可以轻松地增加测试量和覆盖范围。

内容包括:

在 stub 中使用数据源

您配置用于C ++ test的任何数据源都可以在 stubs 数据库中使用。有关详细信息,请参阅 在 Stubs 中使用数据源

添加数据源

可以使用 GUI 向导在 C++test 中定义数据源。该向导允许您从逗号分隔的值文件(.csv),Excel 电子表格(.xls)中指定数据源,或 C++test 托管数据源表。在测试用例执行过程中,测试用例使用从给定数据源收集的值。

可以从【测试用例浏览器】在项目级别(对于所有项目测试套件可见)或在单个测试套件级别(仅由给定测试套件使用)定义托管数据源。此外,可以在以下位置创建托管数据源:解决方案级别)。

在项目/测试套件级别添加现有数据源

要在项目/测试套件级别创建托管数据源:

  1. 在【测试用例浏览器】视图中选择项目或测试套件节点。
  2. 右键单击所选内容,然后从快捷菜单中选择 新建> 数据源
  3. 指定数据源类型。

  4. 配置数据源

 使用 NULL 引用而不是 NULL 字符串

要使用 NULL 引用而不是 NULL 字符串,请从特殊值前缀 字段中选择 $ , 然后在 CSV 文件输入 NULL 之前使用 $ 前缀; 例如:
$NULL

在解决方案级别添加现有数据源


在以下位置创建托管数据源 解决方案 级别:

  1. 在【测试用例浏览器】视图中,右键单击 全局数据源 节点然后选择 新建> 数据源



  2. 定义新的托管数据源。

自动生成新数据源

C++test 可以使用自动生成的数据源值来生成逗号分隔值文件(.csv) 或 C++test 托管数据源表。

有关在【测试用例编辑器】中自动生成新数据源的信息,请参阅 使用数据源对在【测试用例编辑器】中添加的测试用例进行参数化。

如果正在【测试用例向导】中配置测试用例:

  1. 单击【测试用例向导】的编辑器页面中的 自动生成 按钮。
  2. 在打开的【自动生成】窗口中指定所需的设置。


生成数据源时,C++test 为每个具有可编辑值(布尔、整数、浮点和字符串类型)的前置条件和后置条件创建一个单独的列。数据源在测试套件级别生成。

一旦生成,就可以使用生成的数据源对测试套件中的其他测试用例进行参数化。

使用数据源值对测试用例进行参数化

使用数据源对【测试用例编辑器】中添加的测试用例进行参数化 

您可以使用数据源值来参数化使用测试用例编辑器创建的测试用例(请参见 使用测试用例编辑器添加测试套件和测试用例)。可以在内置于测试用例的数据源表中或在外部数据源中提供这些值。

  1. 打开【测试用例浏览器】,然后右键单击测试套件
  2. 选择 Add New> Test Case using Editor…
  3. 用于创建测试用例 下拉列表中选择一个函数。
  4. 单击创建新的参数化测试用例 按钮 () 以打开数据源选择对话框。
  5. 选择要使用的数据源。可以使用以下选项:
    Built-in table - 向您的测试用例中添加一个用于指定参数化值的表 (请参见 Adding Test Case Parameterization 有关可用于访问内置表中指定的值的 Parameters API 的详细信息)。
    External data source - 自动生成用于指定指定参数化值的外部数据源:逗号分隔值文件(.csv)或表数据源. 如果选择此选项, 请在打开的 自动生成 窗口中指定所需的设置然后单击 确定.数据源在测试套件级别生成。

         
  6. 保存测试用例以将其添加到测试套件中。

使用数据源对【测试用例向导】中编写的测试用例进行参数化

您可以使用数据源值来参数化现有的(自动生成的或用户定义的)测试用例,以及在【测试用例向导】中编写测试用例时定义测试用例的值。如上所述,可以从 C++test 中定义的任何数据源获取数据源值。

注意

C++test 无法自动验证由于执行了用数据源值参数化的测试用例而导致的未验证结果和失败的断言。这是因为它通常需要使用预期结果,该预期结果也已与数据源一起参数化。

通过测试用例向导配置数据源使用率

要使用测试用例向导来添加新的测试用例,用从先前定义的托管数据源中提取值:

  1. 在测试用例浏览器中, 右键单击测试套件节点,然后从快捷菜单中选择 Add New> Test Caseusing Wizard
  2. 在第一页上,指定要为其添加测试用例的源文件(编译单元)和功能,然后输入测试用例的名称。
  3. 单击 下一步 打开下一个向导页面。
  4. 选中 Use data source 复选框,然后选择适当的数据源。



  5. 通过使用 GUI 控件指定测试用例的输入和预期输出值来配置测试用例。
    • 要将数据源值用于给定的前置条件或后置条件,请双击相关节点,然后选择适当的数据源列名称。数据源值在组合框中列为大括号括起来的列名,例如"{myColumnName}"。
  6. 单击 完成 以生成测试用例。新的测试用例将被添加到测试套件中,并且所生成的源代码将在编辑器中打开。

从测试案例代码配置数据源使用率

要使用先前定义的托管数据源对现有(自动生成或用户定义的)测试用例进行参数化:

  1. 指定要与注册宏一起使用的数据源
    CPPTEST_TEST_DS(<TEST_CASE_NAME>,
    CPPTEST_DS("<MANAGED_DATA_SOURCE_NAME>"));
  2. 指定如何通过 CPPTEST_DS* 宏使用数据源值(在 Macros for Accessing Data Source Values中进行了说明)。

示例

例如,要使用 Excel 工作表中的值来参数化现有测试用例,我们将其称为"MyDataSourceForSum":

  1. 打开项目。
  2. 如果尚未这样做,请将 Excel 工作表添加为托管数据源:
    1. 在测试用例浏览器中, 右键单击测试套件节点,然后从快捷菜单中选择 新建> 数据源
    2. 选择 Excel, 然后单击完成。
    3. 输入数据源的有意义的名称(例如, "MyDataSourceForSum")。
    4. 输入您的 .xsl 文件的位置。
    5. (可选)单击显示列,然后快速验证列名称。
    6. 点击 确定。新的数据源将显示在测试用例浏览器中。
  3. 在测试用例浏览器中,双击要参数化的测试用例。
  4. 查找测试用例注册行(在测试套件文件中)。示例

    ...
    CPPTEST_TEST(sumTest1);
    ...
  5.  更改注册类型以使用数据源(your_Data_Source_name):

    ...
    CPPTEST_TEST_DS(sumTest1, CPPTEST_DS("MyDataSourceForSum")); 
    ...
  6. 转到测试用例定义并添加代码,该代码表明 C++test 如何使用数据源列中的值。使用中描述的宏 Macros for Accessing Data Source Values
    示例
    ...
    /* CPPTEST_TEST_CASE_BEGIN sumTest1 */     
    void MyTestSuite::sumTest1()
    {
	int iVal = CPPTEST_DS_GET_INTEGER("i"); 
	int jVal = CPPTEST_DS_GET_INTEGER("j");
	int expectedResult = CPPTEST_DS_GET_INTEGER("result"); 
	CPPTEST_ASSERT_INTEGER_EQUAL(expectedResult, sum(iVal, jVal));
    }
    /* CPPTEST_TEST_CASE_END sumTest1 */    
    ...

执行测试用例时,将使用 Excel 类型的 "MyDataSourceForSum” 数据源中的值对其进行参数化。

用于访问数据源值的宏

以下宏可用于访问数据源中的值。每个宏都使用参数 NAME,该参数为数据源列指定唯一的标识符。

为了这样...使用此宏...注意
返回以空值终止的字符串值

const char*
CPPTEST_DS_GET_CSTR(const char* NAME)

N/A
返回一个字符值

字符

CPPTEST_DS_GET_CHAR(const char* NAME)

N/A
返回一个整数值

long long
CPPTEST_DS_GET_INTEGER(const char* NAME)

N/A
返回无符号整数值unsigned long long CPPTEST_DS_GET_UINTEGER(const char* NAME)N/A
返回浮点值long double
CPPTEST_DS_GET_FLOAT(const char* NAME)
N/A
返回一个布尔值int
CPPTEST_DS_GET_BOOL(const char* NAME)
N/A
返回内存缓冲区const char*
CPPTEST_DS_GET_MEM_BUFFER (const char* NAME, unsigned int* SIZE_PTR)
如果 SIZE_PTR 不为 null,则缓冲区的大小将存储在此处。
返回一个枚举值

<范围枚举名称>

CPPTEST_DS_GET_ENUM(<scoped enum name>, const char* NAME)

<范围枚举名称> 是枚举的全名,包括所有命名空间名称。示例INNER_NS::MyEnumeration, INNER_NS::MyClass::MyEnumeration 
从 SOURCE 数组返回一个值CPPTEST_DS_GET_VALUE(SOURCE)

应该将数组类型的变量指定为 SOURCE 参数:

在每个后续测试用例执行之后,从中提取值的行数将自动增加。

返回当前迭代(行号)unsigned int
CPPTEST_DS_GET_ITERATION( )
可用于确定当前的迭代/行数。
如果当前数据源的当前迭代中存在“名称”列,则返回非零值。int
CPPTEST_DS_HAS_COLUMN(const char* name)
可以在 stubs 用于指定测试用例的行为 (详情参见 Using Data Sources in Stubs )。如果不使用数据源,则返回零。

数据源值的格式

下表提供了关于指定类型的数据源值的受支持格式信息:

数据源类型C++test API 函数支持格式
布尔CPPTEST_DS_GET_BOOLEAN()

关于 true:

    • true
    • 非零整数常量;例如 1

关于 false:

    • false
    • 0
有符号整数CPPTEST_DS_GET_INTEGER()

整数的十进制表示形式 (可选用前缀 - 或 + );例如。

    • 0
    • 1
    • -200
    • +55

前缀为 0x 或 0X 的整数的十六进制表示形式 (可选用前缀 - 或 + );例如。

    • 0x1a
    • -0XFF
    • +0x12

前缀为0的整数的八进制表示形式(可选用前缀 - 或 + );例如...

    • 0711
    • -0123
    • +055

前缀为 0b 或 0B 的整数的二进制表示(可选用前缀 - 或 + );例如。

    • 0b01010101
    • -0B1111
    • +0b11
无符号整数CPPTEST_DS_GET_UINTEGER()

整数的十进制表示形式;例如。

    • 0
    • 1
    • 200

前缀为 0x 或 0X 的整数的十六进制表示形式;例如。

    • 0x1a
    • 0XFF

前缀为 0 的整数的八进制表示形式;例如。

    • 0711
    • 0123

前缀为 0b 或 0B 的整数的二进制表示;例如。

    • 0b01010101
    • 0B1111
浮点CPPTEST_DS_GET_FLOAT()

浮点值的实际格式取决于所用编译器的配置 CPPTEST_STR_TO_FLOAT / CPPTEST_SCANF_FLOAT /
CPPTEST_SCANF_FLOAT_FMT 宏的实际实现。在大多数情况下,十进制数字序列可能包含一个基数字符(小数点,与语言环境有关,通常为“.”)。

(可选)可以在其后跟随一个十进制指数。十进制指数由”E”或”e”组成,后跟一个可选的加号或减号,后跟一个非空的十进制数字序列,并表示乘以 10 的幂。

示例:

    • 100
    • 1.5
    • -3.14159
    • 0.44E7
    • 99.99e-15
字符CPPTEST_DS_GET_CHAR()

要使用的字符; 例如。

    • a
    • 0
    • $

此外,应使用以下类似C的转义序列来处理特殊字符:

    • \n
    • \t
    • \v
    • \b
    • \r
    • \f
    • \a
    • \\
    • \'
    • \"

对于不可打印的字符,可以使用该字符的八进制(以 \ 开头的1-3位数字)或十六进制(以 \x 开头的1-2位数字)表示。 例如。

    • \13
    • \017
    • \x0A
字符串CPPTEST_DS_GET_CSTR()

要使用的字符串; 例如。

    • abcdefgh
    • qaz123
    • Hello world!

此外,应使用以下类似C的转义序列来处理特殊字符:

    • \n
    • \t
    • \v
    • \b
    • \r
    • \f
    • \a
    • \\
    • \'
    • \''

示例

    • Hello world!

对于不可打印的字符字符串,可以使用该字符的八进制(以\开头的1-3位数字)或十六进制(以 \x 开头的1-2位数字)表示。 例如。

    • \13
    • \017
    • \x0A

要将 null 定义为数据源中的 C 字符串值,可以将托管数据源配置为识别某些字符。 例如 $, 作为特殊值前缀,然后可以在数据源中使用带有前缀字符的 NULL; 例如。:

    • $NULL

请注意,这只能与UI托管的数据源一起使用(通过CPPTEST_DS("ds_name")宏注册的测试用例)。

数据缓冲区CPPTEST_DS_GET_MEM_BUFFER()使用与字符串类型相同的格式(请参见上文)。
枚举值CPPTEST_DS_GET_ENUM()

可以使用简单的枚举器名称或包含所有命名空间名称的全名。例如,如果在 ::INNER_NS::MyClass::DaysEnumeration 中定义了 MON 枚举器,则可以键入 MON 或 ::INNER_NS::MyClass::MON。

要在【数据源和参数】步骤中使用枚举器,请启用【测试配置】选项:“启用枚举数据自动生成”。您可以在以下位置找到此选项:“测试配置>执行选项卡>常规选项卡>检测模式>编辑>检测功能>高级选项”。


下表提供有关使用指定数据源类型格式化数据源值的信息:

数据源类型数据源注册宏附加信息
CSV 文件(托管数据源)CPPTEST_DS()

数据源值可能用引号引起来(引号可以在数据源配置中定义); 例如。:

    • "Hello world!"

如果需要在值中使用分隔符或在值中使用引号本身,则这是必需的。在后一种情况下,用作数据源值元素的引号需要加倍; 例如。:

    • "Hello world!"
    • "Hello, \""world\""!"
Excel 电子表格(托管数据源)CPPTEST_DS()

无需准备 Excel 特定的值。注意数据需要如上所述格式化以用于特定类型。

为了确保 C++test 正确处理值,可以对电子表格中的所有单元格使用文本格式。例如,通过这种方式您可以确保整数值的八进制表示形式将被正确处理。

表格(托管数据源)CPPTEST_DS()无需准备表特定的值。注意数据需要如上所述格式化以用于特定类型。
CSV 文件CPPTEST_DS_CSV()

数据源值可能用引号引起来(引号可以在数据源配置中定义); 例如。:

    • "Hello world!"

如果需要在值中使用分隔符或在值中使用引号本身,则这是必需的。在后一种情况下,用作数据源值元素的引号需要加倍; 例如。:

    • "Hello, world!"
    • "Hello, \""world\""!"
源代码数组CPPTEST_DS_ARRA Y()无需准备数组特定的值。注意数据需要如上所述格式化以用于特定类型。

探索可用的数据源

查看/修改数据源配置

要查看或编辑现有数据源的配置,请执行以下操作:

  • 右键单击该数据源的【测试用例浏览器】节点,然后从快捷菜单中选择 Edit


然后,您可以在打开的窗口中查看数据源配置,并根据需要对其进行修改。

打开数据源文件

要打开数据源文件,请执行以下操作:

  • 右键单击该数据源的【测试用例浏览器】节点,然后从快捷菜单中选择 打开数据文件

共享数据源

有关在项目/测试套件级别添加的数据源的信息存储在每个项目内的 .parasoft 属性文件中。因此,您可以通过源代码控制(通过提交和检出 .parasoft 属性文件)共享有关数据源的信息。

全局数据源-在以下位置添加的数据源解决方案级别-也可以通过这种方式共享,但是您需要定义在何处(例如,在哪个项目内)来创建其他 .datasource 数据文件,其中包含有关全局数据源的信息。默认情况下,全局数据源信息存储在本地。

为全局数据源指定共享位置:

  1. 选择 Parasoft> 首选项。首选项对话框将打开。
  2. 在左窗格中,选择 团队> 数据共享
  3. 指定要保存 datasources.properties 文件的位置。

确保数据源的可移植性(便携模式)

数据源可移植模式旨在处理需要将测试套件文件移动到不同位置的特定开发环境。在标准数据源模式下,如果将测试套件文件移动到其他位置,则该数据源关联将丢失。在便携模式下,您可以轻松地将数据源与测试套件一起移动。

为了确保数据源的可移植性,所有测试套件级别的数据源信息都存储在一个文件中,该文件的名称与测试套件文件的名称相同,并且扩展名为 .properties。因此,每个测试套件都有其自己的数据源设置文件,并且可以与这些数据一起移动。


便携式数据源模式仅适用于在测试套件级别创建的数据源-不适用于项目或解决方案级别。

更改数据源模式

要改数据源模式,请执行以下操作:

  1. 右键单击项目节点,然后选择 Parasoft>来自快捷菜单中的属性

  2. 展开左窗格中的 Parasoft> C++test> 数据源 类别。
  3. 修改 使用便携数据源存储 设置,然后单击 应用确定 按钮。



每次切换模式时,与测试套件关联的所有现有数据源都会自动转换为所选模式。切换到便携模式会使数据源设置从 .parasoft 文件传输到相应的 <test_suite_name>.properties 文件。转换完成时,将会有一条消息通知您。



您可以通过提交并检出所有或选定的 *.properties 文件,通过源代码控制共享有关数据源的信息。

使用 Excel 或 CSV 数据源文件的相对路径

为了确保更好地移植 Excel 和 CSV 数据源类型,可以在 Excel / CSV 文件路径中使用 C++test ${test_suite_loc} 变量。此变量解析为测试套件文件位置的绝对路径。


配置测试以使用“非托管”数组或 CSV 文件数据源-高级

除了使用托管数据源(如上所述,在 C++test 中定义的数据源)外,还可以使用未添加为托管数据源的数组或 CSV 文件中的值。

使用数组数据源值

C++test 中数据源的一种实现是基于类型化的数组,然后由单个测试使用它来逐步遍历数据行。

要创建一个可以访问数组数据源的测试用例:

  • 使用 CPPTEST_TEST_DS(testCaseName, dataSourceCon-fig) 宏注册测试用例。

testCaseName 替换为要访问数据源值的测试用例函数的名称,然后将dataSourceConfig 替换为用于数据源配置的宏。

两个辅助宏可用于 dataSourceConfig: CPPTEST_DS_ARRAY(ARRAY_NAME, ROW, COLUMN)CPPTEST_DS_REPEAT(NUMBER).

CPPTEST_DS_ARRAY(ARRAY_NAME, ROW, COLUMN), 注意:

  • 此宏使用 ARRAY_NAME 作为数据源。ARRAY_NAME 的类型应为 const char* data[ROW][COLUMN].
  • 表中的第一行必须包含列名。
  • 测试用例将执行 (ROW - 1) 次。
  • 数据源访问宏可用于提取值,如以下各节所述。


CPPTEST_DS_REPEAT(NUMBER), 注意:

  • 测试用例将执行 NUMBER 次
  • 测试案例可用于访问自定义数据数组中的值,如 CPPTEST_DS_GET_VALUE 和 CPPTEST_DS_GET_ITERATION descriptions Macros for Accessing Data Source Values说明中所述。

提示

  • 数据源数组可以在测试套件类之外声明(这是 C 测试套件的唯一选项),也可以声明为测试套件类成员(对于 C++ 测试套件)。请注意,C++ 测试套件可用于 C 语言(假设您有 C++ 编译器来构建它们)。
  • 当将数据源数组声明为类成员时,访问范围并不重要,因为只能通过作为成员函数的测试用例函数和 setup/teardown 来访问该数组。
  • 在 setUp 方法中声明类型化数组并对其进行初始化是将数据源数组元素初始化为任意数据的一种非常有效的方法。该数据可以是动态分配的对象,工厂测试对象等。例如:


#include "cpptest.h" 
int plus_one(int);
class TestSuite_3 : public CppTest_TestSuite {
public:
    CPPTEST_TEST_SUITE(TestSuite_3);
    CPPTEST_TEST_DS(test_ds_repeat, CPPTEST_DS_REPEAT(2));     
    CPPTEST_TEST_SUITE_END();
 
    void setUp();
    void tearDown();
 
    void test_ds_repeat();
private:
    int _dsRepeat_arg[2];
    int _dsRepeat_return[2];
};
CPPTEST_TEST_SUITE_REGISTRATION(TestSuite_3); 
 
void TestSuite_3::setUp()
{
    _dsRepeat_arg[0] = 1;
    _dsRepeat_arg[1] = 2;
}
void TestSuite_3::tearDown()
{
}
void TestSuite_3::test_ds_repeat()
{
    int index = CPPTEST_DS_GET_ITERATION() - 1;
    int _value = _dsRepeat_arg[index];
    int _expected = _dsRepeat_return[index];
 
    int _return = plus_one(_value);
    CPPTEST_ASSERT_INTEGER_EQUAL(_expected, _return);
}

使用非托管 CSV 数据源

除了支持本节前面所述的 CSV 数据源外,当 CSV 数据满足以下条件时,C++test 还可以使用“非托管” CSV 数据源:

  • CSV 数据存储在外部文件中。
  • CSV 数据包含用(可自定义的)分隔符分隔的值的记录(行)。
  • CSV 数据可以包含标题。
  • CSV 数据值可以包含空格字符,可以选择将其忽略。

有关支持的文件类型的更多信息,请参见 CSV File Support Details

要创建一个可以访问 CSV 数组数据源的测试用例:

  • 使用 CPPTEST_TEST_DS(testCaseName, dataSourceConfig) 宏注册测试用例。

testCaseName 替换为要访问数据源值的测试用例函数的名称,并将dataSourceConfig 替换为 CPPTEST_DS_CSV(FILE_NAME, SEPARATOR, HAS_HEADER, TRIM)。

CPPTEST_DS_CSV 在 C++test 数据源 API 中定义。它的参数是:

  • FILE_NAME - 带有数据源的数据源文件的名称。  可以使用完整或相对文件路径指定它。
    Note: 如果使用相对路径, 则它相对于测试可执行文件的工作目录,可以在【测试配置】的 测试可执行文件运行目录中自定义。 字段(在 Execution> Runtime tab)。
  • SEPARATOR - 字段分隔符。应将其指定为字符常量(例如:',').
  • HAS_HEADER - 如果第一条记录(行)是标题,则应将其设置为 1。否则,应将其设置为0。
    注意: 如果 CSV 文件中没有标题,则每个列名称都是其序号(从 0 开始)。
  • TRIM - 如果省略值前后的空格,则应将其设置为 1。否则,应将其设置为 0。

如果 CSV 文件中没有标题,则每个字段名称都是其序号(以 0 开头)。值应加引号(字符串类型)。示例:CPPTEST_DS_GET_FLOAT("0");

可以使用完整或相对文件路径指定它。FILE_NAME 可以是完整或相对文件路径。

CPPTEST_DS_CSV 示例

CPPTEST_DS_CSV("/home/project/testdata.csv", ',', 1, 0)

  • "/home/project/testdata.csv” 将用作数据文件。
  • 值用',’字符分隔。
  • 第一条记录将被视为标题。
  • 值之前/之后的空格将不会被修剪。

CPPTEST_DS_CSV("testdata.csv", ';', 0, 1)

  • “ testdata.csv”(位于当前工作目录中)将用作数据文件。
  • 值用';’字符分隔。
  • 没有显式标头-第一个记录(行)将用作数据。
  • 值之前/之后的空格将被修剪。

CSV 文件支持详细信息

  • 每个记录位于单独的行上,并由换行符(CRLF)分隔。  例如:
    aaa,bbb,ccc CRLF
    zzz,yyy,xxx CRLF
  • 文件中的最后一条记录可能有也可能没有换行符。  示例:
    aaa,bbb,ccc CRLF
    zzz,yyy,xxx
  • 可能有一个可选的标题行显示为文件的第一行,其格式与普通记录行相同。  该标头将包含与文件中的字段相对应的名称,并且应包含与文件其余部分中的记录相同的字段数(应通过 MIME 类型的可选“ header”参数指示标头行的存在或不存在)。 
    例如:
    field_name,field_name,field_name CRLF
    aaa,bbb,ccc CRLF
    zzz,yyy,xxx CRLF
  • 在标题和每个记录中,可能会有一个或多个字段,以逗号分隔。每行应在整个文件中包含相同数量的字段。  空格被视为字段的一部分,不应忽略。  记录中的最后一个字段不得在后面加上逗号。  例如:
    aaa,bbb,ccc
  • 每个字段可能会或可能不会用双引号引起来(但是,某些程序[例如 Microsoft Excel]根本不使用双引号)。  如果字段没有用双引号引起来,则双引号可能不会出现在字段内。  例如:
    "aaa","bbb","ccc" CRLF
    zzz,yyy,xxx
  • 包含换行符(CRLF),双引号和逗号的字段应用双引号引起来。  例如:
    "aaa","b CRLF
    bb","ccc" CRLF
    zzz,yyy,xxx
  • 如果使用双引号将字段括起来,则必须在字段内部出现双引号,方法是在其前面加上另一个双引号来对其进行转义。  例如:
    "aaa","b""bb","ccc"
  • Lf(代替 CRLF )可用于分隔记录
  • 值前后的空格可以省略
  • 记录中不需要相等数量的值
  • 非逗号字符可用作字段分隔符

示例
Using CPPTEST_DS_ARRAY

在此示例中,使用了数组数据源。首先,我们定义数据数组:

const char* MyData[][3] = {
    { "arg1",  "arg2", "return" },
    {    "1",	"one",	  "111" },
    {	 "0",   "two",    "222" },
    {    "2", "three",    "333" },
};

它具有三列四行。第一行包含列名(arg1, arg2,和 return)。其他三行保留测试用例的数据(因此将执行三个测试用例)。准备好数据后,我们必须按以下方式注册测试用例:

	CPPTEST_TEST_DS(testFoo2, CPPTEST_DS_ARRAY(MyData, 4, 3));

测试用例 testFoo2 将执行3次,并将从 MyData 数组中获取数据。最后,我们需要编写测试用例。被测试的函数采用两个参数并返回一个整数。我们将从数据源中获取两个参数,如下所示:

    int arg1 = CPPTEST_DS_GET_INTEGER("arg1");     
    const char * arg2 = CPPTEST_DS_GET_CSTR("arg2");

如果具有指定名称的列不可用或者其值类型不匹配,则测试用例执行将被中止。

对于后置条件检查,我们将从数据源获取期望值,如下所示:

    int expectedReturn = CPPTEST_DS_GET_INTEGER("return");
    /* check return value with value from data source */     
    CPPTEST_ASSERT_INTEGER_EQUAL(expectedReturn, actualReturn);

这是完成的测试:

class TestWithDataSource : public CppTest_TestSuite 
{
public:
    CPPTEST_TEST_SUITE(TestWithDataSource);
 
    /* register standard test case */     
    CPPTEST_TEST(testFoo1);
 
    /* register test case with "MyData" data source access */     
    CPPTEST_TEST_DS(testFoo2, CPPTEST_DS_ARRAY(MyData, 4, 3));
 
    CPPTEST_TEST_SUITE_END();
...
...
...
 
/* test case using values from data source */
void TestWithDataSource::testFoo2()
{
    /* extract arguments from data source */
    int arg1 = CPPTEST_DS_GET_INTEGER("arg1");
    const char * arg2 = CPPTEST_DS_GET_CSTR("arg2");
 
    /* call tested function */
    int actualReturn = foo(arg1, arg2);
 
    /* extract expected return from data source */
    int expectedReturn = CPPTEST_DS_GET_INTEGER("return");
 
    /* check return value with value from data source */
    CPPTEST_ASSERT_INTEGER_EQUAL(expectedReturn, actualReturn);
}

使用 CPPTEST_DS_REPEAT

在此示例中,我们将使用重复数据源:

/* data source for arg1 */
int _arg1[] = {
     1,
     0,
     2,
};
 
/* data source for arg2 */
const char * _arg2[] = {
   "one",    
   "two",
   "three",
};
/* data source for return */
int _return[] = {
   111,
   222,
   333,
};

这是一个特殊的数据源:它不提供对任何数据的访问权限,它只是按要求的次数重复执行测试用例。用户指定每次运行期间应使用哪些数据。在此示例中,我们将使用三个单独的数组:_arg1, _arg2, and _return

我们按以下方式注册测试用例:

CPPTEST_TEST_DS(testFoo2, CPPTEST_DS_REPEAT(3));

CPPTEST_DS_REPEAT 参数表示测试用例 testFoo2 应该执行的时间。

在测试案例中,我们将直接从数组中获取数据。为了从适当的行中获取值,我们可以将 CPPTEST_DS_GET_ITERATION() 的值用作数组索引,或者让CPPTEST_DS_GET_VALUE(SOURCE) 宏为我们执行索引,如下所示:

    int arg1 = CPPTEST_DS_GET_VALUE(_arg1);
    const char * arg2 = CPPTEST_DS_GET_VALUE(_arg2);

CPPTEST_DS_GET_VALUE 宏中没有范围或类型检查。它只是一个索引(提供一个具有适当索引的数组)。

这是完成的测试:

class TestWithDataSource : public CppTest_TestSuite 
{
public:
    CPPTEST_TEST_SUITE(TestWithDataSource);
 
    /* register standard test case */
    CPPTEST_TEST(testFoo1);
 
    /* register test case that will be executed number of times */
    CPPTEST_TEST_DS(testFoo2, CPPTEST_DS_REPEAT(3));
 
    CPPTEST_TEST_SUITE_END();
...
...
...
 
/* test case using values from custom arrays */
void TestWithDataSource::testFoo2()
{
    /* extract arguments from data source */
    int arg1 = CPPTEST_DS_GET_VALUE(_arg1);
    const char * arg2 = CPPTEST_DS_GET_VALUE(_arg2);
 
    /* call tested function */
    int actualReturn = foo(arg1, arg2);
 
    /* extract expected return from data source */
    int expectedReturn = CPPTEST_DS_GET_VALUE(_return);
 
    /* check return value with value from data source */
    CPPTEST_ASSERT_INTEGER_EQUAL(expectedReturn, actualReturn);
}

使用 CPPTEST_DS_CSV

这是存储在文件 /home/test/t2.data, 中的数据的数据源声明,其中标头和字段用逗号(',')分隔。不使用修剪。

class TestSuite : public CppTest_TestSuite 
{
	public:
	CPPTEST_TEST_SUITE(TestSuite);
	CPPTEST_TEST_DS(test_fooc_1, CPPTEST_DS_CSV("/home/test/t2.data",',', 1, 0));
	CPPTEST_TEST_SUITE_END();
 
	void setUp(); 
	void tearDown();
 
	void test_fooc_1();
};

这是使用数据源 API 中的标准功能的测试用例的定义:

void TestSuite::test_fooc_1()
{
	int _boo  = CPPTEST_DS_GET_INTEGER("first");
        float _goo  = CPPTEST_DS_GET_FLOAT("second");
 
	int _return  = fooc(_boo, _goo, _g);
	CPPTEST_ASSERT_INTEGER_EQUAL(CPPTEST_DS_GET_INTEGER("result"), ( _return ))
}

这是 CSV 数据源文件 (/home/test/t2.data),其中包含一个标头和三个测试用例。

first,second,result
1,2,3
2,2,4
2,2,5

创建基于数据源的回归测试

要为 C++ test 附带的示例 ATM 项目(在 examples 目录中)创建两个基于数据源的回归测试(一个使用字符串数组数据,另一个使用类型化数组数据):

  1. 右键单击项目节点,然后 选择 C++test> Wizards> Create New Test Suite。这将打开一个新的测试套件向导。

  2. 指定 TestSuiteAccount 作为测试套件名称(这将是C ++测试套件的类名称) 并指定 /ATM/tests/user 作为测试套件的位置 (如果目录不存在,请单击 创建目录y )。
  3. 对于 Test suite language, 选择 C++
  4. 取消选中所有其他选项。
  5. 点击 下一步 并通过两次单击 添加按钮为 Account 类添加两个测试。命名一个测试setPasswordTest,另一个命名为depositTest。完成向导序列将创建一个框架测试套件,并适当注册这些测试。
  6. 打开测试套件源文件。
  7. 创建一个字符串数据源(如下所示)以测试密码设置,并将其放在测试套件类声明上方的测试套件的源文件中。通常,数据源数组可以在文件范围内声明,也可以作为测试套件类的静态成员声明,遵循标准语言惯用法:

    const char* passwordData [] [2] = {
    	{ "arg1", "result" },
    	{ "", "" },
    	{ "a1", "a1" },
    	{ "really_long_password", "really_long_password" },
    	{ "foo", "goo" }
    };
  8. 为 setPassword 方法编写一个测试用例。测试应该设置一个密码,并检查返回的密码是否与数据源中指定的密码一致:

    void TestSuiteAccount::setPasswordTest()
    {
    	const char* password = CPPTEST_DS_GET_CSTR("arg1");
    	const char* result = CPPTEST_DS_GET_CSTR("result");
    	Account _cpptest_object;
    	_cpptest_object.setPassword(password);
    	CPPTEST_ASSERT_CSTR_EQUAL(result, _cpptest_object.getPassword())
    }
  9. 在文件顶部添加 #include “Account.hxx” ,以便保留 Account 类声明。
  10. 修改测试套件声明 CPPTEST_TEST(setPasswordTest) 中的测试用例注册,如下所示:

     CPPTEST_TEST_DS(setPasswordTest, CPPTEST_DS_ARRAY(passwordData, 5, 2));
  11. 创建一个自定义测试配置,它将执行用户定义的测试,如下所示:
    1. 选择 Parasoft> 测试配置
    2. 右键点击 Builtin> Run Unit Tests,,然后选择 Duplicate
    3. 将新的用户定义的测试配置重命名为“运行 DS 测试”。
    4. 打开 Execution> General 选项卡。
    5. 更改测试套件的位置模式,使其仅包含 /tests/user/*中的测试。
    6. 点击 Apply,然后 OK 保存您的更改。
  12. 选择项目节点,然后运行新的【运行 DS 测试】测试配置。
  13. 测试完成后,打开【质量任务】视图。在【修复单元测试】类别中,您应该看到一个指向数据源第 4 行的单元测试断言,其中包含故意不匹配的数据(模拟回归失败),以及来自第二个测试用例的另一个断言。
  14. 使用类型化数组中的数据创建第二个测试用例。创建一个类型为 double 的带有存款值的数据源数组,并创建另一个类型的具有预期账户余额的值。这次,让我们成为测试套件的数组成员。测试套件声明的结尾应如下所示:

     		void depositTest();
    	private:
    		static double deposit []; 
    		static double balance [];
    };
    		double TestSuiteAccount::deposit [] = {
    			0.0,
    			1.0,
    			-2.0,
    			1e06
    		};
    		double TestSuiteAccount::balance [] = {
    			1.0,
    			2.0,
    			-1.0,
    			1000001.0
    };
  15. 为存款函数编写测试,并检查最终余额以进行回归:

    void TestSuiteAccount::depositTest()
    {
    	double dep_value = CPPTEST_DS_GET_VALUE(deposit);
    	double balance_value = CPPTEST_DS_GET_VALUE(balance); 
    	Account _cpptest_object(1.0);  // create account with initial deposit
    	_cpptest_object.deposit(dep_value); // additional deposit
    	CPPTEST_ASSERT_DOUBLES_EQUAL(balance_value, _cpptest_object.getBal-ance(), 1e-6)
    }
  16. 将测试 CPPTEST_TEST(depositTest) 的注册更改为运行 4 次:

        CPPTEST_TEST_DS(depositTest, CPPTEST_DS_REPEAT(4));
  17. 在项目上重新运行“运行 DS 测试”测试配置。
  18. 查看【质量任务】视图的【修复单元测试】类别下报告的结果。由于新测试中的所有值均匹配,因此不应报告其他任务。
  • No labels