Эх сурвалжийг харах

Merge pull request #1619 from nextcloud/feature/1547/setup-test-automation-on-ci

Feature/1547/setup test automation on ci
Tim Krueger 3 жил өмнө
parent
commit
56465e314c

+ 98 - 50
.drone.yml

@@ -1,11 +1,12 @@
 kind: pipeline
+type: docker
 name: generic
 
 steps:
-- name: generic
-  image: nextcloudci/android:android-44
-  commands:
-    - ./gradlew --console=plain assembleGeneric
+  - name: generic
+    image: nextcloudci/android:android-44
+    commands:
+      - ./gradlew --console=plain assembleGeneric
 
 trigger:
   branch:
@@ -16,66 +17,113 @@ trigger:
 
 ---
 kind: pipeline
+type: docker
 name: gplay
 
 steps:
-- name: gplay
-  image: nextcloudci/android:android-44
-  commands:
-    - ./gradlew --console=plain assembleGplay
+  - name: gplay
+    image: nextcloudci/android:android-44
+    commands:
+      - ./gradlew --console=plain assembleGplay
 
 trigger:
   branch:
     - master
   event:
-   - push
-   - pull_request
+    - push
+    - pull_request
+
+---
+kind: pipeline
+type: docker
+name: tests
+
+steps:
+  - name: all
+    image: nextcloudci/android:android-49
+    privileged: true
+    commands:
+      - emulator-headless -avd android-27 -no-snapshot -gpu swiftshader_indirect -no-window -no-audio -skin 500x833 &
+      - scripts/wait_for_emulator.sh
+      - ./gradlew --console=plain testGplayDebugUnitTest connectedGplayDebugAndroidTest
+
+#services:
+#  - name: server
+#    image: nextcloudci/server:server-17 # also change in updateScreenshots.sh
+#    environment:
+#      EVAL: true
+#    commands:
+#      - BRANCH='stable22' /usr/local/bin/initnc.sh
+#      - echo 127.0.0.1 server >> /etc/hosts
+#      - su www-data -c "OC_PASS=user1 php /var/www/html/occ user:add --password-from-env --display-name='User One' user1"
+#      - su www-data -c "OC_PASS=user2 php /var/www/html/occ user:add --password-from-env --display-name='User Two' user2"
+#      - su www-data -c "OC_PASS=user3 php /var/www/html/occ user:add --password-from-env --display-name='User Three' user3"
+#      - su www-data -c "php /var/www/html/occ user:setting user2 files quota 1G"
+#      - su www-data -c "php /var/www/html/occ group:add users"
+#      - su www-data -c "php /var/www/html/occ group:adduser users user1"
+#      - su www-data -c "php /var/www/html/occ group:adduser users user2"
+#      - su www-data -c "git clone -b stable22 https://github.com/nextcloud/activity.git /var/www/html/apps/activity/"
+#      - su www-data -c "php /var/www/html/occ app:enable activity"
+#      - su www-data -c "git clone -b stable22 https://github.com/nextcloud/text.git /var/www/html/apps/text/"
+#      - su www-data -c "php /var/www/html/occ app:enable text"
+#      - su www-data -c "git clone -b stable22 https://github.com/nextcloud/end_to_end_encryption.git /var/www/html/apps/end_to_end_encryption/"
+#      - su www-data -c "php /var/www/html/occ app:enable end_to_end_encryption"
+#      - /usr/local/bin/run.sh
+
+trigger:
+  branch:
+    - master
+  event:
+    - push
+    - pull_request
+
 ---
 kind: pipeline
+type: docker
 name: analysis
 
 steps:
-- name: analysis
-  image: nextcloudci/android:android-44
-  environment:
-    GIT_USERNAME:
-      from_secret: GIT_USERNAME
-    GIT_TOKEN:
-      from_secret: GIT_TOKEN
-    LOG_USERNAME:
-      from_secret: LOG_USERNAME
-    LOG_PASSWORD:
-      from_secret: LOG_PASSWORD
-  commands:
-    - export BRANCH=$(scripts/analysis/getBranchName.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST)
-    - scripts/analysis/analysis-wrapper.sh $GIT_USERNAME $GIT_TOKEN $BRANCH $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER $DRONE_PULL_REQUEST
+  - name: analysis
+    image: nextcloudci/android:android-44
+    environment:
+      GIT_USERNAME:
+        from_secret: GIT_USERNAME
+      GIT_TOKEN:
+        from_secret: GIT_TOKEN
+      LOG_USERNAME:
+        from_secret: LOG_USERNAME
+      LOG_PASSWORD:
+        from_secret: LOG_PASSWORD
+    commands:
+      - export BRANCH=$(scripts/analysis/getBranchName.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST)
+      - scripts/analysis/analysis-wrapper.sh $GIT_USERNAME $GIT_TOKEN $BRANCH $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER $DRONE_PULL_REQUEST
 
-- name: notify
-  image: drillster/drone-email
-  host: $EMAIL_HOST
-  port: 587
-  username: $EMAIL_USERNAME
-  password: $EMAIL_PASSWORD
-  from: nextcloud-drone@kaminsky.me
-  skip_verify: true
-  recipients_only: true
-  recipients: [ $EMAIL_RECIPIENTS ]
-  environment:
-    EMAIL_USERNAME:
-      from_secret: EMAIL_USERNAME
-    EMAIL_PASSWORD:
-      from_secret: EMAIL_PASSWORD
-    EMAIL_RECIPIENTS:
-      from_secret: EMAIL_RECIPIENTS
-    EMAIL_HOST:
-      from_secret: EMAIL_HOST
-  when:
-    event:
-      - push
-    status:
-      - failure
-    branch:
-      - master
+  - name: notify
+    image: drillster/drone-email
+    host: $EMAIL_HOST
+    port: 587
+    username: $EMAIL_USERNAME
+    password: $EMAIL_PASSWORD
+    from: nextcloud-drone@kaminsky.me
+    skip_verify: true
+    recipients_only: true
+    recipients: [ $EMAIL_RECIPIENTS ]
+    environment:
+      EMAIL_USERNAME:
+        from_secret: EMAIL_USERNAME
+      EMAIL_PASSWORD:
+        from_secret: EMAIL_PASSWORD
+      EMAIL_RECIPIENTS:
+        from_secret: EMAIL_RECIPIENTS
+      EMAIL_HOST:
+        from_secret: EMAIL_HOST
+    when:
+      event:
+        - push
+      status:
+        - failure
+      branch:
+        - master
 
 trigger:
   branch:

+ 9 - 1
app/build.gradle

@@ -159,6 +159,7 @@ ext {
     retrofit2Version = "2.9.0"
     workVersion = "2.6.0"
     markwonVersion =  "4.6.2"
+    espressoVersion = "3.4.0"
 }
 
 configurations.all {
@@ -291,11 +292,18 @@ dependencies {
     implementation 'androidx.core:core-ktx:1.6.0'
 
     testImplementation 'junit:junit:4.13.2'
-    testImplementation 'org.mockito:mockito-core:4.0.0'
+    testImplementation 'org.mockito:mockito-core:3.12.4'
     testImplementation "org.powermock:powermock-core:${powermockVersion}"
     testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
     testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
 
+    // Espresso core
+    androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
+    androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
+    androidTestImplementation "androidx.test.espresso:espresso-web:$espressoVersion"
+    androidTestImplementation "androidx.test.espresso:espresso-accessibility:$espressoVersion"
+    androidTestImplementation('com.android.support.test.espresso:espresso-intents:3.0.2')
+
     androidTestImplementation ('androidx.test.espresso:espresso-core:3.4.0', {
         exclude group: 'com.android.support', module: 'support-annotations'
     })

+ 4 - 2
app/src/androidTest/java/com/nextcloud/talk/ExampleInstrumentedTest.java

@@ -28,7 +28,8 @@ import org.junit.runner.RunWith;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Instrumented test, which will execute on an Android device.
@@ -42,6 +43,7 @@ public class ExampleInstrumentedTest {
         // Context of the app under test.
         Context appContext = InstrumentationRegistry.getTargetContext();
 
-        assertEquals("com.nextcloud.talk", appContext.getPackageName());
+        assertNotNull(appContext.getPackageName());
+        assertTrue("The package name must start with 'com.nextcloud.talk2'", appContext.getPackageName().startsWith("com.nextcloud.talk2"));
     }
 }

+ 59 - 0
app/src/androidTest/java/com/nextcloud/talk/activities/MainActivityTest.kt

@@ -0,0 +1,59 @@
+package com.nextcloud.talk.activities
+
+import android.util.Log
+import androidx.test.espresso.intent.rule.IntentsTestRule
+import com.nextcloud.talk.models.database.UserEntity
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import junit.framework.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+
+class MainActivityTest {
+    @get:Rule
+    val activityRule: IntentsTestRule<MainActivity> = IntentsTestRule(
+        MainActivity::class.java,
+        true,
+        false
+    )
+
+    @Test
+    fun login() {
+        val sut = activityRule.launchActivity(null)
+        sut.userUtils.createOrUpdateUser(
+            "test",
+            "test",
+            "http://10.0.2.2/nc",
+            "test",
+            null,
+            true,
+            "test",
+            null,
+            null,
+            null,
+            null
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .subscribe(
+                { userEntity: UserEntity? -> Log.i("test", "stored: " + userEntity.toString()) },
+                { throwable: Throwable? -> Log.e("test", "throwable") },
+                { Log.d("test", "complete") }
+            )
+
+        try {
+            Thread.sleep(2000)
+        } catch (e: InterruptedException) {
+            e.printStackTrace()
+        }
+
+        sut.runOnUiThread { sut.resetConversationsList() }
+
+        assertTrue(sut.userUtils.getIfUserWithUsernameAndServer("test", "http://10.0.2.2/nc"))
+
+        try {
+        } catch (e: InterruptedException) {
+            e.printStackTrace()
+        }
+    }
+}

+ 2 - 0
app/src/androidTest/java/com/nextcloud/talk/utils/ShareUtilsIT.kt

@@ -3,10 +3,12 @@ package com.nextcloud.talk.utils
 import at.bitfire.dav4jvm.HttpUtils
 import org.apache.commons.lang3.time.DateUtils
 import org.junit.Assert.assertEquals
+import org.junit.Ignore
 import org.junit.Test
 import java.util.Date
 import java.util.Locale
 
+@Ignore("Test fails on CI server. See issue https://github.com/nextcloud/talk-android/issues/1737")
 class ShareUtilsIT {
     @Test
     fun date() {

+ 2 - 2
app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java

@@ -268,7 +268,7 @@ public class UserUtils {
         }
 
         return dataStore.upsert(user)
-                .toObservable()
-                .subscribeOn(Schedulers.io());
+            .toObservable()
+            .subscribeOn(Schedulers.io());
     }
 }

+ 6 - 3
app/src/test/java/com/nextcloud/talk/utils/DoNotDisturbUtilsTest.java

@@ -36,6 +36,7 @@ import org.mockito.MockitoAnnotations;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -66,9 +67,11 @@ public class DoNotDisturbUtilsTest {
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mockStatic(NextcloudTalkApplication.class);
-        PowerMockito.when(NextcloudTalkApplication.getSharedApplication()).thenReturn(application);
+        MockitoAnnotations.openMocks(this);
+        mockStatic(NextcloudTalkApplication.Companion.class);
+        NextcloudTalkApplication.Companion companionMock = PowerMockito.mock(NextcloudTalkApplication.Companion.class);
+        Whitebox.setInternalState(NextcloudTalkApplication.class,"Companion",companionMock);
+        PowerMockito.when(NextcloudTalkApplication.Companion.getSharedApplication()).thenReturn(application);
         when(application.getApplicationContext()).thenReturn(context);
         when(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager);
         when(context.getSystemService(Context.AUDIO_SERVICE)).thenReturn(audioManager);

+ 4 - 2
app/src/test/java/com/nextcloud/talk/utils/ShareUtilsTest.kt

@@ -27,9 +27,10 @@ import com.nextcloud.talk.R
 import com.nextcloud.talk.models.database.UserEntity
 import com.nextcloud.talk.models.json.conversations.Conversation
 import com.nextcloud.talk.utils.database.user.UserUtils
-import junit.framework.Assert.assertEquals
 import org.junit.Assert
+import org.junit.Assert.assertEquals
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers
@@ -43,6 +44,7 @@ import java.text.ParseException
 
 @RunWith(PowerMockRunner::class)
 @PrepareForTest(TextUtils::class)
+@Ignore("Test fails on CI server. See issue https://github.com/nextcloud/talk-android/issues/1737")
 class ShareUtilsTest {
     @Mock
     private val context: Context? = null
@@ -63,7 +65,7 @@ class ShareUtilsTest {
 
     @Before
     fun setUp() {
-        MockitoAnnotations.initMocks(this)
+        MockitoAnnotations.openMocks(this)
         PowerMockito.mockStatic(TextUtils::class.java)
         Mockito.`when`(userUtils!!.currentUser).thenReturn(userEntity)
         Mockito.`when`(userEntity!!.baseUrl).thenReturn(baseUrl)

+ 24 - 0
scripts/wait_for_emulator.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Originally written by Ralf Kistner <ralf@embarkmobile.com>, but placed in the public domain
+
+bootanim=""
+failcounter=0
+checkcounter=0
+
+until [[ "$bootanim" =~ "stopped" ]]; do
+   bootanim=`adb -e shell getprop init.svc.bootanim 2>&1`
+   echo "($checkcounter) $bootanim"
+   if [[ "$bootanim" =~ "not found" || "$bootanim" =~ "error" ]]; then
+      let "failcounter += 1"
+      if [[ $failcounter -gt 3 ]]; then
+        echo "Failed to start emulator"
+        exit 1
+      fi
+   fi
+   let "checkcounter += 1"
+   sleep 20
+done
+echo "($checkcounter) Done"
+adb -e shell input keyevent 82
+echo "($checkcounter) Unlocked emulator screen"