2

使用私有访问器测试一段代码有什么缺点吗?

我正在权衡仅使用私有访问器来测试我的 GUI 的选项,而不是公开公开的方法/属性。

这将允许我需要进行一些 GUI 测试,我只是想确保它们在使用私有访问器的行为方式时没有任何隐藏的“陷阱”。

4

3 回答 3

1

最好不要使用它们,而是尝试找出是否可以注入任何依赖项。除非您正在处理想要使用私有访问器创建一些单元测试的遗留代码,否则我建议不要使用它们,即使在这种情况下,我也建议您暂时这样做,直到您重构遗留代码。

于 2012-12-07T20:49:00.993 回答
1

回顾一下,您的既定目标是:

我正在权衡仅使用私有访问器来测试我的 GUI 的选项...这将允许我需要进行一些 GUI 测试...

简而言之,是的,有陷阱。您正在测试的代码仍然与用户界面紧密耦合。

在评论中,您将您的目标/问题阐明为:

如果我想测试,拖/放怎么办。自定义控件,覆盖事件?

我只能说欢迎登机。软件行业为此苦苦挣扎了近半个世纪。事实仍然是测试 UI 很难,真的很难。是的,您可以使用一段与 UI 元素紧密耦合的代码并尝试将其自动化;但是,您将竭尽全力对抗糟糕的假设。

可测试 UI 的“技巧”不是让您的 UI 可测试,而是从 UI 中删除您想要测试的代码。因此,N-Tier 应用程序开发和演示设计模式(如 MVC、MVVM 等)得到广泛接受。

请参阅以下内容:

许多这些设计模式背后的主要目标或驱动力是消除行为和表示之间的紧密耦合。这使您能够在没有用户界面的情况下测试诸如拖放之类的行为。我的建议是查看模式,选择你喜欢的模式,然后在编写单元测试时开始重构代码。

另一种考虑编写用于测试的 UI 的方法是从用户界面代码中删除每个 if、else、for、while、switch 或其他控制语句。UI 的最终“外壳”应该非常适应变化。在使用依赖反射的数据绑定之类的东西时要小心(这通常是一种可接受的做法)。这样做的主要缺点是编译器无法告诉您成员不再存在。

更新

@timmy 你写道:

...例如,如果我想测试鼠标点击行为...

那么鼠标点击行为不能移动到控制器而不是嵌入到表单中呢?我猜“关闭”按钮可能有问题,但除此之外,为什么不将逻辑移到另一个可以测试的类呢?

顺便说一句,您不必只选择一种模式 MVC、MVVM 等,它们是“指南”或“建议”而不是硬规则,所以不要对此感到可笑。只需尝试将逻辑与 UI 分开并独立测试即可。例如,也许您的“单击”事件更适合简单的命令类?使用命令模式很容易,新建一个对象并执行它。考虑文件夹复制表单的示例代码:

private void OnCopyClick(object sender, EventArgs args)
{
    var cmd = new MyCopyCommand(this.FolderPath, this.txtTargetFolderPath.Text);
    new ErrorHandler(this).Perform(cmd);
}

这很好用,除了提供命令的内容之外没有“真正的”逻辑,也没有条件代码路径。请注意,我们甚至不直接调用该命令,而是将其交给可以适当处理错误的人。通常这个'ErrorHandler'会被提供给表单而不是直接构造,但你明白了。

由此我们应该能够很容易地验证 MyCopyCommand 的正确行为。最后,您应该在 UI 中使用一堆“平面功能”,即。没有嵌套或花括号的函数。当然,这是一条经验法则,不要走极端,以免妨碍您的工作效率。

我知道这可能看起来需要做很多工作,但说实话,当你已经在努力编写一组测试时,情况并非如此。您可以高效编写可靠的代码。你只需要知道什么时候作弊,什么时候不作弊。这伴随着经验,在 20 年后,其中 10 位编写 NUnit 的人,我仍然偶尔会失败。当由于您没有这样做而导致故障时,首先从 UI 中提取逻辑,然后编写一个单元测试来证明它已损坏,然后修复它。

于 2012-12-10T22:16:26.907 回答
0

除了 AD.NET 所说的。我只能在测试中使用这些私有属性,直到我完成重构(到模型视图控制器、模型视图演示器、模型视图视图模型),这样我根本不需要测试 GUI!

于 2012-12-07T20:54:29.257 回答