作者:灬猎丶豹灬_511 | 来源:互联网 | 2023-01-15 18:34
我开始进行单元测试,但在理解某些内容时遇到了麻烦。我的努力归结为如何测试仅在.c源代码中而不在.h标头中声明的函数。某些功能不需要在实现之外调用,因为它们仅与该特定文件有关。由于它们对程序的其他部分不可见,这意味着我的单元测试用例文件看不到那些内部功能,因此使我无法对其进行测试。我已经通过在测试用例文件中使用前向声明解决了这个问题,但是这似乎有点混乱,如果修改函数参数,更改和更改将很痛苦。
这些功能是否不打算包含在单元测试中?我已经读过OOP,您不应该测试私有功能,因为它们是通过公共功能隐式测试的,但是不覆盖这些功能(某些功能可能会变得非常复杂)感到不舒服。
1> ScottK..:
黑盒测试是关于测试您公开可见的界面和用户之间的软件合同。为了进行测试,通常使用工具或单独的测试程序创建一组测试用例,这#include
就是定义外部接口的头文件.h。听起来您已经有了这个。大!
缺少的是白盒测试的概念。对于许多行业,例如电信,铁路,航空航天或任何其他需要高度确保高可用性和高质量的行业,这与黑匣子测试一样重要。
对于白盒测试,请创建一个单独的“专用”界面,该界面仅由白盒测试程序使用。注意,C
您可以在其中为给定的C实现文件创建多个头文件。从编译器的角度来看,并没有真正强制执行标头或其名称的数量。最好遵守项目或团队所规定的约定。
对于我们的项目,我们为外部接口创建一个公共头(带有简单的.h后缀),为我们的私有接口创建一个私有头(_pi.h),供需要访问私有接口(如白盒测试)的少数用户使用,审核数据结构,内部配置和诊断以及调试工具。当然,_pi.h后缀只是一个约定,但在实践中效果很好。
白盒测试对于测试内部功能和数据结构非常有用,并且可以远远超出黑盒测试的范围。例如,我们使用White Box测试用例测试内部接口,并查看数据结构损坏时发生的情况,以及一些极端情况,例如测试内部传递意外参数值时代码的行为。
例如,假设我们有一个名为foo.c的文件,希望对其执行白盒测试。然后,我们将创建两个标头:foo.h和foo_pi.h分别用于外部和内部用户。
文件foo.h
#ifndef FOO_H
#define FOO_H
typedef int FooType;
// Public header for Foo
void Foo(FooType fooVal);
void Bar(void);
#endif
文件foo_pi.h
#ifndef FOO_PI_H
#define FOO_PI_H
// PI should also include the public interface
#include "foo.h"
// Private header for Foo
// Called by White Box test tool
void FooBar_Test1(FooType fooVal);
void Foo_Internal(void);
void Bar_Internal(void);
#endif
文件foo.c
#include "foo.h"
#include "foo_pi.h"
// Notice you need to include both headers
// Define internal helpers here
static FooType myFooVal = 0;
void FooBar_Test1(FooType fooVal) {myFooVal = fooVal;}
void Foo_Internal() {Bar_Internal();}
void Bar_Internal(void) {myFooVal++;}
// Define external interfaces after the helpers
void Foo(FooType fooVal) {myFooVal = fooVal; Foo_Internal();}
void Bar(void) {Bar_Internal();}
// Main() not typically included
// if this is just one module of a bigger project!
int main(int argc, char** argv)
{
Foo(argc);
}
如果你感到困惑什么那些#ifndef
/ #define
/ #endif
东西,这些都是CPP
宏,这种用法不是在C强制执行,但它是一种广泛使用的约定。有关更多详细信息,请参见/sf/ask/17360801/
尽管在上面的示例中没有显示它,但是Foobar_test()例程(以及其他任何内部测试方法)通常都放置在为内部测试功能保留的单独模块中,然后可以将它们包装到最终产品中。借助一些我在这里不会描述的高级CPP预处理,您可以有条件地编译出专用头文件和测试函数,并使接口对生产负载安全(在完成白盒测试后)。很多细节!