Coder Social home page Coder Social logo

harshvs / android-gtest-driver Goto Github PK

View Code? Open in Web Editor NEW
18.0 4.0 10.0 730 KB

Google Test for native (NDK/C++) Android Apps

License: MIT License

CMake 0.15% Java 0.46% C++ 98.40% Objective-C 0.24% C 0.59% Python 0.16%
gtest android-gtest-driver ndk cpp google-test android gtest-support android-test

android-gtest-driver's Introduction

android-gtest-driver

Google Test for NDK based Android Apps

Here we have a sample NDK based Android project and a python script to show the integration of the Google Tests to run native (C++) instrumented unit tests.

Background & Rationale

The Unit testing of the shared native (C++) modules typically requires a large overhead of extracting/maintaining/running the modules outside of their real context so they could run under tests on the development/test machines. This usually requires rebuilding the binaries for the target machine with mocking and simulating things around it.

In practice, real systems are complex with myriad inter-dependencies. Testing a component by mocking its actual dependencies and, that too, outside of its actual run-time context is a complex, costly and tedious task. It is also hard to guarantee that the module under test will behave in exactly the same way in both test(dev box) and production environment. Also, it becomes increasingly hard to maintain the pure unit testing with mock everything strategy in presence of pressing deadlines and influx of new features. Often the ball gets dropped in the middle of the project and thereafter abandoned - as the cost (engineering debt) to revive it then gets prohibitively expensive.

The instrumented unit tests which run on actual device/emulator provide a better alternative. It gets us higher ROI as the effort to run and maintain it is lower, and it gives greater confidence in resutls (as entities get tested under real conditions). The downside of it could be slowness and flakiness of the test runs. But those concerns can be mitigated by avoiding delay causing steps like UI interactions and by providing controlled network conditions (say by testing against services available in the local network).

Using instrumented unit tests helps to reduce the effort to write and maintain mock code. We are free to use a mocking framework, if we choose, to simulate any dependency (say a flaky external service or faking UI interaction).

A unit in this context can be as small or big as we choose or see fit. The same test strategy, therefore covers a wide spectrum of testing (Unit/Component/Integration). This reasonable approach can potentially give us a far greater ROI and control over writing/maintaining test cases.

Problem

The tooling support for writing/maintaining instrumented C++ unit tests seems absent for Android. Here we may choose to hand-craft instrumentation tests but that effort won't scale in comparison to using an industry standard testing framework like Google Test.

Google Test is a popular open sourced xUnit based C++ testing framework from Google. It is put to use for testing large scale and critical projects like Chromium, LLVM, Protocol Buffer and the Android NDK etc. It is a command line based system, though its integration in IDEs (VS, CLion) is supported. There are some open source UI front-ends are available too. Google Test is light-weight, robust and having good eco-system/community - but it lacks support when it comes to its integration in Android projects. Android Studio does not provide any tooling support for it either.

android-gtest-driver tries to fill that gap.

Idea

Google Test invokes the tests for the system under test by parsing the supplied command line parameters and puts the result into its STDOUT channel.

The idea is to introduce a proxy program which runs on the command shell (on dev machine) which mimics the command line behavior of the Google Tests running inside the App. The driver program behaves as if it is the system under test, but the actual test initialization and the test runs happen on the device/emulator in the context of the app process.

This proxy way of interaction is achieved using ADB channel and by redirection of the app process's STDOUT channel to Android logs. The driver program keeps track of test results by scanning adb logs.

Design

Android Google Test Driver

Input to Google Test Run

The input from console to Google Test runtime inside the app is handled by the following steps:

  1. Test driver (gtest.py) takes the test command line params.
  2. A broadcast intent (GTEST_CMD) with those parameters as intent extra is sent via ADB to the device
  3. The broadcast is received by the app's GTest Driver receiver.
  4. The test parameters are extracted from the intent.
  5. The native Google test run (a JNI call) is initiated by initializing gtest for the supplied parameters.

Output from Google Test Run

The output (result) from the Google Test is delivered to console by the following steps:

  1. The Google test runtime generates results on the app process's STDOUT channel.
  2. The STDOUT of the process is funneled via a PIPE to a new FILE handle.
  3. The input stream from the PIPE is put into Android logs (by a worker thread, AppStdoutPump).
  4. The ADB gets the logs from the device to the test driver (gtest.py).
  5. The driver monitors the start and the end of Google Test specific logs.
  6. The driver outputs the results to its own STDOUT channel.

Sample Runs

Listing Test Cases

Running Test Cases

android-gtest-driver's People

Contributors

harshvs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

android-gtest-driver's Issues

gtest.py hangs

I'm trying to get this working with a modern ndk (20) against a nexus 5 emulator. I updated the build to use the latest gradle so it's not looking for mips anymore. The app is installed and running in the foreground in the emulator. However, any calls to gtest.py just hang. Here's the logcat.

2019-11-14 15:58:10.313 24256-24280/com.example.harsh.testcpp D/OpenGLRenderer: HWUI GL Pipeline
2019-11-14 15:58:10.358 24256-24280/com.example.harsh.testcpp I/OpenGLRenderer: Initialized EGL, version 1.4
2019-11-14 15:58:10.358 24256-24280/com.example.harsh.testcpp D/OpenGLRenderer: Swap behavior 1
2019-11-14 15:58:10.359 24256-24280/com.example.harsh.testcpp W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
2019-11-14 15:58:10.359 24256-24280/com.example.harsh.testcpp D/OpenGLRenderer: Swap behavior 0
2019-11-14 15:58:10.366 24256-24280/com.example.harsh.testcpp D/EGL_emulation: eglCreateContext: 0xa61040c0: maj 2 min 0 rcv 2
2019-11-14 15:58:10.375 24256-24280/com.example.harsh.testcpp D/EGL_emulation: eglMakeCurrent: 0xa61040c0: ver 2 0 (tinfo 0xa61032d0)
2019-11-14 15:58:10.420 24256-24280/com.example.harsh.testcpp D/EGL_emulation: eglMakeCurrent: 0xa61040c0: ver 2 0 (tinfo 0xa61032d0)

It looks like it starts up logcat and... that's it.

`
ppetraki@vanguard:~/Sandbox/Games/android-gtest-driver$ ps aux | grep adb
ppetraki 26422 0.4 0.0 561452 5876 ? Ssl 15:27 0:08 adb -L tcp:5037 fork-server server --reply-fd 5
ppetraki 32685 0.0 0.0 36784 2796 pts/2 T 15:58 0:00 /usr/bin/adb logcat

ppetraki@vanguard:~/Sandbox/Games/android-gtest-driver$ fg
python gtest.py --gtest_list_tests

^CTraceback (most recent call last):
File "gtest.py", line 63, in
scanLogcat()
File "gtest.py", line 33, in scanLogcat
line = p.stdout.readline()
KeyboardInterrupt
`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.