Running android UI tests in a slave node

Dockerized Jenkins for mobile CI/CD — PART 2

Running mobile UI Test in a node slave

--

Hello folks, thanks for coming back for the second part, you might have come here only if you liked previous article and you are excited to look more inside it. In the first part we learned how to build and run unit test for an Android Application. So, what I’ll be covering in this part is how to run UI test continuing with our containerized our previous Jenkins.

The problem with android UI Test in Docker

We are still not going to run the connectedDebugAndroidTest task which run the UI tests, because we are running Jenkins in a Docker container ands it’s not a good idea to create Android Emulators in a Docker container, based on my experience. Moreover, Android Emulators might be of different architectures such as ARM and x86, ARM emulators are available everywhere but are too slow for running ui tests, and x86 emulators are lightning fast but requires KVM(Kernel-based virtual machine) which means that you can deploy only with hardware linux machine and enable the HAXM Hypervisor.

That’s why if we add the connectedDebugAndroidTest Gradle task like this:

We will get an error like this:

Then nucleus: Continuous Integration

The final purpose of using Jenkins for mobile is to take advantage of the great features of this technology and make our software development and release process faster and robust. The first bare step is to start with continuous integration because is the initial part for a new culture. Later, you and your team will be able to implement the next practices like Continuous Delivery and Continuous Deployment.

According to wikipedia

In software engineering, continuous integration (CI) is the practice of merging all developer working copies to a shared mainline several times a day.

Running android UI Test in a containerized Jenkins

When you are working on a number of projects which get built on a regular basis or want to run multiple jobs or might need several different environments to test your builds, then a single Jenkins server cannot simply handle the entire load. Jenkins supports the master-slave architecture, i.e. many slaves work for a master and this is only possible thanks to JNLP(Java Network Launch Protocol)

So, what we need for running UI Test is a different environment rather than docker container which doesn’t support KVM(Kerne-based virtual machine). In this case, I’ll use my macOS machine as our slave node, something like this:

macOS slave node that runs ui test for Mobile

Java Network Launch Protocol (JNLP)

According to Jenkins official website…

The Java Network Launch Protocol (JNLP) enables an application to be launched on a client desktop by using resources that are hosted on a remote web server. The Java Plug-in software and Java Web Start software are considered JNLP clients because they can launch remotely hosted applets and applications on a client desktop.

Managing Jenkins master and slave nodes

The master-slave architecture in Jenkins is also known as Jenkins Distributed Builds. It also allows you to run jobs on different environments like Linux, Windows, MacOS, etc. We can also run the same test case on different environments in parallel using Jenkins Distributed Builds, which in turn helps you to achieve the desired results quickly using this distributed approach. All of the job results are collected and combined on the master node for monitoring.

Master-slave architecture that Jenkins supports

The Fun Part

In this walkthrough, we’re going to deploy Jenkins with these architectural components:

Jenkins Master

Your main Jenkins server is the master machine. Java process, plugins, job definitions, artifact storage, etc. The tasks performed by the master are :

  • Scheduling build jobs.
  • Dispatching builds to the slaves for the execution.
  • Monitor the slaves.
  • Recording and presenting the build results.
  • Can also execute build jobs directly.

Jenkins Slave

A slave is a Java executable that runs on a remote machine due to it uses JNLP(Java Launch Network Protocol) to connect with the master server. The characteristics of the slave are :

  • It hears requests from the Jenkins Master instance.
  • Slaves can run on a variety of operating systems.
  • The job of a Slave is to do as they are told to, which involves executing build jobs dispatched by the Master.
  • We can configure a project to always run on a particular Slave machine or a particular type of Slave machine, or simply let Jenkins pick the next available Slave.

Let’s get down to business

How to create Nodes in Jenkins

Go to Manage Jenkins > Manage Nodes > New Node. Here you can give your node a name, then select Permanent Agent and click OK.

Create or choose a directory in your computer to be the remote root directory where all network connection logs will be saved. For example: /Users/carlitosdroid/android_slave.

How to connect to Nodes with Jenkins

An easy way to control a node is by using Launch agent by connecting it to the master (Recommended for Windows). So, for macOS (behind Unix) and Linux the desired Launch method must be Launch agents via SSH but you have to install a plugin first SSH Build Agents.

Recommended way for macOS or Linux

Let’s download the SSH Build Agents . Go to the Manage Jenkins > Manage Plugins.

In your mac go to System Preferences > Sharing and activate Remote Login.

After enabling Remote Login, go inside your docker container with “docker container exec -it YOUR_CONTAINER_ID bash” and do the following:

Adding the localhost as known_host in the container

In the picture above, put the password you log in into your Desktop with. Then the container bash process will probably finish, don’t get worried. Let’s go inside the container again in order to checkout the known_host.

Go again inside the docker container and check it out

Now that’s we installed the plugin and setup the container, let’s come back to the nodes section in Jenkins. Select Launch agents via SSH, in Host you must put your localhost ip (192.168.1.4 in my case).

  • In credentials: Add and choose “Username with password”, then you must put your credentials of you current user for logging into your desktop.
This is my current logged in user
Put your current user credentials for logging into your desktop

Your final configuration must look something like this:

Your final configuration

Click on Save, come back to nodes screen and relaunch your node. That’s all 👊

Recommended way for Windows

I’m going to choose Launch agent by connecting it to the master. If someone can do it with macOS and help me, I’ll be very grateful.

We get an error because we didn’t still linked our node slave to a real machine (in my case my macOS machine)

Click on the node android and you’ll see the error details.

And now, just follow the instructions for running agent from command line:

  • Click on the agent.jar in order to download the jar file.
  • Place into the folder where the agent.jar was downloaded.
  • Copy and paste the command line instruction.

Go back to the Jenkins Interface and reload the webpage

Selecting our node in our Free Style Job

Once you have stablished the connection with the slave node, let’s go back to our Free Style Job configuration and you’ll see a new option added in the General section

Check the box Restrict where this project can be run and write the name of the slave node which is android.

By doing this we are telling Jenkins to run everything in our node slave (in my case is a macOS machine). If we run the Job, Jenkins will tell us that doesn’t find the SDK path /var/jenkins_home/sdk which is the SDK path in the container and it’s also what we wrote in the Environment Variables.

But remember, now we are in the node slave (our localhost, macOS in my case). That’s why Jenkins we need to specify our Android SDK in Jenkins in Global properties.

ANDROID_HOME
/Users/carlosleonardocamilovargashuaman/Library/Android/sdk

In addition to this, due to I’m using Fastlane for my projects, I’m also going to add my Fastlane bin path and required environment variables. For this example purpose, let’s change the SDK path in Jenkins

Don’t forget to have an emulator running on your computer or a device connected. In my case I have a real device connected. Let’s build again and surprised!. Test are running

UI Tests running

Things to pay attention

Take a look at the console log and pay attention to the details, which node the build took place to and the tasks we executed

As you can see my device is a Samsung SM-G90F — 7.0 where I run the ui test.

Coming soon…

So far, we have learned how to use node slaves with Jenkins, in order not to handle all the entire load by a single Jenkins master. Understanding theses topics are the basis, because in the next sections we will see Basic Continuous Integration and Continuous Delivery Flows, working with Webhooks in Bitbucket and taking advantage of the power Jenkins pipelines (Declarative and Scripted).

# CONCLUSION

Honestly, I would like to run everything in a docker container, but a fast Android Emulator requires certain hardware. Learning how to use tools at the beginning might be difficult, but with continuous usage, it becomes part of you. To create our Continuous Integration flow, understand the basics are necessary.

Learn More

If you would like to learn more, check out some other topics

docker-android : https://github.com/budtmo/docker-android

robolectric : http://robolectric.org/

Thank you for reading so far.

Happy coding! If you enjoyed the article make sure to show me some love and hit that clap button!

REFERENCES

--

--