Export (0) Print
Expand All

Automating the Testing Process for Smart Tag Development

Click here to download sample - odc_TestSmartTags.exe. (49 KB) Click here to download sample - stsdk.exe. (496 KB) This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.
 

Chris Kunicki
OfficeZealot.com

May 2002

Applies To:
     Microsoft® Office XP
     Microsoft Smart Tag Enterprise Resource Kit

Summary: Explore the Smart Tag Developer Services Library included with the Microsoft Smart Tag Enterprise Resource Kit, and discover how this library can be used to automate the testing process of custom Smart Tags built by enterprise or an independent software vendor (ISV). (12 printed pages)

Download Odc_testsmarttags.exe.

Contents

Introduction
STDSL Object Model
   Recognizer Object
   Recognizers Collection
   Calling a Recognizer's Recognize Method
   Actions Collection and Action Object
   SystemConfiguration, ExcelSettings and WordSettings Objects
Conclusion

Introduction

In January 2002 Microsoft released the Smart Tag Enterprise Resource Kit or STERK for short. The main objective of the STERK is to equip enterprises with additional information, samples, and developer utilities that can aid them in building robust and stable smart tags. One of my favorite aspects of the STERK is the developer utilities. The following list summarizes these utilities:

  • Smart Tag Explorer gives the developer a snapshot view of how smart tags are configured on their system.
  • Smart Tag .Recognize() Tester allows for testing of a smart tag recognizer's Recognize method outside of a host application. This can greatly simplify the complexity of testing recognizer code.
  • Smart Tag Host Assistant for Word and Excel is a COM add-in for Microsoft® Word and Microsoft® Excel that reveals smart tag activity in documents and spreadsheets. The Smart Tag Host Assistant also saves the developer time by providing shortcuts to commonly used host level smart tag settings.

These utilities can save a lot of time as they help you interrogate and understand how your custom smart tags affect the smart tag host environment, namely Microsoft Word or Microsoft Excel. Behind these utilities lies an often undiscovered gem: the source code for the smart tag developer utilities which is included with the STERK as part of the installation. The source code can be found at <STERK Install Path>\Developer Utilities. Table 1 lists the source code directories.

Why has the source code been provided? The source code allows a developer to tailor these utilities to the specific needs of their organization. However, far more can be done than simply extending the existing developer utilities. The STERK developer utilities are based on a shared code library called the Smart Tag Developer Services Library or STDSL for short (pronounced as sted-zel). STDSL provides access to all the installed recognizer and action DLLs through a simple object model.

With STDSL in hand it is easy to develop scripts in any COM compliant language to automate the testing of custom smart tags. Why is this of value? Custom applications built for use within the enterprise often go through rigorous testing to ensure they will reliably function after the application has been deployed. Sufficiently testing an enterprise application requires multiple steps: unit testing by the developer, functionality testing by the business owner, and usability testing by the users.

Enterprise applications are often large and complex. For this reason development teams will automate the testing as much as possible. Automated testing can reduce the costly and error-prone testing of a human user. Additionally, automated testing scripts can be configured to run behind the scenes during the development cycle without consuming the valuable time of developer resources. To summarize, automated testing helps organizations find bugs that have subtly crept into the code base during development.

Until now, testing smart tags often required human intervention, as they are primarily a usability feature for Microsoft Office XP. Using STDSL, about 90% to 95% of a custom smart tag can be tested in an automated fashion. The rest of this article will explore the STDSL object model. Armed with this knowledge, you will be able to extend the existing smart tag developer utilities, create your own, and better yet, develop automated testing scripts for smart tags.

Table 1. Developer utilities source code directories

DirectoryDescription
\ExplorerSmart Tag Explorer
\HostAssistantSmart Tag Host Assistant for Word and Excel
\ProgressBarProgress bar used by Smart Tag Explorer and Smart Tag .Recognizer() Tester implemented as an ActiveX EXE
\RecognizerTesterSmart Tag .Recognizer()
\STDSLSmart Tag Developer Services Library

STDSL Object Model

The STDSL object model is fairly simple compared to other object models found in applications like Microsoft Word or Microsoft Excel. Figure 1 shows the STDSL object model. The object model is broken up into three primary categories:

  • Recognizers to represent recognizer DLLs.
  • Actions to represent action DLLs.
  • System Configuration for shared smart tag settings specific to Microsoft Word and Microsoft Excel.

Aa163628.odc_testsmarttags1(en-us,office.10).gif

Figure 1. The Smart Tag Developer Services Library (STDSL) object model

The diagram in Figure 1 represents a logical hierarchy of the object model. Some of these objects can be created independently of each other. For example, the Recognizers collection returns a collection of all the installed recognizer DLLs as individual Recognizer objects. A Recognizer object represents an individual instance of a recognizer DLL on the developer's workstation. A Recognizer object can also be created by itself and manually loads a specific recognizer DLL.

Let's examine each of these objects in more detail by looking at some code samples. For the purpose of demonstration, I need a custom smart tag that both you and I have access to. For this reason, I will use the SimpleTerm smart tag sample that is included with the Smart Tag SDK. To use the code examples, you will also need to install the STERK. The code samples presented here are developed with Microsoft Visual Basic® 6.0. If you're stepping through the code as you read the article, you will want to set a project reference to the following libraries:

  • Microsoft Smart Tag Developer Services Library
  • Microsoft Smart Tag 1.0 Type Library

Recognizer Object

The Recognizer object represents an instance of a recognizer DLL installed on the local system. This object will return all the properties of the recognizer and also allows you to use the .Recognize() method of the smart tag. The following code snippet demonstrates loading the SimpleTerm smart tag into a Recognizer object:

...
Dim lCnt As Long
Dim rec As STDSL.Recognizer

Set rec = New STDSL.Recognizer
rec.LoadDLL "{E8B4F79B-93D8-4279-A4C2-B967C30744D9}"
'or use: rec.LoadDLL "SimpleTerm.SmartTagRecognizer"
...

First, it is necessary to create an object of type STDSL.Recognizer. Refer to Table 2 for a list of the Recognizer object's properties and methods. Using the LoadDLL method, the class ID of the smart tag Recognizers COM object is passed in as a parameter. The LoadDLL method loads an instance of the actual smart tag recognizer DLL into memory. Alternatively, the Recognizer object can use the progID to load the recognizer DLL. Once the recognizer DLL is loaded into memory, the STDSL Recognizer object exposes all the properties and methods of the underlying smart tag recognizer.

Table 2. Recognizer object members

Member NameDescription
DescProperty that returns the smart tag description.
FileNameProperty that returns/sets the file name from registry.
Note   Modifying the Microsoft Windows registry in any manner, whether through the Registry Editor or programmatically, always carries some degree of risk. Incorrect modification can cause serious problems that may require you to reinstall your operating system. It is a good practice to always back up a computer's registry first before modifying it. If you are running Microsoft Windows NT or Microsoft Windows 2000, you should also update your Emergency Repair Disk (ERD). For information about how to edit the registry, view the "Changing Keys and Values" Help topic in the Registry Editor (Regedit.exe) or the "Add and Delete Information in the Registry" and "Edit Registry Information" topics in the Registry Editor (Regedt32.exe).
HostStatusProperty that returns/sets which host applications this smart tag is enabled for.
LocaleIDProperty that returns/sets the locale ID language identifier (default=1033 for U.S.).
NameProperty that returns the smart tag name.
ProgIDProperty that returns the COM programmatic identifier.
SmartTagCountProperty that returns the count of smart tag types supported by this recognizer.
SmartTagDownloadURLProperty that returns the download URL path for a specific smart tag type.
SmartTagIdentifierProperty that returns the class ID or progID for the recognizer DLL.
SmartTagNameProperty that returns the smart tag type.
AddToOfficeRegistryAdds the COM DLL SmartTagIdentifier to the Office registry HKCU\Software\Microsoft\Office\Common\Smart Tag\Recognizers. Use this in combination with DeleteFromOfficeRegistry to programmatically add and remove registered recognizers.
DeleteFromOfficeRegistryDeletes the COM DLL SmartTagIdentifier to the Office registry HKCU\Software\Microsoft\Office\Common\Smart Tag\Recognizers. Use this in combination with AddToOfficeRegistry to programmatically add and remove registered recognizers.
LoadDLLLoads a recognizer DLL into memory.
RecognizeCalls the Recognize method of the loaded recognizer DLL.

The following three lines of code dump the recognizer DLL's smart tag name, description, and count of smart tag types supported by this DLL:

...
Debug.Print "Name: ", rec.Name
Debug.Print "Description: ", rec.Desc
Debug.Print "ST Count: ", rec.SmartTagCount
...

With the following output:

Name:         My Simple Term Recognizer
Description:  Simple Term Recognizer recognizes Fourth Coffee 
   flavors in documents
ST Count:     1

The remaining lines of code iterate through all the smart tag types based on SmartTagCount:

...
For lCnt = 1 To rec.SmartTagCount
    Debug.Print "Namespace: ", rec.SmartTagName(lCnt)
Next
...

In the case of the SimpleTerm smart tag, there is only one type supported. The following is the output from the code loop through the smart tag types:

Namespace:    schemas-fourth-com/fourthcoffee#flavor 

Recognizers Collection

The Recognizers collection is a collection of Recognizer objects that represents all the recognizer DLLs registered in the registry under HKCU\Software\Microsoft\Office\Common\Smart Tag\Recognizers. This collection provides a convenient way to walk through all the installed recognizers and to interrogate them collectively. The following code snippet demonstrates how to use this collection:

...
Dim recs As STDSL.Recognizers
Dim rec As STDSL.Recognizer

Set recs = New STDSL.Recognizers

Debug.Print "Recognizer Count:" & recs.Count
For Each rec In recs
    Debug.Print "Recognizer Name:", rec.Name
    Debug.Print "           Identifier:", rec.SmartTagIdentifier
    Debug.Print "           Descriptions:", rec.Desc
Next
... 

First, a STDSL.Recognizers collection object is declared. When it is instantiated with the New keyword, the Recognizers collection object loads each registered recognizer DLL into an internal collection of Recognizer objects. The code then loops through the collection of Recognizer objects and outputs the following:

Recognizer Count:3
Recognizer Name:            Recent Outlook e-mail recipients
           Identifier:      {4FFB3E8B-AE75-48F2-BF13-D0D7E93FA8F9}
           Descriptions:    Recognizes names of people you have 
         recently sent e-mail messages to. ...
Recognizer Name:            Smart tag lists (MSN MoneyCentral 
         Financial Symbols)
           Identifier:      {64AB6C69-B40E-40AF-9B7F-F5687B48E2B5}
           Descriptions:    Smart tag actions and recognizers 
         specified in list description files. ...
Recognizer Name:            My Simple Term Recognizer
           Identifier:      {E8B4F79B-93D8-4279-A4C2-B967C30744D9}
           Descriptions:    Simple Term Recognizer recognizes Fourth 
         Coffee flavors in ...

Calling a Recognizer's Recognize Method

This is where things start to get interesting. At the end of the day, the job of the recognizer is to look for terms it recognizes by scanning streams of text sent by the host applications, Microsoft Word or Microsoft Excel. So far you have seen that STDSL permits us to iterate through properties of recognizer DLLs. This technique is used by the Smart Tag Explorer to display recognizer DLL properties. STDSL goes further by allowing a developer to send in their own text stream and to inspect the results of the recognizer's Recognize method. Using the code I am about to show, it is possible to write scripts that test the results of a custom recognizer without the need to load Microsoft Word or Microsoft Excel. This can be a time saver for the developer during the testing process, but also can be used in an automated fashion, as no user is required to pilot the host application during the test.

To do this, we first declare a Recognizer object and two new objects: RecognizerResponses and RecognizerResponse. Then we LoadDLL to load the recognizer DLL to be tested.

...
Dim sTestMsg As String
Dim rec As STDSL.Recognizer
Dim rrs As STDSL.RecognizerResponses
Dim rr As STDSL.RecognizerResponse
Dim lCnt As Long
Dim lTemp As Long
Set rec = New STDSL.Recognizer
rec.LoadDLL "{E8B4F79B-93D8-4279-A4C2-B967C30744D9}"        'Smart 
      Tag ClassID for SDK SimpleTerm sample
...

At this point the SimpleTerm smart tag recognizer DLL is loaded into a STDSL Recognizer object and ready for testing. The following code specifies sample text to scan and then calls the Recognize method.

...
sTestMsg = "Test this string to recognize two smart tag terms: Java 
         and Kona."
Set rrs = rec.Recognize(sTestMsg, TYPE_PARA, 1033)
Debug.Print "Terms recognized: " & rrs.Count
...

As you can see, this is a fairly simple process. The Recognize method takes three parameters:

  • A string of text to scan for recognized terms.
  • A string type as indicated by the Smart Tag SDK API documentation. Use TYPE_PARA when simulating Microsoft Word or TYPE_CELL when simulating Microsoft Excel.
  • A locale ID that specifies the language identifier for the string of text. In this sample 1033 U.S. English is used.

The Debug.Print line will output the following to the Immediate Window in the Visual Basic 6.0 IDE:

Terms recognized: 2

The recognizer's Recognize method returns a RecognizerResponses collection. The RecognizerResponses is a collection of RecognizerResponse objects. A RecognizerResponse object represents an instance of recognized terms from the stream of text provided to the recognizer.

I am sure that after you finished that last paragraph you may be feeling a bit confused, as the word recognize is used eight different ways. Let me explain in a different way. The code passes in a string of text: "Test this string to recognize two smart tag terms: Java and Kona" that is scanned by the loaded recognizer DLL. The SimpleTerm smart tag should recognize the terms "Java" and "Kona" from the text string. With this in mind, the RecognizerResponses collection will contain two instances of the RecognizerResponse objects to correspond with the recognized terms "Java" and "Kona". See Table 3 for details about the members of the RecognizerResponse object.

Table 3. RecognizerResponse object members

Member NameDescription
LengthProperty that returns length of recognized text in string (use in conjunction with the Start property).
PropertyCountProperty that returns the count of items in the property bag (a property bag is similar to a Dictionary object).
PropertyKeyFromIndexProperty that returns the key name from the property bag based on the index value.
PropertyReadProperty that returns the value stored in the property bag for the specific key.
PropertyValueFromIndexProperty that returns the value name from the property bag based on the index value.
StartProperty that returns character start position within string that was recognized (use in conjunction with the Length property).
STTypeProperty that returns smart tag type.

The following code demonstrates iterating through these recognized terms by using the RecognizerResponses collection and a RecognizerResponse object to display information about the recognized terms:

...
For Each rr In rrs
    Debug.Print "Term Found: ", Mid(sTestMsg, rr.Start, rr.Length)
    Debug.Print "    First Character: ", rr.Start
    Debug.Print "    Length of term: ", rr.Length
    Debug.Print "    Smart Tag Type: ", rr.STType
    Debug.Print "    # of Properties: ", rr.PropertyCount
    lCnt = rr.PropertyCount
    If lCnt > 0 Then
        'If there are persisted properties, iterate through and 
      list the properties
        For lTemp = 1 To lCnt
            Debug.Print "      Property Name/Value: ", 
         rr.PropertyKeyFromIndex(lTemp), _
            rr.PropertyRead(rr.PropertyKeyFromIndex(lTemp))
        Next
    End If
Next
...

This code will output the following to the Immediate Window in the Visual Basic 6.0 IDE:

Term Found:               Kona
    First Character:         61
    Length of term:          4
    Smart Tag Type:         schemas-fourth-com/fourthcoffee#flavor
    # of Properties:         0
Term Found:               Java
    First Character:         52
    Length of term:          4
    Smart Tag Type:         schemas-fourth-com/fourthcoffee#flavor
    # of Properties:         0

Actions Collection and Action Object

The Actions collection and Action object are similar in purpose to the Recognizers collection and Recognizer object with the obvious difference that they are designed to work with action DLLs. You will find that once you have mastered the syntax of the Recognizers and Recognizer objects that working with Actions and Action objects will feel natural. Table 4 documents the members specific to the Action object.

Table 4. Action object members

Member NameDescription
ApplicationNameProperty that returns/sets application name used for InvokeVerb (for example: Word.Application.10).
DescProperty that returns the smart tag description.
FileNameProperty that returns/sets the file name from the registry.
HostStatusProperty that returns/sets which host applications this smart tag is enabled for.
LocaleIDProperty that returns/sets the locale ID language identifier (default=1033 for U.S.).
NameProperty that returns the smart tag name.
ProgIDProperty that returns the COM programmatic identifier.
SmartTagCaptionProperty that returns a caption for the smart tag type.
SmartTagCountProperty that returns the count of smart tag types supported by this action.
SmartTagIdentifierProperty that returns the class ID or progID for the action DLL.
SmartTagNameProperty that returns the Smart Tag Type.
VerbCaptionFromIDProperty that returns the caption for Action menu item based on VerbID.
VerbCountProperty that returns the count of verbs supported by smart tag type.
VerbIDProperty that returns the ID for verb.
VerbNameFromIDProperty that returns the name based on verb ID.
AddToOfficeRegistryAdds the COM DLL SmartTagIdentifier to the Office registry HKCU\Software\Microsoft\Office\Common\Smart Tag\Actions. Use this to in combination with DeleteFromOfficeRegistry to programmatically add and remove registered actions.
DeleteFromOfficeRegistryDeletes the COM DLL SmartTagIdentifier to the Office registry HKCU\Software\Microsoft\Office\Common\Smart Tag\Actions. Use this to in combination with AddToOfficeRegistry to programmatically add and remove registered actions.
InvokeVerbMethod that executes an action.
LoadDLLLoads an action DLL into memory.

A key difference between the Recognizer object and the Action object is the InvokeVerb method of the Action object. InvokeVerb executes an action based on a verb ID. Using this method, you can test specific actions for your smart tag action DLL. Let's consider an example of programmatically using InvokeVerb. First we have to declare and set our objects:

...
Dim act As STDSL.Action
Dim stp As SmartTagLib.ISmartTagProperties
Dim obj As Object

Set act = New STDSL.Action
Set stp = New STDSL.SmartTagProperties
...

You will note the Dim stp as SmartTagLib.ISmartTagProperties and then Set stp = New STDSL.SmartTagProperties. The Smart Tag Type Library that ships with Office XP does not expose a publicly creatable version of the property bag. For this reason, STDSL includes the SmartTagProperties object that has implemented the interfaces defined by SmartTagLib.ISmartTagProperties. Using SmartTagProperties we can assign key/value pairs to the property bag:

...
stp.Write "KeyName", "KeyValue"
...

With a new Action object and a property bag object in hand, we can now load an action DLL and invoke a specific action:

...
With act
    .ApplicationName = "Word.Application.10"
    .LoadDLL "{7A1A026C-E65A-4EE2-A201-5CA40E9270DB}"        'Smart 
      Tag ClassID for SDK SimpleTerm sample
    .InvokeVerb 1, obj, stp, " <xml></xml> "
End With
...

The most interesting line is the InvokeVerb. The following parameters for InvokeVerb are required:

  • The verb ID to invoke the action. In our case, we are invoking verb ID 1.
  • The target object. In our case, we are passing in an empty object, as the action supported by SimpleTerm doesn't do anything with it. You can pass in any type of object that you want. For example, you could create an instance of Microsoft Word and pass it to the action DLL.
  • SmartTagProperties property bag.
  • A string of XML. Currently this parameter isn't used by most smart tags, so I send in an empty XML document.

As you start testing the InvokeVerb method, you will find that it is not possible to test every smart tag action scenario. This is why I stated earlier that you can test 90% to 95% of a smart tag. The action aspect of a smart tag often involves complex manipulation of Word, Excel, or some other application that your smart tag automates. With this in mind, you will find that you can't always control the targeted environment and will still have to resort to manual testing by a user.

SystemConfiguration, ExcelSettings, and WordSettings Objects

The final set of objects is SystemConfiguration, ExcelSettings, and WordSettings. These objects expose the smart tag settings that are shared and individually available from Microsoft Word and Microsoft Excel. One of the interesting settings you can change through these objects is the wavy underline color used to display smart tags. The sample download included with this article includes a code snippet that demonstrates using these objects.

Conclusion

I hope that this brief introduction to the STDSL library will be useful. Since the source code is included, you can easily step through the library to see how it works. You will find that there are some rather interesting COM interface programming techniques being used. As you explore the library, you might come up with other applications for STDSL, for example:

  • Performance benchmarking of a smart tag.
  • Submitting invalid data to the recognizer to monitor if your smart tag error handling is properly catching those esoteric bugs in your code.

STDSL is a great addition to the toolbox of any smart tag developer and is worth your time exploring.

Show:
© 2014 Microsoft