পাঠ ২০ · ৫৭-এর মধ্যে · মডিউল ৫
Home / Courses / Software Testing & Quality Assurance / কনট্র্যাক্ট টেস্টিং

সার্ভিসগুলোর মধ্যে কনট্র্যাক্ট টেস্টিং

Contract testing between services
৯ মিনিট পড়া মধ্যবর্তী · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

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

  • কনট্র্যাক্ট টেস্টিং কী এবং এটি সাধারণ ইন্টিগ্রেশন টেস্টিং থেকে কীভাবে আলাদা
  • Consumer ও Provider — এই দুই পক্ষ কীভাবে একই কনট্র্যাক্টের বিরুদ্ধে আলাদাভাবে টেস্ট করে
  • কেন এই পদ্ধতি দুটো সার্ভিস একসাথে চালানোর প্রয়োজনীয়তা এড়িয়ে যায়
  • একটি সত্যিকারের, চলমান কনট্র্যাক্ট-ভেরিফিকেশন ফাংশন লেখা ও পরীক্ষা করা

১ · কনট্র্যাক্ট মানে কী, এবং কেন এটি দরকার

কল্পনা করুন একটি Order Service (consumer) একটি User Service-কে (provider) কল করে ব্যবহারকারীর তথ্য জেনে নেয়। L19-এর ইন্টিগ্রেশন টেস্টিং দুটো সার্ভিসকে সত্যিই একসাথে চালিয়ে টেস্ট করত। কিন্তু বাস্তবে দুটো টিম আলাদাভাবে দুটো সার্ভিস ডেভেলপ করে — প্রতিবার Order Service টেস্ট করতে User Service-এর একটি লাইভ ইনস্ট্যান্স লাগলে টেস্টিং ধীর, ভঙ্গুর ও অন্য টিমের উপর নির্ভরশীল হয়ে যায়।

সমাধান: দুই পক্ষ একটি কনট্র্যাক্ট-এ সম্মত হয় — যেমন "User Service একটি ব্যবহারকারীর জন্য id (int), name (str), email (str), আর active (bool) ফিল্ডসহ একটি রেসপন্স দেবে।" এরপর:

Consumer (Order Service) Contract সম্মত ফিল্ড ও টাইপ Provider (User Service) দুটো পক্ষ কখনও একসাথে চালু থাকে না — প্রতিটি আলাদাভাবে এই কনট্র্যাক্টের বিরুদ্ধে যাচাই হয়
Consumer টেস্ট করে "কনট্র্যাক্ট অনুযায়ী রেসপন্স পেলে আমার কোড ঠিক কাজ করে কি না"; Provider টেস্ট করে "আমি সত্যিই কনট্র্যাক্ট অনুযায়ী রেসপন্স দিচ্ছি কি না" — দুটো একসাথে না চালিয়েই।
Full-Stack Web Frameworks কোর্সের সাথে সম্পর্ক

API ডিজাইন ও রিকোয়েস্ট/রেসপন্স শেপের ধারণা Full-Stack Web Frameworks কোর্সে সাধারণভাবে কভার করা হয়েছে — এই পাঠ ধরে নেয় আপনি জানেন একটি API রেসপন্স একটি নির্দিষ্ট শেপ (ফিল্ড ও টাইপ) অনুসরণ করে, এবং সেই শেপ টেস্টিং-এর দৃষ্টিকোণ থেকে কীভাবে যাচাই করা হয় তার উপর ফোকাস করে।

২ · একটি সত্যিকারের কনট্র্যাক্ট-ভেরিফিকেশন ফাংশন

নিচের কোড সেলে CONTRACT নামে একটি স্পেসিফিকেশন সংজ্ঞায়িত করা হয়েছে (ফিল্ডের নাম → প্রত্যাশিত টাইপ), দুটো সিমুলেটেড provider ফাংশন (একটি কনট্র্যাক্ট মেনে চলে, আরেকটি ভাঙে), এবং একটি verify_contract() ফাংশন যা সত্যিই প্রতিটি ফিল্ড উপস্থিত আছে কি না ও সঠিক টাইপের কি না যাচাই করে — কোনো fabricated ফলাফল নয়, প্রতিটি PASS/FAIL সত্যিকারের চেক থেকে আসছে।

Python
# দুই পক্ষের সম্মত কনট্র্যাক্ট: ফিল্ডের নাম -> প্রত্যাশিত টাইপ
CONTRACT = {
    "id": int,
    "name": str,
    "email": str,
    "active": bool,
}

def get_user_v1(user_id):
    # কনট্র্যাক্ট মেনে চলা provider — সব ফিল্ড সঠিক টাইপে আছে
    return {"id": user_id, "name": "Rahim", "email": "rahim@example.com", "active": True}

def get_user_v2_broken(user_id):
    # কনট্র্যাক্ট ভাঙা provider — 'active' অনুপস্থিত, আর 'id' int-এর বদলে str
    return {"id": str(user_id), "name": "Karim", "email": "karim@example.com"}

def verify_contract(contract, response):
    violations = []
    for field, expected_type in contract.items():
        if field not in response:
            violations.append(f"ফিল্ড অনুপস্থিত: '{field}'")
            continue
        if not isinstance(response[field], expected_type):
            actual_type = type(response[field]).__name__
            violations.append(
                f"'{field}' এর টাইপ ভুল — প্রত্যাশিত {expected_type.__name__}, পাওয়া গেছে {actual_type}"
            )
    is_valid = len(violations) == 0
    return is_valid, violations

scenarios = [
    ("conforming provider (v1)", get_user_v1(101)),
    ("non-conforming provider (v2, broken)", get_user_v2_broken(102)),
]

for label, response in scenarios:
    print(f"--- {label} ---")
    print("রেসপন্স:", response)
    ok, violations = verify_contract(CONTRACT, response)
    if ok:
        print("ফলাফল: PASS — কনট্র্যাক্ট পুরোপুরি মেনে চলা হয়েছে")
    else:
        print("ফলাফল: FAIL — কনট্র্যাক্ট লঙ্ঘন পাওয়া গেছে:")
        for v in violations:
            print("  -", v)
    print()

    
লক্ষ্য করুন get_user_v1 সব চেক পাস করে কারণ প্রতিটি ফিল্ড উপস্থিত এবং সঠিক টাইপে আছে। কিন্তু get_user_v2_broken-এ দুটো লঙ্ঘন ধরা পড়ে — একটি অনুপস্থিত active ফিল্ডের জন্য, আরেকটি id-এর টাইপ str হয়ে যাওয়ার জন্য (কনট্র্যাক্ট অনুযায়ী int হওয়ার কথা)। বাস্তবে এই ধরনের চেক Provider-এর নিজস্ব টেস্ট স্যুটে চলে — যাতে Provider টিম কোনো পরিবর্তন করলে সাথে সাথে বুঝতে পারে সেটি Consumer-এর প্রত্যাশা ভেঙে দিয়েছে কি না, Consumer-এর কোড না দেখেই।
মূল কথা · Key takeaway

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

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

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

প্র ০১ কনট্র্যাক্ট টেস্টিং কীভাবে L19-এর সাধারণ ইন্টিগ্রেশন টেস্টিং থেকে আলাদা?

L19-এর ইন্টিগ্রেশন টেস্টিং একাধিক মডিউল/সার্ভিসকে সত্যিই একসাথে চালিয়ে (বা স্টাব/ড্রাইভার দিয়ে ধাপে ধাপে জোড়া লাগিয়ে) টেস্ট করে। কনট্র্যাক্ট টেস্টিং এক ধাপ এগিয়ে — এটি দুটো সার্ভিসকে কখনোই একসাথে চালায় না, বরং প্রতিটি সার্ভিস স্বাধীনভাবে একটি লিখিত, শেয়ার্ড স্পেসিফিকেশনের (কনট্র্যাক্টের) বিরুদ্ধে নিজেকে যাচাই করে। এটি বিশেষভাবে কাজে লাগে যখন দুটো সার্ভিস আলাদা টিম, এমনকি আলাদা ডেপ্লয়মেন্ট সাইকেলে চলে।

প্র ০২ কোড সেলে verify_contract() কেন শুধু contract-এ উল্লেখিত ফিল্ডগুলো চেক করে, রেসপন্সে অতিরিক্ত কোনো ফিল্ড থাকলে সেটা নিয়ে অভিযোগ করে না?

বাস্তব কনট্র্যাক্ট টেস্টিং-এ সাধারণত এটাই সঠিক আচরণ — Consumer শুধু তার প্রয়োজনীয় ফিল্ডগুলোর ব্যাপারে চিন্তিত। Provider যদি ভবিষ্যতে নতুন অতিরিক্ত ফিল্ড যোগ করে (backward-compatible পরিবর্তন), সেটা Consumer-এর কাজ ভাঙার কথা না। যদি অতিরিক্ত ফিল্ড থাকা নিয়েও কড়াকড়ি (strict schema) দরকার হয়, তাহলে verify_contract()-এ একটি অতিরিক্ত চেক যোগ করা যেত যা response-এর কোনো কী contract-এ নেই কি না দেখে।

প্র ০৩ get_user_v2_broken-এর রেসপন্সে ঠিক কয়টি লঙ্ঘন ধরা পড়বে, এবং কী কী?

দুটো লঙ্ঘন ধরা পড়বে। প্রথমত, active ফিল্ডটি রেসপন্সে একেবারেই অনুপস্থিত, তাই "ফিল্ড অনুপস্থিত: 'active'" রিপোর্ট হবে। দ্বিতীয়ত, id ফিল্ড রেসপন্সে আছে কিন্তু str(user_id) হিসেবে (একটি স্ট্রিং), অথচ কনট্র্যাক্ট অনুযায়ী int হওয়ার কথা, তাই একটি টাইপ-মিসম্যাচ লঙ্ঘন রিপোর্ট হবে। name ও email উভয়ই সঠিক টাইপে উপস্থিত থাকায় তাদের নিয়ে কোনো অভিযোগ আসবে না।

অনুশীলন

  1. চিন্তা করুন: যদি CONTRACT-এ একটি নতুন ফিল্ড "created_at": str যোগ করা হয়, কিন্তু get_user_v1 ফাংশনটি আপডেট না করা হয়, তাহলে get_user_v1-এর যাচাইয়ের ফলাফল কী হবে বলে আপনার মনে হয়?

    যাচাই এখন FAIL করবে — কারণ get_user_v1-এর রেসপন্সে created_at ফিল্ড নেই, তাই verify_contract() "ফিল্ড অনুপস্থিত: 'created_at'" রিপোর্ট করবে। এটাই কনট্র্যাক্ট টেস্টিং-এর আসল উপকারিতা — কনট্র্যাক্ট পরিবর্তন হলে সাথে সাথে বোঝা যায় কোন provider implementation সেই পরিবর্তনের সাথে এখনও মিল রাখছে না, একই লাইভ সার্ভিস দুটো একসাথে না চালিয়েই।

  2. পরীক্ষা করুন: কোড সেলে একটি তৃতীয় সিমুলেটেড রেসপন্স যোগ করুন যেখানে active ফিল্ডের মান "yes" (একটি স্ট্রিং, বুলিয়ান নয়) — Run চেপে দেখুন verify_contract() এটাকে সঠিকভাবে একটি টাইপ-লঙ্ঘন হিসেবে ধরে কি না।

    হ্যাঁ — isinstance("yes", bool) মিথ্যা হওয়ায় verify_contract() একটি "'active' এর টাইপ ভুল — প্রত্যাশিত bool, পাওয়া গেছে str" লঙ্ঘন রিপোর্ট করবে, ঠিক অন্য টাইপ-মিসম্যাচ লঙ্ঘনের মতোই — কারণ ফাংশনটি প্রতিটি ফিল্ডের জন্য একই সাধারণ isinstance() চেক প্রয়োগ করে।

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

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ টেস্ট ডিজাইন টেকনিক, ইউনিট টেস্টিং, টেস্ট ডাবলস, ইন্টিগ্রেশন টেস্টিং, কভারেজ, অটোমেশন, পারফরম্যান্স ও সিকিউরিটি টেস্টিং, অ্যাডভান্সড টেকনিক ও CI/CD ইন্টিগ্রেশন — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • Full-Stack Web Frameworks কোর্স সহোদর কোর্স API ডিজাইন ও রিকোয়েস্ট/রেসপন্স শেপের ভিত্তি সেই কোর্সে কভার করা হয়েছে — এই পাঠ সেই শেপ টেস্টিং-এর দৃষ্টিকোণ থেকে যাচাই করার পদ্ধতি শেখায়।
  • সব 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 — সব এক জায়গায়।
আগের পাঠ
ইন্টিগ্রেশন টেস্টিং স্ট্র্যাটেজি