Monday, November 03, 2014

culebra: GUI to automatically generate Android application tests

We have mentioned AndroidViewClient/culebra in many recent post and we reviewed many of the most useful features, however what I'm introducing today is certainly a breakthrough in automatic generation of Android application tests.

The following tests was automatically generated by running culebra and interacting with the window that mimics the content of the device or emulator.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
Copyright (C) 2013-2014  Diego Torres Milano
Created on 2014-11-02 by Culebra v8.11.1
                      __    __    __    __
                     /  \  /  \  /  \  /  \ 
____________________/  __\/  __\/  __\/  __\_____________________________
___________________/  /__/  /__/  /__/  /________________________________
                   | / \   / \   / \   / \   \___
                   |/   \_/   \_/   \_/   \    o \ 
                                           \_____/--<
@author: Diego Torres Milano
@author: Jennifer E. Swofford (ascii art snake)
'''


import re
import sys
import os


import unittest

from com.dtmilano.android.viewclient import ViewClient, CulebraTestCase


class CulebraTests(CulebraTestCase):

    @classmethod
    def setUpClass(cls):
        cls.kwargs1 = {'ignoreversioncheck': False, 'verbose': False, 'ignoresecuredevice': False}
        cls.kwargs2 = {'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True}
        cls.options = {'find-views-by-id': True, 'verbose-comments': False, 'find-views-with-content-description': True, 'save-view-screenshots': None, 'do-not-verify-initial-screen-dump': True, 'use-regexps': False, 'start-activity': None, 'find-views-with-text': True, 'unit-test-class': True, 'window': -1, 'save-screenshot': None, 'use-dictionary': False, 'scale': 0.5, 'use-jar': False, 'output': '/home/brldmila/tmp/calc-1.py', 'auto-regexps': None, 'interactive': False, 'append-to-sys-path': False, 'gui': True, 'dictionary-keys-from': 'id', 'unit-test-method': None}
        cls.sleep = 5

    def setUp(self):
        super(CulebraTests, self).setUp()

    def tearDown(self):
        super(CulebraTests, self).tearDown()

    def preconditions(self):
        return True

    def testSomething(self):
        if not self.preconditions():
            self.fail('Preconditions failed')

        self.vc.dump(window=-1)
        self.vc.device.press("HOME")
        self.vc.dump(window=-1)
        self.vc.findViewWithContentDescriptionOrRaise(u'''Apps''').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.vc.findViewWithTextOrRaise(u'Calculator').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.vc.findViewWithContentDescriptionOrRaise(u'''clear''').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.vc.findViewWithTextOrRaise(u'2').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.vc.findViewWithContentDescriptionOrRaise(u'''plus''').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.vc.findViewWithTextOrRaise(u'1').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.vc.findViewWithContentDescriptionOrRaise(u'''equals''').touch()
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)
        self.assertEquals(self.vc.findViewWithContentDescriptionOrRaise(u'''3''').getText(), u'''3''')
        self.vc.device.touchDip(168.262910798, 932.957746479)
        self.vc.sleep(CulebraTests.sleep)
        self.vc.dump(window=-1)


if __name__ == '__main__':
    CulebraTests.main()

To really appreciate how this test has been automatically generated I uploaded a simple (and crude) video of the steps. In the screencast you can see the emulator window (I used an emulator to easily capture the content but you can use any device), a terminal window where I run culebra and the culebra window where the interaction takes place.


Enjoy the video.
One really (or I should say extremely) cool feature of theses tests is that you can run exactly the same tests on a completely different device, let's say a tablet, and the tests would run exactly the same because culebra is not storing screen coordinates to interact with the Views but its logical attributes, like content description, text or ids. That way the test is device agnostic.
I'm explaining it step-by-step in the next post.

No comments: