আপনার পেজিং বাস্তবায়ন (ভিউ) পরীক্ষা করুন

ধারণা এবং জেটপ্যাক কম্পোজ বাস্তবায়ন

আপনার অ্যাপে পেজিং লাইব্রেরি প্রয়োগ করার সাথে একটি শক্তিশালী টেস্টিং কৌশল থাকা উচিত। PagingSource এবং RemoteMediator এর মতো ডেটা লোডিং কম্পোনেন্টগুলো প্রত্যাশিতভাবে কাজ করছে কিনা, তা নিশ্চিত করার জন্য আপনার সেগুলো পরীক্ষা করা উচিত। এছাড়াও, আপনার পেজিং ইমপ্লিমেন্টেশনের সমস্ত কম্পোনেন্ট কোনো অপ্রত্যাশিত পার্শ্বপ্রতিক্রিয়া ছাড়াই সঠিকভাবে একসাথে কাজ করছে কিনা, তা যাচাই করার জন্য আপনার এন্ড-টু-এন্ড টেস্ট লেখা উচিত।

এই নির্দেশিকায় আপনার অ্যাপের ডেটা লেয়ারে পেজিং লাইব্রেরি কীভাবে পরীক্ষা করতে হয় এবং আপনার সম্পূর্ণ পেজিং বাস্তবায়নের জন্য কীভাবে এন্ড-টু-এন্ড টেস্ট লিখতে হয়, তা ব্যাখ্যা করা হয়েছে।

ডেটা লেয়ার পরীক্ষা

আপনার ডেটা লেয়ারের কম্পোনেন্টগুলো ডেটা সোর্স থেকে সঠিকভাবে ডেটা লোড করছে কিনা, তা নিশ্চিত করতে সেগুলোর জন্য ইউনিট টেস্ট লিখুন। পরীক্ষাধীন কম্পোনেন্টগুলো আলাদাভাবে সঠিকভাবে কাজ করছে কিনা, তা যাচাই করার জন্য ডিপেন্ডেন্সিগুলোর নকল সংস্করণ সরবরাহ করুন। রিপোজিটরি লেয়ারে যে কম্পোনেন্টগুলো আপনাকে পরীক্ষা করতে হবে, তার মধ্যে একটি হলো RemoteMediator

RemoteMediator পরীক্ষা

RemoteMediator ইউনিট টেস্টগুলোর উদ্দেশ্য হলো load() ফাংশনটি সঠিক MediatorResult রিটার্ন করে কিনা তা যাচাই করা। সাইড এফেক্ট, যেমন ডাটাবেসে ডেটা ইনসার্ট হওয়ার মতো বিষয়গুলোর জন্য টেস্ট ইন্টিগ্রেশন টেস্টের জন্য বেশি উপযুক্ত।

প্রথম ধাপ হলো আপনার RemoteMediator ইমপ্লিমেন্টেশনের জন্য কী কী ডিপেন্ডেন্সি প্রয়োজন তা নির্ধারণ করা। নিম্নলিখিত উদাহরণটি এমন একটি RemoteMediator ইমপ্লিমেন্টেশন প্রদর্শন করে যার জন্য একটি Room ডাটাবেস, একটি Retrofit ইন্টারফেস এবং একটি সার্চ স্ট্রিং প্রয়োজন:

জাভা (আরএক্সজাভা)

public class PageKeyedRemoteMediator
  extends RxRemoteMediator<Integer, RedditPost> {

  @NonNull
  private RedditDb db;
  @NonNull
  private RedditPostDao postDao;
  @NonNull
  private SubredditRemoteKeyDao remoteKeyDao;
  @NonNull
  private RedditApi redditApi;
  @NonNull
  private String subredditName;

  public PageKeyedRemoteMediator(
    @NonNull RedditDb db,
    @NonNull RedditApi redditApi,
    @NonNull String subredditName
    ) {
      this.db = db;
      this.postDao = db.posts();
      this.remoteKeyDao = db.remoteKeys();
      this.redditApi = redditApi;
      this.subredditName = subredditName;
      ...
    }
  }

জাভা (গুয়াভা/লাইভডেটা)

public class PageKeyedRemoteMediator
  extends ListenableFutureRemoteMediator<Integer, RedditPost> {

  @NonNull
  private RedditDb db;
  @NonNull
  private RedditPostDao postDao;
  @NonNull
  private SubredditRemoteKeyDao remoteKeyDao;
  @NonNull
  private RedditApi redditApi;
  @NonNull
  private String subredditName;
  @NonNull
  private Executor bgExecutor;

  public PageKeyedRemoteMediator(
    @NonNull RedditDb db,
    @NonNull RedditApi redditApi,
    @NonNull String subredditName,
    @NonNull Executor bgExecutor
  ) {
    this.db = db;
    this.postDao = db.posts();
    this.remoteKeyDao = db.remoteKeys();
    this.redditApi = redditApi;
    this.subredditName = subredditName;
    this.bgExecutor = bgExecutor;
    ...
  }
}

আপনি Retrofit ইন্টারফেস এবং সার্চ স্ট্রিং প্রদান করতে পারেন, যেমনটি "আপনার পেজিং ইমপ্লিমেন্টেশন পরীক্ষা করুন" এর "পেজিংসোর্স টেস্ট" বিভাগে দেখানো হয়েছে। Room ডাটাবেসের একটি মক সংস্করণ প্রদান করা বেশ জটিল, তাই একটি সম্পূর্ণ মক সংস্করণের পরিবর্তে ডাটাবেসের একটি ইন-মেমরি ইমপ্লিমেন্টেশন প্রদান করা সহজ হতে পারে। যেহেতু একটি Room ডাটাবেস তৈরি করার জন্য একটি Context অবজেক্ট প্রয়োজন, তাই আপনাকে এই RemoteMediator টেস্টটি androidTest ডিরেক্টরিতে রাখতে হবে এবং AndroidJUnit4 টেস্ট রানার দিয়ে এটি এক্সিকিউট করতে হবে, যাতে এটি একটি টেস্ট অ্যাপ্লিকেশন কনটেক্সট অ্যাক্সেস করতে পারে। ইন্সট্রুমেন্টেড টেস্ট সম্পর্কে আরও তথ্যের জন্য, "ইন্সট্রুমেন্টেড ইউনিট টেস্ট তৈরি করুন" দেখুন।

টেস্ট ফাংশনগুলোর মধ্যে যেন স্টেট লিক না হয়, তা নিশ্চিত করতে টিয়ার-ডাউন ফাংশন সংজ্ঞায়িত করুন। এটি টেস্ট রানগুলোর মধ্যে সামঞ্জস্যপূর্ণ ফলাফল নিশ্চিত করে।

জাভা (আরএক্সজাভা)

@RunWith(AndroidJUnit4.class)
public class PageKeyedRemoteMediatorTest {
  static PostFactory postFactory = new PostFactory();
  static List<RedditPost> mockPosts = new ArrayList<>();
  static MockRedditApi mockApi = new MockRedditApi();
  private RedditDb mockDb = RedditDb.Companion.create(
    ApplicationProvider.getApplicationContext(),
    true
  );

  static {
    for (int i=0; i<3; i++) {
      RedditPost post = postFactory.createRedditPost(DEFAULT_SUBREDDIT);
      mockPosts.add(post);
    }
  }

  @After
  public void tearDown() {
    mockDb.clearAllTables();
    // Clear the failure message after each test run.
    mockApi.setFailureMsg(null);
    // Clear out posts after each test run.
    mockApi.clearPosts();
  }
}

জাভা (গুয়াভা/লাইভডেটা)

@RunWith(AndroidJUnit4.class)
public class PageKeyedRemoteMediatorTest {
  static PostFactory postFactory = new PostFactory();
  static List<RedditPost> mockPosts = new ArrayList<>();
  static MockRedditApi mockApi = new MockRedditApi();

  private RedditDb mockDb = RedditDb.Companion.create(
    ApplicationProvider.getApplicationContext(),
    true
  );

  static {
    for (int i=0; i<3; i++) {
      RedditPost post = postFactory.createRedditPost(DEFAULT_SUBREDDIT);
      mockPosts.add(post);
    }
  }

  @After
  public void tearDown() {
    mockDb.clearAllTables();
    // Clear the failure message after each test run.
    mockApi.setFailureMsg(null);
    // Clear out posts after each test run.
    mockApi.clearPosts();
  }
}

পরবর্তী ধাপ হলো load() ` ফাংশনটি পরীক্ষা করা। এই উদাহরণে, পরীক্ষা করার জন্য তিনটি ক্ষেত্র রয়েছে:

  • প্রথম ক্ষেত্রটি হলো যখন mockApi বৈধ ডেটা ফেরত দেয়। load() ফাংশনটির MediatorResult.Success রিটার্ন করা উচিত এবং endOfPaginationReached প্রপার্টিটির মান false হওয়া উচিত।
  • দ্বিতীয় পরিস্থিতিটি হলো যখন mockApi একটি সফল প্রতিক্রিয়া ফেরত দেয়, কিন্তু ফেরত আসা ডেটা খালি থাকে। এক্ষেত্রে load ফাংশনটির MediatorResult.Success রিটার্ন করা উচিত এবং endOfPaginationReached প্রপার্টিটির মান true হওয়া উচিত।
  • তৃতীয় ক্ষেত্রটি হলো যখন ডেটা আনার সময় mockApi একটি এক্সেপশন থ্রো করে। সেক্ষেত্রে load() ফাংশনটির MediatorResult.Error রিটার্ন করা উচিত।

প্রথম কেসটি পরীক্ষা করতে এই ধাপগুলো অনুসরণ করুন:

  1. ফেরত দেওয়ার জন্য পোস্ট ডেটা দিয়ে mockApi সেট আপ করুন।
  2. RemoteMediator অবজেক্টটি প্রারম্ভিকীকরণ করুন।
  3. load ফাংশনটি পরীক্ষা করুন।

জাভা (আরএক্সজাভা)

@Test
public void refreshLoadReturnsSuccessResultWhenMoreDataIsPresent()
  throws InterruptedException {

  // Add mock results for the API to return.
  for (RedditPost post: mockPosts) {
    mockApi.addPost(post);
  }

  PageKeyedRemoteMediator remoteMediator = new PageKeyedRemoteMediator(
    mockDb,
    mockApi,
    SubRedditViewModel.DEFAULT_SUBREDDIT
  );
  PagingState<Integer, RedditPost> pagingState = new PagingState<>(
    new ArrayList(),
    null,
    new PagingConfig(10),
    10
  );
  remoteMediator.loadSingle(LoadType.REFRESH, pagingState)
    .test()
    .await()
    .assertValueCount(1)
    .assertValue(value -> value instanceof RemoteMediator.MediatorResult.Success &&
      ((RemoteMediator.MediatorResult.Success) value).endOfPaginationReached() == false);
}

জাভা (গুয়াভা/লাইভডেটা)

@Test
public void refreshLoadReturnsSuccessResultWhenMoreDataIsPresent()
  throws InterruptedException, ExecutionException {

  // Add mock results for the API to return.
  for (RedditPost post: mockPosts) {
    mockApi.addPost(post);
  }

  PageKeyedRemoteMediator remoteMediator = new PageKeyedRemoteMediator(
    mockDb,
    mockApi,
    SubRedditViewModel.DEFAULT_SUBREDDIT,
    new CurrentThreadExecutor()
  );
  PagingState<Integer, RedditPost> pagingState = new PagingState<>(
    new ArrayList(),
    null,
    new PagingConfig(10),
    10
  );

  RemoteMediator.MediatorResult result =
    remoteMediator.loadFuture(LoadType.REFRESH, pagingState).get();

  assertThat(result, instanceOf(RemoteMediator.MediatorResult.Success.class));
  assertFalse(((RemoteMediator.MediatorResult.Success) result).endOfPaginationReached());
}

দ্বিতীয় টেস্টটির জন্য mockApi কে একটি খালি ফলাফল রিটার্ন করতে হবে। যেহেতু আপনি প্রতিটি টেস্ট রানের পর mockApi থেকে ডেটা মুছে ফেলেন, তাই এটি ডিফল্টভাবে একটি খালি ফলাফল রিটার্ন করবে।

জাভা (আরএক্সজাভা)

@Test
public void refreshLoadSuccessAndEndOfPaginationWhenNoMoreData()
  throws InterruptedException() {

  // To test endOfPaginationReached, don't set up the mockApi to return post
  // data here.
  PageKeyedRemoteMediator remoteMediator = new PageKeyedRemoteMediator(
    mockDb,
    mockApi,
    SubRedditViewModel.DEFAULT_SUBREDDIT
  );
  PagingState<Integer, RedditPost> pagingState = new PagingState<>(
    new ArrayList(),
    null,
    new PagingConfig(10),
    10
  );
  remoteMediator.loadSingle(LoadType.REFRESH, pagingState)
    .test()
    .await()
    .assertValueCount(1)
    .assertValue(value -> value instanceof RemoteMediator.MediatorResult.Success &&
      ((RemoteMediator.MediatorResult.Success) value).endOfPaginationReached() == true);
}

জাভা (গুয়াভা/লাইভডেটা)

@Test
public void refreshLoadSuccessAndEndOfPaginationWhenNoMoreData()
  throws InterruptedException, ExecutionException {

  // To test endOfPaginationReached, don't set up the mockApi to return post
  // data here.
  PageKeyedRemoteMediator remoteMediator = new PageKeyedRemoteMediator(
    mockDb,
    mockApi,
    SubRedditViewModel.DEFAULT_SUBREDDIT,
    new CurrentThreadExecutor()
  );
  PagingState<Integer, RedditPost> pagingState = new PagingState<>(
    new ArrayList(),
    null,
    new PagingConfig(10),
    10
  );

  RemoteMediator.MediatorResult result =
    remoteMediator.loadFuture(LoadType.REFRESH, pagingState).get();

  assertThat(result, instanceOf(RemoteMediator.MediatorResult.Success.class));
  assertTrue(((RemoteMediator.MediatorResult.Success) result).endOfPaginationReached());
}

চূড়ান্ত পরীক্ষাটির জন্য mockApi একটি exception থ্রো করতে হবে, যাতে পরীক্ষাটি যাচাই করতে পারে যে load() ফাংশনটি সঠিকভাবে MediatorResult.Error রিটার্ন করছে।

জাভা (আরএক্সজাভা)

@Test
public void refreshLoadReturnsErrorResultWhenErrorOccurs()
  throws InterruptedException {

  // Set up failure message to throw exception from the mock API.
  mockApi.setFailureMsg("Throw test failure");
  PageKeyedRemoteMediator remoteMediator = new PageKeyedRemoteMediator(
    mockDb,
    mockApi,
    SubRedditViewModel.DEFAULT_SUBREDDIT
  );
  PagingState<Integer, RedditPost> pagingState = new PagingState<>(
    new ArrayList(),
    null,
    new PagingConfig(10),
    10
  );
  remoteMediator.loadSingle(LoadType.REFRESH, pagingState)
    .test()
    .await()
    .assertValueCount(1)
    .assertValue(value -> value instanceof RemoteMediator.MediatorResult.Error);
}

জাভা (গুয়াভা/লাইভডেটা)

@Test
public void refreshLoadReturnsErrorResultWhenErrorOccurs()
  throws InterruptedException, ExecutionException {

  // Set up failure message to throw exception from the mock API.
  mockApi.setFailureMsg("Throw test failure");
  PageKeyedRemoteMediator remoteMediator = new PageKeyedRemoteMediator(
    mockDb,
    mockApi,
    SubRedditViewModel.DEFAULT_SUBREDDIT,
    new CurrentThreadExecutor()
  );
  PagingState<Integer, RedditPost> pagingState = new PagingState<>(
    new ArrayList(),
    null,
    new PagingConfig(10),
    10
  );
  RemoteMediator.MediatorResult result =
    remoteMediator.loadFuture(LoadType.REFRESH, pagingState).get();

  assertThat(result, instanceOf(RemoteMediator.MediatorResult.Error.class));
}

এন্ড-টু-এন্ড পরীক্ষা

ইউনিট টেস্ট এই নিশ্চয়তা দেয় যে পেজিং-এর প্রতিটি উপাদান আলাদাভাবে কাজ করে, কিন্তু এন্ড-টু-এন্ড টেস্ট এই বিষয়ে আরও বেশি আস্থা যোগায় যে অ্যাপ্লিকেশনটি সামগ্রিকভাবে কাজ করে। এই টেস্টগুলোর জন্য কিছু মক ডিপেন্ডেন্সির প্রয়োজন হবে, তবে সাধারণত এগুলো আপনার অ্যাপের বেশিরভাগ কোডই কভার করবে।

এই বিভাগের উদাহরণটিতে টেস্টে নেটওয়ার্ক ব্যবহার এড়ানোর জন্য একটি মক এপিআই ডিপেন্ডেন্সি ব্যবহার করা হয়েছে। মক এপিআই-টি একটি সামঞ্জস্যপূর্ণ টেস্ট ডেটা সেট ফেরত দেওয়ার জন্য কনফিগার করা হয়েছে, যার ফলে টেস্টগুলো পুনরাবৃত্তিযোগ্য হয়। প্রতিটি ডিপেন্ডেন্সি কী কাজ করে, এর আউটপুট কতটা সামঞ্জস্যপূর্ণ এবং আপনার টেস্ট থেকে কতটা নির্ভুলতা প্রয়োজন, তার উপর ভিত্তি করে কোন ডিপেন্ডেন্সিগুলোকে মক ইমপ্লিমেন্টেশন দিয়ে প্রতিস্থাপন করবেন, তা স্থির করুন।

আপনার কোড এমনভাবে লিখুন যাতে আপনি সহজেই আপনার ডিপেন্ডেন্সিগুলোর মক ভার্সন অদলবদল করতে পারেন। নিম্নলিখিত উদাহরণটি প্রয়োজন অনুযায়ী ডিপেন্ডেন্সি সরবরাহ এবং পরিবর্তন করার জন্য একটি বেসিক সার্ভিস লোকেটর ইমপ্লিমেন্টেশন ব্যবহার করে। বড় অ্যাপের ক্ষেত্রে, Hilt-এর মতো একটি ডিপেন্ডেন্সি ইনজেকশন লাইব্রেরি ব্যবহার করলে আরও জটিল ডিপেন্ডেন্সি গ্রাফ পরিচালনা করতে সুবিধা হতে পারে।

কোটলিন

class RedditActivityTest {

  companion object {
    private const val TEST_SUBREDDIT = "test"
  }

  private val postFactory = PostFactory()
  private val mockApi = MockRedditApi().apply {
    addPost(postFactory.createRedditPost(DEFAULT_SUBREDDIT))
    addPost(postFactory.createRedditPost(TEST_SUBREDDIT))
    addPost(postFactory.createRedditPost(TEST_SUBREDDIT))
  }

  @Before
  fun init() {
    val app = ApplicationProvider.getApplicationContext<Application>()
    // Use a controlled service locator with a mock API.
    ServiceLocator.swap(
      object : DefaultServiceLocator(app = app, useInMemoryDb = true) {
        override fun getRedditApi(): RedditApi = mockApi
      }
    )
  }
}

জাভা (আরএক্সজাভা)

public class RedditActivityTest {

  public static final String TEST_SUBREDDIT = "test";

  private static PostFactory postFactory = new PostFactory();
  private static MockRedditApi mockApi = new MockRedditApi();

  static {
    mockApi.addPost(postFactory.createRedditPost(DEFAULT_SUBREDDIT));
    mockApi.addPost(postFactory.createRedditPost(TEST_SUBREDDIT));
    mockApi.addPost(postFactory.createRedditPost(TEST_SUBREDDIT));
  }

  @Before
  public void setup() {
    Application app = ApplicationProvider.getApplicationContext();
    // Use a controlled service locator with a mock API.
    ServiceLocator.Companion.swap(
      new DefaultServiceLocator(app, true) {
        @NotNull
        @Override
        public RedditApi getRedditApi() {
          return mockApi;
        }
      }
    );
  }
}

জাভা (গুয়াভা/লাইভডেটা)

public class RedditActivityTest {

  public static final String TEST_SUBREDDIT = "test";

  private static PostFactory postFactory = new PostFactory();
  private static MockRedditApi mockApi = new MockRedditApi();

  static {
    mockApi.addPost(postFactory.createRedditPost(DEFAULT_SUBREDDIT));
    mockApi.addPost(postFactory.createRedditPost(TEST_SUBREDDIT));
    mockApi.addPost(postFactory.createRedditPost(TEST_SUBREDDIT));
  }

  @Before
  public void setup() {
    Application app = ApplicationProvider.getApplicationContext();
    // Use a controlled service locator with a mock API.
    ServiceLocator.Companion.swap(
      new DefaultServiceLocator(app, true) {
        @NotNull
        @Override
        public RedditApi getRedditApi() {
          return mockApi;
        }
      }
    );
  }
}

টেস্টের কাঠামো তৈরি করার পর, পরবর্তী ধাপ হলো Pager ইমপ্লিমেন্টেশন থেকে প্রাপ্ত ডেটা সঠিক কিনা তা যাচাই করা। একটি টেস্টের মাধ্যমে নিশ্চিত করতে হবে যে, পেজটি প্রথমবার লোড হওয়ার সময় Pager অবজেক্টটি ডিফল্ট ডেটা লোড করে, এবং আরেকটি টেস্টের মাধ্যমে যাচাই করতে হবে যে, ব্যবহারকারীর ইনপুটের উপর ভিত্তি করে Pager অবজেক্টটি অতিরিক্ত ডেটা সঠিকভাবে লোড করে।

নিম্নলিখিত উদাহরণে, পরীক্ষাটি যাচাই করে যে, যখন ব্যবহারকারী অনুসন্ধানের জন্য একটি ভিন্ন সাবরেডিট প্রবেশ করান, তখন Pager অবজেক্টটি API থেকে প্রাপ্ত আইটেমের সঠিক সংখ্যা দিয়ে RecyclerView.Adapter কে আপডেট করে।

কোটলিন

@Test
fun loadsTheDefaultResults() {
    ActivityScenario.launch(RedditActivity::class.java)

    onView(withId(R.id.list)).check { view, noViewFoundException ->
        if (noViewFoundException != null) {
            throw noViewFoundException
        }

        val recyclerView = view as RecyclerView
        assertEquals(1, recyclerView.adapter?.itemCount)
    }
}

@Test
// Verify that the default data is swapped out when the user searches for a
// different subreddit.
fun loadsTheTestResultsWhenSearchingForSubreddit() {
  ActivityScenario.launch(RedditActivity::class.java )

  onView(withId(R.id.list)).check { view, noViewFoundException ->
    if (noViewFoundException != null) {
      throw noViewFoundException
    }

    val recyclerView = view as RecyclerView
    // Verify that it loads the default data first.
    assertEquals(1, recyclerView.adapter?.itemCount)
  }

  // Search for test subreddit instead of default to trigger new data load.
  onView(withId(R.id.input)).perform(
    replaceText(TEST_SUBREDDIT),
    pressKey(KeyEvent.KEYCODE_ENTER)
  )

  onView(withId(R.id.list)).check { view, noViewFoundException ->
    if (noViewFoundException != null) {
      throw noViewFoundException
    }

    val recyclerView = view as RecyclerView
    assertEquals(2, recyclerView.adapter?.itemCount)
  }
}

জাভা (আরএক্সজাভা)

@Test
public void loadsTheDefaultResults() {
  ActivityScenario.launch(RedditActivity.class);

  onView(withId(R.id.list)).check((view, noViewFoundException) -> {
    if (noViewFoundException != null) {
      throw noViewFoundException;
    }

    RecyclerView recyclerView = (RecyclerView) view;
    assertEquals(1, recyclerView.getAdapter().getItemCount());
  });
}

@Test
// Verify that the default data is swapped out when the user searches for a
// different subreddit.
public void loadsTheTestResultsWhenSearchingForSubreddit() {
  ActivityScenario.launch(RedditActivity.class);

  onView(withId(R.id.list)).check((view, noViewFoundException) -> {
    if (noViewFoundException != null) {
      throw noViewFoundException;
    }

    RecyclerView recyclerView = (RecyclerView) view;
    // Verify that it loads the default data first.
    assertEquals(1, recyclerView.getAdapter().getItemCount());
  });

  // Search for test subreddit instead of default to trigger new data load.
  onView(withId(R.id.input)).perform(
    replaceText(TEST_SUBREDDIT),
    pressKey(KeyEvent.KEYCODE_ENTER)
  );

  onView(withId(R.id.list)).check((view, noViewFoundException) -> {
    if (noViewFoundException != null) {
      throw noViewFoundException;
    }

    RecyclerView recyclerView = (RecyclerView) view;
    assertEquals(2, recyclerView.getAdapter().getItemCount());
  });
}

জাভা (গুয়াভা/লাইভডেটা)

@Test
public void loadsTheDefaultResults() {
  ActivityScenario.launch(RedditActivity.class);

  onView(withId(R.id.list)).check((view, noViewFoundException) -> {
    if (noViewFoundException != null) {
      throw noViewFoundException;
    }

    RecyclerView recyclerView = (RecyclerView) view;
    assertEquals(1, recyclerView.getAdapter().getItemCount());
  });
}

@Test
// Verify that the default data is swapped out when the user searches for a
// different subreddit.
public void loadsTheTestResultsWhenSearchingForSubreddit() {
  ActivityScenario.launch(RedditActivity.class);

  onView(withId(R.id.list)).check((view, noViewFoundException) -> {
    if (noViewFoundException != null) {
      throw noViewFoundException;
    }

    RecyclerView recyclerView = (RecyclerView) view;
    // Verify that it loads the default data first.
    assertEquals(1, recyclerView.getAdapter().getItemCount());
  });

  // Search for test subreddit instead of default to trigger new data load.
  onView(withId(R.id.input)).perform(
    replaceText(TEST_SUBREDDIT),
    pressKey(KeyEvent.KEYCODE_ENTER)
  );

  onView(withId(R.id.list)).check((view, noViewFoundException) -> {
    if (noViewFoundException != null) {
      throw noViewFoundException;
    }

    RecyclerView recyclerView = (RecyclerView) view;
    assertEquals(2, recyclerView.getAdapter().getItemCount());
  });
}

ইনস্ট্রুমেন্টেড টেস্টের মাধ্যমে যাচাই করা উচিত যে ডেটা UI-তে সঠিকভাবে প্রদর্শিত হচ্ছে কিনা। এটি করার জন্য, হয় RecyclerView.Adapter এ সঠিক সংখ্যক আইটেম আছে কিনা তা যাচাই করুন, অথবা প্রতিটি রো ভিউ-এর মধ্যে দিয়ে পুনরাবৃত্তি করে ডেটা সঠিকভাবে ফরম্যাট করা আছে কিনা তা যাচাই করুন।