CameraKit is an open-source library to support the Android Camera 1 and 2 APIs. Our goal is to massively increase the stability and reliability of photo and video capture on all Android devices with a library that is developer-focused and simple to implement.

In this post, I’m going to cover the techniques and challenges I encountered setting up a suite of unit tests for the CameraKit application.

Part 1. Why unit test

If you’ve not been writing tests in your code in the past it’s not too late to start! Testing should be a staple in every developer’s workflow. It not only ensures that your functions and classes operate as expected, but encourages cleaner design of those functions and classes.

Writing unit tests is a great place to get started. Unlike integration tests, unit tests don’t rely on outside dependencies which may add more complexity to your tests.

Part 2. The testing environment

You can check out the code base of CameraKit here: https://github.com/CameraKit/camerakit-android

To create the unit tests I used the following frameworks:

JUnit

Mockito

The dependencies and test options are shown below.

android {

compileSdkVersion 27

defaultConfig {

minSdkVersion rootProject.ext.minSdkVersion

targetSdkVersion rootProject.ext.targetSdkVersion

}

buildToolsVersion '27.0.3' testOptions {

unitTests.returnDefaultValues = true

}

} dependencies {

implementation 'com.camerakit:jpegkit:0.1.0'

implementation 'com.android.support:support-annotations:27.1.0'

testImplementation 'junit:junit:4.12'

testImplementation 'org.mockito:mockito-core:1.10.19'

}

JUnit and Mockito are the standard unit testing and mocking frameworks, respectively. Each have excellent community support and a wealth of knowledge if you run into issues.

Part 3. The tests

The core of the CameraKit functionality is contained in the class CameraKitView. This class is rather complex and has functions and objects that interact with different elements of the Camera 1 and 2 APIs.

The file CameraKitViewTest.java is split up into several different sections.

First, each dependency of CameraKitView is mocked, such as: Context, an AttributeSet, the GestureListener, etc. We want to be able to test methods in isolation. Mocking effectively hides the complexity of services and methods from other classes.

Next, a setup function is run to create real objects and mock entire function calls encountered in the tests.

Finally come the unit tests. Each unit tests covers a specific short public function of the CameraKitView class. Asserts are used to ensure that the function returns the expected value and will operate properly when used in real world scenarios.

@Test

public void toggleFacingTest() {

cameraKitView.setFacing(CameraKit.FACING_BACK);

cameraKitView.toggleFacing();

assertEquals(cameraKitView.getFacing(), CameraKit.FACING_FRONT);

}

Here’s an example of a test of the toggleFacing function. As one can imagine, the function switches the facing direction of the camera based on its current state. The facing direction is set one direction, toggled, and then an assert is used to make sure the toggle happened.

Part 4. Integrating with Buddy

Buddy.works is a platform to create testing environments and deployment pipelines and comes with native docker support. Buddy is not only a great solution for testing and deployment but they’re a sponsor for CameraKit! We’ve migrated from CircleCI to Buddy for v1.0.0.

With Native docker support, setting up Buddy was a breeze. Just configure the environment with a docker image from DockerHub and you’re free to run tests. I used the ./gradlew test command to download the android dependencies and run the tests. The docker image was created by Dylan McIntyre for this project.

The CameraKit pipeline was setup to run on each push to the GitHub repository using built in Buddy web-hooks.

Part 5. Challenges & what’s next

There is another type of object in the CameraKitView class that I was not able to test using unit tests; the CameraPreview abstract class and its implementations Camera1 and Camera2. These classes are private to CameraKitView and can only be created with proper Android device permissions and context. To set the permissions and context you need an emulated Android device which calls for instrumented testing! These tests will require more setup in Buddy to emulate a device in the docker environment. While they won’t be ready for the stable 1.0.0 release, instrumented tests will be coming soon.

In addition, there are a great number of tasks Buddy can perform for different test results. For example, we can send notifications or stop changes from going to production if the tests are not passed. These features will help speed up the development process and allow us to include more features and contributions from the community.

Keep an eye out for future posts as we continue to improve CameraKit!