สร้างการทดสอบ 1 หน่วยในเครื่อง

การทดสอบในเครื่องจะดำเนินการในเวิร์กสเตชันของคุณเองโดยตรง ไม่ใช่ใน Android อุปกรณ์หรือโปรแกรมจำลอง ด้วยเหตุนี้ ระบบจึงใช้ Java Virtual Machine (JVM) ในเครื่องของคุณ แทนที่จะใช้อุปกรณ์ Android เพื่อทำการทดสอบ การทดสอบในเครื่องจะช่วยให้คุณสามารถประเมิน ตรรกะของแอปคุณได้เร็วยิ่งขึ้น อย่างไรก็ตาม ไม่สามารถโต้ตอบกับ เฟรมเวิร์ก Android สร้างข้อจำกัดประเภทการทดสอบที่คุณจะทำได้

การทดสอบ unit จะยืนยันลักษณะการทำงานของส่วนเล็กๆ ของโค้ด หน่วยที่อยู่ใต้ test โดยการเรียกใช้โค้ดและตรวจสอบผลลัพธ์

การทดสอบ 1 หน่วยมักจะทำได้ง่าย แต่การตั้งค่าอาจทำให้เกิดปัญหาเมื่อหน่วย อยู่ระหว่างทดสอบไม่ได้ออกแบบโดยคำนึงถึงความสามารถในการทดสอบ

  • รหัสที่คุณต้องการยืนยันต้องเข้าถึงได้จากการทดสอบ สำหรับ เช่น คุณจะทดสอบเมธอดส่วนตัวโดยตรงไม่ได้ แต่คุณจะทดสอบชั้นเรียน โดยใช้ API สาธารณะ
  • ในการเรียกใช้การทดสอบหน่วยในการแยก ทรัพยากร Dependency ของหน่วย ที่อยู่ในการทดสอบต้องแทนที่ด้วยคอมโพเนนต์ที่คุณควบคุม เช่น ปลอม หรือ คู่ทดลองอื่นๆ โดยเฉพาะอย่างยิ่งหากโค้ดของคุณขึ้นอยู่กับ เฟรมเวิร์กของ Android

หากต้องการเรียนรู้เกี่ยวกับกลยุทธ์การทดสอบ 1 หน่วยที่พบบ่อยใน Android โปรดอ่านสิ่งที่ต้องทำ test

ตำแหน่งการทดสอบในพื้นที่

โดยค่าเริ่มต้น ไฟล์ต้นฉบับสำหรับการทดสอบหน่วยในเครื่องจะอยู่ใน module-name/src/test/ มีไดเรกทอรีนี้อยู่แล้วเมื่อคุณสร้าง โดยใช้ Android Studio

การเพิ่มทรัพยากร Dependency ทดสอบ

นอกจากนี้ คุณยังต้องกำหนดค่าทรัพยากร Dependency ของการทดสอบสำหรับโปรเจ็กต์ของคุณเพื่อใช้โอเปอเรเตอร์ API มาตรฐานที่ให้บริการโดยเฟรมเวิร์กการทดสอบ JUnit

โดยเปิดไฟล์ build.gradle ของโมดูลแอปและระบุข้อมูลต่อไปนี้ เป็นทรัพยากร Dependency ได้ ใช้ฟังก์ชัน testImplementation เพื่อระบุ ที่ใช้กับชุดแหล่งที่มาทดสอบในเครื่อง ไม่ใช่แอปพลิเคชัน

dependencies {
  // Required -- JUnit 4 framework
  testImplementation "junit:junit:$jUnitVersion"
  // Optional -- Robolectric environment
  testImplementation "androidx.test:core:$androidXTestVersion"
  // Optional -- Mockito framework
  testImplementation "org.mockito:mockito-core:$mockitoVersion"
  // Optional -- mockito-kotlin
  testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
  // Optional -- Mockk framework
  testImplementation "io.mockk:mockk:$mockkVersion"
}

สร้างชั้นเรียนการทดสอบหน่วยท้องถิ่น

คุณเขียนชั้นเรียนการทดสอบหน่วยท้องถิ่นเป็นชั้นเรียนการทดสอบ JUnit 4

โดยให้คุณสร้างชั้นเรียนที่มีวิธีการทดสอบอย่างน้อย 1 วิธี ซึ่งโดยปกติแล้วจะอยู่ใน module-name/src/test/ วิธีการทดสอบเริ่มต้นด้วยคำอธิบายประกอบ @Test และ มีโค้ดสำหรับใช้งานและตรวจสอบองค์ประกอบด้านเดียวที่ ที่คุณต้องการทดสอบ

ตัวอย่างต่อไปนี้สาธิตวิธีใช้คลาสการทดสอบ 1 หน่วยในเครื่อง วิธีการทดสอบemailValidator_correctEmailSimple_returnsTrue()ความพยายามเพื่อยืนยัน isValidEmail() ซึ่งเป็นเมธอดภายในแอป ฟังก์ชันทดสอบจะแสดงผล "จริง" หากisValidEmail() แสดงผลเป็น "จริง" ด้วย

Kotlin

import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

class EmailValidatorTest {
  @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"))
  }

}

Java

import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

class EmailValidatorTest {
  @Test
  public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
    assertTrue(EmailValidator.isValidEmail("name@email.com"));
  }
}

คุณควรสร้างการทดสอบที่อ่านได้เพื่อประเมินว่าองค์ประกอบใน แอปจะแสดงผลลัพธ์ที่คาดหวัง เราขอแนะนำให้คุณใช้ไลบรารีการยืนยัน เป็น junit.Assert, Hamcrest หรือ ความจริง ตัวอย่างด้านบนเป็นตัวอย่างวิธีใช้ junit.Assert

ไลบรารี Android ที่จำลองได้

เมื่อคุณดำเนินการทดสอบหน่วยในเครื่อง ปลั๊กอิน Android Gradle จะมี ที่มี API ทั้งหมดของเฟรมเวิร์ก Android ให้แก้ไข เวอร์ชันที่ใช้ในโปรเจ็กต์ ห้องสมุดเก็บวิธีการสาธารณะทั้งหมด ของ API เหล่านั้น แต่โค้ดภายในเมธอดถูกนำออกไปแล้ว หากมี เมธอดที่มีการเข้าถึง การทดสอบจะแสดงข้อยกเว้น

ซึ่งจะทำให้ระบบสร้างการทดสอบในเครื่องเมื่ออ้างอิงชั้นเรียนใน Android เช่น Context ยิ่งไปกว่านั้น โมเดลนี้ยังช่วยให้คุณใช้การล้อเลียน เฟรมเวิร์กของ Android ได้

การจำลองทรัพยากร Dependency ของ Android

ปัญหาทั่วไปคือเมื่อชั้นเรียนใช้ทรัพยากรสตริง คุณสามารถ รับทรัพยากรสตริงโดยเรียกใช้เมธอด getString() ใน Context แต่การทดสอบในเครื่องจะใช้ Context หรือวิธีการใดๆ ของการทดสอบไม่ได้ เนื่องจาก อยู่ในเฟรมเวิร์กของ Android โดยหลักการแล้ว การเรียกไปยัง getString() จะเป็น ถูกย้ายออกจากชั้นเรียน แต่มักจะเป็นไปในทางปฏิบัติไม่ได้เสมอไป วิธีแก้ไขคือ สร้างแบบจำลองหรือสตั๊นของ Context ที่จะแสดงผลค่าเดียวกันเสมอเมื่อ มีการเรียกใช้เมธอด getString()

มีไลบรารี Android ที่จำลองได้และเฟรมเวิร์กที่จำลอง เช่น Mockito หรือ MockK คุณสามารถตั้งโปรแกรม พฤติกรรมการลอกเลียนชั้นเรียน Android ในแบบทดสอบแต่ละหน่วย

วิธีเพิ่มออบเจ็กต์จำลองไปยังการทดสอบ 1 หน่วยในเครื่องโดยใช้ Mockito มีดังนี้ โมเดลการเขียนโปรแกรม:

  1. รวมทรัพยากร Dependency ของไลบรารี Mockito ไว้ในไฟล์ build.gradle เป็น ตามที่อธิบายไว้ในหัวข้อตั้งค่าสภาพแวดล้อมการทดสอบของคุณ
  2. ในช่วงต้นของคําจํากัดความของคลาสการทดสอบหน่วย ให้เพิ่มเมธอด คำอธิบายประกอบ @RunWith(MockitoJUnitRunner.class) รายการ คำอธิบายประกอบนี้จะบอก ตัวดำเนินการทดสอบ Mockito เพื่อตรวจสอบว่าการใช้เฟรมเวิร์กของคุณถูกต้องและ ทำให้การเริ่มต้นออบเจ็กต์จำลองง่ายขึ้น
  3. หากต้องการสร้างออบเจ็กต์จำลองสำหรับทรัพยากร Dependency ของ Android ให้เพิ่มคำอธิบายประกอบ @Mock ก่อนการประกาศช่อง
  4. หากต้องการสร้างลักษณะการทำงานของทรัพยากร Dependency คุณสามารถระบุเงื่อนไขและ จะแสดงผลค่าเมื่อตรงตามเงื่อนไขโดยใช้ when() และ thenReturn()

ตัวอย่างต่อไปนี้แสดงวิธีสร้างการทดสอบ 1 หน่วยที่ใช้การจำลอง ออบเจ็กต์ Context ใน Kotlin ที่สร้างด้วย Mockito-Kotlin สร้าง

import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock

private const val FAKE_STRING = "HELLO WORLD"

@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {

  @Mock
  private lateinit var mockContext: Context

  @Test
  fun readStringFromContext_LocalizedString() {
    // Given a mocked Context injected into the object under test...
    val mockContext = mock<Context> {
        on { getString(R.string.name_label) } doReturn FAKE_STRING
    }

    val myObjectUnderTest = ClassUnderTest(mockContext)

    // ...when the string is returned from the object under test...
    val result: String = myObjectUnderTest.getName()

    // ...then the result should be the expected one.
    assertEquals(result, FAKE_STRING)
  }
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้เฟรมเวิร์กของ Mockito ได้ที่ Mockito API การอ้างอิง และคลาส SharedPreferencesHelperTest ใน ตัวอย่างโค้ด หรือลองใช้ Android Testing Codelab

ข้อผิดพลาด: "เมธอด ... ไม่ได้มีการเลียนแบบ"

ไลบรารี Android ที่จำลองขึ้นมาจะให้การยกเว้น หากคุณพยายามเข้าถึง ด้วยข้อความ Error: "Method ... not mocked

หากข้อยกเว้นที่ใส่ก่อให้เกิดปัญหาต่อการทดสอบของคุณ คุณสามารถเปลี่ยน เพื่อให้เมธอดแสดงผลเป็น null หรือ 0 แทน ทั้งนี้ขึ้นอยู่กับ ประเภทการแสดงผล ในการดำเนินการนี้ ให้เพิ่มการกำหนดค่าต่อไปนี้ในส่วน ไฟล์ build.gradle ระดับบนสุดใน Groovy:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }