관리 메뉴

나만을 위한 블로그

[Android] 탭 레이아웃 + 뷰페이저2 UI 테스트하는 법 본문

Android

[Android] 탭 레이아웃 + 뷰페이저2 UI 테스트하는 법

참깨빵위에참깨빵 2022. 6. 22. 02:09
728x90
반응형

자투리 시간에 UI 테스트를 짜려고 하는데 어떻게 짜야할지 몰라서 찾아보다가 발견해서 나중에 다시 보려고 포스팅한다.

탭 레이아웃과 뷰페이저2를 사용했고 탭은 5개를 만들었다. 프래그먼트를 대충 5개 만들고 프래그먼트의 코틀린 코드는 아무것도 없으며 XML은 텍스트뷰의 숫자만 프래그먼트별로 바꿨다.

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".tablayout.TestFirstragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="1번 프래그먼트"
        android:textSize="40sp"
        android:textColor="@color/black"/>

</androidx.constraintlayout.widget.ConstraintLayout>
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.kotlinprac.R

class TestFirstragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_test_firstragment, container, false)
    }
}

 

이런 식으로 프래그먼트 5개를 만든 다음 어댑터를 만들었다.

 

import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter

class ViewPagerAdapter(activity: AppCompatActivity): FragmentStateAdapter(activity) {
    override fun getItemCount(): Int = 5

    override fun createFragment(position: Int): Fragment = when (position) {
        0 -> TestFirstragment()
        1 -> TestSecondFragment()
        2 -> TestThirdFragment()
        3 -> TestFourthFragment()
        4 -> TestFifthFragment()
        else -> TestFirstragment()
    }
}

 

그리고 액티비티 XML에 탭 레이아웃과 뷰페이저2를 넣고 코틀린 파일에 대충 필요한 코드들을 넣는다.

TabLayoutMediator 부분은 탭 레이아웃과 뷰페이저2를 연결하는 부분이니 꼭 해준다. 코틀린 코드에서 탭 이름을 넣으면 XML에는 설정할 필요 없으니 참고하자.

 

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".tablayout.TabActivity">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:lineSpacingExtra="8dp"
            android:overScrollMode="never"
            app:tabGravity="center"
            app:tabIndicatorColor="@color/black"
            app:tabRippleColor="@null"
            app:tabPaddingStart="20dp"
            app:tabPaddingEnd="20dp"
            app:tabTextColor="@color/black">

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

        </com.google.android.material.tabs.TabLayout>

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewpager2"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:overScrollMode="never"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tab_layout"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintVertical_bias="0" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityTabBinding
import com.google.android.material.tabs.TabLayoutMediator

class TabActivity : AppCompatActivity() {

    private lateinit var binding: ActivityTabBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_tab)
        binding.run {
            lifecycleOwner = this@TabActivity
            viewpager2.apply {
                adapter = ViewPagerAdapter(this@TabActivity)
            }
            TabLayoutMediator(tabLayout, viewpager2) { tab, position ->
                when (position) {
                    0 -> tab.text = "탭 1"
                    1 -> tab.text = "탭 2"
                    2 -> tab.text = "탭 3"
                    3 -> tab.text = "탭 4"
                    4 -> tab.text = "탭 5"
                }
            }.attach()
        }
    }
}

 

그럼 아래와 같은 화면이 나올 것이다.

 

 

이제 테스트 파일을 작성해보자. 폴더 중 "com (androidTest)"가 쓰여진 폴더에 TabLayoutViewPagerTest란 클래스를 만든다.

 

import android.view.View
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.PerformException
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.kotlinprac.tablayout.TabActivity
import com.google.android.material.tabs.TabLayout
import org.hamcrest.Matchers.allOf
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class TabLayoutWithViewPagerTest {
    @get:Rule
    val activityTestRule = ActivityScenarioRule(TabActivity::class.java)

    private fun selectTabAtPosition(tabIndex: Int): ViewAction {
        return object : ViewAction {
            override fun getDescription() = "with tab at index $tabIndex"

            override fun getConstraints() = allOf(isDisplayed(), isAssignableFrom(TabLayout::class.java))

            override fun perform(uiController: UiController, view: View) {
                val tabLayout = view as TabLayout
                val tabAtIndex: TabLayout.Tab = tabLayout.getTabAt(tabIndex)
                    ?: throw PerformException.Builder()
                        .withCause(Throwable("No tab at index $tabIndex"))
                        .build()

                tabAtIndex.select()
            }
        }
    }

    @Test
    fun `탭_레이아웃_테스트`() {
        onView(withId(R.id.tab_layout))
            .perform(selectTabAtPosition(0))
    }
}

 

이 파일을 실행하면 결과는 아래와 같이 나온다.

 

 

탭 레이아웃을 테스트하는 다른 글을 찾았는데 찾은지 얼마 안 되서 어느 정도 완료되면 그 때 포스팅한다.

반응형
Comments