পূর্ববর্তী একটি নিবন্ধে, আমি বর্ণনা করেছি কিভাবে আপনি আপনার অ্যাপ্লিকেশনে প্রোটো ডেটাস্টোর ব্যবহার করতে পারেন। আমি আমার একটি অ্যাপ্লিকেশনে প্রোটো ডেটাস্টোর ব্যবহার করার অভিজ্ঞতার অংশ হিসাবে সেই নিবন্ধটি লিখেছিলাম৷
৷এর পরে, আমি দেখতে চেয়েছিলাম যে আমার অর্জিত জ্ঞান ব্যবহার করে সেই অ্যাপ্লিকেশনটিতে প্রোটো ডেটাস্টোরের জন্য পরীক্ষা লিখতে কেমন হবে।
গাইডেন্সের জন্য অনলাইনে অনুসন্ধান করা খুব বেশি স্বস্তি দেয়নি, তাই আমি ভেবেছিলাম যে যারা এটি খুঁজছেন তাদের জন্য আমি আমার জ্ঞান ভাগ করব। সবচেয়ে খারাপ ক্ষেত্রে, এটা আমার বংশধরদের জন্য হবে।
আমার অনুসন্ধানে, আমি এই নিবন্ধটি খুঁজে পেয়েছি, কিন্তু এটি বেশিরভাগই পছন্দের ডেটাস্টোর পরীক্ষা করার উপর ফোকাস করে এবং প্রোটো ডেটাস্টোর নয়। এটা বলে যে:
"তবে, মনে রাখবেন আপনি প্রোটো ডেটাস্টোর সেট আপ করার জন্য এই উপাদানটি ব্যবহার করতে পারেন টেস্টিং, কারণ এটি পছন্দের সাথে খুব মিল হবে।"
কিন্তু এটি অনুসরণ করার পরে, আমি খুঁজে পেয়েছি যে নির্ভরতা ছাড়াও, এখানে খুব বেশি মিল নেই এবং আপনার নিজের প্রোটো ডেটাস্টোর পরীক্ষা করার জন্য আপনাকে আলাদা যুক্তি প্রবর্তন করতে হবে।
জিনিস সেট আপ করা
আপনার অ্যাপ্লিকেশনের build.gradle ফাইলে, নিম্নলিখিত নির্ভরতা যোগ করুন:
dependencies {
///.....
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
}
$compose_version আপনি আপনার প্রকল্প স্তর build.gradle ফাইলে সংজ্ঞায়িত পরিবর্তনশীল।
তারপর, আপনার androidTest এ যান ডিরেক্টরি এবং একটি নতুন ফাইল তৈরি করুন। সাধারণত, আপনার কাছে একটি রিপোজিটরি ক্লাস থাকবে যা আপনার প্রোটো ডেটাস্টোরের সাথে ইন্টারঅ্যাক্ট করে, তাই আপনি এই ফাইলটিকে YourRepositoryClassNameTest হিসাবে নাম দিতে পারেন। আমরা MyRepositoryTest নামটি ব্যবহার করব .
আমরা প্রোটো ডেটাস্টোর নিজেই পরীক্ষা করার আগে, আমাদের এটিকে ইনস্ট্যান্টিয়েট করতে হবে। আপনি যদি এই বিষয়ে কোনো ডকুমেন্টেশন খুঁজতে অনলাইনে যান, তবে এটি এক ধরনের বিরল।
একটি প্রোটো ডেটাস্টোরকে ইনস্ট্যান্টিয়েটিং করা বিশ্বব্যাপী প্রেক্ষাপটের সাথে ব্যবহার করা হয় (যখন একটি পরীক্ষার দৃশ্যে ব্যবহার করা হয় না):
private val Context.myDataStore: DataStore<MyItem> by dataStore(
fileName = DATA_STORE_FILE_NAME,
serializer = MyItemSerializer
)
ঠিক আছে, আপনি একটি পরীক্ষার ক্লাসের ভিতরে এটি করতে পারবেন না, কারণ, আপনি উপরের কোডটি কপি-পেস্ট করতে পারলে, আপনি সক্ষম হবেন না অ্যাক্সেস ডেটাস্টোর অবজেক্ট। আপনি এই মত অ্যাপ্লিকেশন প্রসঙ্গ পেতে পারেন:
ApplicationProvider.getApplicationContext()
কিন্তু আমাদের myDataStore এর মাধ্যমে বস্তু পাওয়া যাবে না।
তাহলে, আমরা কি করতে পারি?
উপরে লিঙ্ক করা নিবন্ধে, আমরা কীভাবে PreferenceDataStoreFactory.create পদ্ধতি ব্যবহার করে একটি পছন্দ ডেটাস্টোর তৈরি করতে পারি তার একটি উদাহরণ রয়েছে৷
fun create(
corruptionHandler: ReplaceFileCorruptionHandler<Preferences>? = null,
migrations: List<DataMigration<Preferences>> = listOf(),
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
produceFile: () -> File): DataStore<Preferences>
কিন্তু যেহেতু আমরা একটি পছন্দ ডেটাস্টোর ব্যবহার করছি না, তাই এটি আমাদের জন্য কাজ করবে না। DataStoreFactory.create পদ্ধতি ব্যবহার করে কি কাজ করবে:
fun <T : Any?> create(
serializer: Serializer<T>,
corruptionHandler: ReplaceFileCorruptionHandler<T>? = null,
migrations: List<DataMigration<T>> = listOf(),
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()), produceFile: () -> File): DataStore<T>
এই পদ্ধতির জন্য বেশ কয়েকটি আর্গুমেন্ট রয়েছে (এবং কিছুর ডিফল্ট মান রয়েছে), কিন্তু আমাদের সেগুলিকে পাস করার দরকার নেই। আমরা পাস করব:
- আমাদের সিরিয়ালাইজার ক্লাস
- আমাদের প্রোটো ডেটাস্টোরের জন্য ফাইল তৈরি করার জন্য একটি ল্যাম্বডা পদ্ধতি
dataStore = DataStoreFactory.create(
produceFile = {
testContext.dataStoreFile(TEST_DATA_STORE_FILE_NAME) },
serializer = MyItemSerializer
)
আমরা testContext পাই দ্বারা:
private val testContext: Context = ApplicationProvider.getApplicationContext()
আমাদের প্রোটো ডেটাস্টোর সফলভাবে তৈরি করার পরে, আমরা এটির জন্য কিছু পরীক্ষা লিখতে যেতে পারি। মনে রাখবেন যে আপনার কাছে একটি রিপোজিটরি ক্লাস রয়েছে যা নির্ভরতা হিসাবে প্রোটো ডেটাস্টোরের উদাহরণ গ্রহণ করে, তাই প্রোটো ডেটাস্টোর তৈরি করার পরে, আমাদের সংগ্রহস্থল ক্লাসের একটি উদাহরণ তৈরি করতে হবে৷
private val repository = MyRepository(datastore)
প্রথমে, আসুন আমাদের প্রাথমিক প্রোটো ডেটাস্টোর অবস্থা পরীক্ষা করার জন্য একটি পরীক্ষা তৈরি করি। প্রোটো ডেটাস্টোর নিজেই একটি প্রবাহ প্রকাশ করে যা আমরা ব্যবহার করতে পারি।
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun repository_testFetchInitialState() {
runTest {
testScope.launch {
val dataStoreObject = repository.myFlow.first()
// Insert here whatever we want to assert from our
// Proto DataStore. I.E. a flag whose initial value is false
assert(dataStoreObject.myFlag == false)
}
}
}
☝️ আপনি হয়তো এটি আগে লক্ষ্য করেছেন, কিন্তু আমরা একটি অপ্টইন টীকা ব্যবহার করছি এখানে এর কারণ (বর্তমানে) আমরা যে APIগুলি ব্যবহার করছি তা পরীক্ষামূলক এবং সেগুলি ব্যবহার করার সময় অবশ্যই চিহ্নিত করা উচিত৷
যেহেতু আমরা আমাদের DataStore এর প্রবাহ অ্যাক্সেস করছি , আমাদের এটিকে আমাদের testScope এ মোড়ানো দরকার . TestScope দ্বারা তৈরি করা হয়:
@OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = TestCoroutineDispatcher()
@OptIn(ExperimentalCoroutinesApi::class)
private val testScope = TestCoroutineScope(dispatcher)
এটি চালান এবং আপনার প্রথম প্রোটো ডেটাস্টোর পরীক্ষা উপভোগ করুন৷
৷এটি প্রায় দুই সেকেন্ডের জন্য মজার ছিল।
আসুন আরো অর্থপূর্ণ কিছু করি।
কল্পনা করুন যে আমাদের প্রোটো ডেটাস্টোরের ভিতরে বস্তুর একটি তালিকা রয়েছে এবং আমরা যখন এটিতে একটি আইটেম যোগ করি তখন আমরা এটির অবস্থা পরীক্ষা করতে চাই৷
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun repository_testAdditionOfItem() {
runTest {
testScope.launch {
//1
val item: MyItem = MyItem.newBuilder().setItemId(UUID.randomUUID().toString())
.setItemDescription(TEST_ITEM_DESCRIPTION).build()
//2
repository.updateItem(item)
//3
val items = repository.myFlow.first().itemsList
assert(items.size == 1)
//4
assert(items[0].itemDescription.equals(TEST_ITEM_DESCRIPTION))
}
}
}
- আমরা প্রোটোবাফ থেকে উন্মুক্ত API ব্যবহার করে একটি পরীক্ষা আইটেম তৈরি করি
- আমরা এই আইটেমটিকে প্রোটো ডেটাস্টোরে যুক্ত করি একটি পদ্ধতি ব্যবহার করে যা আমরা MyRepository ক্লাসে প্রকাশ করেছি
- প্রোটো ডেটাস্টোর যে প্রবাহ প্রকাশ করে তা থেকে আমরা আইটেমগুলির তালিকা ধরি
- আমরা নিশ্চিত করি যে প্রোটো ডেটাস্টোরে পাওয়া আইটেমটি আমাদের আগে তৈরি করা আইটেমের সাথে মেলে
আপনার ডেটাস্টোরে একটি লিক আছে
আপনি যদি উপরের পরীক্ষাগুলি একবারে চালানোর চেষ্টা করেন, আপনি শীঘ্রই রানটাইমের সময় একটি ত্রুটি পাবেন:
একই ফাইলের জন্য একাধিক ডেটাস্টোর সক্রিয় রয়েছে:/data/user/0/com.example.app/files/datastore/dataStore_filename.pb। আপনার হয় আপনার ডেটাস্টোরকে সিঙ্গলটন হিসাবে বজায় রাখা উচিত বা নিশ্চিত করা উচিত যে একই ফাইলে দুটি ডেটাস্টোর সক্রিয় নেই (স্কোপটি বাতিল করা হয়েছে তা নিশ্চিত করে)।
ওয়েল, যে সমস্যাযুক্ত. আমরা আমাদের পরীক্ষার ক্লাসে শুধুমাত্র একটি ডেটাস্টোর উদাহরণ তৈরি করেছি৷
৷এখানে কি হচ্ছে?
যেহেতু আমরা আমাদের DataStore (অর্থাৎ Context.datastore) তৈরি করার জন্য প্রপার্টি প্রতিনিধি ব্যবহার করছি না, এটা নিশ্চিত করা হয় না যে যখনই আমরা এটি অ্যাক্সেস করি তখন আমাদের DataStore অবজেক্টটি সিঙ্গলটন হয়।
এই দৃশ্যটি এড়াতে, আমি খুঁজে পেয়েছি যে একটি পদ্ধতি হল প্রতিটি পরীক্ষার ক্ষেত্রে ডেটাস্টোর মুছে ফেলা এবং পুনরায় তৈরি করা। ডেটাস্টোর মুছে ফেলার জন্য, আমরা এটি করতে পারি:
@After
fun cleanup() {
File(testContext.filesDir, "datastore").deleteRecursively()
}
এবং প্রতিটি পরীক্ষার আগে, আমরা এটি পুনরায় তৈরি করি:
@Before
fun setup() {
dataStore = DataStoreFactory.create(
produceFile = {
testContext.dataStoreFile(TEST_DATA_STORE_FILE_NAME)
},
serializer = MyItemSerializer
)
}
একটি সম্পূর্ণ উদাহরণ দেখতে, আপনি এখানে যেতে পারেন।
এই নিবন্ধে, আমি কীভাবে একটি প্রোটো ডেটাস্টোর পরীক্ষা করা যায় তার রূপরেখা দেখাতে চেয়েছিলাম।
আপনার ডেটাস্টোর এবং আপনি সেখানে যে ধরনের কনফিগার করেছেন তার উপর নির্ভর করে আমি দুটি পরীক্ষার ক্ষেত্রে গিয়েছিলাম, লেখার জন্য আরও পরীক্ষার কেস এবং পরিস্থিতি থাকতে পারে। বিল্ডিং ব্লক আছে, আপনাকে শুধু আপনার প্রয়োজনের সাথে খাপ খাইয়ে নিতে হবে।
বিনামূল্যে কোড শিখুন. freeCodeCamp-এর ওপেন সোর্স পাঠ্যক্রম 40,000-এরও বেশি লোককে ডেভেলপার হিসেবে চাকরি পেতে সাহায্য করেছে। শুরু করুন