1. What are RobotiumRC Serializable classes 2. How to use Serializable classes in RobotiumRC 2.1 Used directly 2.2 Used internally 2.3 When to implement a new custom class 2.3.1 Standard Robotium waitForCondition Usage 2.3.2 RobotiumRC waitForCondition Usage 3. Why we need these Serializable classes
com.jayway.android.robotium.remotecontrol
They are compressed to a jar file:
robotium-serializable.jar
After the installation of RobotiumRC, this jar file can be found in:
<robotiumrc>\SoloRemoteControl\libs
For example C:\robotiumrc\SoloRemoteControl\libs if you accepted the default installation directory on Windows.
For now, this jar is including the following classes:
com.jayway.android.robotium.remotecontrol.By com.jayway.android.robotium.remotecontrol.Condition com.jayway.android.robotium.remotecontrol.ObjectCollection com.jayway.android.robotium.remotecontrol.PointF
com.jayway.android.robotium.remotecontrol.By com.jayway.android.robotium.remotecontrol.PointF
Instead of using:
com.jayway.android.robotium.solo.By, with android.graphics.PointFthe developer will use:
com.jayway.android.robotium.remotecontrol.By, with com.jayway.android.robotium.remotecontrol.PointFFor example:
When calling RobotiumRC API clearTextInWebElement(By), user can call like this:
By by = By.id(“webElementID”); solo.clearTextInWebElement(by);When calling API rotateSmall(PointF, PointF), user can call like this:
PointF center1 = new PointF(10.0, 10.0); PointF center2 = new PointF(50.0, 50.0); solo.rotateSmall(center1, center2);
The Conditions we have coded below return true if ALL the current Views are 'visible'.
// native device-side Robotium
void testCondition() {
solo.waitForCondition(new MyCondition(), 10);
}
// native device-side Robotium
//com.jayway.android.robotium.solo.Condition
public class MyCondition implements Condition {
public boolean isSatisfied() {
boolean satisfied = true;
//If all current views are visible,
//the condition is satisfied.
List
In the default package (or user's prefered package), create a subclass of com.jayway.android.robotium.remotecontrol.Condition:
//Serializable class needed on both controller and device //com.jayway.android.robotium.remotecontrol.Condition public class MyCondition extends Condition{ public boolean isSatisfied() { boolean satisfied = true; try{ // View UIDs provided by controller converted to real device-side objects List<Object> views = this.getObjects(); //The TestRunner itself is always item(0) in the list //RobotiumTestRunner runner = (RobotiumTestRunner) views.get(0); //Solo solo = runner.getSolo(); //Remaining objects (Views) begin at item(1) for(int i = 1 ; i < views.size(); i++){ satisfied &= ((View) views.get(i)).isShown(); if(!satisfied) break; } }catch(Exception e){ satisfied = false; } return satisfied; } }
This class will be used on the controller-side AND on the device-side. The class must be available at runtime on the device in the rebuilt TestRunner. We recommend packaging your custom Serializable classes in your own JAR file, or adding them to the robotium-serializable.jar file for the TestRunner project build.
Depending on the complexity of your isSatisfied() method, and the types of objects that must be referenced, JAR files like Android SDK JARs, or the robotium-4.x.JAR normally used only in the TestRunner project may have to be referenced in your Build Path (CLASSPATH) in your RemoteControl project as well.
Finally, the part where we use the Serializable instance on the controller and send it to the TestRunner at runtime:
//RemoteControl controller side use void testCondition(){ //com.jayway.android.robotium.remotecontrol.Condition Condition condition = new MyCondition(); //com.jayway.android.robotium.remotecontrol.solo.Solo List listviews = solo.getCurrentListViews(); condition.addObjects(listviews); //internally transports MyCondition with all object UIDs to device-side solo.waitForCondition(condition, 10); }The point is, the RemoteControl Condition class holds a List of String UIDs from the controller side and the user needs to put the current UIDs into the List at runtime. On the device side our Serializable implementation will get the real View objects from an internal cache and substitute them into the List.
Keep in mind, the first object [ List item(0) ] is reserved as the TestRunner object itself. The actual View objects will start at List item(1).
Beginning with Robotium 4.0, Robotium introduced new APIs accepting complex object instances or Interfaces for some parameters. The most obvious example of this is the Condition Interface used in Solo.waitForCondition(Condition).
This Condition is just an Interface containing one method. Thus, RemoteControl has to have a way to pass the object implementing the Interface along with whatever objects the Interface might need to get its job done. We decided to pass the objects via Serialization between the controller and the TestRunner on the device. This requires the individual classes be Serializable--which the standard classes are not.
Robotium and Android classes NOT Serializable we have dealt with are listed below. There is a RemoteControl version of each of these classes that can be Serialized and sent to the TestRunner to satisfy the new Robotium API arguments:
com.jayway.android.robotium.solo.By com.jayway.android.robotium.solo.Condition android.graphics.PointF
In addition, since it is often likely the Condition may need an object reference to the running TestRunner, or the traditional Robotium Solo object, or other native objects familiar to Robotium users gleaned from the TestRunner Instrumentation--we provide the device-side deserialized object with a reference to the TestRunner--which the controller side does not have and cannot provide.