From 477ab1536efb841b27b83f29322687b33674f6bc Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Mon, 4 Sep 2017 17:19:22 +0200 Subject: [PATCH] New tests --- .travis.yml | 4 +- cameraview/build.gradle | 6 +- .../src/androidTest/AndroidManifest.xml | 7 + .../cameraview/CameraViewTest.java | 151 +++++++++++++++++- .../cameraview/MockCameraController.java | 14 +- .../otaliastudios/cameraview/CameraView.java | 4 +- .../cameraview/GestureLayout.java | 5 + 7 files changed, 177 insertions(+), 14 deletions(-) create mode 100644 cameraview/src/androidTest/AndroidManifest.xml diff --git a/.travis.yml b/.travis.yml index 410e1a0f..c7c60469 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,10 +35,10 @@ before_script: - adb shell input keyevent 82 & script: - - ./gradlew clean testDebugUnitTest connectedCheck coverageReport + - ./gradlew clean testDebugUnitTest connectedCheck mergedCoverageReport after_success: - - bash <(curl -s https://codecov.io/bash) + - bash <(curl -s https://codecov.io/bash) -s "*/build/reports/mergedCoverageReport/" cache: directories: diff --git a/cameraview/build.gradle b/cameraview/build.gradle index 7face5d3..3ca64426 100644 --- a/cameraview/build.gradle +++ b/cameraview/build.gradle @@ -171,14 +171,15 @@ artifacts { apply plugin: 'jacoco' +def reportsDirectory = "$buildDir/reports/" jacoco { // Using a different version might get 0 coverage reports. // No time to investigate now. toolVersion = "0.7.6.201602180812" - reportsDir = file("$buildDir/reports/jacoco/merged/") + reportsDir = file(reportsDirectory) } -task coverageReport(type: JacocoReport) { +task mergedCoverageReport(type: JacocoReport) { dependsOn "testDebugUnitTest" dependsOn "connectedCheck" @@ -202,6 +203,7 @@ task coverageReport(type: JacocoReport) { reports.xml.enabled = true reports.html.enabled = true + reports.xml.destination = "$reportsDirectory/mergedCoverageReport/report.xml" } //endregion diff --git a/cameraview/src/androidTest/AndroidManifest.xml b/cameraview/src/androidTest/AndroidManifest.xml new file mode 100644 index 00000000..90600623 --- /dev/null +++ b/cameraview/src/androidTest/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java index 4e8c94d5..98c29927 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java @@ -4,10 +4,12 @@ package com.otaliastudios.cameraview; import android.app.Instrumentation; import android.content.Context; import android.hardware.Camera; +import android.location.Location; import android.os.Looper; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.runner.AndroidJUnit4; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -30,10 +32,15 @@ public class CameraViewTest { private CameraView cameraView; private MockCameraController mockController; private Preview mockPreview; + private boolean hasPermissions; + + private void postOnUiSync(Runnable runnable) { + InstrumentationRegistry.getInstrumentation().runOnMainSync(runnable); + } @Before public void setUp() { - InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { + postOnUiSync(new Runnable() { @Override public void run() { Context context = InstrumentationRegistry.getContext(); @@ -49,6 +56,11 @@ public class CameraViewTest { mockPreview = new MockPreview(context, container); return mockPreview; } + + @Override + protected boolean checkPermissions(SessionType sessionType) { + return hasPermissions; + } }; } }); @@ -59,12 +71,13 @@ public class CameraViewTest { cameraView = null; mockController = null; mockPreview = null; + hasPermissions = false; } //region testDefaults @Test - public void testNotStarted() { + public void testNullBeforeStart() { assertFalse(cameraView.isStarted()); assertNull(cameraView.getCameraOptions()); assertNull(cameraView.getExtraProperties()); @@ -96,6 +109,23 @@ public class CameraViewTest { assertEquals(cameraView.getGestureAction(Gesture.SCROLL_VERTICAL), GestureAction.DEFAULT_SCROLL_VERTICAL); } + @Test + public void testStartWithPermissions() { + hasPermissions = true; + cameraView.start(); + assertTrue(cameraView.isStarted()); + + cameraView.stop(); + assertFalse(cameraView.isStarted()); + } + + @Test + public void testStartWithoutPermissions() { + hasPermissions = false; + cameraView.start(); + assertFalse(cameraView.isStarted()); + } + //endregion //region testGesture @@ -145,6 +175,94 @@ public class CameraViewTest { //endregion + //region testGestureAction + + @Test + public void testGestureAction_capture() { + MotionEvent event = MotionEvent.obtain(0L, 0L, 0, 0f, 0f, 0); + postOnUiSync(new Runnable() { + @Override + public void run() { + cameraView.mTapGestureLayout = new TapGestureLayout(cameraView.getContext()) { + public boolean onTouchEvent(MotionEvent event) { return true; } + + }; + cameraView.mTapGestureLayout.setGestureType(Gesture.TAP); + } + }); + cameraView.mapGesture(Gesture.TAP, GestureAction.CAPTURE); + cameraView.dispatchTouchEvent(event); + assertTrue(mockController.mPictureCaptured); + } + + @Test + public void testGestureAction_focus() { + MotionEvent event = MotionEvent.obtain(0L, 0L, 0, 0f, 0f, 0); + postOnUiSync(new Runnable() { + @Override + public void run() { + cameraView.mTapGestureLayout = new TapGestureLayout(cameraView.getContext()) { + public boolean onTouchEvent(MotionEvent event) { return true; } + }; + cameraView.mTapGestureLayout.setGestureType(Gesture.TAP); + } + }); + mockController.mFocusStarted = false; + cameraView.mapGesture(Gesture.TAP, GestureAction.FOCUS); + cameraView.dispatchTouchEvent(event); + assertTrue(mockController.mFocusStarted); + + // Try with FOCUS_WITH_MARKER + mockController.mFocusStarted = false; + cameraView.mapGesture(Gesture.TAP, GestureAction.FOCUS_WITH_MARKER); + cameraView.dispatchTouchEvent(event); + assertTrue(mockController.mFocusStarted); + } + + @Test + public void testGestureAction_zoom() { + MotionEvent event = MotionEvent.obtain(0L, 0L, 0, 0f, 0f, 0); + postOnUiSync(new Runnable() { + @Override + public void run() { + cameraView.mPinchGestureLayout = new PinchGestureLayout(cameraView.getContext()) { + public boolean onTouchEvent(MotionEvent event) { return true; } + }; + cameraView.mPinchGestureLayout.setGestureType(Gesture.PINCH); + } + }); + mockController.mZoomChanged = false; + cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM); + cameraView.dispatchTouchEvent(event); + assertTrue(mockController.mZoomChanged); + } + + @Test + public void testGestureAction_exposureCorrection() { + // This needs a valid CameraOptions value. + CameraOptions o = mock(CameraOptions.class); + when(o.getExposureCorrectionMinValue()).thenReturn(-10f); + when(o.getExposureCorrectionMaxValue()).thenReturn(10f); + mockController.setMockCameraOptions(o); + + MotionEvent event = MotionEvent.obtain(0L, 0L, 0, 0f, 0f, 0); + postOnUiSync(new Runnable() { + @Override + public void run() { + cameraView.mScrollGestureLayout = new ScrollGestureLayout(cameraView.getContext()) { + public boolean onTouchEvent(MotionEvent event) { return true; } + }; + cameraView.mScrollGestureLayout.setGestureType(Gesture.SCROLL_HORIZONTAL); + } + }); + mockController.mExposureCorrectionChanged = false; + cameraView.mapGesture(Gesture.SCROLL_HORIZONTAL, GestureAction.EXPOSURE_CORRECTION); + cameraView.dispatchTouchEvent(event); + assertTrue(mockController.mExposureCorrectionChanged); + } + + //endregion + //region testMeasure private void mockPreviewSize() { @@ -268,11 +386,34 @@ public class CameraViewTest { //endregion - // TODO: test setLocation + //region testLocation - // TODO: test touch events + @Test + public void testSetLocation() { + cameraView.setLocation(50d, -50d); + assertEquals(50d, mockController.mLocation.getLatitude(), 0); + assertEquals(-50d, mockController.mLocation.getLongitude(), 0); + assertEquals(0, mockController.mLocation.getAltitude(), 0); + assertEquals("Unknown", mockController.mLocation.getProvider()); + assertEquals(System.currentTimeMillis(), mockController.mLocation.getTime(), 1000f); + + Location source = new Location("Provider"); + source.setTime(5000); + source.setLatitude(10d); + source.setLongitude(-10d); + source.setAltitude(50d); + cameraView.setLocation(source); + Location other = mockController.mLocation; + assertEquals(10d, other.getLatitude(), 0d); + assertEquals(-10d, other.getLongitude(), 0d); + assertEquals(50d, other.getAltitude(), 0d); + assertEquals("Provider", other.getProvider()); + assertEquals(5000, other.getTime()); + } + + //endregion - // TODO: test permissions and start() stop() isStarted() + // TODO: test permissions // TODO: test CameraCallbacks diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java index 113bc7ea..ce150fd2 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java @@ -10,6 +10,12 @@ import java.io.File; public class MockCameraController extends CameraController { + Location mLocation; + boolean mPictureCaptured; + boolean mFocusStarted; + boolean mZoomChanged; + boolean mExposureCorrectionChanged; + MockCameraController(CameraView.CameraCallbacks callback, Preview preview) { super(callback, preview); } @@ -24,21 +30,21 @@ public class MockCameraController extends CameraController { @Override void onStart() { - } @Override void onStop() { - } @Override boolean setZoom(float zoom) { + mZoomChanged = true; return true; } @Override boolean setExposureCorrection(float EVvalue) { + mExposureCorrectionChanged = true; return true; } @@ -74,11 +80,12 @@ public class MockCameraController extends CameraController { @Override void setLocation(Location location) { - + mLocation = location; } @Override boolean capturePicture() { + mPictureCaptured = true; return true; } @@ -109,6 +116,7 @@ public class MockCameraController extends CameraController { @Override boolean startAutoFocus(@Nullable Gesture gesture, PointF point) { + mFocusStarted = true; return true; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 83d11199..485f0475 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -498,7 +498,7 @@ public class CameraView extends FrameLayout { * @return true if we can go on, false otherwise. */ @SuppressLint("NewApi") - private boolean checkPermissions(SessionType sessionType) { + protected boolean checkPermissions(SessionType sessionType) { checkPermissionsManifestOrThrow(sessionType); boolean api23 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; int cameraCheck, audioCheck; @@ -531,7 +531,7 @@ public class CameraView extends FrameLayout { /** * If mSessionType == SESSION_TYPE_VIDEO we will ask for RECORD_AUDIO permission. * If the developer did not add this to its manifest, throw and fire warnings. - * (Hoping this is not cought elsewhere... we should test). + * (Hoping this is not caught elsewhere... we should test). */ private void checkPermissionsManifestOrThrow(SessionType sessionType) { if (sessionType == SessionType.VIDEO) { diff --git a/cameraview/src/main/views/com/otaliastudios/cameraview/GestureLayout.java b/cameraview/src/main/views/com/otaliastudios/cameraview/GestureLayout.java index 5553b2da..6f1fcc36 100644 --- a/cameraview/src/main/views/com/otaliastudios/cameraview/GestureLayout.java +++ b/cameraview/src/main/views/com/otaliastudios/cameraview/GestureLayout.java @@ -39,6 +39,11 @@ abstract class GestureLayout extends FrameLayout { return mType; } + // For tests. + void setGestureType(Gesture type) { + mType = type; + } + public final PointF[] getPoints() { return mPoints; }