|
|
| View previous topic :: View next topic |
| Author |
Message |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Mon Jun 25, 2007 7:27 pm Post subject: FamousNames |
|
|
A question from the iEverywhere division of the bay area fruit company about plist management. In particular accessing property lists and their associated values. This quickly turned into the following FamousNames example handler, which returns a fairly long list of famous names as property lists with the keys (first, middle, last). Dealing with single name people (Prince, Cher, Bono, Pink, String), as well as names with multi middle names shows to be quit simple with the relative chunking.
Use your own web data source, flat file, database CLI calls, or data scraping tool as the rawdata() function allows you to source your data anywhere.
| Code: | repeat with each line name in my rawdata
if the number of words in names < 1 then next repeat
if comma is in name then \
set name to item -1 of name && \
items 2 to -2 of name && \
item 1 of name
set it's first to word 1 of name
set it's middle to words 2 to -2 of name
set it's last to word -1 of name
if it's last = it's first then set it's last to empty
insert it into names
end repeat
put names -- output a big fat list of names
to rawdata -- some names from the web.
return shell(<<curl --silent http://www.loc.gov/rr/print/list/235_alph.html | grep "</a><BR>" | grep "href" | awk -F\< '{print $(NF-2)}' | awk -F\> '{print $NF}'>>)
end rawdata |
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Tue Jun 26, 2007 9:55 pm Post subject: RE: Overriding Eggplant Handlers; the path of a message |
|
|
I got a call today, from none other than one of the top security testing firms in the world. And they are leveraging Eggplant to unobtrusively test devices and systems leveraging VNC enabled KVM switches. This gives a level of abstraction which with today's fast computers can cause the KVM interpretation of events to get out of sync with the remote SUT. Most of the higher quality KVM manufactures, Adder, Raritan have syncronization features forcing the mapping of events before continuing (much like an event queue 'flush' command). In most cases this works well. However in some limited cases its best to allow the KVM time to catch up as if a real world person were using the system under test.
To do so, our friends were using a handler aptly called MyClick, and of course a replacement for the venerable Eggplant Click command. MyClick was a simulation of the Click command, moving the cursor first on the SUT, then waiting a period of time (0.7 seconds in their case worked well), and then clicking where the mouse was located.
| Code: | to MyClick anImage
MoveTo anImage
Wait 0.7
Click -- at the cursor location
end MyClick
|
This works well, yet requires a script developer to rename all automated scripting performed in the capture/script sequence of auto script, from Click to MyClick. We can do this simple enough with Eggplant's script window find and replace features, while introducing potential for errors, incompleteness and forgetfulness in performing the chore, or myspelling or typos. Any way you slice this task, settling for faulty and error prone test suites is not proper practice.
To help solve this challenge, there are some powerful message passing features which can be used within SenseTalk which allow you to take control where messages are sent or even passed. One way to intercept commands is by using the 'start using scriptName' in SenseTalk placing the scriptName.script in the backscripts of the message path. The backscripts allow messages to be handled prior to their arrival at the SenseTalk runtime. This gives us the power to override and act upon a message we feel needs to be replaced in the SenseTalk system, or having it globally changes/altered.
There are other means to do this same thing, like the very powerful and often misunderstood 'to handle <any>' handler, for instance. In our case, we want to supplant the Click Command across the board injecting a time delay for the Adder switch box.
| Code: |
(** A handler to add a bit of delay in between the move and click of the Eggplant Click
command. We basically are replacing the Eggplant Click Command
@param n optional delay value in seconds
@param images the image list to find and click
**)
params n, images...
-- if a delay is provided, use it, otherwise assume an image
-- and insert it into the images list for use in a loop
if n is a positive number then
set omtcd to universal MoveToClickDelay -- store univ delay if n is provided.
set universal MoveToClickDelay to n
else
insert n before images
end if
-- for each image, move, delay and click at it.
repeat with each item image in images
MoveTo image
Wait universal MoveToClickDelay
send Click FoundImageLocation() to SenseTalk -- send to ST runtime, avoid recursion.
end repeat
if omtcd is a number then set universal MoveToClickDelay to omtcd
|
Naming the above Click.script (its in the provided project suite), we can use it in any script by issuing the 'start using click' where the click script is in a helper suite our main suite, or is part of the main suite itself.
| Code: | -- set a delay here, you can set it at any point, our replacement script will
-- use this value to delay xyz seconds.
start using Click -- put our click handler into backscripts.
set universal MoveToClickDelay to 5.0 second -- time to wait from move to click
Click TextEdit -- Click with delay using the universal MoveToClickDelay
TypeCommand "q" -- quit TextEdit program
Click 1, TextEdit -- Click using our override handler with a delay parameter.
TypeCommand "q"
send Click TextEdit to SenseTalk -- bypass our handler, go directly to ST runtime.
TypeCommand "q"
|
In this case, we see 3 different ways to get various results with move, delay and click transparently (or mostly) from our system without renaming handlers or calls that we have in older or legacy scripts. You can see we set up the universal MoveToClickDelay to a suitable delay time for the KVM switch to clear out the event queue. Then just as we have before, we make calls to the Click (our handler) which is used by issuing the 'start using Click' command.
The astute Eggplant test developer will also notice in the 2nd invocation there is an override value of 1 being used for the delay value. This will override the universal MoveToClickDelay, without changing the value permanently when called. You can set your universal MovetoClickDelay value and in some special cases where delay times can or should be changed for tuning purposes. You could also just call your Click command with an initial parameter value less or more as needed. Maybe finding the right value is a matter of using a repeat loop and issuing a few commands, leveraging the new delay value override of this Click command.
Finally, the last Click example command is sent directly to SenseTalk in which no override handler traps the message. Direct sends are powerful in this context, as you may not want your own handler most of the time, yet at times Eggplant's native or direct handlers are necessary for performance and speed tuning when the KVM is bogged down or the added functionality of the override command are not desired.
| Description: |
| Download, unzip, set your sut up to suite info start state, run Main and watch the override begin. |
|
 Download |
| Filename: |
ClickOverrideExample.suite.zip |
| Filesize: |
65.35 KB |
| Downloaded: |
949 Time(s) |
Last edited by Todd on Sun Jul 29, 2007 6:46 pm; edited 2 times in total |
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Fri Jul 20, 2007 1:12 pm Post subject: RE: Global Variables as Property List |
|
|
Recently one of our friends at a famous music software company mentioned to me they would like to have all global variables as a property list. Included here is a quick function call that will give you all globals.
| Code: | to GlobalsAsPropertyList filters...
set r to (:)
if filters is empty then set filters to globalNames()
repeat with each item name in globalNames()
repeat with each item filter in filters
get value( "global" && name )
if filter is in name then set r's (name) to it
end repeat
end repeat
return r
end GlobalsAsPropertyList
|
This handler can be called with a list of filters, or none at all. You can expect the following results:
| Code: | global test1, test2
set ( test1, test2 ) to ( GUITest, BackEndTest)
put GlobalsAsPropertyList() --> (test1:"GUITest", test2:"BackEndTest")
put GlobalsAsPropertyList(1) --> (test1:"GUITest")
put GlobalsAsPropertyList(2) --> (test2:"BackEndTest")
put GlobalsAsPropertyList(1, 2) --> (test1:"GUITest", test2:"BackEndTest")
|
You could easily adjust this for universal variables as well, and left to the reader. Also, any local, global or universal variables may be deleted with the 'delete variable' command.
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Sun Jul 22, 2007 8:26 pm Post subject: RE: Temporary File Names |
|
|
Got some email a long while back, about temp file names in SenseTalk. I finally got the time to spend on the plane back from Italy to write some code and here is one of the many things I'll be posting in the next few weeks. A function to return a temp file name, giving you the power to specify the directory/folder, the seperator used between name components, and also finally the optional file extension.
| Code: | params dir, pre, ext, sep
if dir is empty then set dir to "/tmp"
if dir is not a folder then Throw "Not a valid directory exception"
if last char of dir is not "/" then put "/" after dir
if ext is not empty and if first char of ext is not "." then put "." before ext
set the numberFormat to "00"
get the year & sep & the month & sep & the day
get it & sep & the hour & sep & the minute & sep & the second & sep & the microsecond
return dir & pre & it & ext
|
Without too much explaination of the obvious, some sample calls:
| Code: | put TempFileName()
put TempFileName("/tmp")
put TempFileName("/tmp", "PreFix_")
put TempFileName( , "UniqTemp_", "tmp")
put TempFileName("/tmp", , "toss")
put TempFileName( , , "chuckout", "-")
|
produce some sample output
| Code: | /tmp/20070722230937500207
/tmp/20070722230937525050
/tmp/PreFix_20070722230937594034
/tmp/UniqTemp_20070722230937638956.tmp
/tmp/20070722230937679527.toss
/tmp/2007-07-22-23-09-37-713546.chuckout
|
Thanks go out to Doug Simons of Redstone's Engineering Team for some input on this one.
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Mon Jul 23, 2007 11:59 am Post subject: RE: stripping leading and trailing whitespace |
|
|
There are times when cleaning up a line of text is necessary, and deleting all the whitespace (tabs, spaces, non printables) must be done. Here is a little routine to take a string of any line count, and iterate through each line stripping leading and trailing whitespace.
| Code: | (** Strips the leading and trailing whitespace on each line of a string
@param aString The string to strip leading and trailing whitespace
@returns A string with leading and trailing whitespace stripped
**)
params aString
repeat with each line in aString by reference
set it to first to last words of it
end repeat
return aString |
A little geeky, and less readable, you could also use the
| Code: | set it to words 1 to -1 of it
|
Readability, style and intent shall dictate how you script, and we hope this little example proves valuable as part of your scripting arsenal.
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Mon Jul 23, 2007 12:10 pm Post subject: Random Data Sources |
|
|
When folks turn to Redstone for solutions, we try hard to come up with them... One recent request was a need for random data sources to Black Box text an application, to test it by sending random data to it and see what happens (sometimes called monkey testing, where figuratively putting a monkey in front of the application and computer and have it bang away on the keyboard can produce some interesting application state/conditions to arise).
First was to develop some scripts to generate city, state and name values.
| Code: | (** Returns a random first name from the FirstNames.txt file in the /path/to/this.suite/Data/ folder
@param path A data file path, or defaults to "Data/Firstnames.txt" in the suite
@returns A random line of the file designated by path
**)
params path
if path is empty then set path to my folder's folder & "Data/FirstNames.txt"
return any line of file path
|
which accesses a default file in a folder Data in the suite of the handler. The data source could be any place if provided.
Another handler returns a list of full names (first, middle and last) as property lists which can then be accessed by using obj's first, middle or last properties making for easy access and readable scripts.
| Code: | (** Returns a random full name composed of the random first, middle and last as a list of property lists
@param n the number of random names to return
@returns a list of full names provided as a property list
**)
params n
set r to ()
if n is not a number then set n to 1
repeat n times
set j to (:)
set j's First to RandomFirstName()
set j's Middle to RandomMiddleName()
set j's Last to RandomLastName()
insert j into r
end repeat
return r |
As a side, geeky way to do the above inner loop you could
| Code: | insert ( First: RandomFirstName(), \
Middle: RandomMiddleName(), \
Last: RandomLastName()) into r
|
The family of Random*Name() are provided below in the downloadable suite. Download, unzip and inspect. There are default data files in the suite itself with some random names to start you off.
| Description: |
| Download, unzip and take a look at the Z_Tests.script for some examples. |
|
 Download |
| Filename: |
RandomDataTypes.suite.zip |
| Filesize: |
32.54 KB |
| Downloaded: |
883 Time(s) |
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Sun Jul 29, 2007 5:57 pm Post subject: Ad Hoc Do Box Quick Documentation Opener |
|
|
Often I find myself in need of quick reference to a Eggplant function, or SenseTalk handler. I also like to quit applications when I'm not using them, and Preview goes away immediately after I'm done with a search. Heading to the Eggplant->Help Menu all the time gets old. So, digging into the EggplantCommon.suite, I added the following 'OpenDocs' handler.
| Code: | params toOpen...
if toOpen is empty then set toOpen to ("SenseTalk Reference","Eggplant Reference","Using Eggplant","Getting Started")
set folder to my folder's folder's folder & "Documentation/"
set files to the files in folder
if toOpen = "all" then
set typesAllowed to ( pdf, rtf, rtfd, html, txt, doc )
repeat with each item in files
if the fileExtension of it is in typesAllowed then shell "open " & quote & folder & it & quote
end repeat
else
repeat with each item chunk in toOpen
repeat with each item in files
if chunk is in it then shell "open " & quote & folder & it & quote
end repeat
end repeat
end if |
Now you can open up the default 4 top documents, or all of the supplied documents, or even filter out by keyword on file name in the AdHocDoBox or call these directly from within your scripts (maybe when a throw is caught and handled for instance).
| Code: | OpenDocs -- default 4
OpenDocs all -- opens all the supplied docs
OpenDocs Eggplant -- opens only the Eggplant documents |
I also see this as a starting point of a more robust EggDoc opening filter. This would allow someone working on a project to AHDB instruct Eggplant to find and open the current suite/script/project's EggDoc files.
NOTE: inclusion of scripts into the /path/to/Eggplant.app/... file structure will likely need to be moved when you upgrade the application folder. Ensure your changes are not lost by either linking from within the Eggplant.app folder to your added suite files, or make copies before you delete old Eggplant app folders.
| Description: |
| Download, add to your /path/to/Eggplant.app/Contents/Resources/EggplantCommon.suite |
|
 Download |
| Filename: |
OpenDocs.script |
| Filesize: |
3.03 KB |
| Downloaded: |
780 Time(s) |
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Thu Aug 23, 2007 8:28 pm Post subject: Revisiting the detection of a SUT's Operating System |
|
|
Detecting an operating system is simple, we do it by image or icon visualization. In the Mac world, we look for Mac elements that make it unique; rounded windows, window drop shadows, the dock, etc. In the world of Windows we look for things like shelf at the bottom of the desktop, maybe the default back ground image (in XP, the landscape shot), or even the blue screen of death (just kidding). However, we are looking for images or elements of visual nature, we identify unique things that tell us at some point there is a definitive possibility of a positive identification.
In the world of Eggplant, it is no different. We just pick image elements that are unique to the operating system, that will always be visible and then associate those with the operating system. For Mac, I choose the apple menu icon at the top left. For Windows XP the bottom start menu. I also for completeness choose the normal and clicked/moused over yet not in the image area. For mac, this is 2 images, and for windows you have three image states.
Then using the power of the image collections, these are each grouped into unique folders. Optionally you could just have single images as well, both collections and allowable image formats are allowed. Remember, collections are just folders with captured image elements as their contents.
| Code: | (** assumes images to use for OS search are in the Suite's images folder
and each is properly tagged with a meaningful description field **)
set allowableTypes to ( tiff, icns, ico, pict, gif, bmp, png, pdf, jpg, jpeg, empty )
set dirPath to my folder's folder & "Images/"
repeat with each item name in ( the files of dirPath &&& the folders in dirPath )
if fileExtension(name) is not in allowableTypes then next repeat
if ImageFound(name) then return FoundImageInfo()'s Description
end repeat
Throw "OS Detection Exception", "No known operating system was detected." |
The crux of the code is the above handler, called DetectOS. It first enters the folder and determines the images that are going to be used for the operating system type detection. Then a check of all files and folders is performed, and only file types allowed or folder are used. If a file is usable and located, it's description is returned giving the calling handler a pretty strong clue as to the OS detected. Since the image's description property is used, one must add a meaningful text string to this field in the image element info drawer in the Images tab in a suite.
| Code: | get AllConnectionInfo()
repeat with each item aSUT in it by reference
Connect aSUT
set aSUT's DetectedOS to DetectOS()
end repeat
put it |
And finally here we just loop thru all the known open connections, making a connection to each, and then adding a property to each by reference of it's known operating system type. You could proceed to actually just set the overridden name property and make reference by that name instead in subsequent connections. However, this would need to be sequenced in number if you are testing against more than one of a given type of SUT at a given time. I preferred to just add the DetectedOS property, and leverage that for any setup that is needed as a result of specific OS testing and configuration (start states and such).
| Description: |
| Download, unarchive, open and run Main.script. See the images and their descriptions as well. Note collection use for more powerful and flexible states of each image element. |
|
 Download |
| Filename: |
OSDetection.suite.zip |
| Filesize: |
120.38 KB |
| Downloaded: |
842 Time(s) |
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Tue Sep 25, 2007 4:15 pm Post subject: LogException handler |
|
|
If you generate exceptions a lot like me, learning the power of logging exceptions is important. Log files can then be used for script metrics, in turn to help during analysis and correcting faulty logic and SUT conditions. This all may help you grasp your current state of Eggplanting.
I use this LogException handler to log exceptions. You could change the LogWarning calls (I personally like the orange output) to more simple Log calls to avoid the warning count on your script results.
| Code: | params title, e
if title is empty then set title to "Exception Alert!"
if e is empty then set e to the Exception
LogError title
LogWarning "Exception Name: " & e.name
LogWarning "Exception Reason: " & e.reason
LogWarning "Exception Location: " & e.location
LogWarning "Exception CallStack: " & e.callStack
LogWarning "Exception ScriptError: " & e.scriptError |
Pretty straight forward, just drop it into your Eggplant Library suite and include as a helper suite when you create a new test suite during your daily Eggplanting.
| Description: |
| Download, insert into your library of scripts, and include that suite as a helper into your standard work flow scripts. |
|
 Download |
| Filename: |
LogException.script |
| Filesize: |
298 Bytes |
| Downloaded: |
652 Time(s) |
|
|
| Back to top |
|
 |
Todd AuberGenie

Joined: 20 Jan 2007 Posts: 265
|
Posted: Thu Sep 27, 2007 4:31 am Post subject: Data Driven Testing - Website Hint Verficiation |
|
|
Just had a client reviewing Eggplant for command line only type testing. They didn't want to do any GUI verification. The notion of a site verification script came to mind to show how Eggplant's SenseTalk 'url' command was right for the picking.
| Code: | repeat with each item dataRecord in stdin
CheckSite dataRecord
end repeat |
| Code: | to handle CheckSite site, aHint, emails...
try
get url site
if it doesn't contain aHint then
SendMail(To: emails, \
Subject: "ALERT: a website appears to not be valid...", \
Body: site & return & "==========" & it )
end if
catch e
SendMail(To: "person@superdomain.com", \
Subject: "WARNING: Something is wrong with site checking!!!", \
Body: e & return & "===========" & return & it )
end try
end CheckSite |
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|
|