ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] Robelctric Test๋ž€
    Android 2021. 2. 17. 09:35
    ๋ฐ˜์‘ํ˜•

    Android Test

    Local Unit Test

    • ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ŠคํŠธ์ธ ์œ ๋‹› ํ…Œ์ŠคํŠธ๋Š” JVM์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

    • Unit Test๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” module-name/src/test/java ํด๋”์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    • ์•ˆ๋“œ๋กœ์ด๋“œ ํ”„๋ ˆ์ž„์›Œํฌ ์ข…์†์„ฑ์ด ์—†๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์— ์ฃผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ Android ์ปดํฌ๋„ŒํŠธ๋“ค์„ Unit Test ์ฝ”๋“œ์— ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. Unit Test์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ ์ปดํฌ๋„ŒํŠธ๋“ค์€ android-stubs-src.jar ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜๋Š”๋ฐ ์‹ค์ œ ์ด ํŒŒ์ผ๋“ค์€ ๋นˆ ๊ป๋ฐ๊ธฐ๋“ค๋งŒ ๋ชจ์—ฌ ์žˆ์–ด ์‹คํ–‰๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด Instrumentation Test๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค.

    Instrumentation Test

    • Instrumentation Test๋Š” ํ•˜๋“œ์›จ์–ด ๊ธฐ๊ธฐ๋‚˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

    • ์ด ํ…Œ์ŠคํŠธ๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธํ•  ์•ฑ์˜ Context์™€ ๊ฐ™์€ ์ •๋ณด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” Instrumentation API์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Android ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋˜๋Š” AndroidJUnitRunner๋ฅผ ํ†ตํ•ด์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

    • Instrumentation Tesat๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” module-name/src/test/java ํด๋”์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    • Instrumentation Test๋Š” Unit Test์— ๋น„ํ•ด ์•ฑ์„ ๋นŒ๋“œ -> ๋ฐฐํฌ -> ์‹คํ–‰ ์‹œํ‚ค๋Š” ๊ณผ์ •์ด ๋งค ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ํฌํ•จ๋˜์–ด ์žˆ์–ด์„œ ์ƒ๋Œ€์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ๋˜๊ธฐ๊นŒ์ง€ ์†๋„๊ฐ€ ๋Š๋ฆฝ๋‹ˆ๋‹ค.


    Robolectric

    RObolectri์€ ๋น ๋ฅด๊ณ  ์‹ ๋ขฐ์„ฑ ๋†’์€ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์•ˆ๋“œ๋กœ์ด๋“œ์— ์ œ๊ณตํ•˜๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ์ž…๋‹ˆ๋‹ค. Instrumentatino Test๋ฅผ ๋ณด์™„ํ•˜๊ณ ์ž ๋งŒ๋“  ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์œ ๋‹›ํ…Œ์ŠคํŠธ์—์„œ Insturmentation API์— ์ ‘๊ทผํ•˜์—ฌ ์•ˆ๋“œ๋กœ์ด๋“œ ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜์กด์„ฑ์ด ์žˆ๋Š” ์ฝ”๋“œ๋“ค์„ ์œ ๋‹› ํ…Œ์ŠคํŠธ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1. Robolectric์„ ์ด์šฉํ•œ Unit Test ์‹คํ–‰
    2. RobolectircTestRunner๊ฐ€ JVM์„ ํ›„ํ‚น
    3. Class Loader๊ฐ€ Adnroid Componet ๋กœ๋“œ๊ฐ€ ์•„๋‹Œ Robolectric์˜ Shadow ๊ฐ์ฒด ๋กœ๋”ฉ

    ์ผ๋ฐ˜์ ์œผ๋กœ ์œ ๋‹› ํ…Œ์ŠคํŠธ์—์„œ๋Š” Android ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ๋•Œ, android-stubs-src.jar๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š์ง€๋งŒ, Robolectric์€ ์ž์ฒด์ ์œผ๋กœ android.jar ์˜ ํ–‰๋™์„ Shadowing์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

    Gradle ์„ค์ •

    android {
      testOptions {
        unitTests {
          includeAndroidResources = true
        }
      }
    }
    
    dependencies {
      testImplementation 'org.robolectric:robolectric:4.4'
    }

    build.gradle์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ defaultConfig์— testOptions.uniTests.includeAndroidResources๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  robolectric ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. Robolectric ์‚ฌ์šฉ์‹œ ์ฃผ์˜ํ•  ์ ์€ SdkVersion์ด 29์ด์ƒ์ด ๋˜๋ฉด ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ตœ๋Œ€ 28๊นŒ์ง€๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

    android.enableUnitTestBinaryResources=true

    ํ•ด๋‹น๋˜๋Š” ๋ช…๋ น์–ด๋ฅผ gradle.properies์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜์ง€๋งŒ Android Studio 3.3 ์ด์ƒ๋ถ€ํ„ฐ๋Š” ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.


    Main ์ฝ”๋“œ

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            findViewById(R.id.change_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                    startActivity(intent);
                }
            });
        }
    
        public int tesetMethod(int a,int b){
            return a+b;
        }
    }

    Test ์ฝ”๋“œ

    1. Log -> System.out Test

    @RunWith(RobolectricTestRunner.class)
    public class RobolectricTest {
    
        // Android.util.Log๋ฅผ System.out ์ถœ๋ ฅ
        @Before
        public void setUp() throws Exception {
            ShadowLog.stream = System.out;
        }
    
        @Test
        public void logTest(){
            System.out.println("hello RobolectricTest");
            Log.d("TAG","Log.d change sysout");
        }
    }



    2. Activity change Test

    @Test
    public void changeAcitivityTest(){
        MainActivity activity = Robolectric.buildActivity(MainActivity.class).create().get();
        activity.findViewById(R.id.change_btn).performClick();
        Intent intent = new Intent(activity,SecondActivity.class);
        Intent actual = Shadows.shadowOf(activity).getNextStartedActivity();
        Assert.assertEquals(intent.getComponent(),actual.getComponent());
    }

    3. LifeCycle Test

    @Test
    public void lifecycleActivityTest(){
        ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
        controller.create().start().resume().stop().destroy();
        Assert.assertEquals(true, controller.get().isDestroyed());
    }

    4. Android Component(TextView) Test

    @RunWith(RobolectricTestRunner.class)
    public class RobolectricTest {
    
        MainActivity activity;
    
        @Before
        public void setUp() throws Exception{
            ShadowLog.stream = System.out;
            activity = Robolectric.buildActivity(MainActivity.class)
                    .create()
                    .resume()
                    .get();
        }
    
    
        @Test
        public void textViewTest(){
            TextView textView = activity.findViewById(R.id.textView);
            Assert.assertEquals("Hello World!",textView.getText());
        }
    
    }
    ๋ฐ˜์‘ํ˜•
Designed by Tistory.