×
Crocus
공부한 내용을 정리하는 블로그로 시작한
Crocus는 2014년 1월 14일 부터 시작하여
현재 월 6만명, 총 1,499,763명의 방문자 수를 기록하고 있습니다.
Donation
이제 많은 사용자들이 이용하는 만큼
더 다양한 서비스 개발/제공을 위해 후원금을 모금하고자 합니다.
후원을 해주시는 분들은 Donators 명단에 성명, 후원금을 기입해드리며
Crocus 블로그가 아닌 다른 곳에 정리해둔 저만의 내용을 공유해 드리고자 합니다.
Account
예금주 : 고관우
신한은행 : 110-334-866541
카카오뱅크 : 3333-01-7888060

👉 후원 페이지 바로가기 Donators
익명 : 5000원(Crocus응원합니다.)
busyhuman: 5000원(유용한 지식 감사합니다.)
익명 : 5000원(알고리즘 학습러)

Espresso는 사용자 인터페이스 및 Android 애플리케이션의 사용자 상호 작용을 테스트하기 위해 많은 클래스를 제공한다. 대표적으로 아래에 지정된 5가지 범주로 나타낼 수 있다.

 

JUnit runner

 

안드로이드 테스트 프레임워크는 JUnit3와 JUnit4 스타일로 작성된 에스프레소 테스트 케이스를 실행하기 위한 Android JUnitRunner를 제공한다. JUnit runner는 테스트 케이스를 실행하고 결과를 알려준다.

이러한 AndroidJUnitRunner을 테스트 케이스에서 쓰기 위해서는 반드시 @RunWith 주석을 사용하여 테스트 클래스에 주석을 달고 아래 코드처럼 AndroidJUnitRunner 파라미터를 전달해야한다.

 

@RunWith에 Runner클래스를 설정하면 JUnit에 내장된 Runner대신 그 클래스를 실행한다.

여기서는 AndroidJUnit4라는 Runner 클래스를 설정해 준 것이다.

한 클래스내에 여러개의 테스트가 있더라도 어플리케이션 컨텍스트를 초기 한번만 로딩하여 사용하기 때문에, 여러개의 테스트가 있더라도 처음 테스트만 조금 느리고 그 뒤의 테스트들은 빠르다.

 

Junit은 각각의 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 원칙으로 하기에 @Test 마다 오브젝트를 생성한다.

이와 같은 Junit의 특성으로 인하여 ApplicationContext도 매번 새로 생성되기 때문에 테스트가 느려지는 단점이 있다.

그러나 @RunWith annotation은 각각의 테스트 별로 오브젝트가 생성 되더라도 싱글톤의 ApplicationContext를 보장한다.

 

@RunWith(AndroidJUnit4.class)
public class JUnitRunnerTest {

	@Test
	public void myTest1() {
	}

	@Test
	public void myTest2() {
	}

}

 

 

 

JUnit rules

테스트 케이스를 실행하기 전에 안드로이드 액티비티를 실행하기 위해 ActivityTestRule을 제공한다.

이것은 테스트케이스가 실행되기 전 (@Before)에 실행되고 @Test, @After 이후 종료된다.

 

@Rule
public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

위의 코드에서 MainActivity는 테스트 케이스가 실행되기전에 실행되고 특정 테스트 케이스가 실행된 후 파괴된다.


즉, Rule은 테스트 클래스에서 동작 방식을 재정의 하거나 쉽게 추가하는 것을 가능하게 하고, 사용자는 기존의 Rule을 재사용하거나 확장하는 것이 가능하다.

public static class HasTempFolder {
  @Rule
  public final TemporaryFolder folder = new TemporaryFolder();

  @Test
  public void testUsingTempFolder() throws IOException {
    File createdFile = folder.newFile("myfile.txt");
    File createdFolder = folder.newFolder("subfolder");
    // ...
  }
}

위의 코드는 다음과 같은 의미를 가진다. 
- 임시폴더, 파일들을 생성할 수 있습니다.
- 테스트가 모두 끝난 후(@After) 삭제합니다.
- 기본적으로 resource를 삭제하기 못하는 경우 어떠한 exception도 반환하지 않습니다.

 

 

ViewMatchers

 

에스프레소는 다양한 View matcher class들을 제공한다. (in androidx.test.espresso.matcher.ViewMatchers package)

이 View matcher들은 안드로이드 액티비티 스크린의 뷰 계층에서 UI element, view 들을 찾아준다.

 

에스프레소의 onView 메서드는 하나의 Matcher 타입의 단일 파라미터를 사용하여 해당 UI view를 찾아 적절한 VieInterection Object를 리턴해준다.

 

onView 메서드에 의해 리턴된 ViewInteraction Object는 현재 내가 바라보고 있는 매치된 뷰이며 이를 통해 액션을 주고 받을 수 있다.

"Hello World!"라는 텍스트가 포함 된 뷰를 찾는 샘플 코드는 아래 코드와 같다.

ViewInteraction viewInteraction = Espresso.onView(withText("Hello World!"));

 

 

 

ViewActions

 

에스프레소는 다양한 View action class들을 제공한다. (in androidx.test.espresso.action.ViewActions)

이 View action들은 현재 해당하는 뷰에서 여러가지의 action들을 만든다.

 

onView에 의해 ViewInteraction Object가 리턴되면 ViewInteraction 오브젝트의 "perform" 메서드를 호출하여 적절한 액션을 만들어낼 수 있다.

 

아래 코드는 click()라는 것을 perform 메서드를 통해 만들어내는 코드이다.

ViewInteraction viewInteraction = Espresso.onView(withText("Hello World!"));
viewInteraction.perform(click());

 

 

 

 

ViewAssertions

View matcher, view action과 비슷하게 에스프레소는 다양한 View assertion을 제공한다.(in androidx.test.espresso.assertion.ViewAssertions package)

 

이 ViewAssertions 패키지는 우리가 예상하는 뷰가 매치되는지에 대해 판단해주는 역할을 한다.

 

onView가 현재 해당하는 뷰의 ViewInteraction Object를 리턴해주면 어떤 assert라도 ViewInteraction의 check 메서드를 이용하여 확인할 수 있다. 

말로하긴 어렵지만 아래 코드를 보면 쉽게 이해를 할 수 있다.

ViewInteraction viewInteraction = Espresso.onView(withText("Hello World!"));
viewInteraction.check(matches(withId(R.id.text_view)));

 

 

 

Workflow of Espresso Testing Framework

Let us understand how the espresso testing framework works and how it provides options to do any kind of user interaction in a simple and flexible way. Workflow of an espresso test case is as described below,

  • As we learned earlier, Android JUnit runner, AndroidJUnit4 will run the android test cases. The espresso test cases need to be marked with @RunWith(AndroidJUnut.class). First, AndroidJUnit4 will prepare the environment to run the test cases. It starts either the connected android device or emulator, installs the application and makes sure the application to be tested is in ready state. It will run the test cases and report the results.

  • Espresso needs at least a single JUnit rule of type ActivityTestRule to specify the activity. Android JUnit runner will start the activity to be launched using ActivityTestRule.

  • Every test case needs a minimum of single onView or onDate (used to find data based views like AdapterView) method invocation to match and find the desired view. onView or onData returns ViewInteraction object.

  • Once ViewInteraction object is returned, we can either invoke an action of the selected view or check the view for our expected view using assertion.

  • Action can be invoked using perform method of ViewInteraction object by passing any one of the available view actions.

  • Assertion can be invoked using check method of ViewInteraction object by passing any one of the available view assertions.

 

The diagram representation of the Workflow is as follows.

 

 

 

 

아래 코드는 "Hello world!"라는 텍스트를 가진 뷰가 있는지 체크하는 view_isCorrect() 메서드와

 

해당 패키지 네임이 아래와 같은지 확인하는 useAppContext 메서드가 존재하는 것이다.

 

package com.tutorialspoint.espressosamples.helloworldapp;

import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.matcher.ViewMatchers.withText;;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static org.junit.Assert.*;


@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
   @Rule
   public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
   @Test
   public void view_isCorrect() {
      onView(withText("Hello World!")).check(matches(isDisplayed()));
   }
   @Test
   public void useAppContext() {
      // Context of the app under test.
      Context appContext = InstrumentationRegistry.getTargetContext();
      assertEquals("com.tutorialspoint.espressosamples.helloworldapp", appContext.getPackageName());
   }
}

 

 

 

 

https://www.tutorialspoint.com/espresso_testing/espresso_testing_architecture.htm