Sunday 27 December 2015

Twin Automation Tool - Automate windows calculator application using java client library.

Watch Demo
 

Prerequisites:
- .NET framework installed (version 3.0 or above).

Check Which Version of Microsoft .NET Framework is Installed in your Windows OS?
.Net Framework version can be verified by running below command in command prompt.
wmic /namespace:\\root\cimv2 path win32_product where "name like '%%.NET%%'" get version
 
Reference: http://www.askvg.com/how-to-check-which-version-of-microsoft-net-framework-is-installed-in-windows/ 

Download twin-rc server and twin-java client library from
https://code.google.com/archive/p/twin/downloads 
 

unzip the twin-1.0.zip
 

click 'SharpClaws.exe' to launch twin-rc.
 

Verify twin-rc is running by typing the url http://<<IP Address of machine>>:4444

 By default only 'notepad' application is configured with 'twin-rc'.
 
copy the 'twin-client-standalone-1.0.jar' to the lib folder of the project and set the java build path.
 

twin-ide can be accessed from http://<<IP Address of machine>>:4444/ide


If you are unable to access the twin-ide from browser, then click on link 'standalone app' which downloads 'ide.jar'

For working with windows applications other than 'notepad', add the target application details in 'sharpclaws.xml'.


adding the calculator application details in 'sharpclaws.xml' file.



stop the twin-rc server, if it is already running.
re-launch the twin-rc server.
 

click 'SharpClaws.exe' to launch twin-rc.
 

Launch 'ide.jar', which will launch twin-ide.


twin-ide is launched.
select 'calculator' application and click on 'Connect' button.
 

Expand the tree to identify the elements.


Sample Program:
import static org.ebayopensource.twin.Criteria.className;
import static org.ebayopensource.twin.Criteria.id;
import static org.ebayopensource.twin.Criteria.type;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.ebayopensource.twin.Application;
import org.ebayopensource.twin.Criteria;
import org.ebayopensource.twin.Element;
import org.ebayopensource.twin.TwinException;
import org.ebayopensource.twin.element.Pane;
import org.ebayopensource.twin.element.Window;

public class CalculatorTest {
      static final String RC_URL = "http://127.0.0.1:4444";
      static final String APPLICATION = "calculator";
   
      private Map<Integer,String> calcNumPad_ObjectRepository;
      private Map<String,String> calcOperPad_ObjectRepository;
      {
       //Object Repository for Calculator Numbers
       calcNumPad_ObjectRepository = new HashMap<Integer,String>();
       calcNumPad_ObjectRepository.put(0, "130");
       calcNumPad_ObjectRepository.put(1, "131");
       calcNumPad_ObjectRepository.put(2, "132");
       calcNumPad_ObjectRepository.put(3, "133");
       calcNumPad_ObjectRepository.put(4, "134");
       calcNumPad_ObjectRepository.put(5, "135");
       calcNumPad_ObjectRepository.put(6, "136");
       calcNumPad_ObjectRepository.put(7, "137");
       calcNumPad_ObjectRepository.put(8, "138");
       calcNumPad_ObjectRepository.put(9, "139");

       //Object Repository for Calculator Operators
       calcOperPad_ObjectRepository = new HashMap<String,String>();
       calcOperPad_ObjectRepository.put("+", "93");
       calcOperPad_ObjectRepository.put("-", "94");
       calcOperPad_ObjectRepository.put("*", "92");
       calcOperPad_ObjectRepository.put("/", "91");
       calcOperPad_ObjectRepository.put("=", "121");
       calcOperPad_ObjectRepository.put("clear", "81");
       }
   
      private static Pane pane = null;
      private static Criteria criteria = null;
      private static Window window = null;
     
      //Keypad Panel
      private static Element keyPadPanel = null;
      private static String SCREENSHOT_DIR = System.getProperty("user.dir")+"/Screenshots/";
   
      public static void main(String[] args) throws TwinException, IOException, InterruptedException{
        Application app = null;

        try{
            app = launchApplication();
            CalculatorTest ct = new CalculatorTest();
          
            //Clear Screenshots folder
            clearScreenshotsFolder();
          
            //Perform Addition
            System.out.println("Addition of 1,3 - Actual Results: "+ct.add(1,3)+",  Expected Results: 4");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Add_1_and_3.png"));
          
            System.out.println("Addition of 17,3 - Actual Results: "+ct.add(17,3)+",  Expected Results: 20");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Add_17_and_3.png"));
                      
            //Perform Subtraction
            System.out.println("Subtraction of 5,1 - Actual Results: "+ct.subtraction(5,1)+",  Expected Results: 4");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Subtraction_5_and_1.png"));
          
            System.out.println("Subtraction of 90,7 - Actual Results: "+ct.subtraction(90,7)+",  Expected Results: 83");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Subtraction_90_and_7.png"));
            
            //Perform Multiplication
            System.out.println("Multiplication of 8,2 - Actual Results: "+ct.multiplication(8,2)+",  Expected Results: 16");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Multiplication_8_and_2.png"));

            System.out.println("Multiplication of 15,4 - Actual Results: "+ct.multiplication(15,4)+",  Expected Results: 60");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Multiplication_15_and_4.png"));
            
            //Perform Division
            System.out.println("Division of 9,3 - Actual Results: "+ct.division(9,3)+",  Expected Results: 3");
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Division_9_and_3.png"));

            System.out.println("Division of 100,2 - Actual Results: "+ct.division(100,2)+",  Expected Results: 50");          
            window.getScreenshot().save(new File(SCREENSHOT_DIR + "Division_100_and_2.png"));
          
        }finally{
            //Close the application
            app.close();
        }
    }
     
    private static void clearScreenshotsFolder(){
        for (File f : new File(SCREENSHOT_DIR).listFiles())
        {
            if (f.isFile() && f.exists())
            { f.delete(); }
        }           
    }
   
    private static Application launchApplication() throws MalformedURLException{
        //URL of the remote control, connect to rc
        Application app = new Application(new URL(RC_URL));
          
        //launch application 'calculator' on remote control.      
        app.open(APPLICATION, null);

        window = app.getWindow();
        pane = window.getChild(type(Pane.class));
        criteria = type(Pane.class).and(className("#32770"));

        //Keypad Panel
        keyPadPanel = pane.getChildren(criteria).get(1);
       
        return app;              
    }
   
      //Perform 'Addition'.
     public int add(int a, int b) throws InterruptedException{
      performOperation("clear");
     
      clickNumber(a);
      performOperation("+");
      clickNumber(b);
      performOperation("=");
     
      return Integer.parseInt(getResults().trim());
     }  
   
      //Perform 'Subtraction'.
     public int subtraction(int a, int b) throws InterruptedException{
      performOperation("clear");
     
      clickNumber(a);
      performOperation("-");
      clickNumber(b);
      performOperation("=");

      return Integer.parseInt(getResults().trim());
     }
   
      //Perform 'Multiplication'.
     public int multiplication(int a, int b) throws InterruptedException{
      performOperation("clear");
     
      clickNumber(a);
      performOperation("*");
      clickNumber(b);
      performOperation("=");

      return Integer.parseInt(getResults().trim());
     }

     //Perform 'Division'.
     public int division(int a,int b) throws NumberFormatException, InterruptedException{
      performOperation("clear");
      clickNumber(a);
      performOperation("/");
      clickNumber(b);
      performOperation("=");
     
      return Integer.parseInt(getResults().trim());
     }
   
     //Click the Number in the calculator application.
     private void clickNumber(int number) throws InterruptedException{
        String sNumber = String.valueOf(number);
        for(int i = 0; i < sNumber.length(); i++) {
            String id_ = calcNumPad_ObjectRepository.get(Character.digit(sNumber.charAt(i), 10));
            keyPadPanel.getChildren(id(id_)).get(0).click();
            Thread.sleep(1000);
        }
     }
   
     //Perform operations.
     private void performOperation(String controlID) throws InterruptedException{
      String id_ = calcOperPad_ObjectRepository.get(controlID);
      keyPadPanel.getChildren(id(id_)).get(0).click();    
        
      Thread.sleep(1000);
     }    
   
     //Fetch the results after performing the operations
     private String getResults() throws InterruptedException{
      Thread.sleep(1000);
      Element resultPanel = pane.getChildren(criteria).get(0);
      String result = (resultPanel.getChildren().get(2)).getName();
     
      return result;
     }    
}




 

Related Links

Automating Calculator application using Java and Sikuli.
http://automation-home.blogspot.in/2014/09/AutomateCalcAppWithJavaAndSikuli.html

Java and AutoIt - Automating the calculator application using autoitx4java
http://automation-home.blogspot.in/2015/06/java-and-autoit-automating-calculator-application.html

5 comments:

  1. Replies
    1. Currently 'Twin Automation' library is present only for
      java.

      Delete
  2. is it possible to access existing open Calculator window using TWIN api?? or everytime i have to open calculator window using TWIN API to operate on it??

    ReplyDelete
    Replies
    1. Every time automation script is executed new calculator application is lauched.

      Delete
  3. What's the advantage and disadvantage for theses three ways? Do you have any suggestion about which way should I choose to do automation against the complex product which have more element than the calculator?

    ReplyDelete