8000 GitHub - kyeungk/ScreenCaptor: Simple Android framework to capture screenshots deterministically
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

kyeungk/ScreenCaptor

 
 

Repository files navigation

ScreenCaptor

Simple Android library to capture screenshots deterministically

Features

  • Capture a screenshot of any view in your integration tests
  • Dynamically hide views from your screenshots (Eg. Dates, Account Value, etc)
  • Use ViewMutators to mutate various types of views as needed

Download

Add this dependency in your build.gradle:

implementation 'com.wealthfront:screencaptor:0.1.0'

How do I capture a screenshot?

The simplest way to capture a screenshot is to just pass in the view to be screenshotted with a name for the screenshot when you want to take one.

ScreenCaptor.takeScreenshot(view = rootView, screenshotFilename = "my_favorite_screenshot")

There are other configurations that you can pass in as well,

  • screenshotNameSuffix - for any suffix that you want to attach to your screenshot
  • viewIdsToExclude - takes in a set of ids to exclude from the screenshot
  • viewMutators - allows you to mutate the subclasses of views in any particular way (Hides scrollbars and cursors by default)
  • screenshotDirectory - specify which directory you want to save the screenshot in (sdcard/screenshots/ by default)
  • screenshotFormat - whether the format needs to be JPEG, PNG or WEBP (PNG by default)
  • screenshotQuality - specify the quality of the screenshot (Best quality by default)

Note: You can disable the default mutators by passing in an empty set for the viewMutators argument in the takeScreenshot method.

Here's an example of a complex screencaptor setup:

ScreenCaptor.takeScreenshot(
  view = rootView,
  screenshotFilename = "my_favorite_screenshot",
  screenshotNameSuffix = "latest",
  viewIdsToExclude = setOf(R.id.date, R.id.account_value),
  screenshotFormat = JPEG,
  screenshotQuality = BEST
)

Why is screencaptor more deterministic?

When researching a way to properly take screenshots of a select view deterministically, we couldn't really find a simple framework that did just that and did it well. So, we went ahead and developed this framework for taking screenshots as deterministically as much as possible.

Manually drawing on a Canvas

Instead of using AndroidX's implementation of screenshot which utilizes the UiAutomator to take a screenshot, we manually draw the screen's content onto a bitmap canvas. This is a much more direct approach and ultimately leads to the screenshot process being the most native and close to the metal.

Posting to the MainThread

Another measure we take to improve the determinism is to post to the front of the message queue on the main thread. We do this so that the screenshot is taken as soon as the user requests it. Taking screenshots is a unit of work that doesn't not have any shared mutable state with any other part of the app so this does not cause any issues. This is usually a dangerous thing to do, but in this case it makes sense. We also have to do this operation in the main thread since we will be mutating views visibility of certain dynamic views.

Handling Dynamic data within views

This is a pretty common case that we run into where we have a dynamic piece of data displayed on the view that might change with every run of the test. The classic example is any date that gets displayed on the screen. And for this, we have a way of disabling/hiding these views when we take the screenshot using the ViewVisibilityModifier. This turns the views to be INVISIBLE right before taking the screenshot and turns the views to their initial state after the screenshot is taken.

Disabling cursor and scrollbars

Cursors and scrollbars show up in EditTexts and ScrollViews in an inconsistent manner and having that enabled means that it might make our screenshots more flaky. So to address that issue, we have the ViewTreeMutator which walks through the view hierarchy and disables scrollbars and cursors whenever applicable.

These techniques allow our screenshot framework to be free of flakiness as much as possible and makes it pretty extensible.

How we use screencaptor

We use screencaptor to capture screenshots in various places in our app when running our integration tests and compare the screenshot on master with any new PR that gets created. This helps us narrow down on any visual changes that happens with our app. Like so.

This helps us address a class of bugs before our app rolls out to production :)

License

Copyright 2020 Wealthfront, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

Simple Android framework to capture screenshots deterministically

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Kotlin 100.0%
0