diff --git a/build.gradle b/build.gradle index 78d9e221..c8e3fee6 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.4.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' } diff --git a/cameraview/build.gradle b/cameraview/build.gradle index 1dd5f690..7e806451 100644 --- a/cameraview/build.gradle +++ b/cameraview/build.gradle @@ -12,7 +12,6 @@ def travis = System.getenv("TRAVIS") android { compileSdkVersion rootProject.ext.compileSdkVersion - // buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { minSdkVersion rootProject.ext.minSdkVersion @@ -189,7 +188,7 @@ task mergedCoverageReport(type: JacocoReport) { // Merge unit tests and android tests data executionData = fileTree(dir: "$buildDir", includes: [ "jacoco/testDebugUnitTest.exec", // Unit tests - "outputs/code-coverage/connected/*coverage.ec" // Android tests + "outputs/code_coverage/debugAndroidTest/connected/*coverage.ec" // Android tests ]) // Sources @@ -217,10 +216,14 @@ task mergedCoverageReport(type: JacocoReport) { '**/*Module_*Factory.class', ] if (travis) { - // Since this is not testable on the emulator... - classFilter.add('com/otaliastudios/cameraview/engine/CameraEngine.*') - classFilter.add('com/otaliastudios/cameraview/engine/Camera1Engine.*') - classFilter.add('com/otaliastudios/cameraview/engine/Camera2Engine.*') + // All these classes are tested by the integration tests that we are not able to + // run on the travis emulator. + classFilter.add('**/com/otaliastudios/cameraview/engine/CameraEngine**.*') + classFilter.add('**/com/otaliastudios/cameraview/engine/Camera1Engine**.*') + classFilter.add('**/com/otaliastudios/cameraview/engine/Camera2Engine**.*') + classFilter.add('**/com/otaliastudios/cameraview/picture/**.*') + classFilter.add('**/com/otaliastudios/cameraview/video/**.*') + classFilter.add('**/com/otaliastudios/cameraview/video/encoding/**.*') } classDirectories = fileTree(dir: classDir, excludes: classFilter); diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/DoNotRunOnTravis.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/DoNotRunOnTravis.java index 03860330..388b4728 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/DoNotRunOnTravis.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/DoNotRunOnTravis.java @@ -1,5 +1,17 @@ package com.otaliastudios.cameraview; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Thanks to a testInstrumentationRunnerArgument in our build file, we will not + * execute these tests on Travis CI. + * The {@link RetentionPolicy#RUNTIME} is needed! + * + * https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner + * + */ +@Retention(RetentionPolicy.RUNTIME) public @interface DoNotRunOnTravis { String because() default ""; } diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegration2Test.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegration2Test.java index 54cf6014..32ff78a7 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegration2Test.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegration2Test.java @@ -4,6 +4,7 @@ import com.otaliastudios.cameraview.DoNotRunOnTravis; import com.otaliastudios.cameraview.controls.Engine; import org.junit.Ignore; +import org.junit.Test; import org.junit.runner.RunWith; import androidx.annotation.NonNull; diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java index d4faa385..bc3f39e9 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java @@ -8,10 +8,12 @@ import android.os.Build; import android.util.Log; import com.otaliastudios.cameraview.BaseTest; +import com.otaliastudios.cameraview.CameraException; import com.otaliastudios.cameraview.CameraListener; import com.otaliastudios.cameraview.CameraOptions; import com.otaliastudios.cameraview.CameraUtils; import com.otaliastudios.cameraview.CameraView; +import com.otaliastudios.cameraview.DoNotRunOnTravis; import com.otaliastudios.cameraview.PictureResult; import com.otaliastudios.cameraview.TestActivity; import com.otaliastudios.cameraview.VideoResult; @@ -41,6 +43,7 @@ import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; import java.io.File; import java.util.concurrent.CountDownLatch; @@ -51,14 +54,16 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; - public abstract class CameraIntegrationTest extends BaseTest { + private final static long DELAY = 9000; + @Rule public ActivityTestRule rule = new ActivityTestRule<>(TestActivity.class); @@ -119,7 +124,7 @@ public abstract class CameraIntegrationTest extends BaseTest { } private void waitForUiException() throws Throwable { - Throwable throwable = uiExceptionOp.await(5000); + Throwable throwable = uiExceptionOp.await(DELAY); if (throwable != null) { throw throwable; } @@ -129,7 +134,7 @@ public abstract class CameraIntegrationTest extends BaseTest { camera.open(); final Op open = new Op<>(true); doEndTask(open, 0).when(listener).onCameraOpened(any(CameraOptions.class)); - CameraOptions result = open.await(4000); + CameraOptions result = open.await(DELAY); if (expectSuccess) { assertNotNull("Can open", result); // Extra wait for the bind state. @@ -144,7 +149,7 @@ public abstract class CameraIntegrationTest extends BaseTest { camera.close(); final Op close = new Op<>(true); doEndTask(close, true).when(listener).onCameraClosed(); - Boolean result = close.await(4000); + Boolean result = close.await(DELAY); if (expectSuccess) { assertNotNull("Can close", result); } else { @@ -155,9 +160,16 @@ public abstract class CameraIntegrationTest extends BaseTest { private void waitForVideoEnd(boolean expectSuccess) { final Op video = new Op<>(true); doEndTask(video, true).when(listener).onVideoTaken(any(VideoResult.class)); - Boolean result = video.await(12000); + doEndTask(video, false).when(listener).onCameraError(argThat(new ArgumentMatcher() { + @Override + public boolean matches(CameraException argument) { + return argument.getReason() == CameraException.REASON_VIDEO_FAILED; + } + })); + Boolean result = video.await(DELAY); if (expectSuccess) { assertNotNull("Should end video", result); + assertTrue("Should end video without errors", result); } else { assertNull("Should not end video", result); } @@ -166,7 +178,13 @@ public abstract class CameraIntegrationTest extends BaseTest { private PictureResult waitForPicture(boolean expectSuccess) { final Op pic = new Op<>(true); doEndTask(pic, 0).when(listener).onPictureTaken(any(PictureResult.class)); - PictureResult result = pic.await(5000); + doEndTask(pic, null).when(listener).onCameraError(argThat(new ArgumentMatcher() { + @Override + public boolean matches(CameraException argument) { + return argument.getReason() == CameraException.REASON_PICTURE_FAILED; + } + })); + PictureResult result = pic.await(DELAY); if (expectSuccess) { assertNotNull("Can take picture", result); } else { @@ -179,7 +197,8 @@ public abstract class CameraIntegrationTest extends BaseTest { controller.mStartVideoOp.listen(); File file = new File(context().getFilesDir(), "video.mp4"); camera.takeVideo(file); - controller.mStartVideoOp.await(1000); + controller.mStartVideoOp.await(DELAY); + // TODO assert! } //region test open/close diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/ScrollGestureLayoutTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/ScrollGestureLayoutTest.java index 57ddbfeb..5d2fe093 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/ScrollGestureLayoutTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/gesture/ScrollGestureLayoutTest.java @@ -65,10 +65,10 @@ public class ScrollGestureLayoutTest extends GestureLayoutTest curr); + assertTrue(newValue >= curr); assertTrue(newValue <= max); } else { - assertTrue(newValue < curr); + assertTrue(newValue <= curr); assertTrue(newValue >= min); } } diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/markers/MarkerLayoutTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/markers/MarkerLayoutTest.java index 03ec7c01..451a2bf9 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/markers/MarkerLayoutTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/markers/MarkerLayoutTest.java @@ -11,6 +11,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.manipulation.Filter; import org.mockito.Mockito; import androidx.test.annotation.UiThreadTest; @@ -40,6 +41,7 @@ public class MarkerLayoutTest extends BaseTest { } @Test + @UiThreadTest public void testOnMarker_callsOnAttach() { markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); Mockito.verify(autoFocusMarker, Mockito.times(1)).onAttach( @@ -48,6 +50,7 @@ public class MarkerLayoutTest extends BaseTest { } @Test + @UiThreadTest public void testOnMarker_addsView() { Assert.assertEquals(markerLayout.getChildCount(), 0); markerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/preview/CameraPreviewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/preview/CameraPreviewTest.java index d99da33d..1ae81559 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/preview/CameraPreviewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/preview/CameraPreviewTest.java @@ -25,6 +25,8 @@ import static org.mockito.Mockito.*; public abstract class CameraPreviewTest extends BaseTest { + private final static long DELAY = 4000; + protected abstract CameraPreview createPreview(Context context, ViewGroup parent, CameraPreview.SurfaceCallback callback); @Rule @@ -74,7 +76,7 @@ public abstract class CameraPreviewTest extends BaseTest { // Wait for surface to be available. protected void ensureAvailable() { - assertNotNull(available.await(2000)); + assertNotNull(available.await(DELAY)); } // Trigger a destroy. @@ -85,7 +87,7 @@ public abstract class CameraPreviewTest extends BaseTest { rule.getActivity().getContentView().removeView(preview.getRootView()); } }); - assertNotNull(destroyed.await(2000)); + assertNotNull(destroyed.await(DELAY)); } @After diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 64dcec45..b5aa2c3d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip