DUnit GUI测试:我可以强制"应用"到不同的"形式"吗?

Del*_*ser 6 delphi user-interface dunit

我正在尝试使用DUnit对一个应用程序进行GUI单元测试,该应用程序的mainform动态地为自己创建帧.我已经能够在测试用例中创建应用程序到测试的mainform作为表单并访问其菜单项等.

当应用程序尝试动态创建框架时,问题就出现了.框架的资源读取到了需要窗口句柄的位置(在我的例子中,设置标签页的标题).它从TWinControl.GetHandle到TWinControl.CreateWnd和TCustomFrame.CreateParams.

在这个CreateParams中,代码说:

  if Parent = nil then
    Params.WndParent := Application.Handle;
Run Code Online (Sandbox Code Playgroud)

这就是差异发生的地方.当我运行实际的应用程序(不在测试中)时,Application.Handle返回一个非零数字,流程继续正常.但是在DUnit测试应用程序中,Application.Handle在这里返回0.这会导致TWinControl.CreateWnd中的代码引发异常,告知该帧没有父代:

  with Params do
  begin
    if (WndParent = 0) and (Style and WS_CHILD <> 0) then
      if (Owner <> nil) and (csReading in Owner.ComponentState) and
        (Owner is TWinControl) then
        WndParent := TWinControl(Owner).Handle
      else
        raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);
Run Code Online (Sandbox Code Playgroud)

我想尝试解决这个问题(一般来说,所有测试问题)而不是仅仅因为测试而修改"生产"代码.您是否可以提供任何关于我是否可以某种方式强制将"应用程序"强加给其他东西,或以其他方式解决此问题的线索?

查看代码,一个可能的其他解决方案可能是尝试让所有者(我的应用程序测试的"MainForm",即我想要获得的句柄)在执行时处于csReading状态这个框架在测试中创建,但至少最初看起来并不是那么简单.

Del*_*ser 0

感谢所有的评论和回复!我相信已经解决了这些问题,至少是到目前为止发现的问题。我将在下面总结我的发现和最终情况(以防其他人发现这些有用)。

我有一个继承自 TTestSetup 的测试装饰器类,它包含对其在必要时创建的虚拟(主)表单的引用。

我还找到了一种使用如下方法在运行时切换 Application.MainForm 的方法:http://www.swissdelphicenter.ch/torry/showcode.php ?id=665

在测试装饰器 SetUp 方法中,我首先创建虚拟表单,然后将其设置为应用程序的主表单(此处可能不需要此设置)。

然后我有一个测试用例类(继承自 TGUITestCase),每个测试都会运行其 SetUp 和 TearDown 。在此设置中,我创建了正在测试的主窗体,然后将其设置为应用程序的主窗体。然后,在测试用例的 TearDown 中进行测试后,我再次将虚拟表单设置为应用程序的主表单,并且仅在调用 Close 并 Free 到我正在测试的主表单之后。否则,释放当前为 Application.MainForm 的窗体将导致整个 DUnit 应用程序终止。