跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

这是您第一次登陆到 developerWorks,已经自动为您创建了您的概要文件。 选择您概要文件中可以公开的信息的信息(如姓名、国家/地区,以及公司),这些信息同时也会与您所发布的内容相关联。 您可以随时更新您的 IBM 账号。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

使用 IBM XL C/C++ 和 Fortran 编译器的新测试选择技术构建智能测试环境

在不降低测试覆盖率的情况下减少回归测试使用的测试用例数量

Igor Todorovski, 软件开发人员, IBM
作者照片
Igor Todorovski 是 IBM XL Compilers 小组的软件开发人员。他于 2008 年加入 IBM,专门研究 z/OS C/C++ 编译器。
Jean Saad, 软件开发人员, IBM
作者照片
Jean Saad 是 IBM XL Compilers 小组的软件开发人员。他于 2008 年加入 IBM,他的工作内容是研究 C/C++ 和 COBOL 编译器。
Francesco Cassullo, 软件开发人员, IBM
作者照片
Francesco Cassullo 是 IBM XL Compilers 小组的软件开发人员。他于 2008 年加入 IBM ,他的工作内容是研究 Fortran、C/C++ 和 COBOL 编译器。

简介: Igor Todorovski、Jean Saad 和 Francesco Cassullo 介绍了一项测试选择技术,可在不降低测试覆盖率的情况下减少回归测试使用的测试用例数量。它使用 XL C/C++ 的函数跟踪功能 (functrace) 和 Fortran 编译器的剖析信息来选择最少且精确的测试用例子集。

发布日期: 2013 年 3 月 15 日
级别: 中级 原创语言: 英文
访问情况 : 1459 次浏览
评论: 


下载 XL C/C++ for IBM AIX 试用版  |  XL C/C++ for Linux 试用版
下载 XL Fortran for IBM AIX 试用版  |  XL Fortran for Linux 试用版
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

剖析定向选择简介

回归测试通常是确保软件质量所必需的。但是,它被广泛认为是一种昂贵的过程。要降低这一成本,为整个测试套件应用了测试选择技术。

采用测试选择技术的结果是减少了测试套件。现有的几种测试选择技术试图减小测试套件大小,同时保持高缺陷检测率。

本文介绍了一种安全高效的测试选择技术,它依靠剖析信息选择测试用例。我们将此技术称为剖析定向选择 (profile-directed selection, PDS)

PDS 分两阶段运行:

使用剖析信息填充数据库
第一阶段将应用程序源代码与测试用例关联起来。它在代码覆盖率或剖析检测应用程序上执行完整的测试套件。生成的剖析信息会为每个测试用例调用的源文件、函数名称和行语句编制目录。然后,会将每个测试用例与它遇到的应用程序文件和函数关联起来。在关系数据库中保存此关系。代码覆盖率数据可以和更细的粒度一起应用,但是这样做会产生一定的成本:更多数据意味着更多的处理时间和维护时间。
 
根据更改集选择测试用例
第二个阶段(测试选择阶段)会根据对应用程序所做的源代码修改来构建并执行一个查询。该查询会选择一些测试用例,它会遍历代码更改修改的函数。
 

图 1. 回归测试中的测试选择
构建流程和回归测试图

关键缩写词

S 软件应用程序

S' S 的修订版

T={Ti,...,Tn) 原始测试套件

分析器检测

PDS 依靠剖析信息将测试用例与应用程序的源代码关联起来。因此,必须检测应用程序以生成剖析信息。选择分析器时,需要考虑下列内容:

  • 相对性能影响
  • 工具的输出可用性
  • 存储需求

在我们的实验中,我们选择了通过 IBM XL C/C++ 和 Fortran 编译器的 functrace 功能使用函数挂钩。我们使用此编译器功能在示例应用程序的每个函数上放置 func_trace_enterfunc_trace_exit 挂钩。这些函数生成了剖析信息。

PDS 使用关系数据库将每个函数和源文件与每个测试用例关联起来。我们在实验中使用了 IBM DB2®。

PDS 是一种函数级粒度选择技术。根据需要,代码覆盖粒度可以是细粒度或粗粒度的。我们选择了函数级粒度,因为它表示选择技术处理成本和测试套件大小减小之间的中间值。粒度更细的测试选择技术,比如基于控制流图的方法,可能选择更少的测试用例,但是,它们需要更多的处理时间和更高的存储需求。对于由成千上万的测试用例组成的应用程序来说,处理成本可能会超过方法带来的好处,因此应考虑粒度。

函数更改集检测

SS' 之间的源文件进行的修改被称为更改集。在我们的实验中,在更改集中提取修改的函数和修改的源文件是一个手动步骤。

大多数集成开发环境 (IDE) 应用程序可以自动检测在 SS' 之间进行的更改。

建模选择方法的有效性

剖析定向选择技术的有效性基于缺陷检测有效性和平均测试套件下降率。


剖析定向选择技术(或 PDS)

PDS 方法旨在选择受 SS' 之间的更改集影响的测试用例。

如前所述,PDS 由两个阶段组成:

  1. 使用剖析信息填充数据库
  2. 根据更改集选择测试用例

图 2. Profile-directed selection 概述
填充测试用例数据库和测试选择

算法

PDS 能够以下列伪代码的形式来表示:

1. Test S with T to generate P={P1,…,Pn}, the profile data of S. 
2. For each test case Ti for i=1 to n, relate Pi to Ti in a relational database. 
3. Let P' be the source code change set between S and S'. 
4. For i=1 to n, if |P'∩Pi|>0 then return Ti. 

第 1 阶段. 填充测试用例数据库

PDS 的第 1 阶段是通过将测试用例与源代码关联起来填充数据库。

第 1 阶段的先决条件是必须使用分析器检测 S。在我们的示例中,我们使用了 IBM XL C/C++ 和 Fortran 编译器的 functrace 功能,在每个函数上插入 func_trace_enterfunc_trace_exit 挂钩。


图 3. 使用 functrace 构建支持剖析的应用程序
使用 -qfunctrace 构建的流程图

我们的挂钩定义生成的剖析信息包含执行的源文件路径和函数。为了降低总体存储需求,我们使用了 Set 数据结构来存储惟一函数名称和执行的源路径。我们还保留了每个函数的调用频率。为每个测试用例生成的剖析信息具有下列格式:

 Source:Function:CallFrequency main.c:main():1 main.c:foo():2 boo.c:goo():1 

第一列表示源文件,第二列表示函数名称,最后一列表示调用频率。

使用此设计,我们在 S 上运行了整个测试套件 T。这会为每个测试用例生成剖析信息 P

对于每个测试用例,i=1Tin,我们将剖析信息 Pi 与关系数据库中的 Ti 关联起来。

下面是数据库模式:

TestCaseToSourceCode

 Test Case Path, Function Name, Source Path 

在我们的实现中,如代码清单 1 所示,我们标准化了此表并为测试用例路径、源文件和函数名称创建了三个表。


清单 1. 使用 functrace 的实现示例
#include <iostream>
#include <sstream>
#include <fstream>
#include <map>
#include <demangle.h>

static bool exitedMain = false;

struct ProfileData
{
    std::string sourceFile;
    std::string functionName;
};

struct Comparator
{
    bool operator()(ProfileData s1, ProfileData s2) const
    {
        return strcmp((s1.sourceFile+ s1.functionName).c_str(), 
        (s2.sourceFile + s2.functionName).c_str()) < 0;
    }
};

static std::map<ProfileData, int, Comparator>* tccMap = NULL;

static std::string getDemangledName(std::string mangledFunctionName)
{
    char *rest;
    Name* name;
    if ((name = Demangle(const_cast<char*>(mangledFunctionName.c_str()), rest)) != NULL)  
        return ((FunctionName *)name)->Text();    
    else
        return mangledFunctionName;    
}

static void printData(const ProfileData &data, int callFrequency)
{
    std::string functionName = getDemangledName(data.functionName);
    
    std::ofstream outputFile("func_trace_profile.dat", std::ios::out | std::ios::app); 
    outputFile << data.sourceFile << "|" 
    << functionName << "|" << callFrequency << std::endl; 
    outputFile.close();
}

std::string basename(std::string path)
{
    std::string::size_type size = path.find_last_of ('/');

    if ( size == std::string::npos )
        return path;

    return path.substr(size + 1);
}

extern "C"
void __func_trace_enter(const char *functionName, 
const char *fileName, int lineNumber, void** const id)
{ 
    if (tccMap == NULL)
        tccMap = new std::map<ProfileData, int, Comparator>;

    ProfileData data;
    data.sourceFile = basename(fileName);
    data.functionName = functionName;

    if (tccMap->find(data) == tccMap->end()) 
    {
        if (exitedMain) 
            printData(data, 1);

        (*tccMap)[data] = 1;
    }
    else 
    {
        (*tccMap)[data]++;
    }
}

extern "C"
void __func_trace_exit(const char *functionName, 
const char*fileName, int lineNumber, void** const id)
{
    if (strcmp(functionName, "main") == 0) 
    {
        std::map<ProfileData, int, Comparator>::iterator myIterator;

       for(myIterator = tccMap->begin(); myIterator != tccMap->end(); myIterator++)
        {
    int callFrequency = myIterator->second;
    printData(myIterator->first, callFrequency);
        }
        exitedMain = true;
	}	 
}

我们在实验中省略了剖析信息的调用频率,但是打算在未来针对排名来使用它。

当修改的软件 S' 可用时,我们进入第 2 个阶段。

第 2 阶段. 测试选择

在第 2 阶段中,我们手动检测了在 SS' 之间修改、添加和删除的函数。在删除和添加函数的情况下,我们标识了父函数。根据此更改集,我们从关系数据库构建了查询,这生成了缩减的测试套件 T'


实证分析

在我们建立了根据软件更改集选择测试用例的机制后,我们进行了实验来分析 PDS 方法的有效性。

实验

我们的实验使用完整的测试套件比较了三种测试选择技术(shotgun 或 random、手动选择和 PDS)。我们使用 IBM XL C/C++ Version 11.1 compilers for AIX® 测试了套件。

我们选择了两个内部测试套件。一个拥有 832 个测试用例,另一个拥有 781 个测试用例。

分析

使用两个内部测试套件,在我们选择测试的 IBM XL C/C++ V11.1 编译器的两个版本之间总共发现了 16 个缺陷。运行每个测试套件需要大约 900 秒。

随机和手动选择方法很便宜,所花费的时间是运行完整的测试套件所需时间的不到 50%。但是,它们生成的有效缺陷检测率更低,仅占总缺陷数的 37.5% (6/16) 和 43.75% (7/16)。

平均来说,PDS 方法还将两个测试套件之间的处理时间减少了大约 50%。与随机和手动选择运行相比,它在检测缺陷方面明显更高效,生成了 100% (16/16) 的检测率。

因此,在确定每种方法的经济效益时,我们查看在每个测试套件执行期间发现的缺陷数量。PDS 方法的结果为每秒 0.3 个缺陷,但是完整、随机 (shotgun) 和选择方法(手动选择)的结果为低于每秒 0.2 个缺陷。


图 4. 每种方法的原始实验数据
发现的缺陷和使用的执行时间的图

图 5. 选择方法的有效性
执行期间发现的缺陷

未来方向

在将来,我们将研究各种粒度的影响。具体地讲,我们将比较填充测试用例和源代码关系的处理与维护成本。此外,我们打算寻找提供最低的处理成本并保持高测试套件下降率的粒度。

此方法可应用于健全测试执行运行,其中需要固定数量的测试用例。需要研究的问题是选择哪个测试用例和如何排列这些测试用例。一个可能性可能是组合使用此方法与优先化方法,在优先化方法中,可将调用频率用作排名。

针对自动代码验证的工具集成

最后,我们想要看到对现有的 IBM 应用程序(比如 Rational Application Developer、Rational Developer for System z、Rational Developer for Power Systems Software 和 Rational Team Concert™)实施此算法。理想情况下,在开发人员提交了更改后,应该会选中并执行受指定更改集影响的测试用例列表。

应基于源代码更改根据需要执行测试用例。这使开发人员可以自动验证其代码更改,从而避免运行完整回归的需要。

我们诚挚地邀请您提供与 PDS 方法及其在测试领域的潜在用法相关的意见、反馈或建议。


致谢

作者感谢对本文提供帮助的下列人员:Preston Koo、Roch Archambault 和 Kobi Vinayagamoorthy。



下载

名字大小下载方法
func_trace_profile.dat241KBHTTP
functrace.C.zip3KBHTTP

关于下载方法的信息


参考资料

学习

  • 与本文相关的参考资料:
    • G. Rothermel 和 M.J. Harrold。A Safe, Efficient Regression Test Selection Technique。在 ACM Trans. Software Eng. and Methodology,卷 6,第 2 册,第 173 页至第 210 页,1997 年 4 月。
    • Todd L. Graves、Mary Jean Harrold、Jung-Min Kim、Adam Porter、Gregg Rothermel。回归测试选择技术的实证分析。在 Proceedings of the 20th international conference on Software engineering,第 188 页至第 197 页,1998 年 4 月 19 日至 25 日,日本东京。
    • IBM XL C/C++ for AIX, V11.1,Compiler Reference,2009 年。

  • 有关编译器的更多信息:
    • IBM XL C/C++ compilers for AIX, Linux, IBM z/OS®, IBM z/VM®,以及 XS C/C++ Advanced Edition for Blue Gene® 和 Development Studio for IBM System i®。
    • IBM Fortran 编译器:XL Fortran for AIX、XL Fortran for Linux、XL Fortran Advanced Edition for the Blue Gene、VS Fortran

  • 访问 developerWorks 上的 Rational 软件专区,获取针对 Rational 软件交付平台产品的技术资源和最佳实践。

  • 订阅 developerWorks 的每周电子邮件新闻摘要,并选择要关注的主题。

  • 随时关注 developerWorks 技术活动和网络广播,了解各种 IBM 产品和 IT 行业主题。

  • 参加 免费的 developerWorks Live! 技术讲座,快速了解 IBM 产品和工具,以及 IT 行业趋势。

  • 观看 developerWorks 点播演示,那里提供了面向初学者的产品安装和设置演示,以及面向经验丰富的开发人员的高级功能。

  • 查看 IBM XL 编译器新特性专题,了解 IBM XL 编译器新特性。

获得产品和技术

讨论

  • 与同行联系,在Rational Cafes 中提出问题并回答问题,在那里您会发现 C/C++、COBOL、EGL、Fortran、HATS、PL/I 和更多内容的论坛。

  • 加入 Rational 软件论坛,提出问题并参与讨论。

  • 加入 Rational 论坛cafés维基,提出问题并回答问题,提高您的专业知识。

  • 加入 Rational 社区,分享 Rational 软件知识并与同行进行交流。

  • 评分或评论 Rational 软件。以这种方式进行评分和评论既快又简单。

作者简介

作者照片

Igor Todorovski 是 IBM XL Compilers 小组的软件开发人员。他于 2008 年加入 IBM,专门研究 z/OS C/C++ 编译器。

作者照片

Jean Saad 是 IBM XL Compilers 小组的软件开发人员。他于 2008 年加入 IBM,他的工作内容是研究 C/C++ 和 COBOL 编译器。

作者照片

Francesco Cassullo 是 IBM XL Compilers 小组的软件开发人员。他于 2008 年加入 IBM ,他的工作内容是研究 Fortran、C/C++ 和 COBOL 编译器。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational
ArticleID=861574
ArticleTitle=使用 IBM XL C/C++ 和 Fortran 编译器的新测试选择技术构建智能测试环境
publish-date=03152013