การทดสอบในเครื่องจะทํางานบนเวิร์กสเตชันของคุณเองโดยตรง ไม่ใช่ในอุปกรณ์หรือโปรแกรมจําลอง Android ด้วยเหตุนี้ ระบบจึงใช้ Java Virtual Machine (JVM) ในเครื่องของคุณ แทนที่จะใช้อุปกรณ์ Android เพื่อทำการทดสอบ การทดสอบในเครื่องช่วยให้คุณประเมินตรรกะของแอปได้เร็วขึ้น อย่างไรก็ตาม การที่โต้ตอบกับเฟรมเวิร์ก Android ไม่ได้จะจํากัดประเภทการทดสอบที่คุณทําได้
การทดสอบหน่วยจะยืนยันลักษณะการทํางานของโค้ดส่วนเล็กๆ ซึ่งเป็นหน่วยที่อยู่ภายใต้การทดสอบ โดยการเรียกใช้โค้ดและตรวจสอบผลลัพธ์
การทดสอบ 1 หน่วยมักจะทำได้ง่าย แต่การตั้งค่าอาจทำให้เกิดปัญหาเมื่อหน่วย อยู่ระหว่างทดสอบไม่ได้ออกแบบโดยคำนึงถึงความสามารถในการทดสอบ
- รหัสที่คุณต้องการยืนยันต้องเข้าถึงได้จากการทดสอบ เช่น คุณจะทดสอบเมธอดส่วนตัวโดยตรงไม่ได้ แต่คุณทดสอบคลาสโดยใช้ API สาธารณะแทน
- หากต้องการเรียกใช้การทดสอบหน่วยแบบแยกส่วน คุณต้องแทนที่การพึ่งพาของหน่วยทดสอบด้วยคอมโพเนนต์ที่คุณควบคุม เช่น คอมโพเนนต์จำลองหรือการทดสอบจำลองอื่นๆ ปัญหานี้จะเกิดขึ้นได้เมื่อโค้ดของคุณใช้เฟรมเวิร์ก Android
หากต้องการดูข้อมูลเกี่ยวกับกลยุทธ์การทดสอบหน่วยทั่วไปใน Android โปรดอ่านสิ่งที่ต้องทดสอบ
ตำแหน่งการทดสอบในพื้นที่
โดยค่าเริ่มต้น ไฟล์ต้นฉบับสำหรับการทดสอบหน่วยในเครื่องจะอยู่ใน
module-name/src/test/
ไดเรกทอรีนี้มีอยู่แล้วเมื่อคุณสร้างโปรเจ็กต์ใหม่โดยใช้ Android Studio
การเพิ่มการพึ่งพาการทดสอบ
นอกจากนี้ คุณยังต้องกําหนดค่าการพึ่งพาการทดสอบสําหรับโปรเจ็กต์เพื่อใช้ 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"
}
สร้างชั้นเรียนการทดสอบหน่วยท้องถิ่น
คุณเขียนคลาสการทดสอบ 1 หน่วยในเครื่องเป็นคลาสทดสอบ JUnit 4
โดยสร้างคลาสที่มีเมธอดทดสอบอย่างน้อย 1 รายการ ซึ่งโดยปกติจะอยู่ในไฟล์ module-name/src/test/
วิธีการทดสอบเริ่มต้นด้วยคำอธิบายประกอบ @Test
และ
มีโค้ดสำหรับใช้งานและตรวจสอบองค์ประกอบด้านเดียวที่
ที่คุณต้องการทดสอบ
ตัวอย่างต่อไปนี้สาธิตวิธีใช้คลาสการทดสอบ 1 หน่วยในเครื่อง
วิธีการทดสอบemailValidator_correctEmailSimple_returnsTrue()
ความพยายามเพื่อยืนยัน
isValidEmail()
ซึ่งเป็นเมธอดภายในแอป ฟังก์ชันทดสอบจะแสดงผล
"true" หาก isValidEmail()
แสดงผลเป็น "true" ด้วย
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("[email protected]")) } }
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("[email protected]")); } }
คุณควรสร้างการทดสอบที่อ่านง่ายซึ่งประเมินว่าคอมโพเนนต์ในแอปแสดงผลลัพธ์ตามที่คาดไว้หรือไม่ เราขอแนะนำให้คุณใช้ไลบรารีการยืนยัน
เป็น 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 มีดังนี้ โมเดลการเขียนโปรแกรม:
- รวมทรัพยากร Dependency ของไลบรารี Mockito ไว้ในไฟล์
build.gradle
เป็น ตามที่อธิบายไว้ในหัวข้อตั้งค่าสภาพแวดล้อมการทดสอบของคุณ - เพิ่มการกำกับเนื้อหา
@RunWith(MockitoJUnitRunner.class)
ที่จุดเริ่มต้นของคำจำกัดความคลาสการทดสอบหน่วย คําอธิบายประกอบนี้บอกโปรแกรมรันทดสอบ Mockito ให้ตรวจสอบว่าการใช้เฟรมเวิร์กถูกต้อง และลดความซับซ้อนในการเริ่มต้นวัตถุจำลอง - หากต้องการสร้างออบเจ็กต์จำลองสําหรับการพึ่งพา Android ให้เพิ่มแอตทริบิวต์
@Mock
ก่อนการประกาศฟิลด์ - หากต้องการจำลองลักษณะการทํางานของ 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
}