Monday, August 01, 2016

Turns your Android smartphone into a complete laptop

I do not usually mention third party products in this blog unless there is a very good reason. The Superbook certainly is one of those.  It is a smart laptop shell that provides a large screen, keyboard and multi-touch trackpad, 8+ hours of battery, and phone charging capabilities. When plugged into your Android smartphone, it launches our app to deliver the full laptop experience.

The idea of using the same core device for your mobile and desktop experiences has been tried before, but this time, the Superbook gives it a twist and uses a full Android desktop. This is mainly possible due to the huge improvement lastest Android versions received in areas as multi-window support,  Android for work and Keyboard Shortcuts screen that surely move  the platform in the desktop direction.

That was not true some years ago. 6 years to be more precise, when one of the projects I was part of implemented the same concept but in the opposite direction I would say.

A mobile computing device with a mobile operating system and desktop operating system running concurrently and independently on a shared kernel without virtualization. The mobile operating system provides a user experience for the mobile computing device that suits the mobile environment. The desktop operating system provides a full desktop user experience when the mobile computing device is docked to a secondary terminal environment. The mobile computing device was a smartphone running the Android mobile OS and a full desktop Linux distribution (Ubuntu) on a modified Android kernel.

The concept included also a Smart book where you could dock your device.

Unfortunately, this project was later discontinued.

As I mentioned, a lot has changed in these last 6 years on Android and devices are much more powerful now to support this approach so take a look at Superbook as it might change your mobile and desktop experiences.

Friday, May 20, 2016

No Espresso Test Recorder in Android Studio 2.2

After all the frustration you may have experienced after discovering that Espresso Test Recorder is not in Android Studio 2.2 as announced in Google IO/16 presentation (see you can have something to play with today. Sign up for CulebraTester private beta see opt-in form)

Saturday, May 14, 2016

CulebraTester Private Beta Opt-in

Android testing can be complicated, time-consuming, and tedious. 
What if it didn’t have to be?

CulebraTester provides a real-time point and click test recording through a web browser. This browser is connected to the Android device under test. Not sure what we mean?
Visit for details.

If you are interested in being part of the Private Beta please fill out this form.


Tuesday, December 22, 2015

AndroidViewClient/culebra vs. MonkeyRunner

More than 2 years ago I took a crucial decision in AndroidViewClient/culebra development plan and that was to free it from `monkeyrunner`, Jython and Chimpchat.

AndroidViewClient/culebra was liberated and starting with version 4.0.0 it does not require any other runtime environment than python 2.x (read announcement). It can be installed and upgraded using the corresponding platform tools like easy_install or pip and can be easily integrated into IDEs like Eclipse PyDev or Pycharm. It also improves speed, solves chimpchat bugs, and even provides a GUI whre you can automatically create tests or scripts without writing a single line of code.

Nonetheless, from time to time, I receive some questions or reports about problems with scripts created with `culebra` that are attempted to run with `monkeyrunner` or some other combinations. I take the blame for it. I failed at communicating that AndroidViewClient/culebra is a complete replacement and should not be used together.

In order to improve the situation I gave a very detailed, easy to follow, step-by-step answer to
Error of Script with MonkeyRunner and AndroidViewClient (Touch) on Stackoverflow, showing how you can create a test case that automatically starts.and Activity (Duolingo) , checks if some Views are on the screen, touches them and finally take the screenshot. All from the GUI.

I hope you find this explanation useful.

Monday, August 24, 2015

culebra: concertina mode

One of the latest additions to culebra is the concertina mode. Named after the concertina movement occurring in snakes and other legless organisms that consists of gripping or anchoring with portions of the body while pulling/pushing other sections in the direction of movement, this mode allows culebra to move across the UI.

You may have used android's monkey before. monkey is a UI/Application exerciser that generates pseudo-random streams of user events such as clicks, touches, or gestures, as well as a number of system-level events. It is commonly used to stress-test application. While it may serve this purpose, it's overly complicated to be used in other scenarios.

Then, it comes culebra concertina mode that instead of sending pseudo-random events, analyzes the content of the screen and randomly selects a suitable event or action for the also randomly selected target, normally a View.

For example, if the randomly selected view is an EditText, culebra enters some random text. However if the EditText turns to be a password, it sends random passwords, that is instead of just entering a normal sentence it selected sample passwords from a list like the infamous "querty".
Furthermore, if it detects the EditText is expecting an email address, by inspecting the id, the hint or anything else that may suggest that, it sends random email addresses like Of course, other Views, receive other treatment, like Buttons being clicked, Scrollables being scrolled, etc.

Additionally, if the content description suggest the application may be awaiting for you to talk, like 'Tap to Speak' or 'Voice Search', culebra will actually speak random text to the app (this feature is only available on Linux and OSX).

You should check this aspect, it's sometimes hilarious.

Taking advantage of the culebra GUI already described in previous posts, while it's running the randomly selected Views are highlighted. At the same time, the python script is being generated. You can save it, modify it and run the same tests again and again. It's worth to mention that commonly the script eliminates the random selection of components and thus it runs deterministically.

Run culebra in concertina mode

$ culebra --gui --concertina --scale=0.5

and you can obtain something like this, where the nickname of a new contact was randomly selected from the available Views and the random text "chaos reigned" was entered.

BTW, this screenshot was taken via dump as described in android: obtaining beautiful screenshots automatically.

Friday, May 29, 2015

Google Cloud Test Lab

Yesterday, at Google I/O 2015, Cloud Test Lab was announced. One of its promoted features is: "you can run all of your tests across all devices, all at the same time--giving you access to massively parallel testing, bringing you deep and scaled insight".
Wow, that's pretty much the same I described in my previous post,
android: culebra multi-device capabilities, minus the devices of course. You have to provide them.

Wouldn't it be great if Cloud Test Lab allows you to create your personalized tests, in addition to the automatically generated ones, using something like culebra GUI, where you can just point and click?

Tuesday, May 19, 2015

android: culebra multi-device capabilities

culebra and its GUI both include multi-device capabilities in auto-generated test cases and scripts.

The test case or script is created as usual, but when the --multi-device option is present in the command line, the statements generated will be slightly different, still you can easily recognize them. These statements will include support for several devices using python's list comprehension.

For example, a typical will become

 [vc.dump(window=-1) for vc in self.allVcs()]

that is, for all the ViewClient's dump the content of the default window. You may wonder where the list of all ViewClient's obtained by self.allVcs() comes from. CulebraTestCase class handles multiple devices in its setUp() method and it's there where the lists of all devices, serial numbers and ViewClient's are handled

self.devices.append(ConnectedDevice(serialno=serialno, device=device, vc=vc))

Everything is handled automatically, so there's nothing to worry about. If only one device is connected to adb or a single serial number is passed to the test case as an argument, then the test case behaves exactly as single-device. However, if more than one device is connected to adb and they are specified on the command line the multi-device capabilities kicks-in and the test is run on all devices at the same time.
The special command line keyword all can be used to mean all the connected devices.

This trivial test for Calculator generated using

$ culebra --gui --multi-device \
    --unit-test-class \
    --do-not-verify-screen-dump \
    -o ~/tmp/

shows multi-device capabilities.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
Copyright (C) 2013-2014  Diego Torres Milano
Created on 2015-05-19 by Culebra v10.5.1
                      __    __    __    __
                     /  \  /  \  /  \  /  \ 
____________________/  __\/  __\/  __\/  __\_____________________________
___________________/  /__/  /__/  /__/  /________________________________
                   | / \   / \   / \   / \   \___
                   |/   \_/   \_/   \_/   \    o \ 
@author: Diego Torres Milano
@author: Jennifer E. Swofford (ascii art snake)

import re
import sys
import os

import unittest

    sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))

from import ViewClient, CulebraTestCase


class CulebraTests(CulebraTestCase):

    def setUpClass(cls):
        cls.kwargs1 = {'ignoreversioncheck': False, 'verbose': False, 'ignoresecuredevice': False}
        cls.kwargs2 = {'compresseddump': True, 'startviewserver': True, 'forceviewserveruse': False, 'autodump': False, 'ignoreuiautomatorkilled': True}
        cls.options = {'start-activity': None, 'device-art': None, 'use-jar': False, 'multi-device': True, 'unit-test-class': True, 'save-screenshot': None, 'use-dictionary': False, 'glare': False, 'dictionary-keys-from': 'id', 'scale': 1, 'find-views-with-content-description': True, 'window': -1, 'orientation-locked': None, 'save-view-screenshots': None, 'find-views-by-id': True, 'log-actions': False, 'use-regexps': False, 'null-back-end': False, 'auto-regexps': None, 'do-not-verify-screen-dump': True, 'verbose-comments': False, 'gui': True, 'find-views-with-text': True, 'prepend-to-sys-path': True, 'drop-shadow': False, 'output': '/Users/diego/tmp/', 'unit-test-method': None, 'interactive': False}
        cls.sleep = 5

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

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

    def preconditions(self):
        if not super(CulebraTests, self).preconditions():
            return False
        return True

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

        _s = CulebraTests.sleep
        _v = CulebraTests.verbose

        [_vc.dump(window=-1) for _vc in self.allVcs()]
        [_vc.findViewWithTextOrRaise(u'2').touch() for _vc in self.allVcs()]
        [_vc.sleep(_s) for _vc in self.allVcs()]
        [_vc.dump(window=-1) for _vc in self.allVcs()]
        [_vc.findViewWithContentDescriptionOrRaise(u'''plus''').touch() for _vc in self.allVcs()]
        [_vc.sleep(_s) for _vc in self.allVcs()]
        [_vc.dump(window=-1) for _vc in self.allVcs()]
        [_vc.findViewWithTextOrRaise(u'1').touch() for _vc in self.allVcs()]
        [_vc.sleep(_s) for _vc in self.allVcs()]
        [_vc.dump(window=-1) for _vc in self.allVcs()]
        [_vc.findViewWithContentDescriptionOrRaise(u'''equals''').touch() for _vc in self.allVcs()]
        [_vc.sleep(_s) for _vc in self.allVcs()]
        [_vc.dump(window=-1) for _vc in self.allVcs()]

if __name__ == '__main__':

Then, when you run the test with several devices connected as

$ ~/tmp/ -s all

you will obtain something like this