gpt4 book ai didi

Delphi GUI 测试和模态表单

转载 作者:行者123 更新时间:2023-11-28 19:41:13 25 4
gpt4 key购买 nike

delphiXtreme 上这篇有趣的博文中我了解了 DUnit 的内置 GUI 测试功能(基本上是在 GUITesting 单元中定义的替代测试用例类 TGUITestCase,它具有多个用于在 GUI 中调用操作的实用函数)。我对它很满意,直到我注意到它不适用于模态表单。例如,如果第一个按钮显示模态配置表单,则以下序列将不起作用:

Click ('OpenConfigButton');
Click ('OkButton');

第二个 Click 仅在模态窗体关闭时执行,我必须手动执行此操作。

我不太了解模态表单在后台如何工作,但必须有某种方法来规避这种行为。天真地,我想以某种方式“在线程中”执行 ShowModal,以便“主线程”保持响应。现在我知道在线程中运行 ShowModal 可能会搞砸一切。有没有其他选择?有什么方法可以规避 ShowModal 的阻塞性质?有人有在 Delphi 中进行 GUI 测试的经验吗?

我知道外部工具(来自 QA 或其他人)并且我们使用这些工具,但这个问题是关于 IDE 中的 GUI 测试。

谢谢!

最佳答案

您不能通过调用ShowModal 来测试模态形式;因为正如您已经非常正确地发现的那样,这会导致您的测试用例代码在模态表单等待用户交互时“暂停”。

原因是 ShowModal 将您切换到一个“辅助消息循环”,该循环在表单关闭之前不会退出。

但是,模态形式仍然可以被测试。

  1. 使用正常 Show 方法显示通常的模态形式
  2. 这允许您的测试用例代码继续并模拟用户操作。
  3. 这些 Action 和效果可以正常测试。
  4. 您将需要一个针对模态形式的额外测试:
    1. 模态窗体通常通过设置模态结果来关闭。
    2. 您使用 Show 的事实意味着不会通过设置模态结果关闭表单。
    3. 这很好,因为如果您现在模拟单击“确定”按钮...
    4. 您可以简单地检查 ModalResult 是否正确。

警告

您可以使用此技术通过显式非模态显示来测试特定模态形式。但是,任何显示模态形式的被测代码(例如错误对话框)都会暂停您的测试用例。

即使是您的示例代码:Click ('OpenConfigButton'); 也会导致调用 ShowModal,并且无法以这种方式进行测试。

要解决此问题,您需要将“显示命令”注入(inject)到您的应用程序中。如果您不熟悉依赖项注入(inject),我推荐 You Tube 上的 Misko Hevery 的 Clean Code Talks 视频。然后在测试时,您注入(inject)一个合适的“显示命令”版本,它不会显示模态形式。

例如,如果在单击“确定”按钮时验证失败,您的模态表单可能会显示一个错误对话框。

所以:

1) 定义一个接口(interface)(或抽象基类)来显示错误信息。

IErrorMessage = interface
procedure ShowError(AMsg: String);
end;

2) 您正在测试的表单可以包含对接口(interface)的注入(inject)引用 (FErrorMessage: IErrorMessage),并在验证失败时使用它来显示错误。

procedure TForm1.OnOkClick;
begin
if (Edit1.Text = '') then
FErrorMessage.ShowError('Please fill in your name');
else
ModalResult := mrOk; //which would close the form if shown modally
end;

3) 为生产代码使用/注入(inject)的默认版本的 IErrorMessage 将像往常一样简单地显示消息。

4) 测试代码将注入(inject)模拟版本的 IErrorMessage 以防止您的测试被暂停。

5) 您的测试现在可以执行通常会显示错误消息的案例。

procedure TTestClass.TestValidationOfBlankEdit;
begin
Form1.Show; //non-modally
//Do not set a value for Edit1.Text;
Click('OkButton');
CheckEquals(0, Form1.ModalResult); //Note the form should NOT close if validation fails
end;

6) 您可以进一步使用模拟 IErrorMessage 来实际验证消息文本。

TMockErrorMessage = class(TInterfaceObject, IErrorMessage)
private
FLastErrorMsg: String;
protected
procedure ShowError(AMsg: String); //Implementaion trivial
public
property LastErrorMsg: String read FLastErrorMsg;
end;

TTestClass = class(TGUITesting)
private
//NOTE!
//On the test class you keep a reference to the object type - NOT the interface type
//This is so you can access the LastErrorMsg property
FMockErrorMessage: TMockErrorMessage;
...
end;

procedure TTestClass.SetUp;
begin
FMockErrorMessage := TMockErrorMessage.Create;
//You need to ensure that reference counting doesn't result in the
//object being destroyed before you're done using it from the
//object reference you're holding.
//There are a few techniques: My preference is to explicitly _AddRef
//immediately after construction, and _Release when I would
//otherwise have destroyed the object.
end;

7) 现在之前的测试变成了:

procedure TTestClass.TestValidationOfBlankEdit;
begin
Form1.Show; //non-modally
//Do not set a value for Edit1.Text;
Click('OkButton');
CheckEquals(0, Form1.ModalResult); //Note the form should NOT close if validation fails
CheckEqulsString('Please fill in your name', FMockErrorMessage.LastErrorMsg);
end;

关于Delphi GUI 测试和模态表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6573446/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com