随着时间的推移,我通过重构函数改进了我的单元测试,因此它们是pure functions意味着一组输入始终产生相同的输出,而不依赖于任何类型的状态并且不会产生副作用。
偶尔我遇到的情况我不知道如何编写好的单元测试,例如函数(或对象)必须依赖于以前的值。为了演示的目的,我在这里包含了这个用于平均滤波器的代码摘录,但实际上我的问题非常普遍。
我创建CAvgFilter :: Clear方法的原因之一是,我可以始终确保过滤器在启动时以理想的方式响应。在启动时,CAvgFilter :: Push输出非常接近地跟踪输入,但是一旦m_samples列表已满,由于过滤,与CAvgFilter :: Push的输入的偏差就不那么明显了。
对于像这样的对象,我通常想要一种在检查输出时调用具有多个输入系列的方法的方法,理想情况下,我的单元测试尽可能少地依赖于数据排序(理想情况下没有)。
创建测试向量时,我经常从函数输出中记录数据,手动验证,然后将其用于将来的测试(以确保如果我稍后重构或修改它,类不会中断)。无论如何,我想到我不能在某个范围的中间使用任何系列的输入/输出。我必须从过滤器清除开始(或添加一些功能,否则将其初始化以用于测试目的)。任何人都可以就单元测试中如何解决这类问题提出一些建议吗?您是否始终在初始化状态下开始测试,或者您是否以某种方式提供单元测试以设置初始条件?
CAvgFilter::CAvgFilter(int length)
{
m_maxLength = length;
}
//pass the new value and receive the moving average
long CAvgFilter::Push(long newValue)
{
m_samples.push_back(newValue);
if ((int) m_samples.size() > m_maxLength)
{
m_samples.pop_front();
}
long sum = 0;
for (FILTER_CONTAINER_IT it = m_samples.begin(); it != m_samples.end(); ++it)
{
sum += *it;
}
return (sum / (long) m_samples.size()); //cast size() as long to preserve sign of the average value
}
void CAvgFilter::Clear(void)
{
m_samples.clear();
}
答案 0 :(得分:3)
(通常)您的情况很普遍。例如,状态机的行为取决于输入的历史记录。有很多解决方法。
与以往一样,不同方法也各有利弊。