Showing posts with label Test Automation. Show all posts
Showing posts with label Test Automation. Show all posts

Friday, April 06, 2007

GUI test automation of web applications

In course of my past projects, I've multiple times tried to establish effective GUI test automation and for some reasons my attempts always failed. It does not mean that automation was not created at all, but very low effectiveness for significant effort. One of the interesting side effect, that I've seen was that complex GUI test automation usually require someone's attention - you cannot just add it into task scheduler at 2 o'clock in the night, and get result in the morning.
I've tried it with the different people (sometime I even assign good developers into it), but still they encountered enormous amount of technical problems. So I've realized that its not the fault of the people, but rather fault of software. No matter whenever you are using cheap AutomatedQA TestComplete or expensive Mercury WinRunner/QTP, the tools are huge, pretend to do everything and but actually did each task with significant limitations. The worst thing about this is that if you encounter a problem, neither google nor support usually cannot help you.
Recently I was thinking about problem of automated periodic posting of some information on various web-sites. We've tried to automate it using TestComplete, but stability and speed was far from perfect. In fact it refuses to work through TaskScheduler at all, and you will need someone, who will manually run corresponding .bat file from time to time. In order to change this situation, I've start thinking about tools like NUnitASP. It looks lightweight and cool, but does not suite my needs, because of the nature of my task. Usually such type of sites are not really happy when someone is using robot to post data there, so they actively resisting it. I need an ability to click on links and fill fields in the actual browser.
So I was thinking - if I need a real browser to automate this task - why cannot I incorporate one in my C# program? Quick search shows me one good sample on codeproject. I've downloaded it and tweaked according to my needs and it works! I've running this on task scheduler completely unattended, and just getting results from there.
I'm going to post technical details and some point of time later, when I will polish them, but the idea of this post is very simple: if you need GUI test automation - consider writing your own tool for this. Of cause it is not free, and you will have to fight with non-trivial MS implementation of DOM, but this is the only thing you will have to fight - your own automation code will be very small and lightweight (mine is less than 300 lines now :)

Tuesday, April 03, 2007

FindWindowEx() does not always return child window controls

There was a task to control separate application via button clicks. We've created a small prototype, that can identify top-level window, and after that found necessary control inside this window using FindWindowEx. To my surprise it was not always working as I expected. Sometimes I was getting null instead of handle to the corresponding window. So I decided to create my own version of that method:


private static IntPtr WaitChild(IntPtr parent, string windowClass,
string windowCaption) {
IntPtr result = IntPtr.Zero;
do {
Thread.Sleep(10);
EnumChildWindows(parent, delegate(IntPtr hWnd, IntPtr lParam) {
StringBuilder className = new StringBuilder(200);
GetClassName(hWnd, className, 200);
StringBuilder caption = new StringBuilder(200);
GetWindowText(hWnd, caption, 200);
if (className.ToString() == windowClass &&
caption.ToString() == windowCaption)
result = hWnd;
return true;
}, IntPtr.Zero);
} while (result == IntPtr.Zero);
return result;
}

[DllImport("user32.dll")]
private static extern bool EnumChildWindows(IntPtr hwndParent,
EnumWindowsProc lpEnumFunc, IntPtr lParam);

private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
private static extern int GetWindowText(IntPtr hWnd,
[Out] StringBuilder lpString, int nMaxCount);

[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd,
StringBuilder lpClassName, int nMaxCount);

Sometimes it takes one or two loops while the window is finally appears on the screen, but it works pretty stable now