GithubHelp home page GithubHelp logo

facebook / screenshot-tests-for-android Goto Github PK

View Code? Open in Web Editor NEW
1.7K 67.0 243.0 2.59 MB

Generate fast deterministic screenshots during Android instrumentation tests

Home Page: http://facebook.github.io/screenshot-tests-for-android

License: Apache License 2.0

Java 63.26% Python 27.42% CSS 0.91% JavaScript 0.64% Groovy 0.96% Kotlin 5.11% Starlark 1.69%

screenshot-tests-for-android's Introduction

Screenshot Tests for Android

screenshot-tests-for-android is a library that can generate fast deterministic screenshots while running instrumentation tests on Android.

We mimic Android's measure(), layout() and draw() to generate screenshots on the test thread. By not having to do the rendering on a separate thread we have control over animations and handler callbacks which makes the screenshots extremely deterministic and reliable for catching regressions in continuous integration.

We also provide utilities for using screenshot tests during the development process. With these scripts you can iterate on a view or layout and quickly see how the view renders in a real Android environment, without having to build the whole app. You can also render the view in multiple configurations at one go.

Documentation

Take a look at the documentation at http://facebook.github.io/screenshot-tests-for-android/#getting-started

Requirements

screenshot-tests-for-android is known to work with MacOS or Linux.

The host tooling probably doesn't work on Windows, but can be made to work with a little effort. We'll happily accept pull requests!

You need python-2.7 for the gradle plugin to work, and we also recommending installing the python-pillow library which is required for recording and verifying screenshots.

Building screenshot-tests-for-android

You don't have to build screenshot-tests-for-android from scratch if you don't plan to contribute. All artifacts are available from Maven Central.

If you plan to contribute, this is the code is broken up into a few modules:

  • The core module is packaged as part of your instrumentation tests and generates screenshots on the device.

  • The plugin module adds Gradle tasks to make it easier to work with screenshot tests.

  • The layout-hierarchy-common module adds extra common View information to your reports' layout hierarchy viewer

  • The layout-hierarchy-litho module adds extra Litho component information to your reports' layout hierarchy viewer

In addition you'll find python code inside plugin/src/py. This code is packaged into the gradle plugin.

We have tests for the python code and the core library. Run these commands to run all the tests:

  $ gradle :plugin:pyTests
  $ gradle :core:connectedAndroidTest

Both need a running emulator.

Python tests rely on the mock and Pillow libraries. Both can be installed via pip install mock and pip install Pillow.

You can install all the artifacts to your local maven repository using

  $ gradle installArchives

Running With a Remote Service

For usage with a remote testing service (e.g. Google Cloud Test Lab) where ADB is not available directly the plugin supports a "disconnected" workflow. Collect all screenshots into a single directory and run the plugin using the following options

Example

The location of the screenshot artifacts can be configured in the project's build.gradle:

  screenshots {
      // Points to the directory containing all the files pulled from a device
      referenceDir = path/to/screenshots
  }

Then, screenshots may be verified by executing the following:

  $ gradle :<project>:verify<flavor>ScreenshotTest

To record, simply change verify to record.

Contributing

Please see the contributing file.

Authors

screenshot-tests-for-android was originally written by Arnold Noronha ([email protected]) You can reach him at @tdrhq on GitHub.

It is currently maintained by Hilal Alsibai (@xiphirx)

License

screenshot-tests-for-android is Apache-2-licensed.

screenshot-tests-for-android's People

Contributors

aahlenst avatar alexmalyshev avatar alonsch avatar astreet avatar blavalla avatar brosenfeld avatar caiiiycuk avatar cgrushko avatar colinrtwhite avatar dalyadickstein avatar daniel9z avatar doodla avatar gavinweng avatar ianchilds avatar jbaginski avatar josedlpozo avatar jrodbx avatar kylannjohnson avatar lwasyl avatar marcinkunert avatar pedrovgs avatar rratmansky avatar scottkennedy avatar scottrice avatar stanislavglebik avatar tdrhq avatar ttsugriy avatar vanniktech avatar xiphirx avatar zertosh avatar

Stargazers

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

Watchers

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

screenshot-tests-for-android's Issues

Version of dexmaker included here, conflicts with dexmaker in my tests.

screenshot-tests-for-android includes com.google.dexmaker
my tests use com.crittercism.dexmaker .

When applying the screenshot-tests-for-android plugin, about 40% of the time some of my tests that use Mockito will fail with error like this:

    at com.google.dexmaker.mockito.InvocationHandlerAdapter.invoke(InvocationHandlerAdapter.java:49)
    at java.lang.reflect.Proxy.invoke(Proxy.java:397)
    at $Proxy33.clearOffersCache(Unknown Source)
    at ```

and 

```org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-> at 
Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.

I can tell it is related to the com.google.dexmaker dependancy, because of com.google.dexmaker.mockito.InvocationHandlerAdapter in the stacktrace.

com.crittercism.dexmaker uses a different package name -> "com.android.dx.mockito"

use tags

please tag your releases here, it'll be much easier to follow.

Document `testApkTarget`

I added the plugin to my build, with the instructions found in http://facebook.github.io/screenshot-tests-for-android/#getting-started and then tried running gradle tasks. I got the error:

Execution failed for task ':tasks'.
> Could not determine the dependencies of task ':app:pullScreenshots'.

Through looking through the stacktrace and googling I found #1 and the fact I need to do the following to inform screenshots about the name of the test task:

screenshots {
    testApkTarget = 'connectedAndroidTestDebug'
}

Which will be different for a lot of users. It would be good if either the docs mentioned this or there was a more helpful error message when it's not configured properly.

Record resources displayed in a screenshot

There probably isn't even a way to do this reliably, but recording the resources displayed on the screen would be a boon for translators. There would need to be a way to tag the loading of resources (e.g., string from strings.xml) all the way to the View that it's associated with. Then this information combined with the screenshot and a snapshot of the view hierarchy it could be used to provide context images for translators.

Verify fails for no reason

I did recordMode screenshotTests and then without changing anything, right after I ran verifyMode screenshotTests. I have just one screen covered now. The test failed with:
Image /var/folders/xx/ylzhl52j66xcf367d8d502tc0000gn/T/tmpyoCni4/<package>.LoginScreenTest_loginAndLogout.png is not same as screenshots/<package>.LoginScreenTest_loginAndLogout.png

I compared screenshots manually and I don't see any differences. Attaching both, recorded and verified screnshoots. Those look the same to me. If it painted some colour differences, that would be great.

screenshots

EDIT:
It passed once today. Gussing that alghoritm is too sensitive for changes

Execution failed for task ':app:clearScreenshots'. > A problem occurred starting process 'command 'adb''

I use 0.2.3

classpath 'com.facebook.testing.screenshot:plugin:0.2.3'

When I run

$./gradlew --stacktrace screenshotTests

It gave me wrong message like 'can't find adb', but I'm pretty sure my adb is in PATH.

Parallel execution is an incubating feature.
{[email protected], snapshotRepository=null, pomFilterContainer=o[email protected]78f561fe, repository=null, name=null, activePomFilters=[[email protected]fd0], [email protected]a8bc, class=class org.gradle.api.publication.maven.internal.deployer.DefaultGroovyMavenDeployer, configuration=null, uniqueVersion=true, artifactPomContainer=org.gr[email protected]5171ea50, po[email protected]dce53f6}
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
WARNING [Project: :app] To shrink resources you must also enable ProGuard
:app:clearScreenshots
:protocol:compileLint
:appkit:compileLint
:protocol:copyReleaseLint UP-TO-DATE
:protocol:preBuild
:appkit:copyReleaseLint UP-TO-DATE
:protocol:preBuild UP-TO-DATE
:appkit:preBuild
:protocol:preReleaseBuild UP-TO-DATE
:appkit:preBuild UP-TO-DATE
:appkit:preReleaseBuild UP-TO-DATE
:app:clearScreenshots FAILED
:appkit:checkReleaseManifest

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:clearScreenshots'.
> A problem occurred starting process 'command 'adb''

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:clearScreenshots'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.process.internal.ExecException: A problem occurred starting process 'command 'adb''
    at org.gradle.process.internal.DefaultExecHandle.setEndStateInfo(DefaultExecHandle.java:196)
    at org.gradle.process.internal.DefaultExecHandle.failed(DefaultExecHandle.java:325)
    at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:83)
    ... 2 more
Caused by: net.rubygrapefruit.platform.NativeException: Could not start 'adb'
    at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
    at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)
    at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:65)
    ... 2 more
Caused by: java.io.IOException: Cannot run program "adb" (in directory "/Users/zhenfangzhang/android/example/app"): error=2, No such file or directory
    at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
    ... 4 more
Caused by: java.io.IOException: error=2, No such file or directory
    ... 5 more


BUILD FAILED

Total time: 2.037 secs

Error " output files to contain exactly one file, however, it contains 2 files" when running verifyMode screenshotTests

Hi, So I'm not sure what the problem is, but when I run ./gradlew verifyMode screenshotTests --stacktrace I get the below error. I'm running under ubuntu. Any idea of what the problem could be? Below is what the error is:

* What went wrong:
Execution failed for task ':sample:pullScreenshots'.
> Expected task ':sample:packageDebugAndroidTest' output files to contain exactly one file, however, it contains 2 files.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':sample:pullScreenshots'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:66)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
        at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
        at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
        at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:153)
        at org.gradle.internal.Factories$1.create(Factories.java:22)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:150)
        at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:98)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:92)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:92)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:83)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:99)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:48)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:237)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: java.lang.IllegalStateException: Expected task ':sample:packageDebugAndroidTest' output files to contain exactly one file, however, it contains 2 files.
        at org.gradle.api.internal.file.AbstractFileCollection.getSingleFile(AbstractFileCollection.java:59)
        at org.gradle.api.file.FileCollection$getSingleFile.call(Unknown Source)
        at com.facebook.testing.screenshot.build.ScreenshotsPlugin.getTestApkOutput(ScreenshotsPlugin.groovy:120)
        at com.facebook.testing.screenshot.build.ScreenshotsPlugin$_apply_closure1_closure8.doCall(ScreenshotsPlugin.groovy:43)
        at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:67)
        at org.gradle.api.internal.file.DefaultFileOperations.exec(DefaultFileOperations.java:175)
        at org.gradle.api.internal.project.AbstractProject.exec(AbstractProject.java:856)
        at org.gradle.api.internal.project.AbstractProject.exec(AbstractProject.java:852)
        at org.gradle.api.Project$exec$1.call(Unknown Source)
        at com.facebook.testing.screenshot.build.ScreenshotsPlugin$_apply_closure1.doCall(ScreenshotsPlugin.groovy:42)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:590)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:571)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:77)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:73)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 68 more

I can share my build.gradle file if i will help. I'll test it out on a mac to see if I get the same problem. The only thing I did recently is update to latest android studios not sure how it changes things.

The actual tests themselves run correctly.

Allow Plugin to specify screenshot directory under test

It would be great to specify the location of the generated screenshots to the plugin as an alternative to using an adb pull to retrieve them each time.

For our CI build, we run our instrumentation tests in separate runs across multiple devices in parallel. IF we could specify the location of the screenshots, we could perform one verification at the end of the build

FAILURE when running ./gradlew clean recordMode screenshotTests --stacktrace

Offending setup/environment

OSX 10.10.5 & Windows 10
Nexus 7 running 5.1.1 & Nexus 6 running N preview
Gradle 2.13
Android tools 2.1.0
screenshot-tests-for-android 0.4.1

Stacktrace

Incremental java compilation is an incubating feature.
:clean
:app:clean
:app:recordMode
:app:clearScreenshots
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAnimatedVectorDrawable2330Library
:app:prepareComAndroidSupportAppcompatV72330Library
:app:prepareComAndroidSupportDesign2330Library
:app:prepareComAndroidSupportRecyclerviewV72330Library
:app:preDebugAndroidTestBuild UP-TO-DATE
:app:prepareComAndroidSupportSupportV42330Library
:app:prepareComAndroidSupportSupportVectorDrawable2330Library
:app:prepareComJakewhartonTimberTimber412Library
:app:prepareComSquareupLeakcanaryLeakcanaryAndroid131Library
:app:prepareInfoAndroid15NucleusNucleusSupportV7300Library
:app:prepareIoReactivexRxandroid120Library
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig
:app:mergeDebugShaders
:app:compileDebugShaders
:app:generateDebugAssets
:app:mergeDebugAssets
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
:app:generateDebugSources
:app:incrementalDebugJavaCompilationSafeguard
:app:compileDebugKotlin
...
:app:compileDebugNdk UP-TO-DATE
:app:compileDebugSources
:app:prePackageMarkerForDebug
:app:unzipJacocoAgent
:app:transformClassesWithJacocoForDebug
:app:transformClassesWithDexForDebug
Result compacted from 8520.3KiB to 6582.5KiB to save 1937.8KiB
Merged dex #1 (5 defs/15.3KiB)
Merged dex #2 (329 defs/536.4KiB)
Merged dex #3 (182 defs/255.7KiB)
Merged dex #4 (134 defs/303.8KiB)
Merged dex #5 (770 defs/937.2KiB)
Merged dex #6 (17 defs/48.5KiB)
Merged dex #7 (5 defs/9.6KiB)
Merged dex #8 (67 defs/58.3KiB)
Merged dex #9 (37 defs/18.1KiB)
Merged dex #10 (1717 defs/1878.8KiB)
Merged dex #11 (220 defs/251.6KiB)
Merged dex #12 (3 defs/4.1KiB)
Merged dex #13 (333 defs/262.4KiB)
Merged dex #14 (10 defs/7.8KiB)
Merged dex #15 (128 defs/234.4KiB)
Merged dex #16 (6 defs/1.6KiB)
Merged dex #17 (202 defs/134.1KiB)
Merged dex #18 (299 defs/854.9KiB)
Merged dex #19 (8 defs/17.1KiB)
Merged dex #20 (19 defs/10.2KiB)
Merged dex #21 (106 defs/198.5KiB)
Merged dex #22 (33 defs/29.6KiB)
Merged dex #23 (931 defs/763.4KiB)
Merged dex #24 (41 defs/6.5KiB)
Result is 5602 defs/6582.5KiB. Took 1.3s
:app:mergeDebugJniLibFolders
:app:transformNative_libsWithMergeJniLibsForDebug
:app:processDebugJavaRes UP-TO-DATE
:app:transformResourcesWithMergeJavaResForDebug
:app:validateDebugSigning
:app:packageDebug
:app:zipalignDebug
:app:assembleDebug
:app:prepareComAndroidSupportTestEspressoEspressoContrib222Library
:app:prepareComAndroidSupportTestEspressoEspressoCore222Library
:app:prepareComAndroidSupportTestEspressoEspressoIdlingResource222Library
:app:prepareComAndroidSupportTestEspressoEspressoIntents222Library
:app:prepareComAndroidSupportTestExposedInstrumentationApiPublish05Library
:app:prepareComAndroidSupportTestRules05Library
:app:prepareComAndroidSupportTestRunner05Library
:app:prepareComAndroidSupportTestUiautomatorUiautomatorV18212Library
:app:prepareDebugAndroidTestDependencies
:app:compileDebugAndroidTestAidl
:app:processDebugAndroidTestManifest
:app:compileDebugAndroidTestRenderscript
:app:generateDebugAndroidTestBuildConfig
:app:mergeDebugAndroidTestShaders
:app:compileDebugAndroidTestShaders
:app:generateDebugAndroidTestAssets
:app:mergeDebugAndroidTestAssets
:app:generateDebugAndroidTestResValues UP-TO-DATE
:app:generateDebugAndroidTestResources
:app:mergeDebugAndroidTestResources
:app:processDebugAndroidTestResources
:app:generateDebugAndroidTestSources
:app:incrementalDebugAndroidTestJavaCompilationSafeguard
:app:compileDebugAndroidTestKotlin
...
:app:compileDebugAndroidTestNdk UP-TO-DATE
:app:compileDebugAndroidTestSources
:app:prePackageMarkerForDebugAndroidTest
:app:transformClassesWithDexForDebugAndroidTest
...
Result compacted from 7152.7KiB to 5534.1KiB to save 1618.6KiB
Merged dex #1 (63 defs/79.8KiB)
Merged dex #2 (252 defs/277.8KiB)
Merged dex #3 (770 defs/937.2KiB)
Merged dex #4 (2 defs/1.0KiB)
Merged dex #5 (22 defs/37.8KiB)
Merged dex #6 (108 defs/113.8KiB)
Merged dex #7 (27 defs/29.1KiB)
Merged dex #8 (2002 defs/2162.6KiB)
Merged dex #9 (4 defs/4.1KiB)
Merged dex #10 (49 defs/39.5KiB)
Merged dex #11 (84 defs/126.7KiB)
Merged dex #12 (29 defs/39.0KiB)
Merged dex #13 (36 defs/19.6KiB)
Merged dex #14 (38 defs/62.9KiB)
Merged dex #15 (381 defs/515.5KiB)
Merged dex #16 (9 defs/9.6KiB)
Merged dex #17 (45 defs/38.2KiB)
Merged dex #18 (5 defs/2.9KiB)
Merged dex #19 (35 defs/54.8KiB)
Merged dex #20 (333 defs/262.4KiB)
Merged dex #21 (2 defs/15.7KiB)
Merged dex #22 (15 defs/4.9KiB)
Merged dex #23 (34 defs/8.8KiB)
Merged dex #24 (286 defs/238.9KiB)
Merged dex #25 (694 defs/665.8KiB)
Merged dex #26 (37 defs/27.0KiB)
Merged dex #27 (6 defs/11.3KiB)
Result is 5368 defs/5534.1KiB. Took 3.4s
:app:mergeDebugAndroidTestJniLibFolders
:app:transformNative_libsWithMergeJniLibsForDebugAndroidTest
:app:processDebugAndroidTestJavaRes UP-TO-DATE
:app:transformResourcesWithMergeJavaResForDebugAndroidTest
:app:packageDebugAndroidTest
:app:assembleDebugAndroidTest
:app:connectedDebugAndroidTest
:app:createDebugAndroidTestCoverageReport
:app:connectedAndroidTest
:app:pullScreenshots
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/Users/gallal/.gradle/caches/modules-2/files-2.1/com.facebook.testing.screenshot/plugin/0.4.1/95bb67a888bc9791a5b8e3a575c98b38bfd9bc75/plugin-0.4.1.jar/android_screenshot_tests/pull_screenshots.py", line 275, in <module>
  File "/Users/gallal/.gradle/caches/modules-2/files-2.1/com.facebook.testing.screenshot/plugin/0.4.1/95bb67a888bc9791a5b8e3a575c98b38bfd9bc75/plugin-0.4.1.jar/android_screenshot_tests/pull_screenshots.py", line 272, in main
  File "/Users/gallal/.gradle/caches/modules-2/files-2.1/com.facebook.testing.screenshot/plugin/0.4.1/95bb67a888bc9791a5b8e3a575c98b38bfd9bc75/plugin-0.4.1.jar/android_screenshot_tests/pull_screenshots.py", line 209, in pull_screenshots
  File "/Users/gallal/.gradle/caches/modules-2/files-2.1/com.facebook.testing.screenshot/plugin/0.4.1/95bb67a888bc9791a5b8e3a575c98b38bfd9bc75/plugin-0.4.1.jar/android_screenshot_tests/recorder.py", line 16, in <module>
ImportError: No module named PIL
:app:pullScreenshots FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:pullScreenshots'.
> Process 'command 'python'' finished with non-zero exit value 1

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:pullScreenshots'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:68)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
        at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
        at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
        at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
        at org.gradle.internal.Factories$1.create(Factories.java:22)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
        at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
        at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
        at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
        at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:51)
        at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:28)
        at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:43)
        at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:173)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:241)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:214)
        at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
        at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:207)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
        at org.gradle.launcher.Main.doAction(Main.java:33)
        at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:55)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:36)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
        at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:30)
        at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:129)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
Caused by: org.gradle.process.internal.ExecException: Process 'command 'python'' finished with non-zero exit value 1
        at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:367)
        at org.gradle.process.internal.DefaultExecAction.execute(DefaultExecAction.java:31)
        at org.gradle.api.internal.file.DefaultFileOperations.exec(DefaultFileOperations.java:176)
        at org.gradle.api.internal.project.AbstractProject.exec(AbstractProject.java:841)
        at org.gradle.api.internal.project.AbstractProject.exec(AbstractProject.java:837)
        at org.gradle.api.Project$exec$3.call(Unknown Source)
        at com.facebook.testing.screenshot.build.ScreenshotsPlugin$_apply_closure1.doCall(ScreenshotsPlugin.groovy:42)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:554)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:535)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:77)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:73)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 60 more


BUILD FAILED
=

Update consumption of Gradle api's

If using the plugin in a more recent version of Gradle the following message gets printed:
The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.

Our CI builds typically run with the --stacktrace argument to help capture any issues in the build script, unfortunately this causes a great deal of noise.

If you invoke gradle with --stacktrace it becomes:

The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at org.gradle.api.internal.AbstractTask.leftShift(AbstractTask.java:513)
        at org.gradle.api.Task$leftShift$1.call(Unknown Source)
        at com.facebook.testing.screenshot.build.ScreenshotsPlugin.apply(ScreenshotsPlugin.groovy:41)
        at com.facebook.testing.screenshot.build.ScreenshotsPlugin.apply(ScreenshotsPlugin.groovy)
        at org.gradle.api.internal.plugins.ImperativeOnlyPluginApplicator.applyImperative(ImperativeOnlyPluginApplicator.java:35)
        at org.gradle.api.internal.plugins.RuleBasedPluginApplicator.applyImperative(RuleBasedPluginApplicator.java:43)
        at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:139)
        at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:112)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.applyType(DefaultObjectConfigurationAction.java:113)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.access$200(DefaultObjectConfigurationAction.java:36)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction$3.run(DefaultObjectConfigurationAction.java:80)
        at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.execute(DefaultObjectConfigurationAction.java:136)
        at org.gradle.api.internal.project.AbstractPluginAware.apply(AbstractPluginAware.java:44)
        at org.gradle.api.internal.project.ProjectScript.apply(ProjectScript.java:34)
        at org.gradle.api.Script$apply.callCurrent(Unknown Source)
        at build_bbmt0wex8uufxh9dwjkyrnlz1.run(/Sources/busybusy/busy-android/busybusy/build.gradle:3)
        at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:90)
        at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl$2.run(DefaultScriptPluginFactory.java:176)
        at org.gradle.configuration.ProjectScriptTarget.addConfiguration(ProjectScriptTarget.java:77)
        at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:181)
        at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:39)
        at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:26)
        at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.doConfigure(LifecycleProjectEvaluator.java:70)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.access$000(LifecycleProjectEvaluator.java:33)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:53)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$1.execute(LifecycleProjectEvaluator.java:50)
        at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:61)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:50)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:628)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:129)
        at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
        at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:38)
        at org.gradle.initialization.DefaultGradleLauncher$1.execute(DefaultGradleLauncher.java:161)
        at org.gradle.initialization.DefaultGradleLauncher$1.execute(DefaultGradleLauncher.java:158)
        at org.gradle.internal.Transformers$4.transform(Transformers.java:169)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:106)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:56)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:158)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:119)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:102)
        at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:71)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:44)
        at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:29)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:47)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

ImportError: No module named PIL

I'm having an issue trying to run

gradle recordMode screenshotTests

It seems I'm missing a Python library. I tried to install it via:

pip install PIL

but I get the following message

Could not find a version that satisfies the requirement PIL (from versions: )
No matching distribution found for PIL

However, installing Pillow works:

pip install Pillow

I tried running gradle recordMode screenshotTests again after, but I still get the same message.

I know nothing about Python, please help.

Could not find build-tools

Hi,

I can't run this gradle command on Windows: gradle recordMode screenshotTests. I always get the "TaskExecutionException: Execution failed for task ':pullScreenshots'" error
I already installed Python 2.7.1 and the Pillow library 2.1.0 and set my ANDROID_HOME variable.

Above the error there's a message saying: RuntimeError: Could not find build-tools in D:\tools\Android\sdk

Is there anything I can do, or it shouldn't suppose to work on Windows at this time?

Thanks

`repoClean` task dependency

Hi,

This project is a great idea and I'm looking into getting it to run on windows. At the moment I'm trying to build the source and I'm running into a problem running a simple gradlew tasks to get a list of available tasks. Gradle reports that Could not determine the dependencies of task ':uploadAllLocal'.

I've fiddled with the build.gradle and it seems that the dependsOn of ":repoClean" for the task is causing the issue.

I can't find any other reference to a repoClean task in this project, or elsewhere on the internet. Can you point me in the right direction at all?

Thanks,
Jon

Support for multiple build variants

Thanks for releasing this! I've been looking forward to taking a look at it.

My app has a bunch of build types and a couple build flavors yielding lots of different build variants. When I follow the docs to add your project and run a simple test, I get the following error:

$ ./gradlew screenshotTests

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':ExampleCompany:pullScreenshots'.
> Task with path ':packageDebugAndroidTest' not found in project ':ExampleCompany'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 12.355 sec

It looks like the plugin is trying to find the packageDebugAndroidTest task, which doesn't exist in my app. Instead, I would like to use the packagePlayInternalDebugAndroidTest task.

Looking around in the plugin, I found this, which suggests that I can configure the plugin like so:

screenshots {
    testApkTarget = 'packagePlayInternalDebugAndroidTest'
}

Even with this line, I get the same error. Any advice?

Inflating views with application context does not use styles

I noticed an issue with inflating layouts using something like

LayoutInflater layoutInflater = LayoutInflater.from(InstrumentationRegistry.getTargetContext());

in that this uses a context that does not honor the use of attributes in the layout xml view tags such as

style="@style/TextAppearance.AppCompat.Title"

I was able to work around this issue by creating an ActivityTestRule and getting the layout inflater from the activity:

LayoutInflater layoutInflater = activityTestRule.getActivity().getLayoutInflater();

While this does work, it is not quite as fast since the activity needs to be started before the test is run. Is there a way to include styles in the context so that using an activity is not necessary? I tried InstrumentationRegistry.getTargetContext().setTheme(R.style.AppTheme); with no avail.

Make mTileSize configurable to avoid tiling when not required

I'm seeing 7 files being created per screenshot call. Is it not possible to get just a single png? I don't want a debug dump and tiled images. None of the images are a complete screenshot of what's on the screen.

Screenshot.snapActivity(getActivity()).setName(name).record();

com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials.png
com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials_0_1.png
com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials_0_2.png
com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials_1_0.png
com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials_1_1.png
com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials_1_2.png
com.my.pkg.test.LoginTest-loginRejectsInvalidCredentials_dump.xml

Failed to create snapshoot on view not measured

could someone explain me what I am doing wrong?

public void test_view(){
   View view = new ImageView(getInstrumentation().getTargetContext());
   view.setBackgroundColor(Color.RED);

   ViewHelpers.setupView(view)
          .setExactWidthDp(widthDp)
          .layout();

   Screenshot.snap(view).record();
}

java.lang.RuntimeException: java.lang.RuntimeException: Can't take a screenshot, since this view is not measured

Can't execute pullScreenshots

On a fresh project, running one test, one screenshot, with Gradle plugin 2.6. I get the following stack trace

 What went wrong:
Execution failed for task ':app:pullScreenshots'.
> java.lang.NullPointerException (no error message)

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:pullScreenshots'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:90)
    at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:50)
    at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:27)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:40)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:169)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
    at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:30)
    at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:127)
    at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
Caused by: java.lang.NullPointerException
    at org.gradle.process.internal.DefaultProcessForkOptions.getActualEnvironment(DefaultProcessForkOptions.java:75)
    at org.gradle.process.internal.AbstractExecHandleBuilder.build(AbstractExecHandleBuilder.java:124)
    at org.gradle.process.internal.DefaultExecAction.execute(DefaultExecAction.java:28)
    at org.gradle.api.internal.file.DefaultFileOperations.exec(DefaultFileOperations.java:154)
    at org.gradle.api.internal.project.AbstractProject.exec(AbstractProject.java:787)
    at org.gradle.api.internal.project.AbstractProject.exec(AbstractProject.java:783)
    at org.gradle.api.Project$exec$8.call(Unknown Source)
    at com.facebook.testing.screenshot.build.ScreenshotsPlugin$_apply_closure1.doCall(ScreenshotsPlugin.groovy:38)
    at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:558)
    at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:539)
    at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:77)
    at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:73)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    ... 49 more

Failed to create the directory for screenshots. Is your sdcard directory read-only?

Im trying to get the plugin working on api 23+. I have already added a task to grant the required permission, but im getting "Failed to create the directory for screenshots. Is your sdcard directory read-only?" after calling

Screenshot.snap(view)
                .record();

Im not sure why im not able to create a new directory even when i got the correct permission.

runTests[MI 3C - 6.0.1] FAILED - can not install apk

execute gradle screenshotTests, show error as below:

Starting a new Gradle Daemon for this build (subsequent builds will be faster).
Parallel execution is an incubating feature.
Incremental java compilation is an incubating feature.
Probe disabled for demoDebug
Probe disabled for demoRelease
Probe disabled for fullDebug
Probe disabled for fullRelease
:clearScreenshots
:preBuild UP-TO-DATE
:preFullDebugBuild UP-TO-DATE
:checkFullDebugManifest
:preDemoDebugBuild UP-TO-DATE
:preDemoReleaseBuild UP-TO-DATE
:preFullReleaseBuild UP-TO-DATE
:prepareComAndroidSupportCardviewV72400Library UP-TO-DATE
:prepareComAndroidSupportRecyclerviewV72400Library UP-TO-DATE
:prepareComAndroidSupportSupportV42400Library UP-TO-DATE
:prepareOrgLucasrProbeProbe013Library UP-TO-DATE
:prepareFullDebugDependencies
:compileFullDebugAidl UP-TO-DATE
:compileFullDebugRenderscript UP-TO-DATE
:generateFullDebugBuildConfig UP-TO-DATE
:mergeFullDebugShaders UP-TO-DATE
:compileFullDebugShaders UP-TO-DATE
:generateFullDebugAssets UP-TO-DATE
:mergeFullDebugAssets UP-TO-DATE
:generateFullDebugResValues UP-TO-DATE
:generateFullDebugResources UP-TO-DATE
:mergeFullDebugResources
:processFullDebugManifest UP-TO-DATE
:processFullDebugResources
:generateFullDebugSources
:incrementalFullDebugJavaCompilationSafeguard UP-TO-DATE
:compileFullDebugJavaWithJavac
注: 某些输入文件使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
注: 某些输入文件使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
:compileFullDebugNdk UP-TO-DATE
:compileFullDebugSources
:prePackageMarkerForFullDebug
:transformClassesWithDexForFullDebug
Running dex in-process requires build tools 23.0.2.
For faster builds update this project to use the latest build tools.
:mergeFullDebugJniLibFolders UP-TO-DATE
:transformNative_libsWithMergeJniLibsForFullDebug UP-TO-DATE
:processFullDebugJavaRes UP-TO-DATE
:transformResourcesWithMergeJavaResForFullDebug UP-TO-DATE
:validateDebugSigning
:packageFullDebug
:zipalignFullDebug
:assembleFullDebug
:preFullDebugAndroidTestBuild UP-TO-DATE
:prepareFullDebugAndroidTestDependencies
:compileFullDebugAndroidTestAidl UP-TO-DATE
:processFullDebugAndroidTestManifest UP-TO-DATE
:compileFullDebugAndroidTestRenderscript UP-TO-DATE
:generateFullDebugAndroidTestBuildConfig UP-TO-DATE
:mergeFullDebugAndroidTestShaders UP-TO-DATE
:compileFullDebugAndroidTestShaders UP-TO-DATE
:generateFullDebugAndroidTestAssets UP-TO-DATE
:mergeFullDebugAndroidTestAssets UP-TO-DATE
:generateFullDebugAndroidTestResValues UP-TO-DATE
:generateFullDebugAndroidTestResources UP-TO-DATE
:mergeFullDebugAndroidTestResources UP-TO-DATE
:processFullDebugAndroidTestResources UP-TO-DATE
:generateFullDebugAndroidTestSources UP-TO-DATE
:incrementalFullDebugAndroidTestJavaCompilationSafeguard UP-TO-DATE
:compileFullDebugAndroidTestJavaWithJavac UP-TO-DATE
:compileFullDebugAndroidTestNdk UP-TO-DATE
:compileFullDebugAndroidTestSources UP-TO-DATE
:prePackageMarkerForFullDebugAndroidTest
:transformClassesWithDexForFullDebugAndroidTest UP-TO-DATE
:mergeFullDebugAndroidTestJniLibFolders UP-TO-DATE
:transformNative_libsWithMergeJniLibsForFullDebugAndroidTest UP-TO-DATE
:processFullDebugAndroidTestJavaRes UP-TO-DATE
:transformResourcesWithMergeJavaResForFullDebugAndroidTest UP-TO-DATE
:packageFullDebugAndroidTest UP-TO-DATE
:assembleFullDebugAndroidTest UP-TO-DATE
:connectedFullDebugAndroidTest
Unable to install /Users/longerian/Documents/android-workspace/longerian/ABCAndroid/build/outputs/apk/ABCAndroid-full-debug.apk
com.android.ddmlib.InstallException: Failed to establish session
        at com.android.ddmlib.SplitApkInstaller.install(SplitApkInstaller.java:66)
        at com.android.ddmlib.Device.installPackages(Device.java:901)
        at com.android.builder.testing.ConnectedDevice.installPackages(ConnectedDevice.java:119)
        at com.android.builder.internal.testing.SimpleTestCallable.call(SimpleTestCallable.java:121)
        at com.android.builder.internal.testing.SimpleTestCallable.call(SimpleTestCallable.java:48)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

com.android.builder.testing.ConnectedDevice > runTests[MI 3C - 6.0.1] FAILED 
        com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: Failed to establish session
                at com.android.builder.testing.ConnectedDevice.installPackages(ConnectedDevice.java:129)

FAILURE: Build failed with an exception.

* What went wrong:
Could not receive a message from the daemon.

dev env:

systemProp.compileSdkVersion=23
systemProp.buildToolsVersion=23.0.1

    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        classpath 'org.lucasr.probe:gradle-plugin:0.1.3'
        classpath 'com.facebook.testing.screenshot:plugin:0.4.2'
    }
  • mac os

Add a helpful hint about using target sdk to 22

Can anyone point me to a fully fleshed out example of how this can be used? I've implemented everything I can find from the instructions page, this bug tracker, the wiki and the examples on the master branch and it's still not working.

Addendum: Don't you need to grant external storage permission to the app by means of a pop-up in order to write the screenshots to disk in the first place?

Facebook>Chat panel

There is a bug in facebook in chat, there is a chat panel in right side of facebook page, when there are lots of people are online and that time, if we scroll the scroll bar, then last user are not showing properly.

see the attachment..

screenshot 100

screenshot 100 _3

Not able to make tests work with AndroidJunitRunner

While trying to run screenshots with my UI tests, i am always getting no tests found the moment i add the screenshot plugin.
I extended AndroidJunitRunner i am always getting that error.

Can you please provide a working example with tests that using AndroidJunitRunner and not instrumentedTestcase that is deprecated

When running on an api 23 emulator and targeting api 23, permissions are not granted

Since write_external_storage is required, if an app compiles and targets api 23 it needs to accept the external storage permission. This can be done by installing with -g, however the screenshot tests don't do this so writing to external storage always fails.

Compiling against 23 and targeting 22 does not exhibit these symptoms as it automatically grants all requested permissions.

App-Example screenshot doesn't build

I've try to launch the screenshot-tests-for-android example using ./gradlew screenshotTests --info and the gradle build fails with the following info trace.

:compileDebugAndroidTestNdk (Thread[main,5,main]) started.
:compileDebugAndroidTestNdk
Skipping task ':compileDebugAndroidTestNdk' as it has no source files.
:compileDebugAndroidTestNdk UP-TO-DATE
:compileDebugAndroidTestNdk (Thread[main,5,main]) completed. Took 0.007 secs.
:compileDebugAndroidTestSources (Thread[main,5,main]) started.
:compileDebugAndroidTestSources
Skipping task ':compileDebugAndroidTestSources' as it has no actions.
:compileDebugAndroidTestSources UP-TO-DATE
:compileDebugAndroidTestSources (Thread[main,5,main]) completed. Took 0.002 secs.
:preDexDebugAndroidTest (Thread[main,5,main]) started.
:preDexDebugAndroidTest
Skipping task ':preDexDebugAndroidTest' as it is up-to-date (took 0.01 secs).
:preDexDebugAndroidTest UP-TO-DATE
:preDexDebugAndroidTest (Thread[main,5,main]) completed. Took 0.012 secs.
:dexDebugAndroidTest (Thread[main,5,main]) started.
:dexDebugAndroidTest
Skipping task ':dexDebugAndroidTest' as it is up-to-date (took 0.011 secs).
:dexDebugAndroidTest UP-TO-DATE
:dexDebugAndroidTest (Thread[main,5,main]) completed. Took 0.015 secs.
:packageDebugAndroidTest (Thread[main,5,main]) started.
:packageDebugAndroidTest
Skipping task ':packageDebugAndroidTest' as it is up-to-date (took 0.012 secs).
:packageDebugAndroidTest UP-TO-DATE
:packageDebugAndroidTest (Thread[main,5,main]) completed. Took 0.015 secs.
:assembleDebugAndroidTest (Thread[main,5,main]) started.
:assembleDebugAndroidTest
Skipping task ':assembleDebugAndroidTest' as it has no actions.
:assembleDebugAndroidTest UP-TO-DATE
:assembleDebugAndroidTest (Thread[main,5,main]) completed. Took 0.001 secs.
:connectedDebugAndroidTest (Thread[main,5,main]) started.
:connectedDebugAndroidTest
Executing task ':connectedDebugAndroidTest' (up-to-date check took 0.0 secs) due to:
Task has not declared any outputs.
deleteDir(/Users/Victor/Proyects/git/screenshot-tests-for-android/examples/app-example/build/outputs/androidTest-results/connected) returned: true
deleteDir(/Users/Victor/Proyects/git/screenshot-tests-for-android/examples/app-example/build/outputs/code-coverage/connected) returned: true
Starting 3 tests on Nexus 4 - 4.4.2

com.facebook.testing.screenshot.SearchBarTest > testChinese[Nexus 4 - 4.4.2] SUCCESS

com.facebook.testing.screenshot.SearchBarTest > testLongText[Nexus 4 - 4.4.2] SUCCESS

com.facebook.testing.screenshot.SearchBarTest > testRendering[Nexus 4 - 4.4.2] SUCCESS
deleteDir(/Users/Victor/Proyects/git/screenshot-tests-for-android/examples/app-example/build/reports/androidTests/connected) returned: true
:connectedDebugAndroidTest (Thread[main,5,main]) completed. Took 17.516 secs.
:connectedAndroidTest (Thread[main,5,main]) started.
:connectedAndroidTest
Skipping task ':connectedAndroidTest' as it has no actions.
:connectedAndroidTest (Thread[main,5,main]) completed. Took 0.001 secs.
:pullScreenshots (Thread[main,5,main]) started.
:pullScreenshots
Executing task ':pullScreenshots' (up-to-date check took 0.0 secs) due to:
Task has not declared any outputs.
:pullScreenshots FAILED
:pullScreenshots (Thread[main,5,main]) completed. Took 0.034 secs.

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':pullScreenshots'.

    java.lang.NullPointerException (no error message)

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output.

BUILD FAILED

Total time: 28.71 secs
Stopped 0 compiler daemon(s).

Error inflating class

Some custom views throws android.view.InflateException
For example

    @Test
    public void testDoScreenshot() throws Exception {
        Context appContext = InstrumentationRegistry.getTargetContext();
        LayoutInflater inflater = LayoutInflater.from(appContext);

        View view = inflater.inflate(R.layout.activity_main, null, false);

        SwipeLayout swipeLayout  = (SwipeLayout) view.findViewById(R.id.swipeLayout);

        ViewHelpers.setupView(swipeLayout)
                .setExactWidthDp(300)
                .layout();

        Screenshot.snap(swipeLayout)
                .record();
    }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.daimajia.swipe.SwipeLayout
        android:id="@+id/swipeLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="Hello World"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </com.daimajia.swipe.SwipeLayout>

</LinearLayout>
android.view.InflateException: Binary XML file line #6: Error inflating class com.daimajia.swipe.SwipeLayout
at android.view.LayoutInflater.createView(LayoutInflater.java:640)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
at recyclerview.research.funbox.io.ScreenTest.testDoScreenshot(ScreenTest.java:53)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1873)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
at android.view.LayoutInflater.createView(LayoutInflater.java:614)
... 35 more
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.view.GestureDetector$GestureHandler.<init>(GestureDetector.java:258)
at android.view.GestureDetector.<init>(GestureDetector.java:363)
at android.view.GestureDetector.<init>(GestureDetector.java:344)
at com.daimajia.swipe.SwipeLayout.<init>(SwipeLayout.java:1073)
at com.daimajia.swipe.SwipeLayout.<init>(SwipeLayout.java:79)
... 38 more

recordMode not saving files locally?

Hi,

As I understand it, running

./gradlew recordMode screenshotTests

should save generated pngs to a local screenshot directory. Is the intention here that this will be a directory under the project root named screenshots or the tmp directory that gets generated?

I'm seeing files in the temp directory, but nothing makes it to my screenshots directory.

BUCK support

Hey, do you have any plan to support BUCK? If so, what's the timeline?
We're using BUCK instead of gradle at work, we're looking for some command line (e.g. 'adb shell instrument') to run screenshot-tests-for-android, so it would great if you can provide any pointer to the gradle task implementation or how we should do if we need to get BUCK support by ourselves. Appreciate your help!

How to save screenshots on PC disk, instead of phone storage?

When I run

gradlew recordMode screenshotTest

all screenshots by deafult stores in phone storage in screenshot/ folder

And my question is : how I can setup path to saving screenshots.
We want to use the next scenario :

  1. Execute gradlew recordMode screenshotTest
  2. All recorded screenshots should save into app/screenshots folder on PC.
  3. Run gradlew clean build in pair with verifyMode screenshotTest
  4. If all is ok commit and push into CI
  5. If not - fix problems and make step 4;

But. We are developers and we all know about human factor. Sometimes developers could forget to execute verifyMode and push changes without checking.

We have a CI. And I saw that this library works with CI, but saving in PC storage will be very helpfull from automated point of view. Thanks!

Fix error messages when used with flavors

In trying to run gradle screenshotTests I encountered the following issue:

Expected task ':your-app:connectedFlavor1Flavor2DebugAndroidTest' output files to contain exactly one file, however, it contains no files.

I did the screenshots testApkTarget setup; not sure if I'm pointing it at the wrong thing, or if there's something else I'm doing wrong.

Verification process does not account for missing screenshot

When attempting a verification of screenshots, there seems to be a missing case: a missing screenshot in the run when compared to reference set

Below is the verification code in the python module. It iterates over the screenshots in the metadata.xml file and verifies against a "master" copy. However, if the metadata doesn't contain a reference to the master file, then no error will be raised.

I can see the rationale for this method if you've only run a sub-set of your tests and simply want to ensure that set is right. But what if you want to run them all (such as running a nightly build or gated checkin).

It seem that the opposite should used; reference should be the iterative case, not generated.

`def verify(self):
self._output = tempfile.mkdtemp()
self._record()

    root = self._get_metadata_root()
    for screenshot in root.iter("screenshot"):
        name = screenshot.find('name').text + ".png"
        actual = join(self._output, name)
        expected = join(self._realoutput, name)
        if not self._is_image_same(expected,
                                   actual):
            raise VerifyError("Image %s is not same as %s" % (actual, expected))

    shutil.rmtree(self._output)`

Add TextureView/SurfaceView support

We are working on adding screenshot testing to the Mapbox SDK Test App.
In order to try screenshot-tests-for-android I added a test (which takes a screenshot after a simple map gets loaded) in app-example-androidjunitrunner.

The problem is that I'm getting a screenshot with the part of the map transparent.
Screenshot:

com example screenshots mapboxsimplemapactivitytest_checksmapboxsimplemapwithclipped

Examining the code I found you're not taking into account views like TextureView or SurfaceView (we use them to paint maps).

Trying to add this enhancement (firstly with TextureView) I added some changes and got same screenshot 😕

com example screenshots mapboxsimplemapactivitytest_checksmapboxsimplemapwithclipped

Funny thing is if I remove the drawClippedView() call, I get the screenshot with map properly painted but (obviously) the rest of the views not (e.g. Mapbox logo). Even clearer checking another screenshot generated from other test (whole screenshot is transparent).
Screenshot:

com example screenshots mapboxsimplemapactivitytest_checksmapboxsimplemapwithoutclipped

Any thoughts on how to fix this?
Any info would help us adding this feature to the framework.

Run screenshot tests without other instrumentation tests

Is there a way to run the screenshot tests without also running all other instrumentation tests (like espresso)? This adds a significant amount of time to the screenshot testing task and it seems like it should be able to be run independently.

Malformed metadata.xml file when running under firebase test lab with many tests

I get a malformed metadata.xml file when I run the screenshot tests under firebase test lab.

RuntimeError: Unable to parse metadata file, this commonly happens if you did not call ScreenshotRunner.onDestroy() from your instrumentation

I'm very sure that we're calling ScreenshotRunner.onDestroy(), and have confirmed this by logging.

The metadata.xml file end like:

...</relative_file_name></screenshot>

All data up to is well formed. However not all the test names are included.

This does not happen when running locally, or when the # of test cases are small. (around 15~20)

Enable testing on multiple devices

First of all, this library is amazing. I've been playing around with it at Airbnb and I think it could be of huge value to us.

However, I think it would be n times more useful if we could have all of the screenshot tests run on multiple versions of Android as well as with multiple device configurations.

Setting the width to tablet width doesn't help because it doesn't use the tablet resource qualifiers when inflating views and getting other resources.

Could not determine the dependencies of task ':MainModule:pullScreenshots'

I have two modules with UI layouts that I want to test. When I trying to launch my tests I got exception :

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':presentation:pullScreenshots'
.
> Task with path 'packageDebugAndroidTest' not found in project ':presentation'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.

BUILD FAILED

Total time: 2.653 secs

I applied plugin

apply plugin: 'com.facebook.testing.screenshot'

and set custom runner

testInstrumentationRunner "com.presentation.FacebookScreenshotRunner"

Also I added classpath to root build.gradle inside dependencies block

    // Facebook library for testing views with screenshots
    classpath 'com.facebook.testing.screenshot:plugin:0.4.2'

What I'm doing wrong?

Execution failed for task ':pullScreenshots'.

Hi,

when i try to "gradlew pullScreenshots" i get the following error:

  • What went wrong:
    Execution failed for task ':pullScreenshots'.

    A problem occurred starting process 'command 'python''

My python-version is 3.4.1 on a windows machine.

The newest SDK is installed, the version of the library is 0.2.3.

Here is the "Stacktrace" of gradlew pullScreeshots:

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':pullScreenshots'.

    A problem occurred starting process 'command 'python''

  • Try:
    Run with --info or --debug option to get more log output.

  • Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':pullScr
    eenshots'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.ex
    ecuteActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.ex
    ecute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExec
    uter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.exec
    ute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execut
    e(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecu
    ter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter
    .execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execut
    e(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter
    .execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTa
    skWorker.execute(DefaultTaskGraphExecuter.java:208)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTa
    skWorker.execute(DefaultTaskGraphExecuter.java:186)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorW
    orker.processTask(AbstractTaskPlanExecutor.java:62)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorW
    orker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(Defaul
    tTaskPlanExecutor.java:25)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(Defau
    ltTaskGraphExecuter.java:111)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTask
    ExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecute
    r.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExec
    uter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecu
    ter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildEx
    ecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecute
    r.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecute
    r.java:55)
    at org.gradle.initialization.DefaultGradleLauncher$6.run(DefaultGradleLa
    uncher.java:174)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(Defaul
    tBuildOperationExecutor.java:62)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(Defaul
    tBuildOperationExecutor.java:47)
    at org.gradle.initialization.DefaultGradleLauncher.runBuildOperation(Def
    aultGradleLauncher.java:189)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(Default
    GradleLauncher.java:171)
    at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGra
    dleLauncher.java:35)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradl
    eLauncher.java:104)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradl
    eLauncher.java:97)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(Defaul
    tBuildOperationExecutor.java:62)
    at org.gradle.initialization.DefaultGradleLauncher.runRootBuildOperation
    (DefaultGradleLauncher.java:184)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradle
    Launcher.java:97)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLaun
    cher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildCon
    troller.run(InProcessBuildActionExecuter.java:93)
    at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(Exe
    cuteBuildActionRunner.java:28)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildA
    ctionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProce
    ssBuildActionExecuter.java:43)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProce
    ssBuildActionExecuter.java:27)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(Contin
    uousBuildActionExecuter.java:72)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(Contin
    uousBuildActionExecuter.java:44)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBu
    ild.java:49)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(Build
    CommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(
    WatchForDisconnection.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute
    (ResetDeprecationLogger.java:26)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.
    execute(RequestStopIfSingleUsedDaemon.java:34)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(Forw
    ardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(Forw
    ardClientInput.java:72)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(For
    wardClientInput.java:72)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(
    DaemonHealthTracker.java:47)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClien
    t.java:66)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(Build
    CommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBu
    ild(EstablishBuildEnvironment.java:71)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(Build
    CommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(Hin
    tGCAfterBuild.java:41)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(
    DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.
    run(StartBuildOrRespondWithBusy.java:50)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(Daemon
    StateCoordinator.java:246)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.
    onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableE
    xecutorImpl.java:40)
    Caused by: org.gradle.process.internal.ExecException: A problem occurred startin
    g process 'command 'python''
    at org.gradle.process.internal.DefaultExecHandle.setEndStateInfo(Default
    ExecHandle.java:197)
    at org.gradle.process.internal.DefaultExecHandle.failed(DefaultExecHandl
    e.java:326)
    at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.jav
    a:86)
    ... 2 more
    Caused by: net.rubygrapefruit.platform.NativeException: Could not start 'python'

    at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(Def
    

    aultProcessLauncher.java:27)
    at net.rubygrapefruit.platform.internal.WindowsProcessLauncher.start(Win
    dowsProcessLauncher.java:22)
    at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(Wra
    pperProcessLauncher.java:36)
    at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.jav
    a:68)
    ... 2 more
    Caused by: java.io.IOException: Cannot run program "python" (in directory "C:\so
    urces\AS24-Android-App-V3"): CreateProcess error=2, Das System kann die angegebe
    ne Datei nicht finden
    at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(Def
    aultProcessLauncher.java:25)
    ... 5 more
    Caused by: java.io.IOException: CreateProcess error=2, Das System kann die angeg
    ebene Datei nicht finden
    ... 6 more

BUILD FAILED

Total time: 51.062 secs

NullPointer on make screenshot if use anotation tests

I have

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.app.Instrumentation.getContext()' on a null object reference
at com.facebook.testing.screenshot.internal.ScreenshotImpl.getInstance(ScreenshotImpl.java:338)
at com.facebook.testing.screenshot.Screenshot.snapActivity(Screenshot.java:45)
at com.mobium.reference.activity.Util.takeScreenshot(Util.java:32)
at com.mobium.reference.activity.SimpleActicityTest.lambda$testLeftMenuTest$1(SimpleActicityTest.java:52)
at com.mobium.reference.activity.SimpleActicityTest.access$lambda$0(SimpleActicityTest.java)
at com.mobium.reference.activity.SimpleActicityTest$$Lambda$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5549)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)

when I run test:

@LargeTest
@RunWith(AndroidJUnit4.class)
public class SimpleActicityTest {


@Rule
public ActivityTestRule<MainActivity> activityActivityTestRule =
        new ActivityTestRule<>(MainActivity.class);

@Test
public void testActivity() throws Exception {
    Activity a = activityActivityTestRule.getActivity();
    Screenshot.snapActivity(activity).setName("s1").record();
}
}

`ScreenshotImpl getInstance() creates Registry and take public field instrumentation, but there are not instrumentation initializations in Registry constructor.

Animation timing issues when using TextInputLayout

I have a TextInputLayout containing an AppCompatAutoCompleteTextView in one of the views I'm testing:

...
<android.support.design.widget.TextInputLayout
            android:id="@+id/text_input_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.AppCompatAutoCompleteTextView
                android:id="@+id/edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:saveEnabled="false"/>
</android.support.design.widget.TextInputLayout>
...

I'm noticing some timing issues in the screenshots that are being generated. If I call setText() as is, I get this in the screenshot (notice the hint-text overlap):

screen shot 2017-03-25 at 6 50 04 pm

However, this doesn't happen if I call Thread.sleep(100) after calling setText() but before ViewHelpers.setupView().layout() and Screenshot.snap(view).record(). This also doesn't happen if I have other rendering steps following the setText() call in some other views that reuse the above XML. Am I missing something?

Chat panel

There is a bug in facebook in chat, there is a chat panel in right side of facebook page, when there are lots of people are online and that time, if we scroll the scroll bar, then last user are not showing properly.

see the attachment..
screenshot 100
screenshot 100 _3

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.