আমার উপহাস এবং জাল জিনিসগুলির প্রাথমিক ধারণা আছে তবে আমি কখন / কোথায় উপহাস ব্যবহার করব সে সম্পর্কে আমার একটা অনুভূতি আছে তা নিশ্চিত নই - বিশেষত এটি এখানে এই দৃশ্যের ক্ষেত্রে প্রযোজ্য ।
আমার উপহাস এবং জাল জিনিসগুলির প্রাথমিক ধারণা আছে তবে আমি কখন / কোথায় উপহাস ব্যবহার করব সে সম্পর্কে আমার একটা অনুভূতি আছে তা নিশ্চিত নই - বিশেষত এটি এখানে এই দৃশ্যের ক্ষেত্রে প্রযোজ্য ।
উত্তর:
ইউনিট পরীক্ষার জন্য একটি পদ্ধতিতে একটি কোডপথ পরীক্ষা করা উচিত। যখন কোনও পদ্ধতির এক্সিকিউশনটি সেই পদ্ধতির বাইরে, অন্য কোনও অবজেক্টে চলে যায় এবং আবার ফিরে আসে তখন আপনার নির্ভরতা থাকে।
যখন আপনি সেই কোড পাথটিকে প্রকৃত নির্ভরতার সাথে পরীক্ষা করেন, আপনি ইউনিট পরীক্ষা করছেন না; আপনি ইন্টিগ্রেশন পরীক্ষা। যদিও এটি ভাল এবং প্রয়োজনীয়, এটি ইউনিট পরীক্ষার নয়।
যদি আপনার নির্ভরতা বগি হয় তবে আপনার পরীক্ষাটি কোনও মিথ্যা ইতিবাচক প্রত্যাবর্তনের জন্য এমনভাবে প্রভাবিত হতে পারে। উদাহরণস্বরূপ, আপনি নির্ভরতাটি একটি অপ্রত্যাশিত শূন্যতা অতিক্রম করতে পারেন, এবং নির্ভরতাটি নথিতে লিপিবদ্ধ থাকায় শূন্যতা ফেলতে পারে না। আপনার পরীক্ষাটি নাল আর্গুমেন্টের মতো হওয়া উচিত নয় যেমনটি হওয়া উচিত এবং পরীক্ষাটি পাস হয়।
এছাড়াও, আপনি পরীক্ষার সময় আপনি যা চান ঠিক তেমন নির্ভরযোগ্য নির্ভরযোগ্য জিনিসটি প্রত্যাবর্তনযোগ্যভাবে নির্ভরযোগ্যভাবে পাওয়া, এটি অসম্ভব না হলেও অসম্ভব বলে মনে করতে পারেন hard এর মধ্যে পরীক্ষার মধ্যে প্রত্যাশিত ব্যতিক্রম ছুঁড়ে ফেলাও অন্তর্ভুক্ত।
একটি উপহাস সেই নির্ভরতা প্রতিস্থাপন করে। আপনি নির্ভরশীল অবজেক্টের কলগুলিতে প্রত্যাশাগুলি সেট করেছেন, আপনি যে পরীক্ষাটি চান তা সম্পাদনের জন্য আপনাকে দেওয়া উচিত সঠিক রিটার্ন মানগুলি এবং / অথবা কোন ব্যতিক্রম নিক্ষেপ করতে হবে যাতে আপনি আপনার ব্যতিক্রম হ্যান্ডলিং কোডটি পরীক্ষা করতে পারেন set এইভাবে আপনি সহজেই প্রশ্নে ইউনিটটি পরীক্ষা করতে পারেন।
টিএল; ডিআর: আপনার ইউনিট পরীক্ষার প্রত্যেকটি নির্ভরতাকে মক করুন।
মক অবজেক্টগুলি দরকারী যখন আপনি পরীক্ষার অধীনে কোনও শ্রেণি এবং একটি নির্দিষ্ট ইন্টারফেসের মধ্যে ইন্টারঅ্যাকশন পরীক্ষা করতে চান ।
উদাহরণস্বরূপ, আমরা পরীক্ষা করতে চান যে পদ্ধতি sendInvitations(MailServer mailServer)
কল MailServer.createMessage()
ঠিক একবার, এবং এছাড়াও কল MailServer.sendMessage(m)
ঠিক একবার এবং অন্য কোনো পদ্ধতি উপর বলা হয় MailServer
ইন্টারফেস। এটি তখনই যখন আমরা মক অবজেক্টগুলি ব্যবহার করতে পারি।
মক অবজেক্টস সহ, একটি বাস্তব MailServerImpl
বা পরীক্ষা পাস করার পরিবর্তে TestMailServer
, আমরা MailServer
ইন্টারফেসের একটি মক প্রয়োগটি পাস করতে পারি । আমরা কোনও উপহাস পাস করার আগে MailServer
, আমরা এটিকে "প্রশিক্ষণ" দিই, যাতে এটি জানে যে কোন পদ্ধতিটি প্রত্যাশার জন্য কল করে এবং কোনটি ফিরে আসার মান দেয়। শেষে, মক অবজেক্ট দৃser়ভাবে জানায় যে সমস্ত প্রত্যাশিত পদ্ধতিগুলি প্রত্যাশিত হিসাবে ডাকা হত।
এটি তাত্ত্বিকভাবে ভাল শোনাচ্ছে তবে কিছু ডাউনসাইডও রয়েছে।
যদি আপনার জায়গায় মক কাঠামো থাকে তবে পরীক্ষার অধীনে ক্লাসে ইন্টারফেসটি পাস করার সময় প্রতিবার আপনি মক অবজেক্টটি ব্যবহার করতে প্ররোচিত হন । এটি যখন প্রয়োজন হয় না তখনও আপনি মিথস্ক্রিয়াগুলি পরীক্ষা করে দেখেন । দুর্ভাগ্যক্রমে, মিথস্ক্রিয়াগুলির অবাঞ্ছিত (দুর্ঘটনাজনিত) পরীক্ষা করা খারাপ, কারণ তারপরে আপনি পরীক্ষা করছেন যে কোনও নির্দিষ্ট প্রয়োজনীয়তা একটি বিশেষ উপায়ে প্রয়োগ করা হয়েছে, তার পরিবর্তে বাস্তবায়ন প্রয়োজনীয় ফলাফল তৈরি করেছে।
সিউডোকোডের একটি উদাহরণ এখানে। ধরা যাক আমরা একটি MySorter
ক্লাস তৈরি করেছি এবং আমরা এটি পরীক্ষা করতে চাই:
// the correct way of testing
testSort() {
testList = [1, 7, 3, 8, 2]
MySorter.sort(testList)
assert testList equals [1, 2, 3, 7, 8]
}
// incorrect, testing implementation
testSort() {
testList = [1, 7, 3, 8, 2]
MySorter.sort(testList)
assert that compare(1, 2) was called once
assert that compare(1, 3) was not called
assert that compare(2, 3) was called once
....
}
(এই উদাহরণে আমরা ধরে নিই যে এটি কোনও নির্দিষ্ট বাছাইকরণ অ্যালগরিদম নয়, যেমন দ্রুত সাজানোর, যা আমরা পরীক্ষা করতে চাই; সেক্ষেত্রে, পরবর্তী পরীক্ষাটি আসলে বৈধ হবে would)
এইরকম চরম উদাহরণে পরবর্তী কারণটি কেন ভুল তা স্পষ্ট। যখন আমরা এর বাস্তবায়ন পরিবর্তন করি MySorter
, প্রথম পরীক্ষাটি নিশ্চিত করে তোলে আমরা এখনও সঠিকভাবে বাছাই করার একটি দুর্দান্ত কাজ করে যা পরীক্ষার পুরো বিষয়টি - তারা আমাদের নিরাপদে কোড পরিবর্তন করতে দেয়। অন্যদিকে, পরবর্তী পরীক্ষাটি সর্বদা বিরতি হয় এবং এটি সক্রিয়ভাবে ক্ষতিকারক; এটি রিফ্যাক্টরিংয়ে বাধা দেয়।
মক ফ্রেমওয়ার্কগুলি প্রায়শই কম কড়া ব্যবহারেরও অনুমতি দেয়, যেখানে আমাদের ঠিক কতবার পদ্ধতিগুলি কল করা উচিত এবং কোন পরামিতিগুলি প্রত্যাশিত তা নির্দিষ্ট করতে হবে না; তারা স্টক হিসাবে ব্যবহৃত মক অবজেক্ট তৈরি করার অনুমতি দেয় ।
ধরা যাক আমাদের একটি পদ্ধতি আছে sendInvitations(PdfFormatter pdfFormatter, MailServer mailServer)
যা আমরা পরীক্ষা করতে চাই। PdfFormatter
বস্তুর আমন্ত্রণ তৈরি করতে ব্যবহার করা যেতে পারে। পরীক্ষাটি এখানে:
testInvitations() {
// train as stub
pdfFormatter = create mock of PdfFormatter
let pdfFormatter.getCanvasWidth() returns 100
let pdfFormatter.getCanvasHeight() returns 300
let pdfFormatter.addText(x, y, text) returns true
let pdfFormatter.drawLine(line) does nothing
// train as mock
mailServer = create mock of MailServer
expect mailServer.sendMail() called exactly once
// do the test
sendInvitations(pdfFormatter, mailServer)
assert that all pdfFormatter expectations are met
assert that all mailServer expectations are met
}
এই উদাহরণস্বরূপ, আমরা PdfFormatter
বস্তুর সত্যই যত্ন নিই না তাই আমরা কেবল এটিকে কোনও কল গ্রহণ sendInvitation()
করতে এবং এই মুহুর্তে কল হতে পারে এমন সমস্ত পদ্ধতির জন্য কিছু বুদ্ধিমান ক্যানড ফেরতের মানগুলি ফিরিয়ে আনতে প্রশিক্ষণ দিচ্ছি । প্রশিক্ষণের জন্য পদ্ধতিগুলির সঠিক তালিকাটি কীভাবে আমরা সামনে এলাম? আমরা কেবল পরীক্ষাটি চালিয়েছি এবং পরীক্ষাটি পাস না হওয়া পর্যন্ত পদ্ধতিগুলি যুক্ত করতে থাকি। লক্ষ্য করুন, আমরা স্টাবকে কোনও পদ্ধতির প্রতিক্রিয়া জানাতে প্রশিক্ষণ দিয়েছিলাম কারণ এটির জন্য কেন এটি কল করা প্রয়োজন, আমরা পরীক্ষার বিষয়ে যা অভিযোগ করেছিল তার সবই আমরা যুক্ত করে দিয়েছি। আমরা খুশি, পরীক্ষা পাস।
তবে পরে কী ঘটে, যখন আমরা পরিবর্তন করি sendInvitations()
বা আরও কিছু ক্লাসিক sendInvitations()
ব্যবহার করি যা আরও অভিনব পিডিএফ তৈরি করতে পারে? আমাদের পরীক্ষা হঠাৎ করে ব্যর্থ হয় কারণ এখন আরও বেশি পদ্ধতি PdfFormatter
বলা হয় এবং আমরা আমাদের স্টাবকে সেগুলি প্রত্যাশা করতে প্রশিক্ষণ দিই না। এবং সাধারণত এটি কেবল একটি পরীক্ষা যা এই জাতীয় পরিস্থিতিতে ব্যর্থ হয় না, এটি কোনও পরীক্ষা যা প্রত্যক্ষ বা অপ্রত্যক্ষভাবে sendInvitations()
পদ্ধতিটি ব্যবহার করে ঘটে । আরও প্রশিক্ষণ যুক্ত করে আমাদের সে সমস্ত পরীক্ষাগুলি ঠিক করতে হবে। এছাড়াও লক্ষ করুন, আমরা যে পদ্ধতিগুলির আর প্রয়োজন নেই তা মুছে ফেলতে পারি না, কারণ আমরা জানি না যেগুলির মধ্যে কোনটির প্রয়োজন নেই। আবার এটি রিফ্যাক্টরিংয়ে বাধা দেয়।
এছাড়াও, পরীক্ষার পঠনযোগ্যতা ভয়াবহভাবে ভোগ করেছে, সেখানে প্রচুর কোড রয়েছে যা আমরা চেয়েছিলাম বলে লিখেনি, তবে আমাদের ছিল কারণ; এটি আমাদের নয় যারা সেখানে কোডটি চান। মক অবজেক্ট ব্যবহার করা টেস্টগুলি খুব জটিল দেখায় এবং প্রায়শই পড়া শক্ত হয়। পরীক্ষাগুলি পাঠককে বুঝতে সাহায্য করবে, পরীক্ষার অধীন শ্রেণিটি কীভাবে ব্যবহার করা উচিত, সুতরাং এগুলি সহজ এবং সহজবোধ্য হওয়া উচিত। সেগুলি পাঠযোগ্য না হলে কেউ এগুলি রক্ষণাবেক্ষণ করছে না; আসলে এগুলি বজায় রাখার চেয়ে এগুলি মুছে ফেলা সহজ।
কীভাবে ঠিক করব? সহজেই:
PdfFormatterImpl
। যদি এটি সম্ভব না হয় তবে এটি সম্ভব করার জন্য আসল শ্রেণী পরিবর্তন করুন। পরীক্ষায় ক্লাস ব্যবহার করতে সক্ষম না হওয়া সাধারণত শ্রেণীর কিছু সমস্যা চিহ্নিত করে। সমস্যাগুলি স্থির করা একটি জয়-পরিস্থিতি - আপনি ক্লাসটি ঠিক করেছেন এবং আপনার একটি সহজ পরীক্ষা আছে। অন্যদিকে, এটি সংশোধন না করা এবং মকগুলি ব্যবহার করা কোন জয়যুক্ত পরিস্থিতি নয় - আপনি আসল শ্রেণিটি ঠিক করেন নি এবং আপনার আরও জটিল, কম পাঠযোগ্য টেস্ট রয়েছে যা আরও রিফ্যাক্টরিংগুলিকে বাধা দেয়।TestPdfFormatter
কিছুই না যে তৈরি করুন । এইভাবে আপনি সমস্ত পরীক্ষার জন্য একবার এটি পরিবর্তন করতে পারেন এবং যেখানে আপনি আপনার স্টাবগুলি প্রশিক্ষণ দেন সেখানে আপনার পরীক্ষাগুলি দীর্ঘ সেটআপগুলির সাথে বিশৃঙ্খলাযুক্ত নয়।সব মিলিয়ে মক অবজেক্টগুলির ব্যবহার রয়েছে তবে সাবধানতার সাথে ব্যবহার না করা হলে তারা প্রায়শই খারাপ অভ্যাসগুলিকে উত্সাহ দেয়, বাস্তবায়নের বিশদ পরীক্ষা করে, রিফ্যাক্টরিংয়ে বাধা দেয় এবং পড়তে অসুবিধা হয় এবং পরীক্ষা বজায় রাখা কঠিন ।
বিদ্রূপের ত্রুটি সম্পর্কিত আরও কিছু তথ্যের জন্য মক অবজেক্টস: স্বল্পতা এবং ব্যবহারের কেসগুলিও দেখুন ।
চলতি নিয়ম:
আপনি যে ফাংশনটি পরীক্ষা করছেন সেটি যদি প্যারামিটার হিসাবে একটি জটিল অবজেক্টের প্রয়োজন হয় এবং এই বিষয়টিকে কেবল তাত্পর্যপূর্ণ করে তোলা ব্যথা হবে (যদি উদাহরণস্বরূপ এটি টিসিপি সংযোগ স্থাপনের চেষ্টা করে), একটি মোক ব্যবহার করুন।
কোডের একটি ইউনিটে আপনার নির্ভরতা থাকলে আপনি পরীক্ষা করার চেষ্টা করছেন যা "ঠিক তাই" হওয়া দরকার আপনার যখন কোনও বিষয়কে বিদ্রূপ করা উচিত।
উদাহরণস্বরূপ, আপনি যখন নিজের কোডের ইউনিটটিতে কিছু যুক্তি পরীক্ষা করার চেষ্টা করছেন তবে আপনাকে অন্য কোনও বস্তুর কাছ থেকে কিছু পাওয়া দরকার এবং এই নির্ভরতা থেকে যা ফিরে আসে তা আপনি যা পরীক্ষা করার চেষ্টা করছেন তা প্রভাবিত করতে পারে - সেই বস্তুকে বিদ্রূপ করুন।