在测试中使用表单
Using forms in tests
我有一个使表单出现的集成测试。它不是编码 UI 测试,它只是碰巧使用表单的测试。现在先不讨论,总的来说这是个好主意还是不好,在我的情况下是有必要的。
如果一切按顺序运行,则出现窗体,调用一些函数,关闭窗体,进行断言,单元测试通过。
但是,如果出现问题...
如果发生异常,那么我得到的不是失败的单元测试,而是 "Unhadled exception occurred" 对话框。此对话框当然会停止应用程序,直到有人单击 "ok"(并且没有人在 CI 服务器上单击 "ok"),然后测试通过。 (或者至少它被标记为绿色。)
问题是,我怎样才能改回这种行为?
经过一些研究,我发现有 2 top level exception handlers,一个用于应用程序,一个用于 UI 线程。
我是这样设置的:
Application.ThreadException += (o, e) => MessageBox.Show("hello ui thread");
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += (o, e) => MessageBox.Show("hello app");
然后,当发生异常时,我得到 "hello ui thread" 消息框。
我可以通过某种方式设置 Application.ThreadException
来恢复原始行为吗?还有其他方法可以解决这个问题吗?
更新
正如一些回答者指出的那样,我手上有一段非常糟糕的代码,这无可否认。相信我,UI 和业务逻辑没有充分分离的事实远不是最糟糕的事情。
我不是来找借口的,但我可以诚实地说,这不是我的错。这段代码是我素未谋面的人写的,已经不在我公司工作了。 (有一个非常好的理由。)
关于这段代码的作用没有足够的文档或规范,但遗憾的是它是软件的重要组成部分,我们不能破坏它,也不能让它比现在更糟糕。
我必须重构它,是的。我 *am* 重构它。但为此我需要先写一些测试。为了编写一些测试,我需要重构它。鸡蛋和鸡肉就是这样。
现在我不需要关于好的软件设计的一般性建议。我不需要判断我所处的情况。我需要对我提出的具体技术问题进行具体的技术解答。
关闭
关于 "if you were one of my developers" 评论。我想你会非常高兴有一个开发人员来清理别人造成的混乱。
运行 在 CI 服务器上进行任何类型的 UI 测试都不是一个好主意,因为您所看到的确切行为。更改生产代码以适合您的测试也不是一个好主意。
如果我处于这种情况,我会做两件事。首先,我将重构代码以确保在没有标准单元测试形式的 UI 的情况下可以驱动尽可能多的表单功能。这可以是演示者、控制器或某种视图模型的形式。
其次,我将从 CI 套件中删除使用实际表单的集成测试,并且仅 运行 手动将其作为最终集成套件的一部分,以确保连接视图模型正确。
在你的例子中,如果你设置你的逻辑模块,如果所有测试都通过表单测试不会抛出任何异常,那么你可以继续运行你的测试,如果如果之前的测试失败,您将表单测试设置为不 运行。
通过这段代码,我可以从主线程上的 UI 线程重新抛出异常:
[TestMethod]
public void Test1()
{
Exception thread_ex = null;
ThreadExceptionEventHandler eventHandler = (o, e) =>
{
thread_ex = e.Exception; //store the exception from the UI thread
Application.ExitThread(); //kill the UI thread
};
Application.ThreadException += eventHandler;
DoTest(); //do the test
Application.ThreadException -= eventHandler;
if (thread_ex != null) //if an exception was stored
throw thread_ex; //throw it again on the main thread
}
因为我使用Application.ThreadException
,"Unhandled exception occurred"对话框不会出现。
我有一个使表单出现的集成测试。它不是编码 UI 测试,它只是碰巧使用表单的测试。现在先不讨论,总的来说这是个好主意还是不好,在我的情况下是有必要的。
如果一切按顺序运行,则出现窗体,调用一些函数,关闭窗体,进行断言,单元测试通过。
但是,如果出现问题...
如果发生异常,那么我得到的不是失败的单元测试,而是 "Unhadled exception occurred" 对话框。此对话框当然会停止应用程序,直到有人单击 "ok"(并且没有人在 CI 服务器上单击 "ok"),然后测试通过。 (或者至少它被标记为绿色。)
问题是,我怎样才能改回这种行为?
经过一些研究,我发现有 2 top level exception handlers,一个用于应用程序,一个用于 UI 线程。
我是这样设置的:
Application.ThreadException += (o, e) => MessageBox.Show("hello ui thread");
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += (o, e) => MessageBox.Show("hello app");
然后,当发生异常时,我得到 "hello ui thread" 消息框。
我可以通过某种方式设置 Application.ThreadException
来恢复原始行为吗?还有其他方法可以解决这个问题吗?
更新
正如一些回答者指出的那样,我手上有一段非常糟糕的代码,这无可否认。相信我,UI 和业务逻辑没有充分分离的事实远不是最糟糕的事情。
我不是来找借口的,但我可以诚实地说,这不是我的错。这段代码是我素未谋面的人写的,已经不在我公司工作了。 (有一个非常好的理由。)
关于这段代码的作用没有足够的文档或规范,但遗憾的是它是软件的重要组成部分,我们不能破坏它,也不能让它比现在更糟糕。
我必须重构它,是的。我 *am* 重构它。但为此我需要先写一些测试。为了编写一些测试,我需要重构它。鸡蛋和鸡肉就是这样。
现在我不需要关于好的软件设计的一般性建议。我不需要判断我所处的情况。我需要对我提出的具体技术问题进行具体的技术解答。
关闭
关于 "if you were one of my developers" 评论。我想你会非常高兴有一个开发人员来清理别人造成的混乱。
运行 在 CI 服务器上进行任何类型的 UI 测试都不是一个好主意,因为您所看到的确切行为。更改生产代码以适合您的测试也不是一个好主意。
如果我处于这种情况,我会做两件事。首先,我将重构代码以确保在没有标准单元测试形式的 UI 的情况下可以驱动尽可能多的表单功能。这可以是演示者、控制器或某种视图模型的形式。
其次,我将从 CI 套件中删除使用实际表单的集成测试,并且仅 运行 手动将其作为最终集成套件的一部分,以确保连接视图模型正确。
在你的例子中,如果你设置你的逻辑模块,如果所有测试都通过表单测试不会抛出任何异常,那么你可以继续运行你的测试,如果如果之前的测试失败,您将表单测试设置为不 运行。
通过这段代码,我可以从主线程上的 UI 线程重新抛出异常:
[TestMethod]
public void Test1()
{
Exception thread_ex = null;
ThreadExceptionEventHandler eventHandler = (o, e) =>
{
thread_ex = e.Exception; //store the exception from the UI thread
Application.ExitThread(); //kill the UI thread
};
Application.ThreadException += eventHandler;
DoTest(); //do the test
Application.ThreadException -= eventHandler;
if (thread_ex != null) //if an exception was stored
throw thread_ex; //throw it again on the main thread
}
因为我使用Application.ThreadException
,"Unhandled exception occurred"对话框不会出现。