تست های یکپارچه سازی با WorkManager

WorkManager یک مصنوع work-testing را ارائه می دهد که به آزمایش کارگران شما کمک می کند.

راه اندازی

برای استفاده از آرتیفکت work-testing ، آن را به عنوان وابستگی androidTestImplementation در build.gradle اضافه کنید.

شیار

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

کاتلین

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

برای اطلاعات بیشتر در مورد افزودن وابستگی‌ها، به بخش Declaring dependencies در یادداشت‌های انتشار WorkManager نگاه کنید.

مفاهیم

work-testing پیاده سازی خاصی از WorkManager را برای حالت تست فراهم می کند که با استفاده از WorkManagerTestInitHelper مقداردهی اولیه می شود.

آرتیفکت work-testing همچنین یک SynchronousExecutor را ارائه می‌کند که نوشتن تست‌ها را به صورت همزمان، بدون نیاز به چندین رشته، قفل یا چفت آسان‌تر می‌کند.

در اینجا یک مثال در مورد نحوه استفاده از همه این کلاس ها با هم آورده شده است.

کاتلین

@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)     } }

جاوا

@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 کپی می کند (اکو می کند).

کاتلین

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

جاوا

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 در یک برنامه واقعی است.

کاتلین

@Test @Throws(Exception::class) fun testSimpleEchoWorker() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = OneTimeWorkRequestBuilder<EchoWorker>()         .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)) }

جاوا

@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() است.

کاتلین

@Test @Throws(Exception::class) fun testEchoWorkerNoInput() {    // Create request    val request = OneTimeWorkRequestBuilder<EchoWorker>()        .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)) }

جاوا

@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 استفاده کنید.

کاتلین

@Test @Throws(Exception::class) fun testWithInitialDelay() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = OneTimeWorkRequestBuilder<EchoWorker>()         .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)) }

جاوا

@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 با محدودیت ها آزمایش کنید آورده شده است.

کاتلین

@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 = OneTimeWorkRequestBuilder<EchoWorker>()         .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)) }

جاوا

@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 استفاده شده است.

کاتلین

@Test @Throws(Exception::class) fun testPeriodicWork() {     // Define input data     val input = workDataOf(KEY_1 to 1, KEY_2 to 2)      // Create request     val request = PeriodicWorkRequestBuilder<EchoWorker>(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)) }

جاوا

@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)); }