আমি কখন উপহাস করব?


137

আমার উপহাস এবং জাল জিনিসগুলির প্রাথমিক ধারণা আছে তবে আমি কখন / কোথায় উপহাস ব্যবহার করব সে সম্পর্কে আমার একটা অনুভূতি আছে তা নিশ্চিত নই - বিশেষত এটি এখানে এই দৃশ্যের ক্ষেত্রে প্রযোজ্য ।


আমি কেবলমাত্র প্রক্রিয়া বহির্ভূত নির্ভরতা এবং কেবলমাত্র সেগুলির সাথেই বিদ্রূপ করার পরামর্শ দিচ্ছি, যার সাথে ইন্টারঅ্যাকশনগুলি বাহ্যিকভাবে পর্যবেক্ষণযোগ্য (এসএমটিপি সার্ভার, বার্তা বাস ইত্যাদি)। ডাটাবেসটিকে উপহাস করবেন না, এটি বাস্তবায়নের বিশদ। এটি সম্পর্কে আরও এখানে: enterprisecraftsmanship.com/posts/when-to-mock
ভ্লাদিমির

উত্তর:


121

ইউনিট পরীক্ষার জন্য একটি পদ্ধতিতে একটি কোডপথ পরীক্ষা করা উচিত। যখন কোনও পদ্ধতির এক্সিকিউশনটি সেই পদ্ধতির বাইরে, অন্য কোনও অবজেক্টে চলে যায় এবং আবার ফিরে আসে তখন আপনার নির্ভরতা থাকে।

যখন আপনি সেই কোড পাথটিকে প্রকৃত নির্ভরতার সাথে পরীক্ষা করেন, আপনি ইউনিট পরীক্ষা করছেন না; আপনি ইন্টিগ্রেশন পরীক্ষা। যদিও এটি ভাল এবং প্রয়োজনীয়, এটি ইউনিট পরীক্ষার নয়।

যদি আপনার নির্ভরতা বগি হয় তবে আপনার পরীক্ষাটি কোনও মিথ্যা ইতিবাচক প্রত্যাবর্তনের জন্য এমনভাবে প্রভাবিত হতে পারে। উদাহরণস্বরূপ, আপনি নির্ভরতাটি একটি অপ্রত্যাশিত শূন্যতা অতিক্রম করতে পারেন, এবং নির্ভরতাটি নথিতে লিপিবদ্ধ থাকায় শূন্যতা ফেলতে পারে না। আপনার পরীক্ষাটি নাল আর্গুমেন্টের মতো হওয়া উচিত নয় যেমনটি হওয়া উচিত এবং পরীক্ষাটি পাস হয়।

এছাড়াও, আপনি পরীক্ষার সময় আপনি যা চান ঠিক তেমন নির্ভরযোগ্য নির্ভরযোগ্য জিনিসটি প্রত্যাবর্তনযোগ্যভাবে নির্ভরযোগ্যভাবে পাওয়া, এটি অসম্ভব না হলেও অসম্ভব বলে মনে করতে পারেন hard এর মধ্যে পরীক্ষার মধ্যে প্রত্যাশিত ব্যতিক্রম ছুঁড়ে ফেলাও অন্তর্ভুক্ত।

একটি উপহাস সেই নির্ভরতা প্রতিস্থাপন করে। আপনি নির্ভরশীল অবজেক্টের কলগুলিতে প্রত্যাশাগুলি সেট করেছেন, আপনি যে পরীক্ষাটি চান তা সম্পাদনের জন্য আপনাকে দেওয়া উচিত সঠিক রিটার্ন মানগুলি এবং / অথবা কোন ব্যতিক্রম নিক্ষেপ করতে হবে যাতে আপনি আপনার ব্যতিক্রম হ্যান্ডলিং কোডটি পরীক্ষা করতে পারেন set এইভাবে আপনি সহজেই প্রশ্নে ইউনিটটি পরীক্ষা করতে পারেন।

টিএল; ডিআর: আপনার ইউনিট পরীক্ষার প্রত্যেকটি নির্ভরতাকে মক করুন।


164
এই উত্তরটি খুব মৌলিক। ইউনিট টেস্টগুলি একক পদ্ধতির চেয়ে বেশি অনুশীলন করতে পারে এবং হওয়া উচিত, যতক্ষণ না এটি সমস্ত একই মিশ্রণ ইউনিটের অন্তর্গত। অন্যথায় এটি করার জন্য অনেক বেশি বিদ্রূপ করা / জাল করা দরকার যা জটিল এবং ভঙ্গুর পরীক্ষার দিকে পরিচালিত করে। পরীক্ষার অধীনে কেবলমাত্র নির্ভরশীলতাগুলি ইউনিটের সাথে সম্পর্কিত নয়, তাদের উপহাসের মাধ্যমে প্রতিস্থাপন করা উচিত।
রোজারিও

10
এই উত্তরটিও খুব আশাবাদী। এটি যদি @ জ্যানের মক অবজেক্টের কমতিগুলি অন্তর্ভুক্ত করে থাকে তবে ভাল হবে।
জেফ অ্যাক্সেল্রড

1
এটি বিশেষত উপহাসের চেয়ে পরীক্ষার জন্য নির্ভরতা ইনজেকশনের পক্ষে যুক্তিযুক্ত আরও কি নয়? আপনার উত্তরে আপনি "মক" কে "স্টাব" দিয়ে প্রতিস্থাপন করতে পারেন। আমি সম্মত হই যে আপনার হয় হয় তাৎপর্যপূর্ণ নির্ভরতা নির্ভর করে বা ঠাট্টা করা উচিত। আমি প্রচুর পরিশ্রমী-ভারী কোড দেখেছি যা মূলত উপহাসকৃত বস্তুর অংশগুলি পুনরায় সংশোধন করে; বিদ্রূপগুলি অবশ্যই রূপোর বুলেট নয়।
ড্রাগন

2
আপনার ইউনিট পরীক্ষা স্পর্শ প্রতিটি নির্ভরতা মক। এটি সবকিছু ব্যাখ্যা করে।
তেওমন শিপাহি

2
টিএল; ডিআর: আপনার ইউনিট পরীক্ষার প্রত্যেকটি নির্ভরতাকে মক করুন। - এটি সত্যই দুর্দান্ত উপায় নয়, মকিতো নিজেই বলেছে - সবকিছুকে উপহাস করবেন না। (ডাউনভোটেড)
পি_চ্যাম্প

167

মক অবজেক্টগুলি দরকারী যখন আপনি পরীক্ষার অধীনে কোনও শ্রেণি এবং একটি নির্দিষ্ট ইন্টারফেসের মধ্যে ইন্টারঅ্যাকশন পরীক্ষা করতে চান ।

উদাহরণস্বরূপ, আমরা পরীক্ষা করতে চান যে পদ্ধতি 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কিছুই না যে তৈরি করুন । এইভাবে আপনি সমস্ত পরীক্ষার জন্য একবার এটি পরিবর্তন করতে পারেন এবং যেখানে আপনি আপনার স্টাবগুলি প্রশিক্ষণ দেন সেখানে আপনার পরীক্ষাগুলি দীর্ঘ সেটআপগুলির সাথে বিশৃঙ্খলাযুক্ত নয়।

সব মিলিয়ে মক অবজেক্টগুলির ব্যবহার রয়েছে তবে সাবধানতার সাথে ব্যবহার না করা হলে তারা প্রায়শই খারাপ অভ্যাসগুলিকে উত্সাহ দেয়, বাস্তবায়নের বিশদ পরীক্ষা করে, রিফ্যাক্টরিংয়ে বাধা দেয় এবং পড়তে অসুবিধা হয় এবং পরীক্ষা বজায় রাখা কঠিন

বিদ্রূপের ত্রুটি সম্পর্কিত আরও কিছু তথ্যের জন্য মক অবজেক্টস: স্বল্পতা এবং ব্যবহারের কেসগুলিও দেখুন


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

1
একটি বিদ্রূপের পুরো বিষয়টি নয় যে আপনার পরীক্ষাগুলি সামঞ্জস্যপূর্ণ, আপনি যে পরীক্ষাগুলি চালানোর সময় প্রতিটি প্রোগ্রামার দ্বারা নিয়মিতভাবে নিয়মিতভাবে পরিবর্তন হয় এবং এমন অবিচ্ছিন্ন পরীক্ষার ফলাফল পেয়ে থাকেন এমন বস্তুগুলি নিয়ে আপনাকে বিদ্রূপ করার চিন্তা করতে হবে না?
PositiveGuy

1
খুব ভাল এবং প্রাসঙ্গিক পয়েন্ট (বিশেষত টেস্ট ভঙ্গুরতা সম্পর্কে)। আমি যখন ছোট ছিলাম তখন আমি প্রচুর পরিমাণে মোক ব্যবহার করতাম, তবে এখন আমি ইউনিট পরীক্ষা বিবেচনা করি যে ভারী হিমাবলগুলি সম্ভাব্য ডিসপোজেবল হিসাবে মকের উপর নির্ভর করে এবং ইন্টিগ্রেশন টেস্টিংয়ে আরও বেশি মনোনিবেশ করে (প্রকৃত উপাদানগুলির সাথে)
কেমোডা

6
"পরীক্ষায় ক্লাস ব্যবহার করতে সক্ষম না হওয়া সাধারণত শ্রেণীর কিছু সমস্যা দেখায়।" ক্লাসটি যদি কোনও পরিষেবা হয় (যেমন ওয়েব ডাটাবেসে ডেটাবেস বা প্রক্সি অ্যাক্সেস), তবে এটি একটি বাহ্যিক
নির্ভরতা

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

55

চলতি নিয়ম:

আপনি যে ফাংশনটি পরীক্ষা করছেন সেটি যদি প্যারামিটার হিসাবে একটি জটিল অবজেক্টের প্রয়োজন হয় এবং এই বিষয়টিকে কেবল তাত্পর্যপূর্ণ করে তোলা ব্যথা হবে (যদি উদাহরণস্বরূপ এটি টিসিপি সংযোগ স্থাপনের চেষ্টা করে), একটি মোক ব্যবহার করুন।


4

কোডের একটি ইউনিটে আপনার নির্ভরতা থাকলে আপনি পরীক্ষা করার চেষ্টা করছেন যা "ঠিক তাই" হওয়া দরকার আপনার যখন কোনও বিষয়কে বিদ্রূপ করা উচিত।

উদাহরণস্বরূপ, আপনি যখন নিজের কোডের ইউনিটটিতে কিছু যুক্তি পরীক্ষা করার চেষ্টা করছেন তবে আপনাকে অন্য কোনও বস্তুর কাছ থেকে কিছু পাওয়া দরকার এবং এই নির্ভরতা থেকে যা ফিরে আসে তা আপনি যা পরীক্ষা করার চেষ্টা করছেন তা প্রভাবিত করতে পারে - সেই বস্তুকে বিদ্রূপ করুন।

বিষয়টিতে একটি দুর্দান্ত পডকাস্ট এখানে পাওয়া যাবে


লিঙ্কটি এখনই চলমান পর্বের দিকে যাত্রা করে, উদ্দেশ্যে করা পর্ব নয়। উদ্দেশ্য পোডকাস্ট এই hanselminutes.com/32/mock-objects ?
সি পার্কিনস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.