Automate Functional Android app testing with Appium

Hello Folks,

Android app base is growing day by day and so it becomes vital to quickly test and release the apps to production. Appium is one among the promising android app testing frameworks. Let us get a grasp of it for testing Android applications.

Appium Architechture:

appium_architecture

Appium follows a server client architecture to execute test cases in real devices or emulator. Appium server is written in node.js and it runs in the developer machine. Once it is started, it will be ready to receive the requests via the test scripts written in any one the languages like Java, Python, Ruby, C#, node.js or Objective C++. Appium server will interpret the command from these languages and will send it to the device in a way that the device can understand. This is how It is able to support many languages.

But still it needs lot of support inside the android device to execute the test cases. So that for Android 4.2 and above, it utilizes UIAutomator along with its own libraries. For Android 2.3 and above , It uses selendroid along with Instrumenation class. To achieve this, Before installing the test apk, It will install all the dependencies to  the device.

Once this is done, test scripts will send the commands to the appium server and appium server will send it to android device. Support tools inside android device will interpret and execute the commands in the device.

Appium Support and Limitations:

Refer here for what can be done and what cannot be done with Appium as of now. Remind yourself to check this frequently as Appium is constantly getting better and better.

Appium Setup:

1. Download and Install node.js. Click here to download . As I told before, Appium server is written in node.js. So that we need to install node.js, before installing appium.

2. Download and install Appium server. Click here to download.

Open appium server and try out the different options provided in the GUI. Most of them are self explanatory. For Android,  Select the Android radio button on top and fill in details like SDK path, Device serial and your apk path, etc.  So with this you are all set with Appium server for android. Now launch appium server by clicking the Launch button on right top corner. It will launch the appium server and logs will get started to flow through in the appium server window.

Appium_server

Incase of any errors, Uncheck your proxy setup and try again.

Writing Appium Test case:

To write appium test cases, you can select any one of the supported languages and install the support libraries to start. In my case, I have chosen Python and installed the appium support libraries for python. Appium Client Libraries can be downloaded from here. Python “unitest” library is used to write Appium test cases.

Here is a simple Python based appium test script with two test cases:

# appium_testcase_android.py
from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import unittest
import time
import os

success = True
desired_caps = {}
desired_caps['appium-version'] = '1.0'
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.4'
desired_caps['deviceName'] = '32338239A8E400EC'
desired_caps['app'] = os.path.abspath('/Users/bala/Desktop/temp/MDusterDemo.apk')

class AppiumTests(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
        self.driver.implicitly_wait(60)

    def tearDown(self):
        self.driver.quit()

    def test_case_1(self):
        self.driver.find_element_by_xpath("//android.widget.ScrollView[1]/android.widget.FrameLayout[1]").click()

        tView = self.driver.find_element_by_xpath("//android.widget.ScrollView[1]/android.widget.TextView[1]")
        text = tView.get_attribute('text')

        self.assertEqual('ReceiveCalls', text);

    def test_case_2(self):
        self.driver.find_element_by_xpath("//android.widget.ScrollView[1]/android.widget.FrameLayout[1]").click()
        self.driver.find_element_by_xpath("//android.view.View[1]/android.widget.LinearLayout[1]").click()

if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(AppiumTests)
    unittest.TextTestRunner(verbosity=2).run(suite)

If you look at the code, most of the part is boilerplate. You can define your test cases by adding more methods starting with ‘test_’ . So let us see, How to write the test commands to perform on our app.

Appium provides a tool called Inspector which provides a recorder interface where it creates the equivalent command for every user action. It supports all the languages that are supported by appium. So just do the test scenario in the recorder and copy the code from Inspector and place it happily in the respective methods of your script.

Appium Inspector:

This is how inspector looks like, I tap on the calendar app’s month spinner,
Inspector

Code is created by the Inspector at the bottom, Now I can copy and use it in my script.
Inspector_1

So in the above screenshot, I have opened the default calendar app, Selected the month spinner and clicked the tap button. So that you can the generated the line of code the next screenshot. So that I will do the sequence of operations this way and finally copy the code and use it my test script. Spend little time to check each and every part of the Inspector.

Running Appium Test case:
Once we write the script, Executing it is like any normal python script execution.
$python app_test_suite_1.py

So the output will look like this,
Appium_output

This test result for another app. So dont get confused about the calendar app example 😉

Unlike few other functional testing frameworks like ‘MonkeyTalk’ Appium never touches the app apk. Also it installs and uninstalls the app for every test case. So that It will be highly effective for automating android app testing.

Happy Coding,
Balachandar KM

Advertisements

Join a WiFi network programmatically in Android

I recently came across a requirement where I need to connect the android device to specific Wifi Networks on request. Here is how i have coded it,

The request will be received through a broadcast

1. Create Wifi Configuration with WifiConfiguration class for the new wifi network.
2. Use wifi manager to disable all other networks except the network that I just added.
3. Now try to connect to an available enabled network. So that the device will connect to the only available enabled network which is the one we added.

Lets go through the code,

WifiConfiguration:

WifiConfiguration wifiConfiguration = new WifiConfiguration();
        wifiConfiguration.SSID = “\”” + networkSSID + “\””;  // This string should have double quotes included while adding.
    wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); // This is for a public network which dont have any authentication

//Add the created wifi configuration to device
        int netId = wifiManager.addNetwork(wifiConfiguration);  //Adds to the list of network and returns the network id which can be used to enable it later.

WifiManager:
WifiManager wifiManager  =(WifiManager)context.getSystemService(Context.WIFI_SERVICE);

       wifiManager.disconnect();
       wifiManager.enableNetwork(netId, true); // Seconds parm instructs to  disableOtherNetworks
       wifiManger.reconnect(); // Now we will connect to the only available enabled network.

Additional Notes:
      WifiManager can switch on your Wi-Fi too. But Incase If you want to switch wifi ON and then do the above, Try to provide few seconds delay (Use thread) for the wifi to switch on before you fire the methods to connect to your network.

To Switch On :  wifiManager.setWifiEnabled(true);
To Switch Off : wifiManager.setWifiEnabled(false);

Thanks to the stack over flow thread here.

Happy Coding, Balachandar KM