Friday, October 30, 2009

WCF Service in IronPython

Until IronPython 2.6, it was not possible to create WCF service host in pure IronPython. The closest way was to create stub in C# and subclass it in IronPython or create the whole service in C# and run it from IronPython. It is now much simpler with IronPython 2.6 although you still have to write a little C# code.

Simple WCF service implemented in C# looks like this:

TestServiceInterface.cs
using System;
using System.ServiceModel;

namespace TestServiceInterface
{
    [ServiceContract]
    public interface ImyService
    {
        [OperationContract]
        string GetData(int value);
    }
}

TestService.cs
using System;
using System.ServiceModel;
using TestServiceInterface;

namespace myWcfService
{
    public class myService : ImyService
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
    }

    public class mySvc
    {
        public static void Main()
        {
            ServiceHost sh = new ServiceHost(
     typeof(myService),
     new Uri("http://localhost:9000/myWcfService"));
   sh.AddServiceEndpoint(
     typeof(ImyService),
     new BasicHttpBinding(),
        "");
            sh.Open();
            Console.WriteLine("Press  to terminate\n");
            Console.ReadLine();
            sh.Close();
        }
    }
}

You build it:
csc /target:library TestServiceInterface.cs
csc /r:TestServiceInterface.dll TestService.cs

The reason I put TestServiceInterface into separate file is that you cannot create interfaces in IronPython. So this is the only part written in C# when implementig WCF service in IronPython.

The implementation then looks like this:

TestService.py
import clr
import clrtype
clr.AddReference('System.ServiceModel')
clr.AddReference('TestServiceInterface')
from TestServiceInterface import ImyService
from System import Console, Uri
from System.ServiceModel import (ServiceHost, BasicHttpBinding,
        ServiceBehaviorAttribute, InstanceContextMode)
ServiceBehavior = clrtype.attribute(ServiceBehaviorAttribute)

class myService(ImyService):
    __metaclass__ = clrtype.ClrMetaclass
    _clrnamespace = "myWcfService"
    _clrclassattribs = [
            ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]

    def GetData(self, value):
        return "IronPython: You entered: %s" % value

sh = ServiceHost(
        myService(),
        Uri("http://localhost:9000/myWcfService")
    )
sh.AddServiceEndpoint(
        clr.GetClrType(ImyService),
        BasicHttpBinding(),
        "")
sh.Open()
Console.WriteLine("Press  to terminate\n")
Console.ReadLine()
sh.Close()

The myService class must have InstanceContextMode.Single ServiceBehavior attribute because we are passing service instance to the ServiceHost constructor. This is done via new __clrtype__ metaclass. See the error if we don't use the attribute. I was not able to pass type into the ServiceHost constructor.

To test the service, you can use C# or IronPython client implementation:

TestClient.cs
using System;
using System.ServiceModel;
using TestServiceInterface;

namespace myWcfClient
{
    public class cli
    {
        public static void Main()
        {
   ChannelFactory mycf = new ChannelFactory(
     new BasicHttpBinding(),
        new EndpointAddress("http://localhost:9000/myWcfService"));
   ImyService wcfcli = mycf.CreateChannel();
   Console.WriteLine("Calling GetData(33) returns:\n{0}", wcfcli.GetData(33));
        }
    }
}

TestClient.py
import clr
clr.AddReference('System.ServiceModel')
import System.ServiceModel
clr.AddReference('TestServiceInterface')
from TestServiceInterface import ImyService

mycf = System.ServiceModel.ChannelFactory[ImyService](
        System.ServiceModel.BasicHttpBinding(),
        System.ServiceModel.EndpointAddress("http://localhost:9000/myWcfService"))
wcfcli = mycf.CreateChannel()
print "WCF service returned:\n%s" % wcfcli.GetData(11)

Disadvantages:
  • You can have only single instance of the service because you are passing the service instance instead of service type.
  • You cannot easily use .config file to configure your service.

Note: If you see closing tags (e.g. enter or ImyService) at the end of listings, it looks like SyntaxHighlighter bug in Google Chrome...

Thursday, September 24, 2009

How to clone VirtualBox virtual machine

VirtualBox is great piece of software for virtualization. I like it more than VMWare or VirtualPC. The downside of it is its lack of easy cloning or copying capabilities. There are none. And because everything in VirtualBox has UUID (guid), pure file copy does not work well.

All advices I have seen were about: create the new virtual machine manually, clone HDD .vdi file with  VBoxManage clonevdi command and attach it to the newly created virtual machine. Manually!?

That's why I've created a simple Python script that cares about exporting and importing virtual machines (Thanks for the VirtualBox 3 SDK!). When exporting, you can select the virtual machine and snapshot you want to export:



The exported machines are stored in exp folder at the script file. The time stamp is added to the machine name for unique identification. When importing, you are offered with the saved virtual machines and you simply choose one. Of course you can copy the exported machine to different computer (having the same VirtualBox versions is recommended).

The script is very simple and targeted to my needs. That means it exports only primary HDD and network adapter 0. It does not export CD/DVD-ROM, Floppy nor Serial ports.

Try it and let me know whether it's helpful: download script (it requires ConfigObj 4)

Update 1. 10. 2009: I struggled running the script on my new Win 7 64-bit system. It complained class is not registered for VirtualBox.Session. The reason was mixing 32-bit and 64-bit programs - see the explanation. If you use 64-bit OS, you have to have installed 64-bit version of Python and pywin32!

Saturday, May 16, 2009

Pycon 2009: Functional Testing of Desktop Applications

Here is a link to Michael Foord talk at Pycon 2009 in Chicago about functional testing of desktop applications:

Functional Testing of Desktop Applications
Many advocates of unit testing believe that testing desktop (GUI) applications is so difficult as to not be worth it. Not only is it possible, but 'functional testing' (testing an application from the point of view of the user) is an important part of an agile development process.

I watched it yesterday and it is very good!

Friday, May 15, 2009

Testing an unknown application

From time to time you may need to test an unknown application. I have encounter it when I needed to test our installation program. The task was simple - install the application for automated smoke tests. In such cases I gladly return to Accessibility.

Let's pretend our testing application is not written in .NET and the only way how to explore it is through the accessibility (AccExplorer):



All we need to do is to access Accessibility objects from IronPython. There is a project called Managed Windows API that nicely wraps accessibility for .NET. It also wraps other Win32 API calls (mouse clicks etc.) but I stay with Win32API.dll because of my laziness :-).

Utilizing the Managed Windows API you can control the accessibility objects. Here is the snippet:
import clr
# Win32API provide access to Win32 API functions
clr.AddReference('Win32API')
from Win32API import Win32API
# ManagedWinapi provide access to Accessibility objects
clr.AddReference('ManagedWinapi')
import ManagedWinapi.Accessibility as ma
import ManagedWinapi.Windows as mw

def GetGUIATWindow():
""" Return GUIAT_PoC window accessibility object. """
def callback(aWindow):
return aWindow.Title == 'GUIAT - Proof of Concept'
guiat_window = mw.SystemWindow.FilterToplevelWindows(callback)
# assume guiat_window is list with just one object
return ma.SystemAccessibleObject.FromWindow(guiat_window[0],
ma.AccessibleObjectID.OBJID_WINDOW)

guiat_acc = GetGUIATWindow()
# position of the 'New listbox item' text box
pos = guiat_acc.Children[3].Children[1].Location
# focus the text box
Win32API.MouseClick(pos.X + pos.Width/2, pos.Y + pos.Height/2)
Win32API.SendString('Accessibility test')
# position of the 'Add Item' button
pos = guiat_acc.Children[3].Children[2].Location
# click the button
Win32API.MouseClick(pos.X + pos.Width/2, pos.Y + pos.Height/2)
To run it, download managedwinapi-0.3.zip and extract the ManagedWinapi.dll to the same folder as the source code.

When you run the code, it enters Accessibility test text into New listbox item text box and clicks Add Item button. The controls are always on the same position within the Children enumeration so we can use direct referencing: e.g. guiat_acc.Children[3].Children[2] is the button accessibility object.

Enhancing this example is up to you - I have created several functions that take care about entering the text into text boxes, selecting buttons or a checking check boxes. That's all I need to create a script that installs our application.

Thursday, October 30, 2008

Building the framework (3)

After a while, it's time to continue building the GUI Automated Testing framework. Today, I focus on a list box. You can download the source as usual.

I assume standard windows list box component where only unique items are stored and only one item can be selected. These two conditions are set only because of simplicity of the example. If you don't like them, enhance the example by yourself as your homework :-)

The list box component is again a subclass of BaseComponent. It is quite simple - it has one method and two properties:

Select(self, aItem)
The method selects aItem in the list box.
def Select(self, aItem):
""" select an item from list box
@aItem - string with item to select
"""
if aItem not in self.items:
raise Exception("Item '%s' not in list box" % aItem)
self.guiat.Activate()
self._CheckVisibility()
pos = self.location
# click on the first item to focus the list box
Win32API.MouseClick(pos[0] + (pos[2]/2), pos[1] + 3)
# send Home to be sure we are on the first item
# (we could be scrolled down a little)
Win32API.SendKey(Win32API.VK_HOME)
# simulate pressing down arrow until we find the item
# we should find it because it is among self.items
while self.value != aItem:
Win32API.SendKey(Win32API.VK_DOWN)
First, it checks whether aItem is in the list box and raises an exception if not. Then it clicks onto the first visible list box item, simulates pressing Home key to focus the first item and repeatedly press Down key until the value equals aItem.
This approach has the advantage we don't need to care about scroll box. The basic windows list box does not provide nice properties or methods to return its state. We would have to dive into Win32 API to find it. For example, the DevExpress ListBoxControl has method GetViewInfo that returns information about internal list box state.

This brings us to the important note:

We do not test the list box component. We test the application.

One way of selecting item in a list box is enough. Of course, we must be aware of its limitations and side effects. Selecting an item with our GUIAT component fires one OnClick and several OnChange events.

items
The property contains read only list of all items in the list box.

value
The property contains the selected item in the list box. User can assign a string to it to select the string in the list box.

Incorporating the new GUIAT ListBox class into the framework is easy - just add it into the RecognizableComponents dictionary of the Form class.

This is the last post about controlling components. You know the idea so developing a new GUIAT class controlling your component should be easy.

Next time, I show how to control application that is already started.

Friday, September 26, 2008

GUI Testing at Resolver Systems

I'm currently quite busy at work and with my other activities (like photos). That's why instead of writing another chapter of the GUI Automated Testing framework, I point you to the great article of Michael Foord:

Functional Testing of GUI Applications

Michael describes his experiences with GUI automated testing in Resolver Systems.

They use quite similar approach to run the tested application. It is run in another thread but the thread invoking is different. I am not a specialist in threading but I will try to find out more about which way is better or whether there are any catches[1].

They also do not use win32api for simulating user's input. They usually call directly the .NET method responsible for generating the requested event (e.g. PerformClick). That can be dangerous because your test can pass even when user is unable to click the button - the button could be hidden behind another component.

[1] My current problem can be caused by threading. When I run our application from automated testing tool, two buttons overlap. When I run it normally, it is OK. To be it stranger, it occurs only on my PC. I have no idea why...

Update 10/30/2008: I have not found any problem with my way of starting the tested application. I asked my co-workers, searched for articles about threading and found both ways should be similar. [1] is still mystery to me, though.

Update 8/20/2009: Mystery [1] solved - it was bug in our application :-)

Monday, August 18, 2008

Building the framework (2)

Last time we have started building the GUI Automated Testing framework. Today we are going to enhance it. Download the source to be able to follow the text.

The first version implemented the BaseComponent class to represent windows components. We could not do anything but find out location of the component. It would be nice to be able write text into a text box or click a button by simple method, wouldn't it?

To do that, we need to know the type of each component. The type name of .NET components is stored in component.GetType().Name. Knowing the type, we create subclass of BaseComponent for each type. In the subclass, we provide nice methods and properties.

First, we enhance BaseComponent class. We add _CheckVisibility(self) method that checks whether the component is visible. If not, it raises an exception. We need it for checking if button is visible so we can click it or text box is visible to write it. And we add guiat property to be able to activate the tested application from a component by calling self.guiat.Activate().

Let's look on a button. The Button class is very simple:
from time import sleep
from Win32API import Win32API
from BaseComponent import BaseComponent

class Button(BaseComponent):
"""interface to the Button component"""

def Click(self):
""" perform left mouse click on the center of the button, no parameters"""
self.guiat.Activate()
self._CheckVisibility()
pos = self.location
Win32API.MouseClick(pos[0] + (pos[2]/2), pos[1] + (pos[3]/2))
sleep(0.1)
The Click(self) method activates the tested application, checks whether the component is visible, finds out the position of the button, clicks into the middle of the button position, and finally waits a little bit. I do not like the waiting but it is here for safety. Windows may repainting some areas or do some other cool thinks, so it is better to give them some time for it.

The TextBox class provides three methods and one property:
  • FocusEditor(self)
    The method essentially does the same as Button's Click method. It activates the tested application, checks whether the component is visible, and clicks into the middle of the TextBox position to focus the editor.
  • Clear(self)
    The method focuses the text box, moves cursor to the start position simulating pressing Home key, and simulates pressing Delete key until the text in text box is empty. If the text is not empty then, it raises exception.
  • Write(self, aString)
    The method clears the text box and uses Win32API method SendString to simulate typing aString. Then checks whether the text box contains the aString value and raises exception if not.
  • value
    The property contains the actual value of the text box. When user assigns a string to it, the string is written to the text box.
Now look on the creating instances of GUIAT components in the Form class. We have simply added dictionary with known component types (RecognizableComponents). When we go through all components on the form in the _AnalyzeStructure method, we first check whether we know the component type or not. If so, we create instance of the appropriate component type class (e.g. Button or TextBox). If not, we create instance of the BaseComponent class.

Let's try a small example:
>>> import GUIAT
>>> g = GUIAT.GUIAT()
>>> g.Run()
Starting GUIAT...
"frmGUIAT" (frmGUIAT)
"btnAddItem" (Button)
"lblNewItem" (Label)
"txtNewItem" (TextBox)
"lbxItems" (ListBox) - UNKNOWN
"btnQuit" (Button)
Starting GUIAT done.
>>> txt = g.mainForm._GetComponentByName('txtNewItem')
>>> btn = g.mainForm._GetComponentByName('btnAddItem')
>>> txt.value = 'Hello world!'
>>> btn.Click()
The result of the above small script is a new line in the list box. You see that the button, label, and text box are know component types. The label is treated as BaseComponent (see RecognizableComponents in Form.py). The list box is unknown component.

Today, we have shown how to create button and text box GUIAT classes that control respective .NET components. We can already script our small tested application!

Next time, we add list box class and logging.