Explorar el Código

refactoring deps_versions.gradle and build.gradle for feature_auth add espresso
add DI for androidTest, testApplication and my own TestRunner
add UI tests for RegistrationFragment

MrOzOn hace 5 años
padre
commit
2220d4df4a

+ 2 - 1
.gitignore

@@ -83,4 +83,5 @@ lint/generated/
 lint/outputs/
 lint/tmp/
 # lint/reports/
-/.idea/
+/.idea/
+/projectFilesBackup/.idea/workspace.xml

+ 5 - 1
feature_auth/build.gradle

@@ -13,7 +13,7 @@ android {
         versionCode 1
         versionName "1.0"
 
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        testInstrumentationRunner "com.mrozon.feature_auth.MockTestRunner"//"androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"
     }
 
@@ -64,6 +64,10 @@ dependencies {
     testImplementation androidXCoreTest
     //Instrumental Test
     androidTestImplementation junitInstrumental
+    androidTestImplementation androidXRulesTest
+    androidTestImplementation androidXRunnerTest
     androidTestImplementation espressoCore
+    androidTestImplementation androidXFragmentTest
+    kaptAndroidTest daggerCompiler
 
 }

+ 0 - 24
feature_auth/src/androidTest/java/com/mrozon/feature_auth/ExampleInstrumentedTest.kt

@@ -1,24 +0,0 @@
-package com.mrozon.feature_auth
-
-import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.ext.junit.runners.AndroidJUnit4
-
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import org.junit.Assert.*
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-@RunWith(AndroidJUnit4::class)
-class ExampleInstrumentedTest {
-    @Test
-    fun useAppContext() {
-        // Context of the app under test.
-        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
-        assertEquals("com.mrozon.feature_auth.test", appContext.packageName)
-    }
-}

+ 17 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/MockTestRunner.kt

@@ -0,0 +1,17 @@
+package com.mrozon.feature_auth
+
+import android.app.Application
+import android.content.Context
+import androidx.test.runner.AndroidJUnitRunner
+import com.mrozon.feature_auth.presentation.TestApp
+
+class MockTestRunner: AndroidJUnitRunner() {
+
+    override fun newApplication(
+        cl: ClassLoader?,
+        className: String?,
+        context: Context?
+    ): Application {
+        return super.newApplication(cl, TestApp::class.java.name, context)
+    }
+}

+ 23 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/TestApp.kt

@@ -0,0 +1,23 @@
+package com.mrozon.feature_auth.presentation
+
+import android.app.Application
+import com.mrozon.core_api.providers.AppWithFacade
+import com.mrozon.core_api.providers.ProvidersFacade
+import com.mrozon.feature_auth.di.FacadeComponent
+
+class TestApp: Application(), AppWithFacade {
+
+    companion object {
+        private var facadeComponent: FacadeComponent? = null
+    }
+
+    override fun onCreate() {
+        super.onCreate()
+        (getFacade() as FacadeComponent).inject(this)
+    }
+
+    override fun getFacade(): ProvidersFacade {
+        return facadeComponent ?: FacadeComponent.init(this).also { facadeComponent = it }
+    }
+
+}

+ 39 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/di/AppComponent.kt

@@ -0,0 +1,39 @@
+package com.mrozon.feature_auth.di
+
+import android.app.Application
+import android.content.Context
+import com.mrozon.core_api.providers.AppProvider
+import dagger.BindsInstance
+import dagger.Component
+import javax.inject.Singleton
+
+@Singleton
+@Component(
+    modules = []
+)
+interface AppComponent: AppProvider {
+
+    companion object {
+
+        private var appComponent: AppProvider? = null
+
+        fun create(application: Application): AppProvider {
+            return appComponent ?: DaggerAppComponent
+                .builder()
+                .application(application.applicationContext)
+                .build().also {
+                    appComponent = it
+                }
+        }
+    }
+
+    @Component.Builder
+    interface Builder {
+
+        @BindsInstance
+        fun application(context: Context): Builder
+
+        fun build(): AppComponent
+    }
+
+}

+ 30 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/di/FacadeComponent.kt

@@ -0,0 +1,30 @@
+package com.mrozon.feature_auth.di
+
+import android.app.Application
+import com.mrozon.core.CoreProvidersFactory
+import com.mrozon.core_api.db.DatabaseProvider
+import com.mrozon.core_api.network.NetworkProvider
+import com.mrozon.core_api.providers.AppProvider
+import com.mrozon.core_api.providers.ProvidersFacade
+import com.mrozon.core_api.viewmodel.ViewModelsFactoryProvider
+import com.mrozon.feature_auth.presentation.TestApp
+import dagger.Component
+
+@Component(
+    dependencies = [AppProvider::class, DatabaseProvider::class, NetworkProvider::class],
+    modules = [NavigationModule::class]
+)
+interface FacadeComponent : ProvidersFacade {
+
+    companion object {
+
+        fun init(application: Application): FacadeComponent =
+            DaggerFacadeComponent.builder()
+                .appProvider(AppComponent.create(application))
+                .databaseProvider(CoreProvidersFactory.createDatabaseBuilder(AppComponent.create(application)))
+                .networkProvider(CoreProvidersFactory.createNetworkBuilder())
+                .build()
+    }
+
+    fun inject(app: TestApp)
+}

+ 30 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/di/NavigationModule.kt

@@ -0,0 +1,30 @@
+package com.mrozon.feature_auth.di
+
+import com.mrozon.core_api.navigation.*
+import dagger.Binds
+import dagger.Module
+import dagger.Reusable
+
+@Module
+interface NavigationModule {
+
+    @Reusable
+    @Binds
+    fun splashNavigator(navigator: SplashNavigatorImpl): SplashNavigator
+
+    @Reusable
+    @Binds
+    fun loginNavigator(navigator: TestNavigatorImpl): LoginNavigator
+
+    @Reusable
+    @Binds
+    fun registrationNavigator(navigator: TestNavigatorImpl): RegistrationNavigator
+
+    @Reusable
+    @Binds
+    fun listPersonNavigator(navigator: TestNavigatorImpl): ListPersonNavigator
+
+    @Reusable
+    @Binds
+    fun editPersonNavigator(navigator: TestNavigatorImpl): EditPersonNavigator
+}

+ 16 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/di/SplashNavigatorImpl.kt

@@ -0,0 +1,16 @@
+package com.mrozon.feature_auth.di
+
+import androidx.navigation.NavController
+import com.mrozon.core_api.navigation.SplashNavigator
+import javax.inject.Inject
+
+class SplashNavigatorImpl @Inject constructor()
+    :SplashNavigator {
+
+    override fun navigateToAuth(navController: NavController) {
+    }
+
+    override fun navigateToListPerson(navController: NavController) {
+    }
+
+}

+ 26 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/di/TestNavigatorImpl.kt

@@ -0,0 +1,26 @@
+package com.mrozon.feature_auth.di
+
+import androidx.navigation.NavController
+import com.mrozon.core_api.navigation.EditPersonNavigator
+import com.mrozon.core_api.navigation.ListPersonNavigator
+import com.mrozon.core_api.navigation.LoginNavigator
+import com.mrozon.core_api.navigation.RegistrationNavigator
+import javax.inject.Inject
+
+class TestNavigatorImpl @Inject constructor(): RegistrationNavigator, LoginNavigator,
+    ListPersonNavigator, EditPersonNavigator {
+
+    override fun navigateToLoginUser(navController: NavController, userName: String) {
+
+    }
+
+    override fun navigateToRegisterUser(navController: NavController) {
+    }
+
+    override fun navigateToListPerson(navController: NavController) {
+    }
+
+    override fun navigateToEditPerson(navController: NavController, title: String, id: Long) {
+
+    }
+}

+ 85 - 0
feature_auth/src/androidTest/java/com/mrozon/feature_auth/presentation/RegistrationFragmentTest.kt

@@ -0,0 +1,85 @@
+package com.mrozon.feature_auth.presentation
+
+import android.content.Context
+import androidx.fragment.app.testing.launchFragmentInContainer
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers.*
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.mrozon.feature_auth.R
+import org.hamcrest.Matchers.not
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class RegistrationFragmentTest {
+
+    lateinit var context: Context
+
+    @Before
+    fun setup() {
+        context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
+    }
+
+    @Test
+    fun all_input_value_is_corrected() {
+
+        launchFragmentInContainer<RegistrationFragment>()
+
+        val password = "Password1!"
+        onView(withId(R.id.etUserName)).perform(ViewActions.typeText("vasya@mail.ru"))
+        onView(withId(R.id.etUserPassword)).perform(ViewActions.typeText(password))
+        onView(withId(R.id.etUserPasswordAgain)).perform(ViewActions.typeText(password))
+        onView(withId(R.id.etFirstName)).perform(ViewActions.typeText("first_name"))
+        onView(withId(R.id.etLastName)).perform(ViewActions.typeText("last_name"))
+
+        onView(withId(R.id.btnRegistration)).check(matches(isEnabled()))
+    }
+
+    @Test
+    fun input_incorrect_email() {
+
+        launchFragmentInContainer<RegistrationFragment>()
+
+        val password = "Password1!"
+        onView(withId(R.id.etUserName)).perform(ViewActions.typeText("vasyamail.ru"))
+        onView(withId(R.id.etUserPassword)).perform(ViewActions.typeText(password))
+        onView(withId(R.id.etUserPasswordAgain)).perform(ViewActions.typeText(password))
+        onView(withId(R.id.etFirstName)).perform(ViewActions.typeText("first_name"))
+        onView(withId(R.id.etLastName)).perform(ViewActions.typeText("last_name"))
+
+        onView(withId(R.id.etUserName)).check(matches(hasErrorText(context.getString(R.string.uncorrect_email))))
+    }
+
+    @Test
+    fun input_different_passwords() {
+
+        launchFragmentInContainer<RegistrationFragment>()
+
+        onView(withId(R.id.etUserName)).perform(ViewActions.typeText("vasya@mail.ru"))
+        onView(withId(R.id.etUserPassword)).perform(ViewActions.typeText("password"))
+        onView(withId(R.id.etUserPasswordAgain)).perform(ViewActions.typeText("1"))
+        onView(withId(R.id.etFirstName)).perform(ViewActions.typeText("first_name"))
+        onView(withId(R.id.etLastName)).perform(ViewActions.typeText("last_name"))
+
+        onView(withId(R.id.etUserPassword)).check(matches(hasErrorText(context.getString(R.string.equals_psw))))
+    }
+
+    @Test
+    fun dont_type_all_needed_params() {
+
+        launchFragmentInContainer<RegistrationFragment>()
+
+        val password = "Password1!"
+        onView(withId(R.id.etUserName)).perform(ViewActions.typeText("vasya@mail.ru"))
+        onView(withId(R.id.etUserPassword)).perform(ViewActions.typeText(password))
+        onView(withId(R.id.etUserPasswordAgain)).perform(ViewActions.typeText(password))
+        onView(withId(R.id.etFirstName)).perform(ViewActions.typeText("first_name"))
+
+        onView(withId(R.id.btnRegistration)).check(matches(not(isEnabled())))
+    }
+
+}

+ 6 - 2
scripts/deps_versions.gradle

@@ -22,7 +22,8 @@ ext {
     appCompatVersion = "1.2.0"
     androidxCoreVersion = "1.3.1"
     robolectricVersion = "4.4"
-    androidXCoreTest = "2.1.0"
+    androidXCoreTestVersion = "2.1.0"
+    androidXTestVersion = "1.1.0"
 
     // DI
     dagger = "com.google.dagger:dagger:$daggerVersion"
@@ -59,8 +60,11 @@ ext {
     kotlinxCoroutinesTest =  "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinxCoroutinesTestVersion"
     junitInstrumental =  "androidx.test.ext:junit:$junitInstrumentalVersion"
     espressoCore = "androidx.test.espresso:espresso-core:$espressoCoreVersion"
+    androidXRunnerTest = "androidx.test:runner:$androidXTestVersion"
+    androidXRulesTest = "androidx.test:rules:$androidXTestVersion"
     robolectric = "org.robolectric:robolectric:$robolectricVersion"
-    androidXCoreTest = "androidx.arch.core:core-testing:$androidXCoreTest"
+    androidXCoreTest = "androidx.arch.core:core-testing:$androidXCoreTestVersion"
+    androidXFragmentTest = "androidx.fragment:fragment-testing:$androidXTestVersion"
     // Support Library AndroidX
     legacySupport = "androidx.legacy:legacy-support-v4:$legacySupportVersion"
     appCompat =  "androidx.appcompat:appcompat:$appCompatVersion"