This represents the proposed Java interface for Tool-Independent Drivers and Engines.
See also: SAFS Framework, JSAFS Design, JSAFS Javadoc, SAFS Driver Development, SAFSDEV Project
That is the goal. We are coding the tool-independent Driver (TID) to take advantage of these interfaces. However, the existing SAFS/RobotJ and SAFS/DriverCommands engines will need to be refactored to fully realize this capability. These engines are currently hardcoded to use our STAF services through specific classes. This engine refactoring, however, should not be too extreme, but is not part of the current Driver effort. The Driver will use the concrete implementations that talk with STAF, but the engines will talk with STAF directly until they are refactored.
These interfaces generally allow us to categorize a tool, and provide a simple interface to launch, reset, and shutdown the various tools through a common API.
Our default, concrete org.safs.tools.vars.SAFSVARS implementation simply wraps our existing SAFSVARS STAF service. Each method in the class will simply be the appropriate STAF call to the running SAFSVARS service--just like any other client that wants to use SAFSVARS. Yet, this insulates any Driver/Client from talking with STAF directly and allows for alternative implementations and custom enhancements.
To accomplish this interface with STAF, the implementation will need to use org.safs.staf.STAFProcessHelpers to obtain an instance of a org.safs.STAFHelper specific for the Driver process. All concrete classes used for and by the Driver will talk to STAF using the same process name/id. The class will communicate with the running STAF service through the STAFHelper. (A review of STAFHelper shows it looks pretty ugly, and may need some refactoring. Definitely it needs more documentation.)
The launchInterface(Object) call required from the ConfigurableToolsInterface would be tasked with verifying the SAFSVARS service is running, or launching the SAFSVARS service if it is not already running. This may be tempered by AUTOLAUNCH=FALSE settings provided in the configuration file. Configuration information is accessible through the DriverInterface object passed to the launchInterface function, or via System Properties set with command-line arguments when the Driver was launched.
The shutdown() call required from the ConfigurableToolsInterface would be used to close down the SAFSVARS service through STAF, but it should only do this if it was the call to launchInterface that started the service. shutdown() should not stop the service if it was already running prior to the call to launchInterface.
Our default, concrete org.safs.tools.input.SAFSMAPS implementation simply wraps our existing SAFSMAPS STAF service. Each method in the class will simply be the appropriate STAF call to the running SAFSMAPS service--just like any other client that wants to use SAFSMAPS. Yet, this insulates any Driver/Client from talking with STAF directly and allows for alternative implementations and custom enhancements.
To accomplish this interface with STAF, the implementation will need to use org.safs.staf.STAFProcessHelpers to obtain an instance of a org.safs.STAFHelper specific for the Driver process. All concrete classes used for and by the Driver will talk to STAF using the same process name/id. The class will communicate with the running STAF service through the STAFHelper.
The launchInterface(Object) call required from the ConfigurableToolsInterface would be tasked with verifying the SAFSMAPS service is running, or launching the SAFSMAPS service if it is not already running. This may be tempered by AUTOLAUNCH=FALSE settings provided in the configuration file. Configuration information is accessible through the DriverInterface object passed to the launchInterface function, or via System Properties set with command-line arguments when the Driver was launched.
The shutdown() call required from the ConfigurableToolsInterface would be used to close down the SAFSMAPS service through STAF, but it should only do this if it was the call to launchInterface that started the service. shutdown() should not stop the service if it was already running prior to the call to launchInterface.
Our default, concrete org.safs.tools.logs.SAFSLOGS implementation simply wraps our existing SAFSLOGS STAF service. Each method in the class will simply be the appropriate STAF call to the running SAFSLOGS service--just like any other client that wants to use SAFSLOGS. Yet, this insulates any Driver/Client from talking with STAF directly and allows for alternative implementations and custom enhancements.
To accomplish this interface with STAF, the implementation will need to use org.safs.staf.STAFProcessHelpers to obtain an instance of a org.safs.STAFHelper specific for the Driver process. All concrete classes used for and by the Driver will talk to STAF using the same process name/id. The class will communicate with the running STAF service through the STAFHelper.
The launchInterface(Object) call required from the ConfigurableToolsInterface would be tasked with verifying the SAFSLOGS service is running, or launching the SAFSLOGS service if it is not already running. This may be tempered by AUTOLAUNCH=FALSE settings provided in the configuration file. Configuration information is accessible through the DriverInterface object passed to the launchInterface function, or via System Properties set with command-line arguments when the Driver was launched.
The shutdown() call required from the ConfigurableToolsInterface would be used to close down the SAFSLOGS service through STAF, but it should only do this if it was the call to launchInterface that started the service. shutdown() should not stop the service if it was already running prior to the call to launchInterface.
The implementation needs to take into consideration whatever Remote Logging capabilities we already support with our SAFSLOGS service to insure these continue to be supported.
The default. concrete tools.input.SAFSINPUT provides our interface to the SAFSINPUT STAF service.
Actual processing of test records happens in the Driver. The only exception will be that the current SAFSTextFile file reading class already knows how to skip blank lines and comment lines. Thus, it is able to skip those until it finds a real test record to send to the Driver. The SAFSINPUT Service command to OPEN a new file should accept optional parameters that allow us to enable those line-skipping features.
That tells the Driver we are looking for a Suite level test table--a file--with the default Suite level file extension (.STD) in the current default or "Datapool" directory.
But the following lines should also locate the exact same file, and the Driver or the SAFSINPUT Class or the SAFSINPUT Service needs to accomodate all these:
The existing STAF SAFSTextFile implementation pretty much encapsulates the way the desired file reading should work. Each SAFSTextFile class handles working with one file and that is all it knows about. The SAFSINPUT STAF service handles the instantiation of these SAFSTextFile classes and routes incoming STAF service requests to the appropriate instance. The individual file readers shouldn't know anything about Cycles, Suites, or Steps--they are just forwarding records from the file they were told to play with. They have no idea what it is going to be used for. It is the Driver that handles which inputs are at what test level.
Like our SAFSMAPS, SAFSLOGS, and SAFSVARS wrapper classes; the launchInterface(Object) call required from the ConfigurableToolsInterface would be tasked with verifying the SAFSINPUT service is running, and perhaps even launching the SAFSINPUT service if this is applicable. This may be tempered by AUTOLAUNCH=FALSE settings provided in the configuration file. Configuration information is accessible through the DriverInterface object passed to the launchInterface function, or via System Properties set with command-line arguments when the Driver was launched.
The DriverInterface is primarily provided for use by the other tool interfaces. ConfigurableToolsInterface objects require access to configuration information or even other tools to perform their functions. The DriverInterface provides a centralized access-point for gaining access to most configuration information, or other required tools.
Of key importance, is that the Driver will provide access to the critical ConfigureInterface instance. This allows configurable tools to retrieve configuration information from external sources (like configuration files, etc.).
Our default, concrete org.safs.tools.drivers.SAFSDRIVER is currently designed as a standalone, Java application or class that will be launched into its own JVM. As it currently is designed, there is no GUI associated with the Driver. It is strictly a "run the specified test" class. Though it is easy to envision some optional GUI front-end that will allow the user to interactively specify test configuration information and parameters and then launch the Driver from there.
SAFSDRIVER Command Line Options
Command
Line Options:
|
Enhancements, corrections, and more detail will be added as necessary.
SAFSDRIVER Configuration File Options
The
default name of the configuration file is "safstid.ini".
This file is
readable by Windows AND Java classes. Items commented out with semicolons tell
the DRIVER to use its pre-programmed default values, or items passed in via command-line
arguments. Multiple configuration files can be used in a chain with values
in one file overriding or masking values in another file. The default priority
of the chain is:
For space conservation, items are shown in 3 columns below. A real configuration file will only have one entry per line in a single column format.
[SAFS_VARS] AUTOLAUNCH=TRUE ;Item=Alt VarsInterface Class ;ServiceClass=Alt Service Class ;ServiceClass=org.safs.staf.service.var.EmbeddedVariableService ;Service=Alt Service Name ;Options= ;EmbedVars=TRUE [SAFS_MAPS] AUTOLAUNCH=TRUE ;Item=Alt MapsInterface Class ;ServiceClass=Alt Service Class ;ServiceClass=org.safs.staf.service.map.EmbeddedMapService ;Service=Alt Service Name ;Options= [SAFS_LOGS] AUTOLAUNCH=TRUE OVERWRITE=TRUE CAPXML=TRUE TRUNCATE=ON|numChars ;Item=Alt LogsInterface Class ;ServiceClass=Alt Service Class ;ServiceClass=org.safs.staf.service.logging.EmbeddedLogService ;Service=Alt Service Name ;Options= ;= accept.slf4j.debug and accept.slf4j.test are used to turn on/off ;= the switch to write message from slf4j to SAFS debug/test log file. ;accept.slf4j.debug=true|false ;accept.slf4j.test=true|false [SAFS_INPUT] AUTOLAUNCH=TRUE ;Item=Alt InputInterface Class ;ServiceClass=Alt Service Class ;ServiceClass=org.safs.staf.service.input.EmbeddedInputService ;Service=Alt Service Name ;Options= [SAFS_ENGINES] First=org.safs.tools.engines.SAFSROBOTJ Second=Classname Third=Classname Fourth=Classname Fifth=Classname Sixth=Classname Seventh=Classname Eighth=Classname Ninth=Classname Tenth=Classname [SAFS_DROID] AUTOLAUNCH=FALSE DROIDPROJECT=C:\SAFS\samples\Droid CONSOLE2DEBUG=True SHUTDOWNDELAY=10 ;EMULATOR_AVD="SprintEVO" ;PersistEmulators=False ;PersistJVM=False ;DeviceSerial=serial number ANDROID-SDK=Android SDK Root Dir ANDROID-TOOLS=Android SDK Tools Dir FORCECLOSE=True FORCESTOP=True FORCECLEAR=True TCPMessengerAPK=path to TCP Messenger APK ;TCPMessengerPackage="org.safs.android.messenger" TestRunnerAPK=path to TestRunner APK ;TestRunnerPackage="org.safs.android.engine" ;TestRunnerSource=path to TestRunner project ;TestInstrument=from AndroidManifest.xml TargetAPK=path to Target APP APK TargetResignJar=path to re-sign.jar ;TargetPackage="com.example.android.apis" AntRebuildArgs="-noclasspath" AntRebuildForce=True PortForwarding=True ;HOOK=org.safs.android.DJavaHook ;TIMEOUT=120 ;STAFID="SAFS/DROID" ;JVM=JVMpath ;JVMARGS=JVM Args ;CLASSPATH=altClasspath ;XBOOTCLASSPATH=<CLASSPATH> [SAFS_IOS] AUTOLAUNCH=FALSE Project=/Library/SAFS/samples/UICatalog/ Template="UICatalogInstruments.tracetemplate" ;HOOK=org.safs.ios.JavaHook ;TIMEOUT=30 ;STAFID="SAFS/IOS" ;JVM=JVMpath ;JVMARGS=JVM Args ;CLASSPATH=altClasspath ;XBOOTCLASSPATH=<CLASSPATH> [SAFS_REST] ;= AUTH holds the authorization/authentication ;= file (relative to project or absolute) for REST testing AUTH=config\auth2.xml ;= PROXY holds the proxy information for REST testing PROXY=proxy.host.name:port | [SAFS_TC] AUTOLAUNCH=FALSE HOOK="C:SAFS\TCAFS\TCAFS.VBS" ;TIMEOUT=45 ;SuiteName="C:\Path\To\AProject.pjs" ;ProjectName="ProjectName" ;ScriptName="StepDriver" ;OPTIONS="/customArg:value /Another" ;ConvertSAFSInputKeysSyntax=True|False ;ConvertSAFSItemPathSyntax=True|False ;SECSWaitForWindow=30 ;SECSWaitForComponent=30 ;TFSMOnly=True|False ;DepthLevel=25 [SAFS_ROBOTJ] AUTOLAUNCH=TRUE DATASTORE=<FullPathTo>\RFTProjectDir ;ClearProxiesAlways=True|False ;TIMEOUT=45 (launch timeout) ;SECSWaitForWindow=30 ;SECSWaitForComponent=30 ;TESTDomains=Html,Net,Java,Win,Flex,SWT ;CommandLineBreakpoint=True|False ;STAFID="SAFS/ROBOTJ" ;JVM=altJVMpath\java.exe ;JVMARGS="-Xms512m -Xmx1024m" ;CLASSPATH=altClasspath ;INSTALLDIR=<wswpluginPath> pre-RFT V7 ;JARPATH=<FullPathTo>rational_ft.jar RFT V7+ ;PROJECTPATH=<RFT V7+ CLASSPATH> ;XBOOTCLASSPATH=<Classpath> ;PROJECT=<Project.rsp> ;BUILD=<Build #> ;PLAYBACK=TestScript ;LOGFOLDER=Default ;LOG=TestScript ;USERID=<userid> ;PASSWORD= ;OPTIONS= ;RFSMOnly=True|False ;RFSMCache=True|False ;DynamicEnableTopWindows=True|False [SAFS_SELENIUM] AUTOLAUNCH=FALSE ;JVM=JVMPath to Java 1.5 or higher ;CLASSPATH=altClasspath ;= GATEWAYHOST and GATEWAYPORT are used ;= to connect internet GATEWAYHOST=yourCorpGateway.net GATEWAYPORT=80 ;= Settings for Selnium1.0 ;HOOK=org.safs.selenium.SeleniumJavaHook ;BROWSER=*piiexplore | *firefox | *iexplore ;DEBUGLOG=<fullpathTo>/SeleniumDebug.out ;= Settings for Selnium2.0 WebDriver ;HOOK=org.safs.selenium.webdriver.SeleniumHook ;BROWSER=explorer | firefox | chrome PROXY_BYPASS_ADDRESS=localhost,127.0.0.1,host.not.thru.gateway BROWSER_REMOTE=false|true ;= Selenium Server Settings ;= SELENIUMHOST and SELENIUMPORT are used ;= to connect the Selenium Server (standalone or hub) ;SELENIUMHOST=remote.server.com ;SELENIUMPORT=4444 ;= SELENIUMNODE defines the selenium nodes to run. ;= If SELENIUMNODE is given, SELENIUMHOST will start ;= as a selenium hub; otherwise as a stand-alone server. ;SELENIUMNODE=node1:port:config1;node2:port:config2 ;= SELENIUMSERVER_JVM_OPTIONS is JVM options ;= for starting the Selenium Server ;SELENIUMSERVER_JVM_OPTIONS=-Xmx1g -Xms512m -Xdebug ;= SELENIUMERVER_JVM_Xmx and SELENIUMERVER_JVM_Xms ;= specify the value of JVM options -Xmx and -Xms ;= for the Selenium Server, it will override ;= the default value or the value specified ;= in SELENIUMSERVER_JVM_OPTIONS ;SELENIUMSERVER_JVM_Xmx=4g (default: 2g) ;SELENIUMSERVER_JVM_Xms=256m (default: 512m) ;SELENIUMSERVER_JVM=fullpath\java.exe (default: 1.7.0_45 64bit) ;= CONSOLE_STATE is used to set the state of ;= Selenium Server Console ;CONSOLE_STATE=MIN|MAX|NORMAL ;= WEB_DRIVERS is used to set the specific browser ;= drivers (separated by colon :) to start with the selenium server. ;= IE, Chrome, Firefox and MicrosoftEdge drivers will be started by Default. ;WEB_DRIVERS=explorer:chrome:MicrosoftEdge ;connection.test.command specifies the command to test the connection between WebDriver and BrowserDriver. ;connection.test.command=selenium-driver-command (Default:getAlertText) ;connection.test.max.duration specifies the maximum duration (in milliseconds) that user can accept when executing command defined by connection.test.command ;connection.test.max.duration=Time in milliseconds(Default: 5000) ;connection.test.max.try specifies the maximum times to try to get a good connection between WebDriver and BrowserDriver ;connection.test.max.try=Number(Default: 2) ;delay.get.content specifies the delay (milliseconds) waiting for the refresh of a webelement before getting its content ;delay.get.content=Time in milliseconds(Default: 0) ;timeout in seconds before the hub automatically releases a node that hasn't received any requests for more than the specified number of seconds. ;timeout=Time in seconds(Default: 0) ;timeout in seconds a selenium node is willing to hang inside the browser. ;browser.timeout=Time in seconds(Default: 0) ;By default, search algorithms begin every search by switching back to ;the topmost root HTML document (frame). Set it to true if you wish to ;disable this frames reset at the beginning of every component search. ;But you need to handle the frame-switch by yourself. ;bypass.frame.reset=True | False(Default: False) ;By default, we firstly use Java Robot to do the automation, user can bypass the "Java Robot" and use the selenium directly to do the automation. ;bypass.robot.action=True | False(Default: False) ;With docker, by default, our library will connect the RMI server running on docker container by container's IP and port. But we can map the container's port to local-machine's port so that our library will connect the RMI server (running on docker container) by "localhost" and the mapped port. ;rmi.port.forward=True | False(Default: False) ;Specify the port to get the registry for looking up the RMI server. ;registry.port=port number(Default: 1099) | [SAFS_DRIVERCOMMANDS] AUTOLAUNCH=TRUE ;STAFID="SAFS/DRIVERCOMMANDS" ;JVM=JVMPath ;CLASSPATH=altClasspath ;Hook=String/Classname ;Options=LOG ;= OUT_MAILXXX is Mail setting ;OUT_MAILSERVER="mail server" ;OUT_MAILSERVERPORT=25|465|587 ;OUT_MAILSERVERPROTOCOL=SMTP|SMTPS|TLS ;OUT_MAILUSER=user.name@mail.com ;OUT_MAILPASS=user.password [SAFS_QTP] AUTOLAUNCH=FALSE HOOK=C:\PathTo\QTP.VBS ;Hook=C:\PathTo\AnyExecutable.ext ;TIMEOUT=45 [STAF] ;NOSTAF=TRUE ;EmbedDebug=<filepath> PATH=Path to/STAFProc.exe CONFIG=Path to/staf.cfg ;EmbedSEM=TRUE ;EmbedQUEUE=TRUE [SAFS_DRIVER] DriverName=String DriverRoot=String/DriverRootPath BringMonitorToFrontOnPause=True|False TurnOnPOF=True|False TurnOnPOW=True|False ResolveSkippedRecords=True|False ;ShowMonitor not sought by all Drivers ShowMonitor=True|False [SAFS_PROJECT] ProjectName=ProjectName ProjectRoot=String/ProjectRootPath [SAFS_TEST] ;TestName=String/Path ;TestLevel=CYCLE|SUITE|STEP ;DefaultMap=String ;CycleSeparator="," ;CycleSuffix=".CDD" ;SuiteSeparator="," ;SuiteSuffix=".STD" ;StepSeparator="," ;StepSuffix=".SDD" ;LogLevel=String ;StepLogName=SAFSLOG ;StepLogMode=TEXTLOG|CONSOLELOG|XMLLOG|TOOLLOG|ALL ;SuiteLogName=SAFSLOG ;SuiteLogMode=TEXTLOG|CONSOLELOG|XMLLOG|TOOLLOG|ALL ;CycleLogName=SAFSLOG ;CycleLogMode=TEXTLOG|CONSOLELOG|XMLLOG|TOOLLOG|ALL ;millisBetweenRecords=N (default: 0) ;secsWaitForWindow=N (default: 30) ;secsWaitForComponent=N (default: 30) ;numLockOn=TRUE|FALSE ;UnexpectedAlertBehaviour ONLY works for Selenium2.0 webdriver engine for now accept -> "OK"; dismiss -> "Cancel"; ignore -> "keep Alert"; off -> "don't set this". ;UnexpectedAlertBehaviour=accept|dismiss|ignore|off (default: ignore) ;DndReleaseDelay=N (default: 800 millisecond) ;ProductName, Platform, Track and Branch are orderable information. ;ProductName=Product to test ;Platform=OS platform ;Track=Product track ;Branch=Product branch [SAFS_DIRECTORIES] ;DATADIR=Datapool ;BENCHDIR=Datapool/Bench ;DIFFDIR=Datapool/Dif ;LOGDIR=Datapool/Logs ;TESTDIR=Datapool/Test [SAFS_DIFFER] ;TOOL_EXE=DIFF.EXE ;TOOL_OPTIONS="--text -s -y" ;TOOL_BINARY_OPTIONS="--binary -s" [SAFS_DIFFVIEWER] ;TOOL_EXE=GEMINI.EXE ;TOOL_OPTIONS=" " [SAFS_OCR] ;OCRName=TOCR|GOCR (default:TOCR) ;LanguageID=chi|zh|eng|en|jpn|jp|kor|kr|fra|fr ;(default:system language; only en is support so far) [SAFS_IBT] ;UseMultiThreadSearch=True|False (default:False) ;When UseMultiThreadSearch is true, ;ThreadNumber can be adjusted for best search performance. ;ThreadNumber=N (default:4) ;UsePerImageModifiers=True|False (default:False) |
Enhancements, corrections, and more detail will be added as necessary.
A ConfigureInterface generally represents the need to read a configuration source. Although the source is not required to be in a Windows INI file format, the interface reflects this format convention. The interface reflects name=value pairs that can be separated into named secions. Other implementations are possible as long as the API conforms to the documented interface.
Note the "add" and "insert" methods allow configuration information to be "chained". The parent ConfigureInterface object will maintain storage of any number of other ConfigureInterface objects. The parent ConfigureInterface object is expected to search all stored objects, usually in a documented order (first-in first, or last-in first), to try to locate the requested configuration setting. This allows test-specific or project-specific values to override stored global or machine-specific settings and for all of this to be resolved in a single call to the held ConfigureInterface.
ConfigurableToolsInterface classes will often require either a reference to the Driver, or a reference to the ConfigureInterface maintained by the Driver. A reference to the Driver provides access to the active ConfigureInterface. Thus, these ConfigurableToolsInterface classes may define and even require certain configuration information be made available via the instantiated ConfigureInterface object.
An instance of an engine interface will allow the Driver simple access to the services of the engine. Each unique engine Interface will be instanced with the Class specified in the SAFS_ENGINE section of the ConfigureInterface. The instanced engine will gain access to the ConfigureInterface and proceed with initialization during the call to its ConfigurableToolsInterface launchInterface routine. Thus, each engine can independently specify required and optional configuration parameters the user needs to fulfill in the Configure source.