6

我正在尝试使用 DUnit 对其主窗体为其自身创建动态框架的应用程序运行 GUI 单元测试。我已经能够将应用程序测试的主窗体创建为测试用例中的窗体并访问其菜单项等。

当应用程序尝试动态创建框架时,问题就出现了。框架的资源读取达到需要窗口句柄的程度(在我的情况下,设置选项卡表的标题)。这里它从 TWinControl.GetHandle 到 TWinControl.CreateWnd 和 TCustomFrame.CreateParams。

在这个 CreateParams 中,代码说:

  if Parent = nil then
    Params.WndParent := Application.Handle;

这就是差异发生的地方。当我运行实际的应用程序(不在测试中)时,这里的 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]);

我想尝试解决这个问题(通常是所有测试问题),而不是仅仅因为测试而修改“生产”代码。您能否提供任何线索,说明我是否可以以某种方式将“应用程序”强制为其他东西,或者以其他方式解决这个问题?

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

4

2 回答 2

2

您应该创建一个 TForm,并将您的 frame.parent 设置为该 TForm,而不是解决设置 Application.Handle 的方法。

//Dunit Test Scaffolding code...Set up a workable environment for the test:
aForm := TForm.Create(nil);
aFrame := TFrame.Create(aForm);
aFrame.Parent := aForm;

在真实的应用程序中,框架将有一个父级(通常是窗口、TForm 或 TPanel 的父级)。您试图告诉框架在没有父级的情况下运行,而 TFrame 并非旨在执行此操作。

于 2012-02-22T20:54:15.940 回答
0

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

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

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

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

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

于 2012-02-23T09:30:09.530 回答