Jenkins for PHP from scratch – I

jenkins logoThis is meant to be a full guide of how to set up jenkins for php, starting from the very beginning until the end. As it might become a very long guide, I’ll try to simplify it as much as possible, and I’ll split it in two or three posts.

All the guide was made under Ubuntu 12.10 though it should work fairly well in most of the latest Ubuntu versions, and apart from the apt-get commands the rest should be the almost the same for any unix operating system.

For those who doesn’t know what Jenkins is, here you are a very concise description:

Jenkins is an open source continuous integration tool written in Java.

It’s a very powerful tool and definitely a must have for any development environment that attempts to achieve continuous integration. If you are still not convinced have a look at wikipedia link, and read the fully explanation.

Ok, said that, let’s start, assuming the worst case scenario, where you have your own php application running, but you don’t even have a single automated/unit test.

The first thing you should probably do is install phpunit and start writting some tests. In my case I installed php-test-helpers as well. The installation should be pretty straightforward:

sudo pear config-set auto_discover 1
sudo pear install -a pear.phpunit.de/PHPUnit
sudo pear channel-discover pear.phpunit.de
sudo pecl install phpunit/test_helpers

I’ll skip the part when you learn how to write your own tests :).

Assuming you already have a bunch of tests that cover most of your application code, and you feel like you are ready to install jenkins, let’s do it:

wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

Jenkins should be already installed and its service should  have started automatically. It has a web interface at 8080 port by default, so now you should be able to browse it by typing the following url in your browser: http://localhost:8080

Now you should install several plugins that will probably be useful later. You might eventually get rid of some of them, but I advice you to give them a try, as they can provide you with very interesting information about your application. Typically, it’s recommended to install the following plugins:

– Jenkins GIT plugin: As I use git and my application is stored in bitbucket.
– Checkstyle: Useful if you want to apply some codding standard checks over the code.
– Jenkins Clover PHP: For processing PHPUnit code coverage reports.
–  DRY: For checking for duplicated code in the application
– HTML Publisher: For publishing HTML reports, such as the ones generated by PHPUnit.
– JDepend: For analizing the code coupling and dependencies.
– Plot: For being able to draw/display results as graphs
– PMD: For performing further analysis of the code such as locating unused variables, unnecessary objects and many more.
– Violations: For gathering all the isues found by all the plugins listed above.
– xUnit: To collect PHPUnit test results.

Note that here we are just installing the plugins, but in many cases we will need to install some additional software to actually be able to generate the reports. The plugins will take care of reading and displaying in a friendly way the mentioned reports. But don’t worry, we’ll cross that bridge when we get to it, for the moment installing the plugins is enough.

Once you have installed all the plugins that you want, let’s create our first job and test that everything is working as expected.

Open Jenkins and click on New Job.
Type any job name, select “Build a free-style software project” and hit OK.
In the next window, select your Source Code Management (git in my case) and configure its settings.
Assuming you are using GIT, you have to enter the repository URL, and you’ll probably get an authentication error, unless you are using a public repository.
Note that jenkins runs as an isolated service and it even creates its own pseudo-username. The easiest way to authenticate on the git repository from jenkins is either creating a new public key for jenkins username or just using your own keys. This is how I managed to get it working:
sudo cp .ssh/* /var/lib/jenkins/.ssh/
sudo chown jenkins:nogroup /var/lib/jenkins/.ssh/
This should fix the problem.
Now you just need to select your branch and if you want to browse the code from jenkins, just select the repository browser and enter the url.

Then, under the build section, click on Add build step, select “Execute shell” and type in the following:

phpunit --log-junit 'reports/unitreport.xml' --coverage-html 'reports/coverage' --coverage-clover 'reports/coverage/coverage.xml' path_of_your_tests

Finally, under the post-build section, add the following actions:
– Publish JUnit test result report: Enter the previous used file path: tests/reports/unitreport.xml
– Publish Cover PHP Coverage report: Enter the coverage file path: tests/reports/coverage/coverage.xml
Enable the option Publish HTML Report and enter the path tests/reports/coverage/
– Publish xUnit test result report

Once you are finished doing that, save the job, and start a new build.
If everything works as expected, you should see a blue ball at the end, and and something like this:
blue ball buildIf you have any problems have a look at the Console Output and it should help you to detect the problem. Let me know if you have any other problem and are not able to fix it.

That’s all for now, next time we’ll show how to use all the installed plugins and how to automatically start new builds once new code is pushed to the repository.

Supporting Different Languages

Android will run on many devices in many regions and therefore, the phone will be in different languages. To reach the most users, your application should handle text and graphics in ways appropriate to the locales where your application will be used.

To add support for more languages, create additional values directories inside res/ that include a hyphen and the ISO country code at the end of the directory name. For example, values-es/ is the directory containing simple resourcess for the Locales with the language code “es”. Android loads the appropriate resources according to the locale settings of the device at run time.

Once you’ve decided on the languages you will support, create the resource subdirectories and string resource files. For example:

MyProject/
    res/
       values/
           strings.xml
       values-es/
           strings.xml

Add the string values for each locale into the appropriate file.

At runtime, the Android system uses the appropriate set of string resources based on the locale currently set for the user’s device.

For example, the following are some different string resource files for different languages.

English (default locale), /values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">My Application</string>
<string name="hello_world">Hello World!</string>
</resources>

Spanish, /values-es/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">Mi Aplicación</string>
<string name="hello_world">¡Hola Mundo!</string>
</resources>

The same with images

MyProject/
    res/
       drawable/
           background.png
       drawable-es/
           background.xml

You can download this code: Download code

How to transfer data between two activities in android

The following post demonstrates how to use explicit Intents and how to transfer data between two activities.

The first activity will call the second one via an explicit intent. Once the user select the “Back” button on his phone the first activity will receive some hard-coded data from the sub-activity.

You can download this code: example

Create a new Android application.
Create two layouts. The first activity_one.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    xmlns:tools="http://schemas.android.com/tools"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:background="@drawable/background"
                    android:gravity="center_horizontal"
                    android:orientation="vertical" >

 <TextView android:id="@+id/TextView01"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:minHeight="60dip"
          android:text="@string/text_tv_activity_one"
          android:textSize="20sp" />

 <Button android:id="@+id/Button01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:onClick="onClick"
        android:text="@string/title_button_activity_one" />

</LinearLayout>

Create the second layout, your name activity_two.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:background="@drawable/background"
              android:gravity="center_horizontal"
              android:orientation="vertical" >

<LinearLayout android:layout_width="wrap_content"
              android:layout_height="wrap_content" >

<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/input_one"
          android:textSize="32dip" />

<EditText android:id="@+id/input1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/defaultt" />

</LinearLayout>

<LinearLayout android:layout_width="wrap_content"
              android:layout_height="wrap_content" >

<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/input_two"
          android:textSize="32dip" />

<EditText android:id="@+id/input2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/defaultt" />

</LinearLayout>

<Button android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="@string/finish"
        android:width="80dp" />

</LinearLayout>

Create the following coding for your two activities.


package com.thedeveloperworldisyours.datatransfer;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class ActivityOne extends Activity {

	private static final int REQUEST_CODE = 10;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_one);
    }

    public void onClick(View view) {
        Intent i = new Intent(this, ActivityTwo.class);
        i.putExtra("Value1", "This value one for ActivityTwo ");
        i.putExtra("Value2", "This value two ActivityTwo");
        // Set the request code to any code you like, you can identify the
        // callback via this code
        startActivityForResult(i, REQUEST_CODE);
      }

      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
          if (data.hasExtra("returnKey1")) {
            Toast.makeText(this, data.getExtras().getString("returnKey1"),
                Toast.LENGTH_SHORT).show();
          }
        }
      }

}

and the second activity.


package com.thedeveloperworldisyours.datatransfer;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class ActivityTwo extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_two);
		Bundle extras = getIntent().getExtras();
		if (extras == null) {
			return;
		}
		String value1 = extras.getString("Value1");
		String value2 = extras.getString("Value2");
		if (value1 != null && value2 != null) {
			EditText text1 = (EditText) findViewById(R.id.input1);
			EditText text2 = (EditText) findViewById(R.id.input2);
			text1.setText(value1);
			text2.setText(value2);
		}
	}

	public void onClick(View view) {
		finish();
	}

	@Override
	public void finish() {
		Intent data = new Intent();
		// Return some hard-coded values
		data.putExtra("returnKey1", "Swinging on a star. ");
		data.putExtra("returnKey2", "You could be better then you are. ");
		setResult(RESULT_OK, data);
		super.finish();
	}
}

You can download this code: example

Handling Arrays In PHP

arrays in phpToday, I’ll try to show you how to take advantage of the powerful built-in functions to handle arrays in PHP.

If you are a software developer, you will be used to handle data arrays in any language, so you’ll probably appreciate any given buil-in function that does all the dirty job for you.

This is not intended to be another tutorial of how to use arrays in PHP. I’d like to show you how combine the usage of the built-in functions, and how to create your own callable functions to create your custom filters, sorts or whatever you need.

If you have a look at php.net, PHP provide a lot of built-in functions, that allow you to transform, merge and/or split the data, accoding to your needs. Let’s start having a look at some of them individually, in order to see how to combine them later.


array_unique: Remove the duplicated elements from the array.

$a = array(0, 1, 1, 2);
array_unique($a); // array(0,1,2);

array_diff: Compare two arrays and return the difference respect from the first one.
$a = array(0, 1, 2);
$b = array(0, 2);
array_diff($a, $b); // array(1)

array_filter: Allow to apply a custom filter to the array. By default filters all elements that cast to boolean false.
$a = array(0 => true, 1 => false, 2 => 454, 3 => '');
array_filter($a); //array(0 => true, 2 => 454) Note that the key values are preserved

array_flip: Exchange the keys with the values.
$a = array("key" => "value");
array_flip($a); // array("value" => "key")

array_merge: Join all the arrays into a big one.
$a = array(1, 2, 3);
$b = array(3, 4, 5, 6);
array_merge($a, $b); //array(1, 2, 3, 3, 4, 5, 6) Note that duplicated elements are kept.

array_count_values: Show the number of ocurrences found for each value.
$a = array(1, 2, 1, 3, 2, 1);
array_count_values($a); //array(1 => 3, 2 => 2, 3 => 1);

array_map: Apply the given function to all the elements of the array. Check array_walk as well.
$a = array(" the", " developer ", " world ", " is ", " yours");
array_map("trim", $a); //array("the", "developer", "word", "is", "yours"); Note that the original array remains unchanged.

There are too many functions and I can’t show all of them here, because that would be another whole post. However you can always check the official page for more information and examples.

Now let’s see a couple of usages that can be useful many times.

For instance, imagine you are given an array of data, and first you want to do is clear it, and remove the empty values.

$data = array(" THE ", "developer ", "World", "", "IS", " yours ");
array_map('strtolower', array_filter(array_map('trim', $data)));
array (
  "the",
  "developer",
  "world",
  "is",
  "yours",
)

Firstly, trim all the elements, then filter the empty values, and finally transform all the data to lower case.
Another way of doing the same thing with an anonymous function:

array_filter(array_map(function($value) { return strtolower(trim($value));}, $data));

You might also try array_walk:

//Note that the following line will actually modify the original array
//We might use an anonymous function as well like in the previous example, now we use create_function
array_walk($data, create_function('&$val', '$val = strtolower(trim($val));'));
//Now we just need to clear out the empty values
array_filter($data);

Imagine we are working within a class, we want to apply a class method funcion to each array element, and we need to pass some extra variable as well.

class TheDeveloperWorldIsYours {
    public function parseData(&$data) {
        $prefix = 'Parsed: ';
        return array_walk($data, array($this, 'parseElement'), $prefix);
    }
    /**
     * parseElement
     * Prepend prefix to the given element if the key is even
     *
     * @param mixed $elem
     * @param mixed $key
     * @param mixed $prefix
     * @access protected
     * @return void
     */
    private function parseElement(&$elem, $key, $prefix) {
        $elem = $key % 2 == 0 ? $prefix . $elem : $elem;
    }
}

$data = array(1, 2, 3, 4, 5);
$a = new TheDeveloperWorldIsYours();
$a->parseData($data);
//Output:
array (
  0 => 'Parsed: 1',
  1 => 2,
  2 => 'Parsed: 3',
  3 => 4,
  4 => 'Parsed: 5',
)

Note that array_walk will call the given function with both the value and the key, in this order, and all the additional parameters will be placed afterwards.

Now, Imagine you have an array of data and you want to get only the duplicated elements.

$data = array('handling', 'arrays', 'in', 'php', 'handling', 'php', 'hi', 'php');
array_diff_key($data, array_unique($data));
array (
  "handling",
  "php",
  "php",
)

Note that we are comparing the array keys, because as we said previously, array_unique preserve them. So if we compare the original array with the unique, the repeated values (nor its keys) will not be present in the unique array, and we will get all the repeated elements as a result.
Imagine we just wanted to get once the repeated values. We might just apply an array_unique to the previous code, but we might do the following as well:

array_keys(array_filter(array_count_values($data), function($val) { return $val !=1;}));
array (
  'handling',
  'php',
)

And that’s about it. Now, each time you have to do some array filtering, sorting, transforming or whatever, firstly have a look at the php.net and think how you could do it without creating a loop :).

PHPUnit tips

Hopefully, all this phpunit tips can help you to test your own applications. If you have any questions, or suggestions, feel free to contact me!Some people have asked me to write something about testing, so I’ve decided to make this post and share some phpunit tips that I’ve learn.

This is not meant to be another tutorial of how to start writing your own tests with phpunit. Well, actually it is, but the purpose of my post is to explain you how to deal with real scenarios. If you try to search for phpunit examples, most places will show you how to create very simple test cases, but I haven’t seen many places explaining how to do more complex things. That’s exactly the purpose of this article. Moreover, If you think something’s missing, I encourage you to ask me about it, and I’ll try to append it to the post, or if it’s a big enough subject, I’ll create a whole new article about it.

Let’s begin from a very simple case, and we’ll get into something a bit more complicated step by step.
I assume that you already know what’s PHPUnit, and some basic concepts of how to use it, like for instance the dataproviders or mocks. If you think that you need some help to get started, have a look at PHPUnit’s official page and feel free to ask me, if needed.

Happy case in PHPUnit: Imagine you have an isolated class and you wanna test some of its methods.


/**
 * This code has been taken just as an example, from: http://snipplr.com/view.php?codeview&id=9024
 */
 class TheDeveloperWorldIsYours {
public static function generateUrlFromText($strText) {
 $strText = preg_replace('/[^A-Za-z0-9-]/', ' ', $strText);
 $strText = preg_replace('/ +/', ' ', $strText);
 $strText = trim($strText);
 $strText = str_replace(' ', '-', $strText);
 $strText = preg_replace('/-+/', '-', $strText);
 $strText = strtolower($strText);
 return $strText;
}
}

How would you test that? This might be an attempt:

/**
 * TheDeveloperWorldIsYours_Test
 *
 * @uses PHPUnit_Framework_TestCase
 */
class TheDeveloperWorldIsYours_Test extends PHPUnit_Framework_TestCase {

    public function setUp() {
    }

    protected static $inputs = array(
        array('   string    with  many   spaces   ', 'string-with-many-spaces'),
        array('stríng wïth wêird Àccents', 'str-ng-w-th-w-ird-ccents'),
        array('$peci4l: ch%r·ct3r$.', 'peci4l-ch-r-ct3r'),
        array('nice-string', 'nice-string'),
        array('testing+with+phpunit-is-cool', 'testing-with-phpunit-is-cool')
    );

    public static function providerFormat()
    {
        return self::$inputs;
    }

    /**
     * testFormat
     * Ensure that the string is being properly cleaned
     *
     * @dataProvider providerFormat
     * @param mixed $input
     * @param mixed $result
     * @access public
     * @return void
     */
    public function testFormat($input, $result) {
        $this->assertEquals($result, TheDeveloperWorldIsYours::generateUrlFromText($input));
    }
}

I assume that you have already set up some boostrap that takes care of including the required files (in this case, we just need to include the file where the class TheDeveloperWorldIsYours before executing the test).
If you run the test file with PHPUnit, you’ll notice that all the tests are passing, and you might want to add some corner cases to feel more comfortable, such as very long strings, empty strings, numbers and so. However, that’s out of the scope of this post (I could create a whole article about it). Nobody would know better than you the casuistic of your application, and you are the one responsible to add all the missing tests in each case.

So, in this example, we have the best scenario: The method is public, and even static, so we don’t need to instantiate the class in order to test the method. Also, the class doesn’t inherits from any other class, so we don’t have to worry about including all the required files.

Now, let’s assume we had the following scenario:

 class TheDeveloperWorldIsYours extends Some_Parent_Class {
protected function generateUrlFromText($strText) {
 $strText = preg_replace('/[^A-Za-z0-9-]/', ' ', $strText);
 $strText = preg_replace('/ +/', ' ', $strText);
 $strText = trim($strText);
 $strText = str_replace(' ', '-', $strText);
 $strText = preg_replace('/-+/', '-', $strText);
 $strText = strtolower($strText);
 if($strText === '') {
    die('Unable to generate a valid url from the given input');
 }
 return $strText;
}
}

Continue reading