Grzenio
Grzenio

Reputation: 36679

Programatically finding a message box and generating a click on a button

I am trying to automate testing of a winform application. I am running it in the same process as the test code, so it is fairly easy to find the .Net controls and simulate user action on them. I got however stuck a bit with a message box (created using the standard MessageBox.Show method). How can I get hold of it and simulate that a button is pressed?

Upvotes: 3

Views: 3352

Answers (7)

yoel halb
yoel halb

Reputation: 12711

While it's true (as some users suggested) that for Unit testing and even integration testing you should rather try to design the code in a way that you shouldn't have to deal in the testing process with the MessageBox.

However in functional and end to end testing you would most probably indeed be interested in testing the actual message box as well.

You can nowadays use many different libraries to perform this (I understand that this question is very old already, but StackOverflow is actually meant for anyone in the future as well).

Here is sample code using the FlaUI.UI3 library (code is based on FlaUI own test code but modified):

using var automation = new UIA3Automation();
var desk = automation.GetDesktop();

var searchFunc = () => desk.FindFirstChild(cf =>                                     
                    cf.ByProcessId(Process.GetCurrentProcess().Id)
                    // This is the className for the windows MessageBox
                   .And(cf.ByClassName("#32770")))
                .AsWindow();

var msgBox = Retry.WhileNull(searchFunc, TimeSpan.FromSeconds(10)).Result;   
msgBox.Should().NotBeNull();

var buttonName = "OK";  // Assuming the button you wish is the OK button
var yesButton = msgBox.FindFirstChild(cf => cf.ByName(buttonName )).AsButton();
yesButton.Should().NotBeNull();

yesButton.Invoke();

Upvotes: 0

Avram
Avram

Reputation: 4259

You can use autoit script system.

But i am suggest to separate the GUI and implementation, because basic principle of unit testing is "unit", where unit is class that separated from other classes or real world.
This principle give you good class design and help to avoid software eruption and lot of other good stuff..

Upvotes: 0

Gishu
Gishu

Reputation: 136673

I'd advise treating the underlying disease rather than the symptom. Take a few minutes to read these

In short, use an interface to separate out all modal dialog pop-ups - which are a pain in the neck for UI test automation. You can then substitute a mock implementation of the interface that does nothing or returns predetermined test values. The real implementation of course pops up the actual dialog modally... something like this (from the 2nd link)

public class UserInterrogator : IUserInterrogator
{
    private Form owner;

    public UserInterrogator(Form owner)
    {  this.owner = owner;    }

    public Font GetFontFromUser()  // member of the IUserInterrogator interface
    {
        FontDialog fd = new FontDialog();
        fd.ShowDialog( owner );
        return fd.Font;
    }
}

The easier approach is of course to write some code that finds the dialog and closes/kills it. I've seen some people have some success with Win32 APIs and NUnitForms ...

Upvotes: 6

pvieira
pvieira

Reputation: 1695

One of the best free tools is AutoHotKey.

Upvotes: 2

Henk Holterman
Henk Holterman

Reputation: 273784

If you know the caption (and it is unique) you can loop through Application.OpenForms to find it.

Upvotes: 2

Ray
Ray

Reputation: 1585

You probably will have to use WinAPI calls (FindWindowEx, ect) and send a messages of LMB down and up to a button handle.

Upvotes: 2

Ruben Bartelink
Ruben Bartelink

Reputation: 61893

  • codeplex.com/white - Free

  • testautomationfx.com - Commercial but very good

Upvotes: 3

Related Questions