Ian*_*oyd 5 language-agnostic oop unit-testing
假设我有一个执行一些计算的私有例程:
private function TCar.Speed: float
{
Result = m_furlogs * 23;
}
Run Code Online (Sandbox Code Playgroud)
但现在我想开始更彻底地测试这个计算,所以我将它重构为一个单独的函数:
public function TCar.Speed: float
{
Result = CalculateSpeed(m_furlogs);
}
private function TCar.CalculateSpeed(single furlogs): float
{
Result = furlogs * 23;
}
Run Code Online (Sandbox Code Playgroud)
现在我可以执行各种测试CalculateSpeed:
Check( CalculateSpeed(0) = 0);
Check( CalculateSpeed(1) = 23);
Check( CalculateSpeed(2) = 46);
Check( CalculateSpeed(88) = -1);
Run Code Online (Sandbox Code Playgroud)
除了我不能执行这些测试,因为CalculateSpeed是私有的TCar.单元测试的一个抽象的局面是你永远不会测试私有代码 - 只有公共接口.实际上,*x*Unit通常不能构造为能够访问被测试的单独类的私有方法.
问题是该类的其余部分都没有设置为处理单元测试.这是第一个将进行任何类型测试的例程.并且很难为主机类配置一组初始条件,这些条件允许我使用我想要的每组CalculateSpeed输入来测试调用.
我能看到的唯一选择是将这个私有计算移到它自己的TCarCalculateSpeed类中:
public class TCarCalculateSpeed
{
public function CalculateSpeed(float furlogs)
{
Result = furlogs * 23;
}
}
Run Code Online (Sandbox Code Playgroud)
一个完整的类,专门用于公开一种方法,它应该是私有的,这样我才能测试它?
类爆炸.
加上它是私人的.如果我希望它是公开的,我宁愿将其提升为公众可见度 - 至少我保存了一个单独的类.
我想添加一些单元测试; 但随着代码的变化,它只能以小块形式完成.我无法完全重新设计功能已有12年历史的软件,可能会破坏所有内容,因为我想测试一个内部计算.
我当前最好的想法是Test在我的Car课程中添加一个方法,然后调用它:
TCar Car = new TCar();
Car.RunTests;
public procedure TCar.RunTests
{
Check( CalculateSpeed(0) = 0);
Check( CalculateSpeed(1) = 23);
Check( CalculateSpeed(2) = 46);
Check( CalculateSpeed(88) = -1);
}
Run Code Online (Sandbox Code Playgroud)
但是现在我必须弄清楚如何TCar.RunTests被外部触发,外部TestRunner仅用于使用TestCase类.
注意:我已经尝试过我的damnest来混合一堆语言的语法.换句话说:语言不可知.
这实际上与语言无关,因为保护机制和绕过它们的策略随语言的不同而有很大差异。
但大多数语言确实以某种形式提供绕过,正如其他人指出的那样,有时在私有和公共之间存在中间保护,使测试变得更容易。
例如,在 Java 中,如果您确实需要,反射可以用于私有内容,并且可以将内容设置为受保护或包私有,以便您不需要反射。
一般来说,如果某些东西足够复杂以至于需要测试,那么它不应该作为私有方法或类隐藏在其他东西中。它正在做一些值得拥有自己阶级的事情。
与其担心类的数量,不如担心它们的大小和复杂性。许多遵守单一职责原则的小类比少数在内部做复杂事情的类要好。