您的位置:首页 > 编程语言

华为软件编程规范和范例 5 ——可测性

2015-08-05 15:37 246 查看
7. 可测性

¹7-1 : 在同一项目组或产品组内, 要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数, 并且
要有详细的说明


说明: 本规则是针对项目组或产品组的。

¹7-2 : 在同一项目组或产品组内, 调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块
名(或源文件名)及行号



说明: 统一的调测信息格式便于集成测试。

¹7-3 : 编程的同时要为单元测试选择恰当的测试点, 并仔细构造测试代码、测试用例, 同时给出明确的注释说
明。测试代码部分应作为(模块中的)一个子模块, 以方便测试代码在模块中的安装与拆卸(通过调测开
关)


说明: 为单元测试而准备。

¹7-4 : 在进行集成测试/ 系统联调之前, 要构造好测试环境、测试项目及测试用例, 同时仔细分析并优化测试
用例, 以提高测试效率


说明: 好的测试用例应尽可能模拟出程序所遇到的边界值、各种复杂环境及一些极端情况等。

¹7-5 : 使用断言来发现软件问题, 提高代码可测性

说明: 断言是对某种假设条件进行检查(可理解为若条件成立则无动作, 否则应报告), 它可以快速发现并定位软件问
题, 同时对系统错误进行自动报警。断言可以对在系统中隐藏很深, 用其它手段极难发现的问题进行定位, 从而
缩短软件问题定位时间, 提高系统的可测性。实际应用时, 可根据具体情况灵活地设计断言。

示例: 下面是C语言中的一个断言, 用宏来设计的。(其中NULL为0L)

#ifdef _EXAM_ASSERT_TEST_ // 若使用断言测试

void exam_assert( char * file_name, unsigned int line_no )

{

printf( "\n[EXAM]Assert failed: %s, line %u\n",

file_name, line_no );

abort( );

}

#define EXAM_ASSERT( condition )

if (condition) // 若条件成立, 则无动作

NULL;

else // 否则报告

exam_assert( __FILE__, __LINE__ )

#else // 若不使用断言测试

#define EXAM_ASSERT(condition) NULL

#endif /* end of ASSERT */

¹7-6 : 用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况

¹7-7 : 不能用断言来检查最终产品肯定会出现且必须处理的错误情况


说明: 断言是用来处理不应该发生的错误情况的, 对于可能会发生的且必须处理的情况要写防错程序, 而不是断言。
如某模块收到其它模块或链路上的消息后, 要对消息的合理性进行检查, 此过程为正常的错误检查, 不能用断言
来实现。

¹7-8 : 对较复杂的断言加上明确的注释

说明: 为复杂的断言加注释, 可澄清断言含义并减少不必要的误用。

¹7-9 : 用断言确认函数的参数

示例: 假设某函数参数中有一个指针, 那么使用指针前可对它检查, 如下。

int exam_fun( unsigned char *str )

{

EXAM_ASSERT( str != NULL ); // 用断言检查“假设指针不为空”这个条件

... //other program code

}

¹7-10 : 用断言保证没有定义的特性或功能不被使用

示例: 假设某通信模块在设计时, 准备提供“无连接”和“连接” 这两种业务。但当前的版本中仅实现了“无连接”业务, 且
在此版本的正式发行版中, 用户(上层模块)不应产生“连接”业务的请求, 那么在测试时可用断言检查用户是否使

用“连接”业务。如下。

#define EXAM_CONNECTIONLESS 0 // 无连接业务

#define EXAM_CONNECTION 1 // 连接业务

int msg_process( EXAM_MESSAGE *msg )

{

unsigned char service; /* message service class */

EXAM_ASSERT( msg != NULL );

service = get_msg_service_class( msg );

EXAM_ASSERT( service != EXAM_CONNECTION ); // 假设不使用连接业务

... //other program code

}

¹7-11 : 用断言对程序开发环境(OS/Compiler/Hardware )的假设进行检查

说明: 程序运行时所需的软硬件环境及配置要求, 不能用断言来检查, 而必须由一段专门代码处理。用断言仅可对程
序开发环境中的假设及所配置的某版本软硬件是否具有某种功能的假设进行检查。如某网卡是否在系统运行环
境中配置了, 应由程序中正式代码来检查; 而此网卡是否具有某设想的功能, 则可由断言来检查。

对编译器提供的功能及特性假设可用断言检查, 原因是软件最终产品(即运行代码或机器码)与编译器已没有任
何直接关系, 即软件运行过程中(注意不是编译过程中)不会也不应该对编译器的功能提出任何需求。

示例: 用断言检查编译器的int型数据占用的内存空间是否为2, 如下。

EXAM_ASSERT( sizeof( int ) == 2 );

¹7-12 : 正式软件产品中应把断言及其它调测代码去掉(即把有关的调测开关关掉)

说明: 加快软件运行速度。

¹7-13 : 在软件系统中设置与取消有关测试手段, 不能对软件实现的功能等产生影响

说明: 即有测试代码的软件和关掉测试代码的软件, 在功能行为上应一致。

¹7-14 : 用调测开关来切换软件的DEBUG 版和正式版, 而不要同时存在正式版本和DEBUG 版本的不同源文件, 以减少维护的难度

¹7-15 : 软件的DEBUG 版本和发行版本应该统一维护, 不允许分家, 并且要时刻注意保证两个版本在实现功能上的一致性

½7-1 : 在编写代码之前, 应预先设计好程序调试与测试的方法和手段, 并设计好各种调测开关及相应测试代
码如打印函数等


说明: 程序的调试与测试是软件生存周期中很重要的一个阶段, 如何对软件进行较全面、高率的测试并尽可能地找出软件中的错误就成为很关键的问题。因此在编写源代码之前, 除了要有一套比较完善的测试计划外, 还应设计出一系列代码测试手段, 为单元测试、集成测试及系统联调提供方便。

½7-2 : 调测开关应分为不同级别和类型

说明: 调测开关的设置及分类应从以下几方面考虑: 针对模块或系统某部分代码的调测; 针对模块或系统某功能的调测; 出于某种其它目的, 如对性能、容量等的测试。这样做便于软件功能的调测, 并且便于模块的单元测试、系统联调等。

½7-3 : 编写防错程序, 然后在处理错误之后可用断言宣布发生错误

示例: 假如某模块收到通信链路上的消息, 则应对消息的合法性进行检查, 若消息类别不是通信协议中规定的, 则应进行出错处理, 之后可用断言报告, 如下例。

#ifdef _EXAM_ASSERT_TEST_ // 若使用断言测试

/* Notice: this function does not call 'abort' to exit program */

void assert_report( char * file_name, unsigned int line_no )

{

printf( "\n[EXAM]Error Report: %s, line %u\n",

file_name, line_no );

}

#define ASSERT_REPORT( condition )

if ( condition ) // 若条件成立, 则无动作

NULL;

else // 否则报告

assert_report ( __FILE__, __LINE__ )

#else // 若不使用断言测试

#define ASSERT_REPORT( condition ) NULL

#endif /* end of ASSERT */

int msg_handle( unsigned char msg_name, unsigned char * msg )

{

switch( msg_name )

{

case MSG_ONE:

... // 消息MSG_ONE处理

return MSG_HANDLE_SUCCESS;

... // 其它合法消息处理

default:

... // 消息出错处理

ASSERT_REPORT( FALSE ); // “合法”消息不成立, 报告

return MSG_HANDLE_ERROR;

}

}

示例: 假如某模块收到通信链路上的消息, 则应对消息的合法性进行检查, 若消息类别不是通信协议中规定的, 则应进行出错处理, 之后可用断言报告, 如下例。

#ifdef _EXAM_ASSERT_TEST_ // 若使用断言测试

/* Notice: this function does not call 'abort' to exit program */

void assert_report( char * file_name, unsigned int line_no )

{

printf( "\n[EXAM]Error Report: %s, line %u\n",

file_name, line_no );

}

#define ASSERT_REPORT( condition )

if ( condition ) // 若条件成立, 则无动作

NULL;

else // 否则报告

assert_report ( __FILE__, __LINE__ )

#else // 若不使用断言测试

#define ASSERT_REPORT( condition ) NULL

#endif /* end of ASSERT */

int msg_handle( unsigned char msg_name, unsigned char * msg )

{

switch( msg_name )

{

case MSG_ONE:

... // 消息MSG_ONE处理

return MSG_HANDLE_SUCCESS;

... // 其它合法消息处理

default:

... // 消息出错处理

ASSERT_REPORT( FALSE ); // “合法”消息不成立, 报告

return MSG_HANDLE_ERROR;

}

}

示例: 假设某函数参数中有一个指针, 那么使用指针前可对它检查, 如下。

int exam_fun( unsigned char *str )

{

EXAM_ASSERT( str != NULL ); // 用断言检查“假设指针不为空”这个条件

... //other program code

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: