I have been doing some development of an Office based COM plugin (Word, Excel etc), and have been wanted to do some unit testing of it for a long time. Given that the majority of the code is in VB, it doesn’t lend itself to good test harnesses.
I then realised that I might be able to do something in Python which has excellent COM interfaces. The main pre-requisite was a COM control to look for windows appearing etc for which I used the excellent AutoIt Control.
The thing that took a little investigation was the realisation that you often can’t drive menu options in Word very easily via keystrokes. I then realised that I could drive them by finding the menu controls and directly executing them.
Demo
The following script does a simple demo. Comments at end.
from win32com.client import Dispatch, GetActiveObject
import pythoncom
import threading
class MenuCommand(threading.Thread):
def __init__(self, menu_name, option):
threading.Thread.__init__(self)
self.menu_name = menu_name
self.option = option
def run(self):
pythoncom.CoInitialize()
self.wd = GetActiveObject("Word.Application")
self.wdapp = self.wd.Application
self.menu = self.wdapp.CommandBars(self.menu_name)
print self.menu.Name
self.ctl = self.menu.Controls(self.option)
print self.ctl.Caption
if not self.ctl.Enabled:
self.ctl.Enabled = True
self.ctl.Execute()
pythoncom.CoUninitialize()
auto = Dispatch('AutoItX3.Control')
# First we stop any running version of Word to avoid messing things up
try:
wd = GetActiveObject("Word.Application")
wd.Quit()
except:
pass
wd = Dispatch('Word.Application') # Create a Word OLE object
wd.Application.Documents.Open(r'C:\work\fred-new1.doc')
t = MenuCommand("Help", "&About Microsoft Office Word")
t.start()
title = 'About Microsoft Office Word'
print "waiting window active"
if auto.WinWaitActive(title, '', 5)
print "window active"
auto.WinActivate(title, '')
auto.Send("{ENTER}")
info = auto.ClipGet()
print info
wd.Application.Quit()
Comments
Note that I execute the menu command in its own thread, since if not, the call to execute it will block synchronously and I then can’t check to see if the Window is there or not and click any buttons etc.
In my working version, I also have a similar utility class to open files and suchlike things.
The above has allowed to me to put quite a lot of testing around my app driven by fairly simple keystroke sending and copying things out via the clipboard to see if commands were successful or not.



