Created On:  24 September 2010
 
Creating Verification and a ‘Results’ File in Silk4J
This white paper continues on from where ‘Creating tags in Silk4J’ left off, so we will be using the ‘GMOwithTags’ Silk4J project renamed to ‘GMOwithExternalVerification’ as our base project. We will be dealing with creating verification techniques and how to output pass/fail information within Silk4J.
Creating and running a test case within Silk4J will tell you whether the test has passed or failed and, if it has failed, which line it failed on. If the test passes, all it really means is that the testcase has run without errors. It does not necessarily mean that the test itself has passed – the application itself may have errored unexpectedly but the testcase completed successfully.
Amongst other things there is no native Verify function within Silk4J. We will start the creation of a verify class library that could serve as the basis for your own verify functions. For the GMO website we will create verification for the textfields and for the ‘Ship To: Same As’ checkbox on the Billing Information page.
As with most things in Java, it is possible to create functions local to the testclass or as part of a class library jarfile that can be referenced by multiple projects. In this paper we will skip the local functions and go straight to the class library approach.
Verifying Textfields and Checkboxes
Before creating a verification method you need to consider what will be passed in. At a bare minimum you will need the locator for checking and the expected result. In addition, it would be useful to have a parameter that allows you to state what is being verified. Consider the following piece of code for verifying a textfield (be aware of the linewraps in the failed statements):-


// ------------------------------------------------------------------------
// Textfields
// ------------------------------------------------------------------------
    public static void Text(String sData,String sExpected,String sDesc)
    {
      if(sDesc=="" || sDesc==null)
      {
        if(desktop.find(sData).getText().equals(sExpected)!=true)
         System.out.println("Verification failed. Expected ("+sExpected+"), got ("+desktop.find(sData).getText()+")");
        else
         System.out.println("Verification: ("+sExpected+"): Success");
       }
       else
       {
          if(desktop.find(sData).getText().equals(sExpected)!=true)
           System.out.println(sDesc +" verification failed. Expected ("+sExpected+"), got ("+desktop.find(sData).getText()+")");
          else
           System.out.println(sDesc+" verification: ("+sExpected+"): Success");
        }
      }

In the first section we return a generic message (‘Verification failed/succeeded’ etc.) whereas if we passed in (say) the name of the object being verified, we would get a much more informative message. Suppose we were verifying the number of pairs of Glacier Sunglasses being ordered: passing in ‘Glacier Sunglasses’ as sDesc would get us the following message (assuming that the verification failed):-
Glacier Sunglasses verification failed. Expected (3), got (2)
Note that sDesc must be passed in as “” if no ouput message is required.
To make the description optional as in the SilkTest Classic Verify method, we can overload the method. Consider the following new verifications for the textfield:-
// ------------------------------------------------------------------------
// Textfields
// ------------------------------------------------------------------------
// Verification with description
    public static void Text(String sData,String sExpected,String sDesc)
    {
      if(desktop.find(sData).getText().equals(sExpected)!=true)
System.out.println(sDesc +" verification failed. Expected ("+sExpected+"), got ("+desktop.find(sData).getText()+")");
      else
       System.out.println(sDesc+" verification: ("+sExpected+"): Success");
    }
// Verification without description
    public static void Text(String sData,String sExpected)
    {
      if(desktop.find(sData).getText().equals(sExpected)!=true)
       System.out.println("Text verification failed. Expected ("+sExpected+"), got ("+desktop.find(sData).getText()+")");
      else
       System.out.println("Text verification: ("+sExpected+"): Success");
    }
 
Passing in sData and sExpected with no sDesc would trigger the second version of the verify text method, making sDesc appear to be optional.  You could expand the overloading further so that it deals with all possible SilkTest verification combinations under a single call as the SilkTest Classic Verify method does. The choice is yours as to whether you wish to follow the SilkTest Classic methods or to impose your own. My preference is to have individual named methods because in the event of an unxpected assertion or Java failure, you will know immediately which piece of code was being called at the point of failure.
 Creating the initial Verify Class Library
Start a new Silk4J project. I called the initial one Console Common Functions (for reasons we will see later) and named the initial package as ‘func’. Within func I then created a new class called ‘verify’; inside verify I have two methods ‘Text’ and ‘Chkbox’. Both ‘Text’ and ‘ChkBox’ are overloaded so that sDesc is optional. This will give us the very simple prototype as follows:-
func.verify.method(sData, sExpected, optional sDesc)
We need to instantiate a new desktop as we cannot read the desktop in the main testclass file. Importantly, this desktop must be static because if it is not, amongst other things the intellisense will not be able to see your methods correctly.
package func;
 
import com.borland.silktest.jtf.Desktop;
import com.borland.silktest.jtf.xbrowser.DomCheckBox;
 
public class verify
{
       private static Desktop desktop = new Desktop();
You can see that we have specifically imported the DomCheckBox jtf file. Some methods (such as the getText() method) are common to many windows but others are specific to certain windows. In this case isChecked() is specific to the Checkbox; if we do not add the qualifier to the locator string then Silk4J will look in the common pool and state quite correctly that isChecked() is not a valid call. The overloaded Text verification method is shown above; for completeness we will add the ChkBox verification method here:-
// ------------------------------------------------------------------------------------------
// Checkbox - sExpected should be 'true' or 'false' only.
// ------------------------------------------------------------------------------------------
// With description
public static void ChkBox(String sData,String sExpected,String sDesc)
{
  if(desktop.find(sData).isChecked()==true && sExpected=="false")
    System.out.println(sDesc+" verification failed. Expected ("+sExpected+"), got (true)");
  else if(desktop.find(sData).isChecked()==false && sExpected=="true")
    System.out.println(sDesc+" verification failed. Expected ("+sExpected+"), got (false)");
  else
    System.out.println(sDesc+" verification: ("+sExpected+"): Success");
}
 
// Without description
public static void ChkBox(String sData,String sExpected)
{
  if(desktop.find(sData).isChecked()==true && sExpected=="false")
    System.out.println("Checkbox verification failed. Expected ("+sExpected+"), got (true)");
  else if(desktop.find(sData).isChecked()==false && sExpected=="true")
    System.out.println("Checkbox verification failed. Expected ("+sExpected+"), got (false)");
  else
    System.out.println("Checkbox verification: ("+sExpected+"): Success");
}
To make the verification methods more robust the verification should be aborted if any parameter does not meet the requirements of the method. For example, where ChkBox is concerned the verification should be aborted if sExpected does not equal either ‘true’ or ‘false’.
if(sExpected.equals("true")!=true && sExpected.equals("false")!=true)
  System.out.println("Invalid parameter: sExpected. Should be 'true' or 'false'");       
else
Once the class library is compiled and referenced, we can begin using it. In fig.1 (below) we are calling the optional version of the text verify method (no sDesc) to verify the quantity of items ordered.



Fig.1 – Verifying a text field
Double-clicking on the required method will cause Eclipse to paste in the method parameters. This is useful as it reminds you what is required for that method without having to check the original source code.


Fig.2 – Parameter reminder
Fig.3 shows the completed verifications for the quantities of the items that we are ordering.



Fig.3 – Quantity verification with no description
This screenshot also illustrates one of the very useful qualities of Eclipse. The ‘verify.java’ tab that you can see belongs to the Common Functions project and the GMOSite.java tag belongs to the GMOwithExternalVerification project. You can switch between projects as easily as selecting another tab; if you update the verification class library while working on the testclass, simply calling a refresh (F5) on the testclass project will get it to recognise the changes you have made to the class library.
Fig.4 (below) illustrates verification with description; it also shows verification of the ShipTo checkbox.



Fig.4 – Verification with description
Displaying Results
If we run the GMOwithExternalVerification testclass the results of the verification routines will be output to the Eclipse console. Note that the first three lines (the quantity verifications we discussed above) don’t really provide any useful information (what was verified?).


Fig.5 – Console Output
The “GMOwithExternalVerification” package along with its associated “Console Common Functions” package are attached to this whitepaper.
The Results Class Library
This verification method may be sufficient in many cases but in others you may need a permanent record of the test run. This is going to require sending the results to an external text file. So, the next question is: what information do you need to save? As a minimum, to imitate the SilkTest Classic Agent results file you will need the following:-

·         The ability to select ‘append’ or ‘overwrite’ to the results file

·         The name of the testclass being executed

·         The date and time of the test run

·         How long the test took to complete

It also needs to be able to take a command similar to the Classic Agent ‘Print()’ method which we can call from any functions we create (such as the Verify class discussed above) and also directly from the testclass.
After some thought it was decided that the results class library needed three methods:

·         writeNew. Creates/overwrites a new results file or appends a new run to an existing one. This method would also timestamp the results file and insert the testclass name.

·         writeAppend.  This method would simply print a new line to the current results file.

·         writeClose.  This method would close the file, timestamp it with the close time and calculate the elapsed time for the testclass.

The restrictions are that writeNew must be the first line in the testclass and writeClose must be the last. If you have chosen to create a TestCaseEnter() and a TestCaseExit() for Silk4J then these two commands can be incorporated in the relevant method, thus ensuring they will be called automatically. As long as the jarfile references are correct, writeAppend can be called from within the testclass or any other class library (such as the verify class above) that requires it.
The three prototype calls are as follows.
To open a new results file or to append to an existing results file:-
 Results.FileIO.writeNew(String testcase, String resultsFilename, String writeType)
where
 testcase = the name of the testclass
 resultsFilename = the name given to the current results file (including a path)
 writeType = ‘new’ to create or overwrite an existing file or ‘append’ to add to an existing file. 
To write to an open results file:-
 Results.FileIO.writeAppend(String data)
where
 data = any string statement to be printed to the file
To close the results file:-
 Results.FileIO.writeClose()
No parameters. 
As PrintWriter() and FileWriter() are capable of throwing IOExceptions, we need to enclose all three resultsfile methods within try-catch constructs. In addition, this also means that we have to add a ‘throws IOException’ call to the testclass title:-
@Test
public void recordedTest() throws IOException
{  
There is no need to have a try-catch construct within the testclass (unless your testcase requires it) as all of the error trapping is done at a lower level within the class library. Finally, like the verification package, ResultsFile requires a static Desktop call:
public class FileIO
{
       private static Desktop desktop = new Desktop();
To be able to use the results file class library, export the project as described in ‘Creating tags in Silk4J’.  
The Silk4J package for the complete Results class library (ResultsFile) is included in the zip archive attached to this white paper.
Putting it all together
The “GMOwithResultsFile” package is a copy of “GMOwithExternalVerification” with the Results.FileIO.writeNew() and Results.FileIO.writeClose() methods added. There is no change to the verification calls as we are going to take care of this within the “Common Functions’” package. This is essentially a copy of “Console Common Functions” with the console output lines chnaged to point to the ResultsFile.
You will need to add a build path reference to the ResultsFile jarfile from both the GMO testclass package and also from the Common Functions package.
At the head of the GMO testclass we initialise the results file:
@Test
public void PlaceOrder() throws IOException
{
// Initialise the results file with the testclass name and the path to the file
Results.FileIO.WriteNew("PlaceOrder","c:\\temp\\GMO.txt", "append");
-and as the last line we close the results file:-
// Timestamp the results file and close it            
Results.FileIO.WriteClose();
}
If we return to the verification methods in Common Functions, we need to change the System.out.println() commands for the new Results.FileIO.WriteAppend method. The Console Common Functions package was copied and renamed as Common Functions, thus retaining the verify protoype calls we have already put in place in the GMO testclass. As an example, when finished, the checkbox verification method now looks like this (be aware of the linewraps):-
// -------------------------------------------------------------------------------------------
// Checkbox       - sExpected should be 'true' or 'false' only.
// -------------------------------------------------------------------------------------------
public static void ChkBox(String sData,String sExpected,String sDesc)
{
  if(sExpected.equals("true")!=true && sExpected.equals("false")!=true)
    Results.FileIO.WriteAppend("Attempting to verify "+sDesc+" but got an invalid parameter.       
            sExpected should be 'true' or 'false'");                
  else if(desktop.find(sData).isChecked()==true && sExpected=="false")
    Results.FileIO.WriteAppend(sDesc+" verification failed. Expected ("+sExpected+"), got
            (true)");
  else if(desktop.find(sData).isChecked()==false && sExpected=="true")
    Results.FileIO.WriteAppend(sDesc+" verification failed. Expected ("+sExpected+"), got
            (false)");
  else
    Results.FileIO.WriteAppend(sDesc+" verification: ("+sExpected+"): Success");
}
Finally, two runs through the testclass produces this results file:-

----------------------------------------------
Testcase: PlaceOrder
----------------------------------------------
   Start time: Mon Sep 20 23:36:03 BST 2010
Dome tents verification: (1): Success
Glacier sunglasses verification: (3): Success
Padded socks verification: (3): Success
Customer verification: (John Doe): Success
Address verification: (14 Any Street): Success
City verification: (Livingston): Success
State verification: (Alabama): Success
Zipcode verification: (41504): Success
Phone verification: (1112223333): Success
Email verification: (jdoe@any.com): Success
Card type verification: (Visa): Success
Card number verification: (1234-1234-1234-1234): Success
Expiry date verification: (09/09): Success 
   End time: Mon Sep 20 23:36:09 BST 2010
   Time to complete: 5 secs 400 milliseconds. 
----------------------------------------------
Testcase: PlaceOrder
----------------------------------------------
   Start time: Wed Sep 22 23:17:58 BST 2010
Dome tents verification: (1): Success
Glacier sunglasses verification: (3): Success
Padded socks verification: (3): Success
Customer verification: (John Doe): Success
Address verification: (14 Any Street): Success
City verification: (Livingston): Success
State verification: (Alabama): Success
Zipcode verification: (41504): Success
Phone verification: (1112223333): Success
Email verification: (jdoe@any.com): Success
Card type verification: (Visa): Success
Card number verification: (1234-1234-1234-1234): Success
Expiry date verification: (09/09): Success
   End time: Wed Sep 22 23:18:03 BST 2010
   Time to complete: 5 secs 199 milliseconds.

Nota Bene
The packages in the attached zipfile contain all the required file references for each project. However;

1.       The reference paths are from the machine they were created on, so these will need changing to match your own  environment. These were left to serve as a reminder as to which references are required for which projects.

2.       You will require the tag jarfiles created in the ‘Creating tags in Silk4J’ white paper.