Skip to content

Minimalistic UI testing framework for Android based on ADB calls

License

Notifications You must be signed in to change notification settings

aivanovski/pico-automator

Repository files navigation

pico-automator

Small UI automation library for Android built on top of ADB calls. It provides API to write readable and dynamic tests on Clojure that could be run inside REPL or from command line.

Demo

demo

Motivation

pico-automator is inspired by maestro and allows to write UI tests on Clojure. The choice of Clojure allows to use a lightweight IDE (VS Code, Emacs, Vim and etc.) and REPL when writing tests.

Quickstart

  1. Create file example.clj with the code below:
(start-flow
  "Sample Flow"
  (fn [automator]
    (-> automator
        (launch "org.wikipedia")
        (tap-on {:text "Search Wikipedia"})
        (assert-visible {:text "Recent searches:"})
        (input-text "Monad")
        (assert-visible {:text "Monad (functional programming)"}))))
  1. Download pico-automator.jar from Release page and run the test (in order to work, pico-automator requires Java 11 and ADB binary accessible from the PATH variable)
java -jar pico-automator.jar example.clj

Usage

There are 2 ways to run tests with pico-automator:

  • With standalone CLI application pico-automator.jar
  • With Clojure REPL

Run tests with CLI application

The usage of CLI application is described in Quickstart section.

Run tests with Clojure REPL

The Functional API for pico-automator is provided by pico-automator-clojure project, that can be used as a dependency inside deps.edn file. pico-automator-clojure is available in JitPack maven repository here.

  1. Setup deps.edn file in the directory:
{:paths ["."]

 :mvn/repos
 {"jitpack" {:url "https://jitpack.io/"}}

 :deps
 {com.github.aivanovski/pico-automator-clojure {:mvn/version "X.X.X"}}

 :aliases
 {:repl-server {:extra-deps {nrepl/nrepl       {:mvn/version "1.0.0"}
                             cider/cider-nrepl {:mvn/version "0.37.0"}}
                :main-opts  ["--main"       "nrepl.cmdline"
                             "--middleware" "[cider.nrepl/cider-middleware]"]}}}
  1. Start the REPL server:
clojure -M:repl-server
  1. Create file with the test:
(ns wikipedia-search
  (:require [picoautomator.core :refer :all]))

(defn -main
  [& args]

  (start-flow
    "Search Wikipedia"
    (fn [automator]
      (-> automator
          (launch "org.wikipedia")
          ... ; Implement your test steps here
          ))))
  1. Connect to the REPL and run it.

The example could be found here

API overview

The api namespace is picoautomator.core.

Start the test

Function start-flow starts the test:

(start-flow
  "Test Flow"
  (fn [automator]
    (-> automator
        (launch "org.wikipedia"))))

Launch application

The application could be launched with launch function:

(-> automator
    (launch "org.wikipedia")) ;; specify your application id

Indentify views

Functions that interact with views (for example tap-on, assert-visible, input-text and etc.) require the view paramaters to be specified as follows. By view id:

{:id "viewId"} ;; corresponds to R.id.viewId in android application

By exact text:

{:text "Search Wikipedia"}

By content description:

{:content-desc "search-wikipedia"}

By patricular text matching:

{:contains-text "Wikipedia"}

Assertions

To assert whether an element is visbile or not visible following function could be used:

(-> automator
    (assert-visible {:id "viewId"})
    (assert-not-visible {:id "viewId"}))

Clicks

In order to click/tap on view:

(-> automator
    (tap-on {:id "viewId"})
    (long-tap-on {:id "viewId"}))

Input text

(-> automator
    ;; Inputs text regardless of whether any text field is currently focused or not
    (input-text "Text")

    ;; Taps on view specified by view-parameters and then inputs text
    (input-text "Text" {:id "inputField"}))

Controlling test lifecycle

In order to finish test successfully or with a failure depend on some extenal condition, functions complete and fail could be used:

(-> automator
    ;; Finishes test successfully and prints the message
    (complete "The test is finished successfully")

    ;; Finishes test with an error and prints the message
    (fail "The test is failed"))

Other functions

(-> automator
    ;; Checks if view is visible and returns true of false
    (visible? {:id "viewId"})

    ;; Stops test execution for 5 seconds
    (sleep {:seconds 5})

    ;; Wait until view became visible on the screen for 15 seconds and checks every second
    (wait-until {:text "viewId"} {:seconds 15} {:seconds 1})

    ;; Returns object that represents view tree on the screen
    (ui-tree))

Examples

More examples could be found here