اختبارات الدمج مع WorkManager

يوفّر WorkManager عنصر واحد (work-testing) يساعد في اختبار العاملين.

ضبط إعدادات الجهاز

لاستخدام عنصر "work-testing"، أضِفه كعنصر androidTestImplementation. والتبعية في build.gradle.

Groovy

 dependencies {     def work_version = "2.5.0"      ...      // optional - Test helpers     androidTestImplementation "androidx.work:work-testing:$work_version" } 

Kotlin

 dependencies {     val work_version = "2.4.0"      ...      // optional - Test helpers     androidTestImplementation("androidx.work:work-testing:$work_version") } 

لمزيد من المعلومات حول إضافة التبعيات، انظر إلى قسم إعلان التبعيات في قسم ملاحظات إصدار WorkManager:

المفاهيم

يوفر work-testing طريقة تنفيذ خاصة لتطبيق WorkManager لوضع الاختبار، والتي يتم إعدادها باستخدام WorkManagerTestInitHelper

توفّر عناصر "work-testing" أيضًا SynchronousExecutor وهو ما يسهل كتابة الاختبارات بطريقة متزامنة، دون الحاجة إلى تتعامل مع العديد من الخيوط والأقفال والمزالج.

إليك مثال حول كيفية استخدام جميع هذه الصفوف معًا.

Kotlin

 @RunWith(AndroidJUnit4::class) class BasicInstrumentationTest {     @Before     fun setup() {         val context = InstrumentationRegistry.getTargetContext()         val config = Configuration.Builder()             .setMinimumLoggingLevel(Log.DEBUG)             .setExecutor(SynchronousExecutor())             .build()          // Initialize WorkManager for instrumentation tests.         WorkManagerTestInitHelper.initializeTestWorkManager(context, config)     } } 

Java

 @RunWith(AndroidJUnit4.class) public class BasicInstrumentationTest {     @Before     public void setup() {         Context context = InstrumentationRegistry.getTargetContext();         Configuration config = new Configuration.Builder()                 .setMinimumLoggingLevel(Log.DEBUG)                 .setExecutor(new SynchronousExecutor())                 .build();          // Initialize WorkManager for instrumentation tests.         WorkManagerTestInitHelper.initializeTestWorkManager(             context, config);     } } 

اختبارات البنية

الآن وبعد أن تم إعداد WorkManager في وضع الاختبار، فأنت جاهز لاختبار للعاملين لديك.

لنفترض أنّ لديك EchoWorker يتوقّع مقدار inputData، وببساطة تنسخ (صدى) الإدخال إلى outputData.

Kotlin

 class EchoWorker(context: Context, parameters: WorkerParameters)    : Worker(context, parameters) {    override fun doWork(): Result {        return when(inputData.size()) {            0 - >Result.failure()            else - >Result.success(inputData)        }    } } 

Java

 public class EchoWorker extends Worker {   public EchoWorker(Context context, WorkerParameters parameters) {       super(context, parameters);   }    @NonNull   @Override   public Result doWork() {       Data input = getInputData();       if (input.size() == 0) {           return Result.failure();       } else {           return Result.success(input);       }   } } 

الاختبارات الأساسية

في ما يلي اختبار قياس حالة Android الذي يختبر EchoWorker. المصدر الرئيسي النصيحة الرئيسية هنا هي أن اختبار EchoWorker في وضع الاختبار يشبه إلى حد كبير كيفية ستستخدم EchoWorker في التطبيق الفعلي.

Kotlin

 @Test @Throws(Exception::class) fun testSimpleEchoWorker() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = OneTimeWorkRequestBuilderE<choWorker(>)         .setInputData(input)         .build()      val workManager = WorkManager.getInstance(applicationContext)     // Enqueue and wait for result. This also runs the Worker synchronously     // because we are using a SynchronousExecutor.     workManager.enqueue(request).result.get()     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()     val outputData = workInfo.outputData      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED))     assertThat(outputData, `is`(input)) } 

Java

 @Test public void testSimpleEchoWorker() throws Exception {    // Define input data    Data input = new Data.Builder()            .put(KEY_1, 1)            .put(KEY_2, 2)            .build();     // Create request    OneTimeWorkRequest request =        new OneTimeWorkRequest.Builder(EchoWorker.class)            .setInputData(input)            .build();     WorkManager workManager = WorkManager.getInstance(getApplicationContext());    // Enqueue and wait for result. This also runs the Worker synchronously    // because we are using a SynchronousExecutor.    workManager.enqueue(request).getResult().get();    // Get WorkInfo and outputData    WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();    Data outputData = workInfo.getOutputData();     // Assert    assertThat(workInfo.getState(), is(WorkInfo.State.SUCCEEDED));    assertThat(outputData, is(input)); } 

لنكتب اختبارًا آخر للتأكّد من عدم وصول EchoWorker إلى البيانات. البيانات، فإن القيمة المتوقعة Result هي Result.failure().

Kotlin

 @Test @Throws(Exception::class) fun testEchoWorkerNoInput() {    // Create request    val request = OneTimeWorkRequestBuilderE<choWorker(>)        .build()     val workManager = WorkManager.getInstance(applicationContext)    // Enqueue and wait for result. This also runs the Worker synchronously    // because we are using a SynchronousExecutor.    workManager.enqueue(request).result.get()    // Get WorkInfo    val workInfo = workManager.getWorkInfoById(request.id).get()     // Assert    assertThat(workInfo.state, `is`(WorkInfo.State.FAILED)) } 

Java

 @Test public void testEchoWorkerNoInput() throws Exception {   // Create request   OneTimeWorkRequest request =       new OneTimeWorkRequest.Builder(EchoWorker.class)          .build();    WorkManager workManager = WorkManager.getInstance(getApplicationContext());   // Enqueue and wait for result. This also runs the Worker synchronously   // because we are using a SynchronousExecutor.   workManager.enqueue(request).getResult().get();   // Get WorkInfo   WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();    // Assert   assertThat(workInfo.getState(), is(WorkInfo.State.FAILED)); } 

محاكاة القيود والتأخيرات والعمل الدوري

يقدّم لك WorkManagerTestInitHelper مثالاً على TestDriver الذي يمكن استخدامه لمحاكاة التأخير الأوّلي، والظروف التي يتم فيها استيفاء القيود ListenableWorker حالة وفواصل زمنية لـ PeriodicWorkRequest الحالات.

اختبار التأخيرات الأولية

قد يواجه العمال تأخيرات مبدئية. لاختبار "EchoWorker" باستخدام initialDelay، فبدلاً من الاضطرار إلى انتظار ظهور initialDelay في الاختبار، يمكنك استخدام TestDriver لتمييز التأخير الأولي لطلب العمل على أنه تم تلبيته باستخدام setInitialDelayMet

Kotlin

 @Test @Throws(Exception::class) fun testWithInitialDelay() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = OneTimeWorkRequestBuilderE<choWorker(>)         .setInputData(input)         .setInitialDelay(10, TimeUnit.SECONDS)         .build()      val workManager = WorkManager.getInstance(getApplicationContext())     // Get the TestDriver     val testDriver = WorkManagerTestInitHelper.getTestDriver()     // Enqueue     workManager.enqueue(request).result.get()     // Tells the WorkManager test framework that initial delays are now met.     testDriver.setInitialDelayMet(request.id)     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()     val outputData = workInfo.outputData      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED))     assertThat(outputData, `is`(input)) } 

Java

 @Test public void testWithInitialDelay() throws Exception {   // Define input data   Data input = new Data.Builder()           .put(KEY_1, 1)           .put(KEY_2, 2)           .build();    // Create request   OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(EchoWorker.class)           .setInputData(input)           .setInitialDelay(10, TimeUnit.SECONDS)           .build();    WorkManager workManager = WorkManager.getInstance(myContext);   // Get the TestDriver   TestDriver testDriver = WorkManagerTestInitHelper.getTestDriver();   // Enqueue   workManager.enqueue(request).getResult().get();   // Tells the WorkManager test framework that initial delays are now met.   testDriver.setInitialDelayMet(request.getId());   // Get WorkInfo and outputData   WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();   Data outputData = workInfo.getOutputData();    // Assert   assertThat(workInfo.getState(), is(WorkInfo.State.SUCCEEDED));   assertThat(outputData, is(input)); } 

قيود الاختبار

يمكن أيضًا استخدام TestDriver لوضع علامة على القيود على أنها تم تلبيتها باستخدام setAllConstraintsMet إليك مثال على كيفية اختبار Worker بقيود.

Kotlin

 @Test @Throws(Exception::class) fun testWithConstraints() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      val constraints = Constraints.Builder()         .setRequiredNetworkType(NetworkType.CONNECTED)         .build()      // Create request     val request = OneTimeWorkRequestBuilderE<choWorker(>)         .setInputData(input)         .setConstraints(constraints)         .build()      val workManager = WorkManager.getInstance(myContext)     val testDriver = WorkManagerTestInitHelper.getTestDriver()     // Enqueue     workManager.enqueue(request).result.get()     // Tells the testing framework that all constraints are met.     testDriver.setAllConstraintsMet(request.id)     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()     val outputData = workInfo.outputData      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED))     assertThat(outputData, `is`(input)) } 

Java

 @Test public void testWithConstraints() throws Exception {     // Define input data     Data input = new Data.Builder()             .put(KEY_1, 1)             .put(KEY_2, 2)             .build();      // Define constraints     Constraints constraints = new Constraints.Builder()             .setRequiresDeviceIdle(true)             .build();      // Create request     OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(EchoWorker.class)             .setInputData(input)             .setConstraints(constraints)             .build();      WorkManager workManager = WorkManager.getInstance(myContext);     TestDriver testDriver = WorkManagerTestInitHelper.getTestDriver();     // Enqueue     workManager.enqueue(request).getResult().get();     // Tells the testing framework that all constraints are met.     testDriver.setAllConstraintsMet(request.getId());     // Get WorkInfo and outputData     WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();     Data outputData = workInfo.getOutputData();      // Assert     assertThat(workInfo.getState(), is(WorkInfo.State.SUCCEEDED));     assertThat(outputData, is(input)); } 

اختبار العمل الدوري

تعرض TestDriver أيضًا setPeriodDelayMet الذي يمكن استخدامه إلى اكتمال الفاصل الزمني. فيما يلي مثال على يتم استخدام setPeriodDelayMet.

Kotlin

 @Test @Throws(Exception::class) fun testPeriodicWork() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = PeriodicWorkRequestBuilderE<choWorker(>15, MINUTES)         .setInputData(input)         .build()      val workManager = WorkManager.getInstance(myContext)     val testDriver = WorkManagerTestInitHelper.getTestDriver()     // Enqueue and wait for result.     workManager.enqueue(request).result.get()     // Tells the testing framework the period delay is met     testDriver.setPeriodDelayMet(request.id)     // Get WorkInfo and outputData     val workInfo = workManager.getWorkInfoById(request.id).get()      // Assert     assertThat(workInfo.state, `is`(WorkInfo.State.ENQUEUED)) } 

Java

 @Test public void testPeriodicWork() throws Exception {     // Define input data     Data input = new Data.Builder()             .put(KEY_1, 1)             .put(KEY_2, 2)             .build();      // Create request     PeriodicWorkRequest request =             new PeriodicWorkRequest.Builder(EchoWorker.class, 15, MINUTES)             .setInputData(input)             .build();      WorkManager workManager = WorkManager.getInstance(myContext);     TestDriver testDriver = WorkManagerTestInitHelper.getTestDriver();     // Enqueue and wait for result.     workManager.enqueue(request).getResult().get();     // Tells the testing framework the period delay is met     testDriver.setPeriodDelayMet(request.getId());     // Get WorkInfo and outputData     WorkInfo workInfo = workManager.getWorkInfoById(request.getId()).get();      // Assert     assertThat(workInfo.getState(), is(WorkInfo.State.ENQUEUED)); }