Delphi GUI Testing and Modal Forms

Delphi GUI Testing and Modal Forms

11 April 2024 Stephan Petzl Leave a comment Tech-Help

GUI testing is an integral part of software development, ensuring that user interactions with an application are functioning as expected. In Delphi, GUI testing can present certain challenges, particularly when dealing with modal forms. Modal forms, by design, pause the code execution until the form is closed, which can interrupt automated testing scripts. This article provides a guide on how to test modal forms within Delphi applications effectively.

Understanding Modal Forms in Testing

When a modal form is displayed using the ShowModal method, it initiates a secondary message loop that does not exit until the form is closed. This behavior causes automated test case code to ‘pause’, waiting for user interaction, which is not ideal for GUI testing scenarios.

Testing Modal Forms Non-Modally

To continue with automated testing without manual intervention, modal forms need to be tested in a non-modal state. Here’s how you can achieve this:

  1. Show the usually modal form using the Show method instead of ShowModal. This allows your test case code to continue executing and simulate user actions on the form.
  2. Since the form is shown non-modally, the ModalResult property will not close the form. You can simulate user actions, such as clicking the “Ok” button, and then check if the ModalResult is set correctly.

Injecting Show Commands for Testability

To test code that inherently calls ShowModal, such as displaying an error dialog, you need to make your “show commands” injectable. This technique involves using dependency injection to allow for a mock implementation during testing, which does not pause the test execution.

Steps to Implement Injectable Show Commands:

  1. Define an interface (or abstract base class) for displaying error messages. For instance:
  2. IErrorMessage = interface
      procedure ShowError(AMsg: String);
    end;
    
  3. Have the form under test hold a reference to this interface and use it to show errors when needed.
  4. procedure TForm1.OnOkClick;
    begin
      if (Edit1.Text = '') then
        FErrorMessage.ShowError('Please fill in your name');
      else
        ModalResult := mrOk;
    end;
    
  5. For production code, use a default implementation of this interface that displays messages as usual.
  6. During testing, inject a mock implementation that prevents the form from pausing the test and allows you to verify that the correct error message is generated.
  7. procedure TTestClass.TestValidationOfBlankEdit;
    begin
      Form1.Show; //non-modally
      Click('OkButton');
      CheckEquals(0, Form1.ModalResult);
    end;
    
  8. Enhance the mock implementation to verify the correct message text:
  9. TMockErrorMessage = class(TInterfacedObject, IErrorMessage)
    private
      FLastErrorMsg: String;
    protected
      procedure ShowError(AMsg: String);
    public
      property LastErrorMsg: String read FLastErrorMsg;
    end;
    

Conclusion

By showing modal forms non-modally and injecting show commands, you can effectively test GUI components in Delphi that would otherwise halt automated test execution. This approach allows for a more seamless and continuous testing process, ensuring that your application’s user interface behaves as expected even when modal dialogs are involved.

Like this article? there’s more where that came from!