- দ্বিতীয় অংশ থেকে আমরা দেখেছি যে, ম্যারিওনেট ক্লাইন্ট কমান্ড ব্যবহার করে খুব সহজেই ফায়ারফক্স OS নিয়ন্ত্রণ করতে পারি, কিন্তু পাইথন কনসোলে তা টাইপ করা অত্যন্ত ধৈর্য সাপেক্ষ ব্যাপার। টেস্ট অটোমেশনের প্রধান সুবিধা হল এটি নিজে থেকে রান হতে পারে। এই অংশে আমরা শিখব তা কীভাবে করতে হয়, আমরা আমাদের সব কোড কমান্ড একটি পাইথন ফাইলে রাখি যাতে সবগুলো একবারেই রান হয়ে যায়।
টেস্ট কেস পুনরায় আলোচনা
দ্বিতীয় অংশে আমরা একটি আদর্শ টেস্ট রান করার ধাপগুলো দেখেছি — কন্ট্যাক্ট অ্যাপ ওপেন করা এবং নতুন কোন কন্ট্যাক্ট অ্যাড করাঃ
- ফায়ারফক্স OS আনলক করা (ঐচ্ছিক; দ্বিতীয় অংশে, আমরা লক স্ক্রিন নিষ্ক্রিয় করে দিয়েছিলাম, সেজন্য আমরা সেটি এই অংশের কোডে উল্লেখ করব না।)
- কন্ট্যাক্ট অ্যাপে সুইচ করা
- নতুন কন্ট্যাক্ট আইকন ট্যাপ অ্যাড করা
- কন্ট্যাক্ট তালিকায় টাইপ করা
- done ট্যাপকরা
- অপেক্ষা করা এবং নিরীক্ষণ করা কন্ট্যাক্ট প্রস্তুত কিনা
আমাদের টেস্ট পাইথন ফাইলে রাখা
আমরা যদি এই সমস্ত ধাপগুলো একটি পাইথন ফাইলে রাখি, তবে আমরা তা পুনরায় ব্যবহার করতে পারব এবং অনেক দ্রুত রান করাতে পারব। আপনার পছন্দ মত কোন
convenient directory তে test_add_contact.py নামে
একটি নতুন টেক্সট ফাইল তৈরি করুন।
এই ফাইলে, নিচের লিস্ট অনুসারে, দ্বিতীয় অংশে দেখানো কমান্ডগুলো প্রবেশ করান। আমরা পাইথন পর্যায়ের স্ট্রাকচার ব্যবহার করব, কারণ এটি ভাল চর্চা এবং এই টিউটোরিয়ালে পরবর্তীতে স্টেপে বিল্ড অনের জন্য ভাল ভিত্তি তৈরি করে।
import time from marionette import Marionette class TestContacts: def __init__(self): self.test_add_contacts() def test_add_contacts(self): # Create the client for this session. Assuming you're using the default port on a Marionette instance running locally self.marionette = Marionette() self.marionette.start_session() # Switch context to the homescreen iframe and tap on the contacts icon time.sleep(2) home_frame = self.marionette.find_element('css selector', 'div.homescreen iframe') self.marionette.switch_to_frame(home_frame) contacts_icon = self.marionette.find_element('css selector', "#footer li[aria-label='Contacts']") contacts_icon.tap() # Switch context back to the base frame self.marionette.switch_to_frame() time.sleep(2) # Switch context to the contacts app contacts_frame = self.marionette.find_element('css selector', "iframe[data-url*='contacts']") self.marionette.switch_to_frame(contacts_frame) # Tap [+] to add a new Contact self.marionette.find_element('id', 'add-contact-button').tap() time.sleep(2) # Type name into the fields self.marionette.find_element('id', 'givenName').send_keys('John') self.marionette.find_element('id', 'familyName').send_keys('Doe') # Tap done self.marionette.find_element('id', 'save-button').tap() time.sleep(2) # Close the Marionette session now that the test is finished self.marionette.delete_session() if __name__ == '__main__': TestContacts()
নোটঃএকটি ব্যাপার আপনি খেয়াল করে থাকবেন যেটি আমরা দ্বিতীয় অংশে করি নাই তা হল পাইথন time.sleep()ফাংশন
— এটি একটি নির্দিষ্ট সমযের জন্য স্ক্রিপ্টটি মন্থর করে দেয় (defined in seconds) পরবর্তী লাইনে অগ্রসর হওয়ার আগে। আমরা অটোমেটেড টেস্টে এই লাইনগুলো যুক্ত করেছি কারণ আমাদের ব্যবহারকারীকে বাটন ট্যাপ করা এবং আরও আঞ্জাঞ্জ ব্যাপারে ব্যাপারে সিমুলেট করা দরকার এবং ফায়ারফক্স OS এর resulting কাজ সম্পন্ন হওয়ার জন্য। আমরা যদি কোন দেরি না করেই এই স্ক্রিপ্টটি রান করে করাতাম তবে পাইথন তাৎক্ষণিকভাবে সবকিছু করে ফেলত এবং খুব সম্ভবত সেটি টেস্ট ফেল করার কারণ হত কারণ ফায়ারফক্স OS সেটি করতে সমর্থ নয়।
এখন আপনি ডিরেক্টরিতে নেভিগেট করে টেস্ট রান করতে পারেন। টেস্টটি আপনার টার্মিনালে সেভ হয়ে আছে এবং নিচের কমান্ডটি রান করছেঃ
python test_add_contact.py
নোটঃ পাইথন ইনডেন্টেশন রুল এর ব্যাপারে সতর্ক হন। কপি এবং পেস্ট করার পর কোড সঠিকভাবে রান করানোর জন্য আপনার সবকিছু সঠিকভাবে ইনডেন্ট করার প্রয়োজন হতে পারে। আপনি যদি এই সংক্রান্ত কোন ত্রুটি পেয়ে থাকেন তবে খেয়াল করে দেখুন সব ইনডেন্টেশন লেভেল ভিন্ন ভিন্ন ট্যাবে পৃথকীকৃত কিনা।
নোটঃ আপনি আরো খেয়াল করে থাকবেন যে, উপরের কোড ব্যবহার করে যে নাম যুক্ত করা হয়েছে তা হল "John Doe", দ্বিতীয় অংশে ব্যবহৃত নাম "Foo Bar" এর থেকে আলাদা। এটি করার কারণ হল কোড যাতে করে সফলভাবে রান করানো যায় এবং অন্য কন্ট্যাক্ট যুক্ত করা যায়। আপনি যদি একই নাম ব্যবহার করে অন্য একটি কন্ট্যাক্ট যুক্ত করতে চেষ্টা করেন তবে ফায়ারফক্স OS আপনাকে অনুরূপ কন্ট্যাক্টের ব্যাপারে সতর্ক করে দিবে। এক্ষেত্রে সব থেকে ভাল উপায় হল, ফায়ারফক্স OS ইন্টারফেসে টেস্টটি পুনরায় রান করানো এবং প্রতিবার রান করানোর পূর্বে আগেরটি মুছে ফেলা।
অ্যাসারশন যুক্ত করা
যে জিনিসটি আবারো আমরা আমাদের টেস্ট থেকে মিস করছি, যা অটোমেটেড টেস্টের জন্য যেটি দরকারি, তা হল অ্যাসারশন — ফায়ারফক্স OS কে আমরা যে পর্যায়ে নিয়ে যেতে চাচ্ছি, সেটি সফল ছিল কিনা তা পরিমাপের একটি তথ্য এটি। কিছু কোড যুক্ত করে আমরা দেখব নতুন কন্ট্যাক্টটি যুক্ত হয়েছে কিনা।
# Close the Marionette session...
লাইনের ঠিক আগে, এই কোডটি যুক্ত করুন, তবে তার আগে এটি নিশ্চিত করুন সেটি ওই ক্লাসের অন্য লাইনের সাথে একই লেভেলে ইনডেন্ট হয়েছে কিনাঃ
# Now let's find the contact item and get its text contact_name = self.marionette.find_element('css selector', 'li.contact-item:not([data-group$="ice"]) p').text assert contact_name == 'John Doe'
পুরানো কন্ট্যাক্টটি মুছে ফেলুন এবং নিচেরটিসহ টেস্টটি পুনরায় রান করানোর চেষ্টা করুনঃ
python test_add_contact.py
যদি এগুলো সব থিক্তহাক মত রান করে তাহলে ভাল, এখন আমাদের জন্য আছে ফাংশন টেস্ট!
নোটঃ অ্যাসারশনকে সাথে সাথেই ঠিকভাবে কাজ করতে দেখা যাবে না, কিন্তু টেস্ট রানার শুরু করার জন্য অ্যাসারশন খুবই গুরুত্বপূর্ণ যেমনটি বলা হয়েছে পঞ্চম অংশঃ টেস্ট রানারের সাথে পরিচিত হওয়া। ইউনিটেস্ট এর মত টেস্ট রানার অ্যাসারশন ব্যবহার করে দেখে টেস্ট সফলভাবে শেষ হয়েছে কিনা অতপর এই টেস্টের ফলাফল দিন (OK অথবা FAIL)
সময়ের উপর একটি নোট
অটোমেটেড টেস্ট রান করানোর সময় যে কাজটি বেশ কষ্টসাধ্য তা হল সময় নির্ধারণ। টেস্টটি যদি ফায়ারফক্স OS এর একটি টেস্ট সম্পন্ন হবার আগেই পরবর্তী ধাপে অগ্রসর হয় তবে খুব সম্ভবত আমরা ভুল পথে আগাচ্ছি।
উপরে যেমনটি বলা হয়েছে, নমুনা কোডে আমরা এই সমস্যার সমাধানে time.sleep(x)
কমান্ডটি যুক্ত করেছি। যাই হোক time.sleep(x)
ব্যবহার করা খুব ভাল কথা না। হার্ডকোডেড সেট টাইম ব্যবহার করার ফলে এম্নটি হতে পারে আপনার টেস্ট যথেষ্ট সময় ধরে রান করছে না অথবা অনেক বেশি সময় ধরে রান করছে। সব থেকে খারাপ ব্যাপারটি হল latter; এটি ফলস নেগেটিভ কেস রেসাল্ট দেখাবে — যার মানে হল অ্যাপ যথার্থভাবে কার্যকর হলেও আশানুরূপ গতিতে কাজ না করে কিছুটা ধীরে কাজ করার পরিবর্তে সেটি টেস্ট ব্যর্থতা ফল দেখাবে।
পরবর্তী অংশে, আমরা আলাদা আলাদা পাইথন ফাংশনে টেস্টের বিশেষ কিছু অংশের উপর অগ্রসর হব এবং sleep()
ফাংশনের পরিবর্তে উপযুক্ত ডাইনামিক ওয়েটস দিয়ে।