পাঠ ৩১ · ৫৭-এর মধ্যে · মডিউল ৭
Home / Courses / Software Testing & Quality Assurance / টেস্ট অটোমেশন

একটি মেইনটেইনেবল অটোমেশন স্যুট তৈরি করা

Building a maintainable automation suite
৯ মিনিট পড়া মধ্যবর্তী · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • একটি মেইনটেইনেবল টেস্ট অটোমেশন স্যুটের চারটি মূলনীতি
  • কেন প্রতিটি নীতি লঙ্ঘন করলে দীর্ঘমেয়াদে ব্যয় বাড়ে
  • এই মডিউলের অন্যান্য পাঠের (পেজ অবজেক্ট, ফ্লেকি টেস্ট, ফিক্সচার) সাথে এই নীতিগুলোর সংযোগ
  • Python দিয়ে একটি ওয়েটেড-স্কোরিং চেকলিস্ট প্রয়োগ করে একটি স্যুটের "স্বাস্থ্য" পরিমাপ করা

১ · চারটি মূলনীতি

DRY (Don't Repeat Yourself)
একই সেটআপ কোড বারবার কপি-পেস্ট না করে fixtures (M3/L12) বা পেজ অবজেক্ট (M7/L29) দিয়ে একবার লেখা, বহুবার ব্যবহার করা।
স্পষ্ট নামকরণ
test1, test2-এর বদলে test_login_fails_with_wrong_password-এর মতো নাম — টেস্ট ফেইল করলে নাম দেখেই বোঝা যায় কী ভাঙল।
Sleep-ভিত্তিক ওয়েট এড়ানো
ফিক্সড sleep(5)-এর বদলে "শর্ত সত্যি হওয়া পর্যন্ত অপেক্ষা করো" ধরনের পোলিং — নাহলে টেস্ট অকারণে ধীর হয়, অথবা যথেষ্ট অপেক্ষা না করলে ফ্লেকি হয় (M7/L30)।
টেস্ট স্বাধীনতা
প্রতিটি টেস্ট যেকোনো অর্ডারে, একা বা একসাথে চালালেও একই ফলাফল দেওয়া উচিত — কোনো টেস্ট আরেকটির রেখে যাওয়া স্টেটের উপর নির্ভর করবে না (M3/L12, M7/L30)।
এই মডিউলের বাকি পাঠগুলোর সাথে সংযোগ

এই চারটি নীতি নতুন কিছু নয় — এগুলো এই মডিউলের আগের পাঠগুলোরই সাধারণীকরণ। পেজ অবজেক্ট প্যাটার্ন (M7/L29) DRY-এর একটি বিশেষ প্রয়োগ; ফ্লেকি টেস্টের অনেক কারণ (M7/L30) আসলে sleep-ভিত্তিক ওয়েট বা টেস্ট-স্বাধীনতা লঙ্ঘনের ফল। একটি মেইনটেইনেবল স্যুট মানে এই নীতিগুলো সচেতনভাবে, শুরু থেকেই মেনে চলা — পরে "ঠিক করব" ভেবে রেখে দেওয়া নয়।

২ · একটি "স্যুট হেলথ চেকলিস্ট" স্কোরার

চারটি মানদণ্ডে ০ (খুব খারাপ) থেকে ১ (খুব ভালো) স্কেলে রেটিং দিয়ে, প্রতিটির একটি ওজন (weight) সহ, একটি স্যুটের সামগ্রিক "স্বাস্থ্য স্কোর" গণনা করা যাক — একটি রিফ্যাক্টরের আগে ও পরে তুলনা করে।

Python
import math

# ওজন — যোগফল অবশ্যই ১.০ হতে হবে
WEIGHTS = {
    "independence":  0.30,  # টেস্টগুলো কি সত্যিই একে অপরের থেকে স্বাধীন?
    "naming_clarity": 0.15, # নামকরণ কি স্পষ্ট ও বর্ণনামূলক?
    "no_sleep_waits": 0.25, # ফিক্সড sleep()-এর বদলে শর্ত-ভিত্তিক ওয়েট ব্যবহৃত হয়েছে কি?
    "dry_setup":      0.30, # সেটআপ কোড fixtures/page object দিয়ে শেয়ার্ড, নাকি কপি-পেস্ট করা?
}
assert math.isclose(sum(WEIGHTS.values()), 1.0), "ওজনের যোগফল ১.০ হতে হবে"

def health_score(ratings, weights=WEIGHTS):
    return sum(weights[k] * ratings[k] for k in weights)

# রিফ্যাক্টরের আগে: শেয়ার্ড গ্লোবাল স্টেট, ভাগ নাম (test1, test2), হার্ডকোড sleep(5), কপি-পেস্ট সেটআপ
suite_before = {
    "independence":  0.20,
    "naming_clarity": 0.40,
    "no_sleep_waits": 0.10,
    "dry_setup":      0.30,
}

# রিফ্যাক্টরের পরে: fixtures/page object, বর্ণনামূলক নাম, পোলিং-ভিত্তিক ওয়েট, প্রতিটি টেস্ট স্বাধীন
suite_after = {
    "independence":  0.90,
    "naming_clarity": 0.85,
    "no_sleep_waits": 0.90,
    "dry_setup":      0.85,
}

before_score = health_score(suite_before)
after_score = health_score(suite_after)

print("স্যুট হেলথ চেকলিস্ট — মানদণ্ড অনুযায়ী রেটিং ও ওজন:\n")
for label, ratings, score in [("রিফ্যাক্টরের আগে", suite_before, before_score),
                                ("রিফ্যাক্টরের পরে", suite_after, after_score)]:
    print(f"{label}:")
    for k in WEIGHTS:
        print(f"  {k:16s} রেটিং={ratings[k]:.2f}  ওজন={WEIGHTS[k]:.2f}  →  অবদান={WEIGHTS[k]*ratings[k]:.4f}")
    print(f"  সামগ্রিক স্বাস্থ্য স্কোর = {score:.4f}\n")

improvement = after_score - before_score
print(f"রিফ্যাক্টরের ফলে স্বাস্থ্য স্কোর {before_score:.4f} থেকে {after_score:.4f}-এ উন্নীত হয়েছে "
      f"(+{improvement:.4f}, প্রায় {improvement/before_score*100:.0f}% বৃদ্ধি)।")

    
রিফ্যাক্টরের আগে সামগ্রিক স্বাস্থ্য স্কোর দাঁড়ায় ০.২৩৫ — মূলত no_sleep_waits (মাত্র ০.১০) ও independence (০.২০)-এর নিচু রেটিং টেনে নামায়। রিফ্যাক্টরের পরে স্কোর দাঁড়ায় ০.৮৭৭৫ — প্রায় ২৭৩% বৃদ্ধি, একই চারটি মানদণ্ড ও একই ওজন ব্যবহার করে। এই সংখ্যাটি কোনো জাদু নয় — এটি সরাসরি চারটি রেটিং ও তাদের ওজনের ওয়েটেড যোগফল, তাই কোথায় সবচেয়ে বেশি উন্নতি হয়েছে তা লাইন ধরে ধরে দেখা যায় (এই ক্ষেত্রে no_sleep_waits-এর অবদান ০.০২৫ থেকে ০.২২৫-এ বেড়েছে — সবচেয়ে বড় লাফ)।
মূল কথা · Key takeaway

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

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ "DRY" নীতি টেস্ট কোডেও প্রযোজ্য কেন, যেখানে কিছু মানুষ বলেন টেস্ট কোড কিছুটা পুনরাবৃত্তিমূলক হলেও পড়তে সহজ হয়?

দুটোই আংশিক সত্য — একটি টেস্টের assertion অংশ স্পষ্ট ও সরাসরি রাখা ভালো (পুনরাবৃত্তি হলেও), কিন্তু সেটআপ অংশ (যেমন একটি টেস্ট ইউজার তৈরি করা, বা একটি পেজ অবজেক্ট ইনিশিয়ালাইজ করা) কপি-পেস্ট করলে, সেই সেটআপ লজিক বদলাতে হলে প্রতিটি জায়গায় আলাদাভাবে বদলাতে হয় — ঠিক যেমন M7/L29-এ raw সিলেক্টর কপি-পেস্ট করার সমস্যা দেখা গেছে। তাই DRY মূলত সেটআপ/ইনফ্রাস্ট্রাকচার কোডের জন্য প্রযোজ্য, assertion-এর স্বচ্ছতার জন্য নয়।

প্র ০২ উপরের কোড সেলে no_sleep_waits-এর ওজন সবচেয়ে কম (০.২৫, চারটির মধ্যে দ্বিতীয়-সর্বনিম্ন) না হয়ে সবচেয়ে বেশি হলে চূড়ান্ত ফলাফলের উপর কী প্রভাব পড়ত?

যেহেতু "রিফ্যাক্টরের আগে" স্যুটে no_sleep_waits-এর রেটিং সবচেয়ে কম (০.১০), এই মানদণ্ডের ওজন বাড়ালে "আগে" স্কোর আরও কমে যেত (সমস্যাটি আরও প্রকট দেখাত), আর "পরে" স্কোর আরও বাড়ত (এই মানদণ্ডে রিফ্যাক্টরের উন্নতি সবচেয়ে বেশি, ০.১০ থেকে ০.৯০)। ফলে সামগ্রিক উন্নতির শতাংশও আরও বড় দেখাত — ওজন বদলালে সিদ্ধান্ত কোন সমস্যাকে সবচেয়ে জরুরি হিসেবে তুলে ধরছে তা বদলে যায়।

প্র ০৩ টেস্ট স্বাধীনতা (independence) কেন শুধু "ভালো অভ্যাস" নয়, বরং প্যারালাল টেস্ট এক্সিকিউশনের (একাধিক টেস্ট একসাথে চালানো, সময় বাঁচাতে) জন্য একটি প্রয়োজনীয়তা?

প্যারালাল এক্সিকিউশনে টেস্টগুলো একসাথে, অনির্দিষ্ট অর্ডারে চলে। যদি একটি টেস্ট আরেকটির রেখে যাওয়া স্টেটের উপর নির্ভর করে, প্যারালাল রানে সেই স্টেট হয়তো তখনও তৈরিই হয়নি, অথবা দুটো টেস্ট একই শেয়ার্ড রিসোর্স একসাথে বদলানোর চেষ্টা করতে পারে — উভয় ক্ষেত্রেই ফলাফল অনির্ভরযোগ্য (M7/L30-এর ফ্লেকিনেসের একটি সরাসরি কারণ)। সত্যিই স্বাধীন টেস্ট যেকোনো অর্ডারে, প্যারালালেও, নিরাপদে চলতে পারে।

অনুশীলন

  1. চিন্তা করুন: আপনার দেখা বা কল্পনা করা একটি টেস্ট স্যুটে উপরের চারটি নীতির মধ্যে কোনটি সবচেয়ে বেশি লঙ্ঘিত হতে পারে বলে মনে হয়, এবং কেন?

    বাস্তবে সবচেয়ে সাধারণ লঙ্ঘন সাধারণত no_sleep_waits ও independence — কারণ এই দুটো সমস্যা প্রাথমিকভাবে টেস্ট "পাস" করে বলে নজরে পড়ে না, শুধু CI-তে মাঝে মাঝে ব্যর্থ হওয়া শুরু করলে দল প্রথম বুঝতে পারে যে সমস্যাটি আসলে ছিল।

  2. পরীক্ষা করুন: উপরের কোড সেলে suite_after-এর independence রেটিং 0.90-এর বদলে 0.30 করে (যেন রিফ্যাক্টরের পরও টেস্ট স্বাধীনতা ঠিক না হয়) Run চেপে দেখুন সামগ্রিক স্কোরের উপর প্রভাব কতটা বড়।

    independence ০.৩০ করলে সেই মানদণ্ডের অবদান ০.৩০×০.৩০ = ০.০৯ হবে (আগে ছিল ০.৩০×০.৯০ = ০.২৭) — অর্থাৎ ০.১৮ কমবে, তাই নতুন সামগ্রিক স্কোর হবে ০.৮৭৭৫ − ০.১৮ = ০.৬৯৭৫। এটি দেখায় independence-এর ওজন (০.৩০, সবচেয়ে বেশিগুলোর একটি) কতটা গুরুত্বপূর্ণ — শুধু একটি মানদণ্ড ঠিক না থাকলেও সামগ্রিক স্কোরে বড় প্রভাব পড়ে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ টেস্ট ডিজাইন টেকনিক, ইউনিট টেস্টিং, টেস্ট ডাবলস, ইন্টিগ্রেশন টেস্টিং, কভারেজ, অটোমেশন, পারফরম্যান্স ও সিকিউরিটি টেস্টিং, অ্যাডভান্সড টেকনিক ও CI/CD ইন্টিগ্রেশন — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • Software Engineering Principles & Git কোর্স সহোদর কোর্স DRY-এর মতো সাধারণ সফটওয়্যার ইঞ্জিনিয়ারিং নীতিমালা সেই কোর্সেই তৈরি হয়েছে — এই কোর্স তা টেস্ট কোডে প্রয়োগ করে।
  • সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks, Mobile App Development, Ethics in Computing & AI Safety ও Software Testing & Quality Assurance — সব এক জায়গায়।
আগের পাঠ
ফ্লেকি টেস্ট — কারণ ও সমাধান