【发布时间】:2013-07-25 18:58:22
【问题描述】:
我正在为一项服务进行一些测试自动化,并想出了一个巧妙的方法来将一些常见的设置和验证汇总到一个“会话”类中。
从概念上讲,测试用例可能如下所示:
using (var managerSession = new Session(managerRole))
{
// A manager puts some items in warehouse
}
using (var employeeSession = new Session(employeeRole))
{
// An employee moves items from warehouse to store
}
using (var customerSession = new Session(customerRole))
{
// A customer can buy items from the store
}
在 Session 对象构造函数中,我使用每个角色的适当身份验证等设置到我正在测试的服务的连接,并且在会话 Dispose() 方法中,我有一个公共验证块,例如,检查没有服务器在会话生命周期内引发了-side 错误或警告。
当然,这有点滥用 IDispose 模式,如果 using 块中的测试代码抛出异常并且验证块也抛出异常,则第二个异常将掩盖第一个异常。
从概念上讲,如果我们有这种情况:
using (var managerSession = new Session(managerRole))
{
Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job");
}
...并且断言失败或对 managerSession.DoJob() 的调用引发异常,那么我希望 Session Dispose() 方法跳过验证块,即
public void Dispose()
{
if (NoExceptionThrown())
{
Assert.IsFalse(this.serviceConnection.HasErrors(), "Service connection has errors");
}
this.serviceConnection.Dispose();
}
...这样,如果测试方法实际上因“经理没有完成他的工作”而失败,则该测试方法永远不会因“服务连接有错误”而失败
我的问题是:这里是否有可能实现“NoExceptionThrown()”方法?是否有一些可以检查的全局属性,或者隐藏在 Thread.CurrentThread 中的东西可以使用?
更新:
我的问题是不是如何重构这个:-)
我当然可以改用这种模式:
Session.ForRole(managerRole, (session) => { /* Test code here */ });
静态方法 ForRole() 定义如下
public static void ForRole(Role r, Action<Session> code)
{
var session = new Session(r);
try
{
code(session);
Assert.IsFalse(session.serviceConnection.HasErrors());
}
finally
{
session.Dispose();
}
}
但我很好奇是否存在某种方式来获取如上所述的异常状态。
【问题讨论】:
-
两件事。首先,是的,这是在滥用
IDisposable。使用IDisposable表示“我拥有一个应该尽快释放的非托管资源”。让它意味着别的东西会使你的代码难以阅读。其次,您关心任何异常,还是只关心未捕获异常?假设测试代码抛出异常,捕获它并正常完成。应该标记吗? -
啊,我只关心未捕获异常。我会更新问题...
-
至于滥用 IDisposable:我实际上更担心错过每个会话的通用验证,而不是潜在的错误屏蔽,所以这个问题更像是一个“很高兴拥有”的功能。实际的测试代码块是 10 到 100 行 UI 自动化代码,我们已经发现了未检测到的缺陷,因为其中一个块中遗漏了一个验证步骤(或报告在错误的块中)。