此章节:
静态代码分析
C++test 通过静态分析代码以检查是否符合指定的静态代码分析规则来执行静态代码分析。该分析旨在通过以下方法防止错误并提高代码质量:
- 源代码中检测明确或潜在的缺陷。
- 防止使用可能危害安全性的代码
- 强制执行组织设计准则和规范(特定于应用程序,特定于使用或特定于平台)以及从已知特定错误中摘录的错误预防准则。
- 通过改进类设计和代码组织来提高代码的可维护性。
- 通过应用常见的格式、命名和其他样式约定,提高代码的可读性。
C++test 已预先配置为使用内建规则集执行静态代码分析。在大多数静态代码分析检查测试配置中默认启用的规则已被证明可立即对代码进行显著改进。遵循此核心准则集的代码将更快、更安全、更易于维护且不太可能遇到功能性问题。
除了提供预配置的规则集之外,C++test 还允许您定义自己的规则集(包括自定义规则)来实现特定于您组织的编码策略。为了帮助团队确定要遵守哪些规则,规则按主题(例如安全性、优化、初始化等)进行分类,并按严重程度(检测到的问题导致错误的可能性)进行排名。
要了解有关 C++test 附带的静态代码分析规则的更多信息,请选择Parasoft>帮助,打开C++test 静态分析规则 文档,然后浏览可用的规则描述文件。
C++test 还可以检查您使用 RuleWizard 模块设计的任意数量的自定义规则。使用 RuleWizard,可以以图形方式(通过创建规则的流程图表示形式)或自动(通过提供示例违反规则的代码)来创建规则。通过创建和检查自定义规则,团队可以验证独特的项目和组织要求,并防止重复出现最常见的错误。
有关执行静态代码分析的详细信息,请参见静态代码分析。
抑制
抑制用于防止 C++test 报告特定静态分析任务的其他发生(可能为一个规则报告多个任务)。在通常希望遵循规则的情况下使用抑制,但是在少数特殊情况下决定忽略该规则。使用抑制,您可以继续检查代码是否遵循该规则,而不会收到有关您故意违反规则的重复报文。如果您不想因违反特定规则而收到错误报文,我们建议您修改测试配置,以使它们不再检查该规则。
抑制可以存储在源代码中或本地抑制文件中,可以在源控制系统中对其进行检查,以便在团队中共享它们。
请注意,抑制设置独立于测试配置。为避免混淆,请记住:
- 测试配置定义了在静态分析期间检查的规则集。
- 抑制定义了哪些静态分析结果应该在【质量任务】视图和报告中可见。
这意味着将在分析过程中检查在【测试配置】中选择的规则,但不会显示与抑制条件匹配的结果。
有关创建抑制的详细信息,请参见抑制报告可接受的违规行为。
RuleWizard 图形规则编辑器
RuleWizard 允许您为 C/C++ 代码和格式问题创建自定义静态代码分析规则。C++test 可以自动执行在 RuleWizard 中创建的任何有效规则。通过创建和检查自定义规则,团队可以验证独特的项目和组织要求,并防止重复出现最常见的错误。
使用 RuleWizard,可以以图形方式(通过创建规则的流程图表示形式)或自动(通过提供示例违反规则的代码)来创建规则。编写或修改规则不需要解析器的编码或知识。
有两种方法可以打开 RuleWizard:
- 选择 Parasoft> 启动 RuleWizard。
- 单击【测试配置】面板的静态 标签中的新建按钮。
然后将打开 RuleWizard GUI。RuleWizard 用户指南(可通过在 RuleWizard GUI 中选择 帮助>文档 进行访问)包含有关如何修改、创建和保存自定义规则的信息。
有关创建和使用自定义规则的详细信息,请参见 自定义既有规则以及创建新规则。
流分析
重要的注意事项
使用此功能需要额外的许可证。请与您的 Parasoft 代理联系。
流是一种新型的静态分析技术,它使用多种分析技术(包括对应用程序执行路径的仿真)来识别可能触发运行时缺陷的路径。检测到的缺陷包括未初始化内存的使用、空指针取消引用、零除、内存和资源泄漏。
由于此分析涉及识别和跟踪复杂的路径,因此它暴露了通常逃避静态代码分析和单元测试的错误,这些错误很难通过手动测试或检查来发现。流分析在不执行代码的情况下暴露错误的能力对于具有旧代码库和嵌入式代码(在这种情况下无法有效检测或不可能进行此类错误的运行时)的用户特别有价值。
这种独特的静态分析种类通过搜索代码中的“可疑点”来开始分析被测源代码。可疑点是指可能存在错误的点。这些可疑点在“流分析”规则中定义。每当发现可疑点时,流分析都会调查导致该点的可能执行路径,并检查这些路径中的任何一条是否确实违反了流分析规则。如果找到了这样的路径,则报告违规。
例如,检测可能被零除的规则表示,使用“/”或“%”运算符的任何点都是可疑的。然后,它检查分母中的变量是否可以在导致该变量的任何可能执行路径上的那个点保持零值。如果是这样,则报告一个错误。
对于发现的每个错误,分层流路径数据都会精确地详细描述导致所识别错误的完整执行路径,并以该错误所代表的确切代码行结尾。为了减少诊断和纠正发现的每一个问题所需的时间和精力,数据流路径详细信息添加了大量注释(例如,"避免空指针取消引用"违规描述包含描述哪些变量包含数据流路径中哪个点的空值的注释)。
为了使分析过程更加灵活并适合您的独特项目需求,可以对一些规则进行参数设置。结果,流分析甚至可以用于检测与使用特定的 API 有关的违规行为。
使用流分析,开发团队可以获得以下主要好处:
- 使用现有资源执行更全面的测试:流分析允许您发现原本需要开发、执行和维护复杂测试用例的问题,对其他测试技术进行了补充。流分析调查程序中的各种分支可能性,提供传统测试难以完成的路径覆盖水平。因此,流分析通常会识别在处理测试期间通常未涵盖的罕见情况时出现的问题。此外,如果代码功能发生变化,您可以在修改后的版本中搜索错误,而无需更新或再生测试用例。
- 自动识别通过多个单元的错误:传统的自动化单元测试生成可帮助您识别单个编译单元中的错误。这很关键。然而,大多数开发人员进行了彻底的单位级测试,纠正了所有明显问题,集成了代码,然后又遇到了诸如空指针取消引用之类的问题,这些问题需要数天时间才能诊断,因为它们是由通过多个函数甚至多个编译单元使用流分析的模糊或复杂的执行路径造成的,因此可以自动识别相同的问题
关注实际的错误和设计缺陷:流分析会自动识别 data-dependent 或 flow-dependent 的错误,具有合理的确定性。当流分析报告违规时,通常会存在设计缺陷,这本身表现为简单的违规,例如被零除或资源泄漏。
例如,除非有一个方法调用 calculateBufferLength 并将其传递为空指针,否则流分析将不会报告以下代码的违规情况:
int calculateBufferLength(char* str) { return strlen(str) + 1; }
- 查找 API 误用:实践中的许多错误是由于使用错误的参数调用某些 API 或未正确处理 API 返回的值所致。例如,当参数 1 为 true 时,API 可能期望参数 2 为非 null 参数,否则 API 可能会将对象中的某些字段设置为 null。通过执行过程间分析,流分析可以指出此类 API 使用中的不一致之处。
有关详细信息,请参见流分析 。
单元测试
“单元测试”是指在最简单的功能点(通常是单个类或功能)上测试软件代码。单元测试通常由开发人员在开发周期内而不是 QA 阶段执行。使用单元测试,可以确保应用程序构建模块在集成之前是牢固的,从而提高了整个应用程序的质量。提早进行测试时,此时识别和修复缺陷通常较不困难且耗时。
手动单元测试通常包括手写测试工具,指定输入数据以及提供缺少功能和变量的桩函数。 C++test 自动化这些任务,从而使单元测试过程更加高效和一致。
通常,单元测试可以包括:
- 异常测试(也称为白盒测试,压力测试,结构测试或可靠性测试),用于确认代码在结构上是合理的,并且可以处理所有可行的输入及其组合,而不会引发意外的异常。
- 功能测试,用于验证软件构建基块是否符合其规范,并且所有预期功能都包含并正常工作。在单元级别创建功能测试需要人工输入,以指定特定的输入和状态条件以及预期的输出。功能测试可以实现为白盒测试(使用内部知识和被测单元的实现进行测试)或黑盒测试,其完全基于被测单元的外部行为。
- 回归测试,用于验证现有代码的行为不会随着代码库的发展而改变。这通常是通过开发一组测试、验证其正确性以及在代码更改后运行它们以捕捉代码行为的偏差来完成的。回归测试可能同时依赖于异常测试和功能测试。
C++test 可以执行所有描述的类型的单元测试。可以自定义测试的级别和范围,以反映您的要求和测试偏好。
当您运行 C++test 自动生成的测试用例时,将执行异常测试。这种类型的测试会暴露意外的异常,并检查类在结构上是否合理。可靠性测试的成功取决于代码的全面覆盖,因此您可能需要根据需要扩展自动生成的测试用例,以增加代码覆盖率。C++test 衡量测试覆盖率,以帮助您评估覆盖率并确定需要进行其他测试的地方。
当您扩展自动生成的测试用例以验证类的公共接口是否按照规范中所述运行时,将执行功能测试。
回归测试包括通过运行所有可用的测试用例并检查预期结果是否已更改,来定期测试不断发展的代码基础。当来自当前测试运行的测试用例结果与预期的测试用例结果不匹配时,C++test 报告错误消息。
可以在 C 或 C++ 源代码中实现并保存测试用例。您可以在 IDE 的文本编辑器中扩展和修改生成的测试用例。这些测试用例使用类似于适用的 CppUnit 格式的格式。与 CppUnit 相比,C++test 的测试提供了更广泛的功能,其中包括测试 C 代码并提供对测试框架内私有和受保护数据以及成员函数的编程访问的能力。可以将现有的 CppUnit 测试用例导入 C++test 并与自动生成的测试用例配合使用。
有关执行单元测试的详细信息,请参见 测试创建和执行。
测试用例生成
编写单元测试是确保代码质量的重要任务。单元测试不仅会暴露错误和功能问题,还可以作为常规回归测试来运行,以帮助您确定代码添加/修改是否破坏了现有功能或引起了意外更改。
但是编写测试非常耗时,如果不仔细完成,可能会遗漏许多重要情况。C++test 提供的单元测试支持可帮助开发人员和测试人员快速创建良好的单元测试。它会自动生成许多单元测试,并允许用户自定义测试的生成和执行,以适应他们的喜好和需求。C++test 自动生成大量的测试用例,尝试通过代码使用所有不同的路径,然后保存实际的测试用例结果。这些测试用例实质上是对代码的当前状态进行了 x-ray 检查,并捕获了修改前代码的运行状况快照。它们还帮助确定可能影响代码可靠性和安全性的潜在异常。
C++test 可以为从单个功能到整个项目的任何 C/C++ 代码生成测试用例。通过在 C++test 中运行这些测试用例,可以验证类的健壮性并识别可能导致程序进入不一致状态或终止的输入。您可以自定义预配置的测试模式以及特定的测试生成设置。
测试用例以 C 或 C++ 源代码实现和保存(使用的语言取决于要测试的原始源代码)。这些测试用例使用类似于适用的 CppUnit 格式的格式。与 CppUnit 相比,C++test 的测试提供了更广泛的功能,其中包括测试 C 代码并提供对测试框架内私有和受保护数据以及成员函数的编程访问的能力。可以将现有的 CppUnit 测试用例导入 C++test 并与自动生成的测试用例配合使用。测试套件可以用用户定义的测试用例进行扩展,以提高测试覆盖率并验证特定功能。这些测试可以通过修改自动生成的测试用例或定义新的用例来添加。任何可用的测试用例都可以自动验证并配置用于回归测试。通过保存所有可用的测试用例并利用它们进行自动回归测试,您可以建立回归测试基础结构,该基础结构立即识别出意外的功能更改和代码修改所引入的异常。
自动生成测试用例,使您可以在更短的时间内创建更有效的测试套件。传统上,测试用例开发是单元测试过程中最耗时的部分。在这一代中,您无需编写任何代码即可生成适用于每个类的基础测试用例集,并且可以通过向自动生成的测试用例中添加最少的代码来创建更多测试用例。通常,您不必担心为简单方法编写测试用例,而可以将资源集中在扩展/添加更复杂方法的测试上。
此外,生成测试用例可以通过两种关键方式帮助您防止错误:
- 一旦编写或修改了类,它使您可以立即生成并执行测试用例。通过添加建立在有问题的代码之上或与有问题的代码交互的代码,这可以帮助您在您(或团队成员)无意间引入其他错误之前发现并解决问题。
- 通过自动生成所需测试用例的范围和类型,它可以进行快速、彻底的可靠性测试,而通过手动设计测试用例来实现这一点是不切实际的。C++test 尝试创建测试用例,以执行其测试的每种方法的每个可能分支。例如,如果该方法包含条件语句(例如
if
块),则 C++test 将尝试生成测试if
语句的true
与false
结果的测试用例。
有关执行自动测试用例生成的详细信息,请参见 生成测试用例以进行回归测试和异常查找。
桩函数
桩函数用作功能的替代实现,以便可以将测试与测试功能集之外的依赖项隔离。使用桩函数时,执行流程将重定向到桩函数。
使用桩函数的主要原因有两个:
- 将测试中的代码与集成环境隔离。
- 无法在何时影响功能行为进行测试,需要替代实现。
您可以为任何测试用例(自动生成的测试用例以及用户定义的测试用例)定义自己的桩函数。使用用户定义的桩函数时,您可以完全控制外部函数返回被测类的值,而不必使用实际的外部函数。
如果有用户定义的桩函数,则即使执行原始功能,也将始终在测试执行期间使用它。如果原始定义最初不是可用的,而是在以后添加的,则 C++test 将继续使用用户定义的桩函数。如果您希望它使用原始定义,则需要删除桩函数(或将其注释掉)。
用户定义的桩函数以函数定义的形式实现,函数名称中带有 "CppTest_Stub_”前缀。示例:
/* C++test user stub definition for int doSomething(int i) */ int ::CppTest_Stub_doSomething(int i) { return i + 10; }
桩函数的声明必须可以在桩函数文件中访问。在大多数情况下,通过将适当的头文件包含在桩函数文件中来进行连接。
请注意,C++test 的桩函数(构造函数桩函数除外)采用与原始函数相同的值。
可以根据测试用例动态配置使用桩函数向导自动生成或创建的桩函数,而无需修改桩函数的主体。您可以在测试用例编辑器中动态配置桩函数(请见使用测试用例编辑器添加测试套件和测试用例),也可以使用动态桩函数配置直接从测试用例源代码中配置桩函数(请参见动态存根配置)。
当使用动态桩函数配置不够用时,可以用自定义逻辑实现替换生成的桩函数的主体,并为用户定义的桩函数使用 C++test API 函数(请参见针对用户定义的桩函数的 C++test API 函数)。
要了解有关自动生成的桩函数的更多信息,请参见了解和自定义自动桩函数生成。
要了解如何对测试期间无法(或不想访问)的外部资源使用用户定义的桩函数,请参见添加和修改桩函数。
工厂函数
工厂函数是用户定义的方法,用于初始化给定类型的对象。然后,在自动生成测试用例以及使用“测试用例向导”创建测试用例时,可以使用这种方法。
工厂函数可用于:
- 为用户定义的类型提供复杂的初始化程序(通过编写工厂函数在创建实际对象后执行一些其他初始化)。
- 减少可能的对象创建方法的数量(通过编写仅使用给定类的可用构造函数之一的工厂函数)。
工厂函数是在功能名称中带有“ CppTest_Factory_”前缀的函数。函数返回类型定义将使用给定的工厂函数创建的对象类型。工厂函数可以使用使它们可参数化的参数。例如,这是 std::vector<string> 的工厂函数,其中包含许多字符串:
std::vector<std::string> CppTest_Factory_vector_of_strings(unsigned int size, const std::string&value) { std::vector<std::string> vec; for (int i = 0; i < size; i++) { vec.push_back(value); } return vec; }
有关详细信息,请参见使用工厂函数。
运行时错误检测
C++test 的运行时错误检测使团队能够在单元或应用程序级别自动识别严重的运行时缺陷,例如内存泄漏、空指针、未初始化的内存和缓冲区溢出。 它适用于企业和嵌入式开发。
此功能的适应性使使用非标准内存分配模型(例如嵌入式系统)的团队可以进行运行时内存分析。由于用于该分析的仪器重量轻,因此可以在目标板,模拟器或主机上运行以进行嵌入式测试。
有关详细信息,请参见 运行时错误检测。
应用程序监测
应用程序监测旨在提供来自实际应用程序运行的测试结果。用于执行应用程序监测的仪器轻巧,适合在目标板上运行以进行嵌入式测试。
C++test 可用于监测使用 C++test 工具准备的应用程序可执行文件的执行。通常由开发人员和质量检查人员在常规应用程序测试会话中执行,以及其他补充质量实践(同行评审、静态分析、单元测试等)。
在测试过程中启用应用程序监测后,您可以访问质量检查人员会话通常不可用的详细信息-无需测试人员进行任何其他工作。唯一需要做的准备是,应用程序需要由 C++test 构建。
应用程序监测分析可以提供:
- 覆盖率分析,它提供有关在执行应用程序时覆盖了应用程序代码的哪些部分的信息。这有助于团队确定哪些源代码元素实现了应用程序级测试未涵盖的特定功能或用例。
- 运行时错误检测,可用于检测内存错误,例如内存访问错误、内存泄漏、内存损坏等。
有关执行应用程序监测的详细信息,请参见运行时错误检测。 有关覆盖率分析的详细信息,请参见覆盖率分析。
测试配置
测试配置是一组设置的集合,这些设置定义了您想要与 C++test 一起运行的测试方案。每次 C++test 在 GUI 中或从命令行界面运行测试时,都会使用指定的测试配置(如果未显式选择测试配置,则使用“收藏的测试配置”)。测试配置确定所有测试参数。例如,它确定参数,例如:
- 测试的类型(静态分析、测试用例生成、测试用例执行等)
- 静态分析过程中检查的规则
- 测试用例生成的参数
- 每次测试的范围(涵盖哪些行,使用的截止日期等)
C++test 包含一组预配置的“内建”测试配置,这些配置代表最常见的测试场景。您可以根据需要通过复制和修改内建配置,或者从头开始创建新的用户定义配置,进一步自定义这些配置。用户定义的测试配置可以放在“用户定义”或“团队”类别中。用户定义的测试配置存储在本地计算机上,并且可用于本地 C++test 安装执行的所有测试。 团队测试配置存储在团队的团队服务器上,所有团队成员均可访问。
如果 C++test 连接到 DTP,则可以使用存储在 DTP 中的测试配置运行分析。
有关与配置和共享测试配置有关的一般程序,请参阅 配置用于政策的测试配置和规则 。有关特定于 C++test 的“测试配置”选项的详细信息,请参见配置测试配置。
命令行界面(cli)
C++test 的命令行界面(cpptestcli
)允许您从命令行 shell 执行静态分析和单元测试,并从自动构建实用程序(例如批处理文件、脚本、make 和 Ant)运行 C++test。命令行模式可用于 C++test 的自动化版。
cpptestcli
可以将结果发送到 Parasoft DTP,将综合报告发送到团队经理和 Parasoft 团队服务器,并将重点报告发送给每个团队开发人员。可以 HTML、PDF 和自定义 XSL 格式生成报告。诸如报告首选项(应将报告发送给谁、应如何为那些报告加标签、应使用哪种邮件服务器和域等)之类的详细信息,团队服务器设置、Parasoft 通过选项、电子邮件设置、许可设置等都可以通过选项文件控制。
最佳的团队配置是在团队构建计算机上进行一个 C++test(自动化版),在每个开发人员工作站上进行 C++test,在架构师的计算机上进行一次 C++test,并在团队构建计算机或其他团队计算机安装一个团队服务器 。
开发人员使用他们在本地安装的 C++test 来测试他们编写或修改的代码,进行必要的更正,然后在源代码控制中检查代码和测试用例。每天晚上
C++test 在团队计算机上以 cli 模式运行,以验证签入的代码库;在这里,它执行开发人员创建的所有测试(通过自动测试生成和手动测试定义/自定义)并添加到源代码管理中的所有测试。测试完成后,团队开发人员可以将测试结果导入 C++test GUI 以方便进行错误检查和更正。此外,C++test 将结果发送到 Parasoft
在整个过程中,团队服务器管理测试设置和测试文件的共享和更新;这样可以使整个团队的测试标准化,并帮助团队成员充分利用彼此的工作。标准化测试设置和自定义团队规则由团队架构师配置和维护。
有关使用命令行界面的详细信息,请参见从命令行界面进行测试。
Parasoft DTP
Parasoft DTP 是一种决策支持系统,可为开发团队提供持续的可见性和对软件开发过程的评估,以帮助保持软件项目的正常进行。DTP 收集并整合在开发过程中生成的指标,将这些数据点转化为有意义的统计数据和仪表板,从而使开发经理和团队成员能够连续客观地评估代码库的质量和就绪性、编码过程的状态、以及开发团队的效率。借助 DTP、开发团队可以更轻松地识别、响应和管理威胁项目进度和质量的代码或编码过程中的风险。Parasoft DTP 提供了度量标准,通过这些度量标准管理层可以更有效地评估和引导资源、设置和监测开发目标、交流、指导和衡量对开发策略的符合性,并确保成功的项目成果。
一旦将 C++test 配置为向 DTP 发送信息,开发人员、架构师和管理人员便可以使用 DTP 仪表板访问有关质量,进度和生产率的基于角色的报告。
有关如何连接到 DTP 的详细信息,请参见连接 DTP。
Parasoft 团队服务器
Parasoft 的团队服务器(以前称为团队配置管理器[TCM])组件可确保所有团队成员都可以访问适当的团队测试配置、抑制、规则文件和测试用例文件。团队服务器可用并单独许可。此版本的 C++test 适用于团队服务器 2.0 及更高版本,该服务器作为 Parasoft 服务器工具的一部分分发。
在将团队服务器安装和部署为 Web 服务器之后,团队架构师或经理可以在一个 C++test 安装上配置适当的团队设置和文件,然后告诉团队服务器在何处访问设置和相关的测试文件。然后,开发人员可以将其计算机指向团队服务器位置,然后团队服务器将确保所有开发人员计算机都访问适当的设置和文件。修改、添加或删除文件的主版本后,团队服务器会对所有团队的 C++test 安装进行适当的更新。
必须先在团队的一台计算机上安装和部署团队服务器,然后才能使用团队服务器共享 C++test 文件。有关获取、安装和部署团队服务器的信息,请参考团队服务器文档或联系您的 Parasoft 代理。
有关如何连接到团队服务器的详细信息,请参见连接到Parasoft 团队服务器。