Follow treslines by email clicking Here!

Wednesday, September 24, 2014

How to run junit tests inside the android project

Hi there!

Today i'm gonna show you how to create and run junit tests inside your android project without creating a separated test project. With those tests we will rapidly be able to automate and test the app's logic and some simple UI behaviors. The example below is very straightforward and much more intuitive than other approaches i saw out there.

Defining the TestInstrumentation 

First of all, define in your manifest file the following entries. IMPORTANT: While the definition of the test instrumentation will be placed outside your application tag, the test runner must be defined  inside your application tag.




< manifest >
...
< instrumentation 
  android:name="android.test.InstrumentationTestRunner"
  android:targetPackage="com.treslines.ponto" 
/ >
< / manifest >
< application >
...
< uses-library android:name="android.test.runner" / >
...
< / application >

Creating the test packages

Android works with some conventions while testing. So it is extremelly important to follow those conventions. Otherwise you'll get compile or run errors while trying to run it. One convention is that all tests for a specific class must be placed in the same package structure but with a futher sub-folder called test as you can see below. Because i want to test the activities in the package com.treslines.ponto.activity i must create a test package called com.treslines.ponto.activity.test



Creating the test itself

That's the cool part of it. Here you can write your junit tests as usual. Again android  gives us some conventions to follow. All test classes must have the same name as the class under test with the suffix Test on it. And all test methods must start with the prefix test on it. If you follow those conventions everything will work just fine.

// IMPORTANT: All test cases MUST have a suffix "Test" at the end
//
// THAN:
// Define this in your manifest outside your application tag:
//  < instrumentation 
//    android:name="android.test.InstrumentationTestRunner"
//    android:targetPackage="com.treslines.ponto" 
//  / >
//
// AND:
// Define this inside your application tag:
//  < uses-library android:name="android.test.runner" / >
//
// The activity you want to test will be the "T" type of ActivityInstrumentationTestCase2
public class AlertaActivityTest extends ActivityInstrumentationTestCase2 < AlertaActivity > {

 private AlertaActivity alertaActivity;
 private AlertaController alertaController;

 public AlertaActivityTest() {
  // create a default constructor and pass the activity class
  // you want to test to the super() constructor
  super(AlertaActivity.class);
 }

 @Override
 // here is the place to setup the var types you want to test
 protected void setUp() throws Exception {
  super.setUp();
  
  // because i want to test the UI in the method testAlertasOff()
  // i must set this attribute to true
  setActivityInitialTouchMode(true);

  // init variables
  alertaActivity = getActivity();
  alertaController = alertaActivity.getAlertaController();
 }

 // usually we test some pre-conditions. This method is provided
 // by the test framework and is called after setUp()
 public void testPreconditions() {
  assertNotNull("alertaActivity is null", alertaActivity);
  assertNotNull("alertaController is null", alertaController);
 }

 // test methods MUST start with the prefix "test"
 public void testVibrarSomAlertas() {
  assertEquals(true, alertaController.getView().getVibrar().isChecked());
  assertEquals(true, alertaController.getView().getSom().isChecked());
  assertEquals(true, alertaController.getView().getAlertas().isChecked());
 }

 // test methods MUST start with the prefix "test"
 public void testAlertasOff() {
  Switch alertas = alertaController.getView().getAlertas();
  // because i want to simulate a click on a view, i must use the TouchUtils
  TouchUtils.clickView(this, alertas);
  // wait a little (1.5sec) because the UI needs its time
  // to change the switch's state and than check new state of the switches
  new Handler().postDelayed(new Runnable() {
   @Override
   public void run() {
    assertEquals(false, alertaController.getView().getVibrar().isChecked());
    assertEquals(false, alertaController.getView().getSom().isChecked());
   }
  }, 1500);
 }
}

Running the JUnit tests

The only difference while running junit test in android is that you'll be calling Run As > Android JUnit Test instead of just JUnit Test like you are used to in java.


That's all! Hope you like it! :)

Monday, September 8, 2014

how to import/parse or create json/gson as arraylist from strings.xml in android?

Hi there!

Today i'm gonna show to you, how we can profit from the existing Gson library while dealing with array lists in the string.xml file. The benefits of it is that can define as many strings.xml entries as we need and import/parse the whole list structures almost without any effort.

Gson library

download the Gson library from here Gson 2.2.4. Don't worry about the "deprecated" tag. It is not really deprecated. Only parts of it acc. to its developer. We can continue using it. Than unzip it and cut/paste the following jar (gson-2.2.4.jar) in the libs folder from your project.

Json sample

Open your strings.xml file and copy/paste this line sample entry in it(It is a representation of an array list of Points with x and y coordinates):

 < string name="point_array" > {\"points\":[{\"x\": 255,\"y\": 689},{\"x\": 199,\"y\": 658}< / string > 

Defining a Data Container

You'll need a data container to hold the read points. So lets define a structure for it.
           
public class PointContainer {
    private List < Point > points;
    public List < Point > getPoints() {return points;}
    public void setPoints(List < Point > points) {this.points = points;}
}

Usage of the Gson lib

With the Gson lib, import/parse the array into a json structure. The benefits of it is that can define as many strings.xml entries as you need and import the whole list structure almost without any effort.
           
    String pointArray = getResources().getString(R.string.point_array);
    PointContainer pointContainer = new Gson().fromJson(pointArray, PointContainer.class);
    List < Point > points = pointContainer.getPoints();
    // do something with the data here...

Reading List of Lists

Here it gets more tricky. Offen we will need to read a list of list from json format into java code. To do so, lets see how it works by writing a simple example.We will do the same way as the code above. the only difference is to note that if we have list of list we will need to create a class that holds the sublists and so on...
 
< string name="string_points" >{"items":[{"points":[{"x": 644,"y": 420},{"x": 644,"y": 421},{"points":[{"x": 752,"y": 348},{"x": 752,"y": 349}]}]} < / string >

public class ItemContainer {
 private List < Item > items ;
 public List < Item > getItems() {
  return items 
 }
 public void setItems(List < Item > items ) {
  this.items  = items 
 }
}

public class Item {
 private List < Point > points;
 public List < Point > getPoints() {
  return points;
 }
 public void setPoints(List < Point > points) {
  this.points = points;
 }
}

String string = cxt.getResources().getString(R.string.string_points);
List < ItemContainer > l =  new ArrayList < ItemContainer >();
Gson gson = new Gson();
l.add(gson.fromJson(string, ItemContainer.class));

That's all! Hope you like it!