13

delphiXtremeに関するこの興味深いブログ記事で、 DUnit の組み込み GUI テスト機能 (基本的には、GUI でアクションを呼び出すためのいくつかのユーティリティ関数を持つTGUITestCaseユニットで定義された代替テスト ケース クラス) について読みました。GUITestingモーダル フォームでは機能しないことに気付くまでは、とても満足していました。たとえば、最初のボタンがモーダル構成フォームを表示する場合、次のシーケンスは機能しません。

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

2 つ目Clickは、モーダル フォームが閉じられたときにのみ実行されます。これは手動で行う必要があります。

モーダルフォームがバックグラウンドでどのように機能するかについてはよくわかりませんが、この動作を回避する方法があるはずです。ShowModal素朴に、「メインスレッド」の応答性を維持するために、「スレッド内」を何らかの形で実行したいと考えています。ShowModalスレッドで実行すると、おそらくすべてが台無しになることがわかりました。代替手段はありますか?のブロッキング性質を回避する方法はあり ShowModalますか? Delphi での GUI テストの経験はありますか?

外部ツール (QA などから) については知っており、それらのツールを使用していますが、この質問は IDE 内での GUI テストに関するものです。

ありがとう!

4

2 に答える 2

22

ShowModal;を呼び出してモーダルフォームをテストすることはできません。なぜなら、あなたが非常に正しく発見したように、モーダルフォームがユーザーの操作を待っている間、テストケースコードが「一時停止」する結果になるからです。

ShowModalこれは、フォームが閉じるまで終了しない「セカンダリメッセージループ」に切り替わるためです。

ただし、モーダルフォームは引き続きテストできます。

  1. 通常の方法を使用して、通常のモーダルフォームを表示します。 Show
  2. これにより、テストケースコードを続行し、ユーザーアクションをシミュレートできます。
  3. これらのアクションと効果は、通常どおりテストできます。
  4. モーダルフォームに非常に特有の追加のテストが必要になります。
    1. モーダルフォームは通常、モーダル結果を設定することで閉じられます。
    2. 使用したという事実はShow、モーダル結果を設定してもフォームが閉じられないことを意味します。
    3. 「OK」ボタンのクリックをシミュレートする場合は、これで問題ありません。
    4. ModalResultが正しいことを簡単に確認できます。

警告

この手法を使用して、特定のモーダルフォームを非モーダルで明示的に表示することにより、特定のモーダルフォームをテストできます。ただし、モーダル形式(エラーダイアログなど)を示すテスト対象のコードは、テストケースを一時停止します。

サンプルコードでさえClick ('OpenConfigButton');、ShowModalが呼び出され、その方法でテストすることはできません。

これを解決するには、「showコマンド」をアプリケーションに挿入できるようにする必要があります。依存性注入に慣れていない場合は、YouTubeで入手できるMiskoHeveryのCleanCodeTalksビデオをお勧めします。次に、テスト中に、モーダルフォームを表示しない適切なバージョンの「showコマンド」を挿入します。

たとえば、[OK]ボタンがクリックされたときに検証が失敗した場合、モーダルフォームにエラーダイアログが表示されることがあります。

それで:

1)エラーメッセージを表示するためのインターフェイス(または抽象基本クラス)を定義します。

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

2)テストしているフォームは、インターフェース(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)本番コードに使用/挿入されたデフォルトバージョンのIErrorMessageは、通常どおりメッセージを表示します。

4)テストコードは、テストが一時停止されるのを防ぐために、モックバージョンの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;
于 2011-07-04T16:37:32.700 に答える
11

実際には、Delphi でモーダル ウィンドウをテストする方法があります。モーダル ウィンドウが表示されている場合でも、アプリケーションはウィンドウ メッセージを処理するため、モーダル ウィンドウを表示する直前にヘルパー ウィンドウにメッセージを投稿できます。次に、メッセージはモーダル ループから処理され、モーダル ウィンドウがまだ表示されている間にコードを実行できます。

最近、私はこの問題を処理するための単純なライブラリに取り組んでいます。コードはhttps://github.com/tomazy/DelphiUtils (FutureWindows.pas を参照)からダウンロードできます。

使用例:

uses
  Forms,
  FutureWindows;

procedure TFutureWindowsTestCase.TestSample;
begin
  TFutureWindows.Expect(TForm.ClassName)
    .ExecProc(
       procedure (const AWindow: IWindow)
       var
         myForm: TForm;
       begin
         myForm := AWindow.AsControl as TForm;

         CheckEquals('', myForm.Caption);

         myForm.Caption := 'test caption';
         myForm.Close();
       end
    );

  with TForm.Create(Application) do
  try
    Caption := '';

    ShowModal();

    CheckEquals('test caption', Caption);
  finally
    Free;
  end;
end;
于 2011-08-11T10:25:29.960 に答える