如果私有变量已更改,如何进行单元测试
How to unit test if a private variable has changed
假设我在 C++ 中有这个 class:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
}
如何对 exampleMethod()
进行单元测试?我想做这样的事情:
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.example_var;
obj.exampleMethod();
int after_call_value = obj.example_var;
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
但是 example_var
是私有的。
那么,做这个单元测试的正确方法是什么?我如何测试私有 example_var
是否已更改?
如果您想访问 example_val
,您可以执行以下两项操作之一。第一种是通过让testExampleMethod()
成为好友的方法,如下:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
friend void testExampleMethod(); //Now you can use the function as is.
}
另一方面,您可以在 ExampleClass
中添加一个 getter 来访问变量,例如:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
inline void getExampleVar() const { return example_var; }
}
然后将testExampleMethod()
改为:
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.getExampleVar();
obj.exampleMethod();
int after_call_value = obj.getExampleVar();
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
老实说,我会使用第二种方法,因为通常不建议访问 class 的私有变量。
测试私有 variable/methods 的方法很糟糕。但如果你需要,有很多选择:
你可以做你的测试class作为 ExampleClass 的朋友
可以使用moc对象抓取信息
您只需简单地为您想要获取的 private
变量实现 get
函数。
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
int GetExampleVar(){
return example_var;
}
}
然后这样称呼它
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.GetExampleVar();
obj.exampleMethod();
int after_call_value = obj.GetExampleVar();
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
或者make testExampleMethod
friend function
(友元函数可以访问友元class的私有变量,即使它不是它的方法)。
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
friend void testExampleMethod();
}
在我看来第一个例子会更合适,但是如果你不能修改ExampleClass
,你可以关闭gcc
的访问控制——-fno-access-control
.
我能想到的几个选项:
1) 将测试代码设为class的friend
。这样它就可以访问私有成员。
2) 将 getter 添加到 #ifdef Testing
指令下的 class,该指令仅在构建测试版本时定义(或将 public:
置于该宏下和 private:
在 #else
分支)。
3) #define private public
在构建测试时(不,不是真的)。
4) 在构建要测试的版本时使用 gcc 的 -fno-access-control
标志,这样一切都是 public(如果您使用的是 gcc)。
5) 只需放弃 class 的外部测试,而是将相关的 static_assert
s/assert
s 添加到 class 本身以测试不变量。
6) 不要。坚持测试 public 界面。
希望对您有所帮助:-)
简短回答:不要这样做。
您的测试应该仅针对 public 接口进行测试。让我试着用一些代码来解释:
class Adder {
int a,b;
public:
Adder() : a(0),b(0) {}
void set(int x,int y) { a=x;b=y; }
int get() { return a+b; }
};
和一个测试(暂时假设我们可以访问 a
和 b
):
void testAdder(){
Adder add;
int a = 1;
int b = 2;
add.set(a,b);
ASSERT_EQUALS(add.a,a);
ASSERT_EQUALS(add.b,b);
ASSERT_EQUALS(add.get(),a+b);
}
假设您已经分发了代码并且有人正在使用它。他想继续使用它,但抱怨内存消耗过多。在保持相同 public 界面的同时解决这个问题很简单:
class Adder {
int c;
public:
Adder() : c(0) {}
void set(int x,int y) { c = x+y; }
int get() { return c; }
};
这很简单,但测试会失败:(
结论:测试私有实现细节违背了测试的目的,因为每次修改代码很可能还要"fix"测试。
假设我在 C++ 中有这个 class:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
}
如何对 exampleMethod()
进行单元测试?我想做这样的事情:
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.example_var;
obj.exampleMethod();
int after_call_value = obj.example_var;
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
但是 example_var
是私有的。
那么,做这个单元测试的正确方法是什么?我如何测试私有 example_var
是否已更改?
如果您想访问 example_val
,您可以执行以下两项操作之一。第一种是通过让testExampleMethod()
成为好友的方法,如下:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
friend void testExampleMethod(); //Now you can use the function as is.
}
另一方面,您可以在 ExampleClass
中添加一个 getter 来访问变量,例如:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
inline void getExampleVar() const { return example_var; }
}
然后将testExampleMethod()
改为:
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.getExampleVar();
obj.exampleMethod();
int after_call_value = obj.getExampleVar();
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
老实说,我会使用第二种方法,因为通常不建议访问 class 的私有变量。
测试私有 variable/methods 的方法很糟糕。但如果你需要,有很多选择:
你可以做你的测试class作为 ExampleClass 的朋友
可以使用moc对象抓取信息
您只需简单地为您想要获取的 private
变量实现 get
函数。
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
int GetExampleVar(){
return example_var;
}
}
然后这样称呼它
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.GetExampleVar();
obj.exampleMethod();
int after_call_value = obj.GetExampleVar();
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
或者make testExampleMethod
friend function
(友元函数可以访问友元class的私有变量,即使它不是它的方法)。
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
friend void testExampleMethod();
}
在我看来第一个例子会更合适,但是如果你不能修改ExampleClass
,你可以关闭gcc
的访问控制——-fno-access-control
.
我能想到的几个选项:
1) 将测试代码设为class的friend
。这样它就可以访问私有成员。
2) 将 getter 添加到 #ifdef Testing
指令下的 class,该指令仅在构建测试版本时定义(或将 public:
置于该宏下和 private:
在 #else
分支)。
3) #define private public
在构建测试时(不,不是真的)。
4) 在构建要测试的版本时使用 gcc 的 -fno-access-control
标志,这样一切都是 public(如果您使用的是 gcc)。
5) 只需放弃 class 的外部测试,而是将相关的 static_assert
s/assert
s 添加到 class 本身以测试不变量。
6) 不要。坚持测试 public 界面。
希望对您有所帮助:-)
简短回答:不要这样做。
您的测试应该仅针对 public 接口进行测试。让我试着用一些代码来解释:
class Adder {
int a,b;
public:
Adder() : a(0),b(0) {}
void set(int x,int y) { a=x;b=y; }
int get() { return a+b; }
};
和一个测试(暂时假设我们可以访问 a
和 b
):
void testAdder(){
Adder add;
int a = 1;
int b = 2;
add.set(a,b);
ASSERT_EQUALS(add.a,a);
ASSERT_EQUALS(add.b,b);
ASSERT_EQUALS(add.get(),a+b);
}
假设您已经分发了代码并且有人正在使用它。他想继续使用它,但抱怨内存消耗过多。在保持相同 public 界面的同时解决这个问题很简单:
class Adder {
int c;
public:
Adder() : c(0) {}
void set(int x,int y) { c = x+y; }
int get() { return c; }
};
这很简单,但测试会失败:(
结论:测试私有实现细节违背了测试的目的,因为每次修改代码很可能还要"fix"测试。