কন্ডিশন ও ডিসিশন কভারেজ
এই পাঠে যা শিখবেন
- ডিসিশন কভারেজ ও কন্ডিশন কভারেজের সঠিক সংজ্ঞা
- কম্পাউন্ড বুলিয়ান কন্ডিশনে এই দুটো মেট্রিক কেন ও কীভাবে আলাদা হতে পারে
- একটি নির্দিষ্ট টেস্ট সেটের জন্য উভয় কভারেজ সত্যিকারভাবে গণনা করা
- একটি দুর্বল টেস্ট সেট চিহ্নিত করে সেটিকে আরও ভালো করার উপায়
১ · দুটো ভিন্ন প্রশ্ন, একই if লাইনে
একটি সাধারণ শর্ত যেমন if is_logged_in:-এ ডিসিশন কভারেজ আর কন্ডিশন কভারেজ একই জিনিস — এখানে
মাত্র একটিই বুলিয়ান ভ্যারিয়েবল, আর তার সামগ্রিক সিদ্ধান্তও সেই একটি ভ্যারিয়েবলের উপরই নির্ভর করে। কিন্তু
যখন একাধিক শর্ত and/or দিয়ে জোড়া লাগানো হয় — যেমন
if is_logged_in and is_admin: — তখন দুটো ভিন্ন প্রশ্ন উঠে আসে:
পুরো
is_logged_in and is_admin এক্সপ্রেশনটির সামগ্রিক ফলাফল কি True ও False দুটোই হয়েছে?is_logged_in কি আলাদাভাবে True/False দুটোই হয়েছে? is_admin কি আলাদাভাবে True/False দুটোই হয়েছে?
দুটি বুলিয়ান ইনপুট (a, b) থাকলে মোট $2^2 = 4$টি সম্ভাব্য কম্বিনেশন থাকে:
(True, True), (True, False), (False, True), (False, False)।
একটি টেস্ট সেট এই ৪টির মধ্যে কতগুলো আসলে চালায় তার উপর ভিত্তি করেই ডিসিশন ও কন্ডিশন কভারেজ আলাদা হতে পারে —
নিচের কোড সেলে এটি সরাসরি গণনা করে দেখানো হয়েছে।
def can_access(is_logged_in, is_admin):
if is_logged_in and is_admin:
return "granted"
return "denied"
all_combinations = [(True, True), (True, False), (False, True), (False, False)]
# ইচ্ছাকৃতভাবে বাছাই করা একটি টেস্ট সেট -- দুটোই is_logged_in=True দিয়ে, শুধু is_admin আলাদা
test_set = [(True, True), (True, False)]
print("টেস্ট সেট চালানো হচ্ছে:")
for a, b in test_set:
print(f" can_access({a}, {b}) -> {can_access(a, b)}")
# --- ডিসিশন কভারেজ: সামগ্রিক ফলাফল (granted/denied) কি True ও False দুটোই হয়েছে? ---
decisions_seen = {can_access(a, b) == "granted" for a, b in test_set}
decision_coverage = len(decisions_seen) / 2 * 100
# --- কন্ডিশন কভারেজ: a এবং b প্রতিটি আলাদাভাবে True ও False দুটোই হয়েছে কি না ---
a_values_seen = {a for a, b in test_set}
b_values_seen = {b for a, b in test_set}
condition_slots_covered = len(a_values_seen) + len(b_values_seen) # সর্বোচ্চ সম্ভব 2 + 2 = 4
condition_coverage = condition_slots_covered / 4 * 100
untested_combinations = [c for c in all_combinations if c not in test_set]
print(f"\nমোট সম্ভাব্য কম্বিনেশন: {all_combinations}")
print(f"টেস্ট সেটে বাদ পড়া কম্বিনেশন: {untested_combinations}")
print(f"a (is_logged_in)-এর দেখা ভ্যালু: {sorted(a_values_seen)}")
print(f"b (is_admin)-এর দেখা ভ্যালু: {sorted(b_values_seen)}")
print(f"সামগ্রিক সিদ্ধান্তে দেখা ফলাফল (True=granted, False=denied): {decisions_seen}")
print(f"\nডিসিশন কভারেজ: {decision_coverage:.0f}%")
print(f"কন্ডিশন কভারেজ: {condition_coverage:.0f}%")
test_set-এর দুটো কলেই is_logged_in=True — অর্থাৎ a কখনো
False হয়নি। কিন্তু is_admin (b) একবার True, একবার False হয়েছে বলে
সামগ্রিক সিদ্ধান্তও একবার granted (True) আর একবার denied (False) হয়ে গেছে — তাই ডিসিশন কভারেজ
১০০%। অথচ a-এর ভ্যালু-স্পেসের অর্ধেক (শুধু True, কখনো False নয়) এবং b-এর
দুটোই কভার হওয়ায় মোট ৪টি স্লটের ৩টি কভার হয়েছে — কন্ডিশন কভারেজ মাত্র ৭৫%। এই টেস্ট সেট
কখনো যাচাই করেনি is_logged_in=False হলে কী হয় (এমনকি is_admin=True হলেও) — একটি
বাস্তব বাগের জায়গা লুকিয়ে থাকতে পারে।
২ · টেস্ট সেট উন্নত করা
নিচের কোড সেলে all_combinations-এর বাদ পড়া (False, True) কম্বিনেশনটি যোগ করে
দেখা যাক দুটো কভারেজ সংখ্যাই কীভাবে বদলায় — এবং তার বিপরীত পরিস্থিতিও দেখা যাক: এমন একটি টেস্ট সেট যেখানে
কন্ডিশন কভারেজ ১০০% হলেও ডিসিশন কভারেজ কম থেকে যায়, প্রমাণ করে এই দুটো মেট্রিক সত্যিই স্বতন্ত্র।
# (এই সেলটি আগের সেলে ডিফাইন করা can_access() পুনরায় ব্যবহার করছে)
def coverage_report(name, calls):
decisions_seen = {can_access(a, b) == "granted" for a, b in calls}
decision_cov = len(decisions_seen) / 2 * 100
a_seen = {a for a, b in calls}
b_seen = {b for a, b in calls}
condition_cov = (len(a_seen) + len(b_seen)) / 4 * 100
print(f"{name}: {calls}")
print(f" ডিসিশন কভারেজ: {decision_cov:.0f}% কন্ডিশন কভারেজ: {condition_cov:.0f}%\n")
# সব ৪টি কম্বিনেশন -- দুটো মেট্রিকই সর্বোচ্চ হওয়া উচিত
coverage_report("সব ৪টি কম্বিনেশন", [(True, True), (True, False), (False, True), (False, False)])
# উন্নত সেট -- আগের সেটে বাদ পড়া (False, True) যোগ করা হলো
coverage_report("উন্নত সেট (৩টি কম্বিনেশন)", [(True, True), (True, False), (False, True)])
# বিপরীত কেস -- a এবং b দুটোই আলাদাভাবে True/False দেখেছে (কন্ডিশন কভারেজ ১০০%),
# কিন্তু সামগ্রিক সিদ্ধান্ত সবসময় "denied"-ই থেকেছে (ডিসিশন কভারেজ কম)
coverage_report("বিপরীত কেস: শুধু (True, False) ও (False, True)", [(True, False), (False, True)])
a একবার True একবার False, b-ও একবার True একবার False — তাই
কন্ডিশন কভারেজ ১০০%। কিন্তু (True, False) ও (False, True) — দুটোতেই
can_access() "denied" রিটার্ন করে (যেহেতু and-এর জন্য দুটোই True হতে হয়) —
সামগ্রিক সিদ্ধান্ত কখনো granted (True) হয়নি, তাই ডিসিশন কভারেজ মাত্র ৫০%। এটিই প্রমাণ করে — কন্ডিশন কভারেজ
বেশি থাকলেই ডিসিশন কভারেজও বেশি থাকবে এমন কোনো গ্যারান্টি নেই, উল্টোটাও সত্যি — দুটো সত্যিকারের স্বতন্ত্র
মেট্রিক।
একক শর্তে ডিসিশন ও কন্ডিশন কভারেজ এক হলেও, কম্পাউন্ড বুলিয়ান কন্ডিশনে (and/or)
এই দুটো স্বতন্ত্র মেট্রিক — একটি শুধু সামগ্রিক ফলাফলের দিকে তাকায়, অন্যটি প্রতিটি উপাদান শর্তের দিকে
আলাদাভাবে। শুধু ডিসিশন কভারেজ ১০০% দেখেই সন্তুষ্ট হওয়া বিপজ্জনক হতে পারে — L23-এর ব্রাঞ্চ কভারেজের মতোই,
এটিও একটি সুনির্দিষ্ট সীমাবদ্ধতা যা L26-এ কভারেজের বৃহত্তর সীমাবদ্ধতার আলোচনার সাথে যুক্ত হবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
একক শর্ত (যেমন if is_admin:) থাকলে ডিসিশন কভারেজ আর কন্ডিশন কভারেজ কেন সবসময় একই
সংখ্যা হবে?
কারণ একক শর্তে সিদ্ধান্তের ভেতরে মাত্র একটিই বুলিয়ান "উপাদান" আছে (নিজেই), তাই সামগ্রিক সিদ্ধান্তের
ফলাফল (ডিসিশন) সরাসরি সেই একক ভ্যারিয়েবলের ভ্যালুর (কন্ডিশন) সমান — এদের আলাদা হওয়ার কোনো সুযোগ নেই।
দুটো ভিন্ন হওয়ার সুযোগ তৈরি হয় শুধু তখনই যখন একাধিক সাব-কন্ডিশন and/or দিয়ে
মিলিয়ে একটি সামগ্রিক সিদ্ধান্ত তৈরি হয়।
প্র ০২
প্রথম কোড সেলের test_set-এ যদি তৃতীয় একটি কল (False, False) যোগ করা হয়,
তাহলে ডিসিশন ও কন্ডিশন কভারেজের সংখ্যা কী হবে বলে আপনার মনে হয়?
ডিসিশন কভারেজ আগের মতোই ১০০% থাকবে (ইতিমধ্যে True ও False দুটোই দেখা গেছে, নতুন কলটিও denied অর্থাৎ
False-ই দেয়)। কিন্তু কন্ডিশন কভারেজ বেড়ে ১০০%-এ পৌঁছাবে — কারণ এখন a (is_logged_in)
False মানও অন্তত একবার নিয়েছে, ফলে চারটি স্লটের (a=True, a=False, b=True, b=False)
সবগুলোই কভার হয়ে যাবে। এটিই দেখায় কীভাবে একটি ছোট, লক্ষ্যভেদী টেস্ট কেস যোগ করে দুর্বল কন্ডিশন কভারেজ
ঠিক করা যায়।
প্র ০৩ দ্বিতীয় কোড সেলের "বিপরীত কেস"-এ ডিসিশন কভারেজ মাত্র ৫০% হওয়া কেন বাস্তব ঝুঁকির লক্ষণ?
কারণ can_access()-এর "granted" (অ্যাক্সেস দেওয়া) পথটি এই টেস্ট সেটে কখনোই এক্সিকিউট হয়নি —
এমনকি যদি সেই পথে (উদাহরণস্বরূপ) একটি ভুল থাকে যা ভুলভাবে ভুল ব্যবহারকারীকে অ্যাক্সেস দিয়ে দেয়, এই টেস্ট
সেট তা কখনো ধরতে পারবে না। প্রতিটি কম্পাউন্ড অ্যাক্সেস-কন্ট্রোল শর্তে "গ্রান্টেড" পথটি অন্তত একবার
সত্যিই টেস্ট করা বিশেষভাবে গুরুত্বপূর্ণ — এটি ঠিক সেই পথ যা নিরাপত্তার দৃষ্টিকোণ থেকে সবচেয়ে বেশি
গুরুত্বপূর্ণ (M9-এ অথেন্টিকেশন/অথোরাইজেশন টেস্টিং নিয়ে আরও বিস্তারিত থাকবে)।
অনুশীলন
-
চিন্তা করুন:
if a or b:-এর জন্য একটি টেস্ট সেট ডিজাইন করুন যার ডিসিশন কভারেজ ১০০% কিন্তু কন্ডিশন কভারেজ ৫০%-এর কম। কোন দুটি কম্বিনেশন বেছে নেবেন?(True, True)এবং(False, False)বেছে নিলে: সিদ্ধান্ত একবার True (দুটোই True-তেorTrue) আর একবার False (দুটোই False-এorFalse) — ডিসিশন কভারেজ ১০০%। কিন্তুa-এর দেখা ভ্যালু {True, False} (দুটোই) এবংb-এরও {True, False} (দুটোই) — আসলে এই কম্বিনেশনে কন্ডিশন কভারেজও ১০০% হয়ে যায়, তাই এই জোড়াটি কাজ করবে না। বরং(True, True)ও(True, False)বেছে নিলে: ডিসিশন উভয়ক্ষেত্রে True (যেহেতুor-এ যেকোনো একটি True হলেই যথেষ্ট), তাই ডিসিশন কভারেজ মাত্র ৫০% (False কখনো হয়নি) — এটি বরং বিপরীত উদাহরণ দেখায়। মূল কথা হলো: এই দুই মেট্রিকের মধ্যে কোনটি বেশি/কম হবে তা নির্ভর করে অপারেটর (andনাকিor) ও ঠিক কোন কম্বিনেশনগুলো বেছে নেওয়া হয়েছে তার উপর — তাই বাস্তবে সবসময় সরাসরি গণনা করে দেখাই নির্ভরযোগ্য উপায়, শুধু অনুমান নয়। -
পরীক্ষা করুন: প্রথম কোড সেলে
can_access-এরand-কেor-এ পরিবর্তন করে (এবংtest_setঅপরিবর্তিত রেখে) Run চাপুন। ডিসিশন ও কন্ডিশন কভারেজের সংখ্যা কি বদলায়?কন্ডিশন কভারেজ অপরিবর্তিত থাকবে (৭৫%) — কারণ সেটি শুধু
aওb-এর দেখা ভ্যালুর উপর নির্ভর করে, অপারেটরের উপর নয়। কিন্তু ডিসিশন কভারেজ বদলে যেতে পারে, কারণ(True, True)-তেor-ও True দেয় (আগের মতোই), আর(True, False)-তেorএখনও True দেয় (and-এ যা False দিত) — অর্থাৎ এই নির্দিষ্টtest_set-এ উভয় কলই এখন "granted" দেবে, ফলে সিদ্ধান্তের False দিক আর কখনো দেখা যাবে না — ডিসিশন কভারেজ কমে ৫০%-এ নেমে যাবে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ টেস্ট ডিজাইন টেকনিক, ইউনিট টেস্টিং, টেস্ট ডাবলস, ইন্টিগ্রেশন টেস্টিং, কভারেজ, অটোমেশন, পারফরম্যান্স ও সিকিউরিটি টেস্টিং, অ্যাডভান্সড টেকনিক ও CI/CD ইন্টিগ্রেশন — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
- ডিসিশন টেবিল টেস্টিং L07 একাধিক বুলিয়ান শর্তের কম্বিনেশন থেকে টেস্ট কেস ডিজাইন করার টেকনিক — আজকের কন্ডিশন/ডিসিশন কভারেজ ধারণার সরাসরি পূর্বসূরি।
- সব 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 — সব এক জায়গায়।