একটি ডোমেন অবজেক্ট তৈরির পরীক্ষা করার জন্য ইউনিট টেস্ট


11

আমার একটি ইউনিট টেস্ট রয়েছে, যা দেখতে এটির মতো দেখাচ্ছে:

[Test]
public void Should_create_person()
{
     Assert.DoesNotThrow(() => new Person(Guid.NewGuid(), new DateTime(1972, 01, 01));
}

আমি দৃ am়ভাবে বলছি যে এখানে একটি ব্যক্তি অবজেক্ট তৈরি করা হয়েছে অর্থাৎ বৈধতা ব্যর্থ হয় না। উদাহরণস্বরূপ, যদি গাইডটি শূন্য হয় বা জন্ম তারিখটি 01/01/1900 এর আগে হয় তবে বৈধতা ব্যর্থ হবে এবং একটি ব্যতিক্রম নিক্ষেপ করা হবে (যার অর্থ পরীক্ষা ব্যর্থ হয়)।

কনস্ট্রাক্টর এর মত দেখাচ্ছে:

public Person(Id id, DateTime dateOfBirth) :
        base(id)
    {
        if (dateOfBirth == null)
            throw new ArgumentNullException("Date of Birth");
        elseif (dateOfBith < new DateTime(1900,01,01)
            throw new ArgumentException("Date of Birth");
        DateOfBirth = dateOfBirth;
    }

এটি কি পরীক্ষার জন্য ভাল ধারণা?

দ্রষ্টব্য : আমি ইউনিট পরীক্ষার জন্য ক্লাসিস্ট পদ্ধতির অনুসরণ করছি ডোমেন মডেলটির যদি কোনও প্রভাব থাকে।


আরম্ভের পরে-পরে নির্ধারকের পক্ষে যুক্তিযুক্ত কোনও যুক্তি আছে কি?
লাইভ

2
পরীক্ষার নির্মাণকারীদের কখনও বিরক্ত করবেন না !!! নির্মাণ সোজা এগিয়ে করা উচিত। আপনি কি গাইড / নিউগুইড (), বা ডেটটাইম নির্মাতায় ব্যর্থতা আশা করছেন?
ivenxu

@ লাইভ, দয়া করে প্রশ্নের আপডেট দেখুন।
w0051977

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

3
পরীক্ষাটি দুর্দান্ত দেখায়, একটি জিনিসের জন্য সংরক্ষণ করুন: নাম। Should_create_person? কোন ব্যক্তি তৈরি করা উচিত? এটিকে একটি অর্থপূর্ণ নাম দিন Creating_person_with_valid_data_succeeds
ডেভিড আরনো

উত্তর:


18

এটি একটি বৈধ পরীক্ষা (যদিও অত্যধিক মাত্রায় alousর্ষান্বিত) এবং আমি কখনও কখনও এটি নির্মাণকারীর যুক্তি পরীক্ষা করার জন্য করি, তবে লাইভ মন্তব্যগুলিতে উল্লেখ করেছেন যেমন আপনাকে নিজেরাই জিজ্ঞাসা করা উচিত।

যদি আপনার কনস্ট্রাক্টর এর মত দেখাচ্ছে:

public Person(Guid guid, DateTime dob)
{
  this.Guid = guid;
  this.Dob = dob;
}

এটি ছোঁড়ে কিনা তা পরীক্ষা করার অনেকগুলি পয়েন্ট আছে? প্যারামিটারগুলি সঠিকভাবে নির্ধারিত হয়েছে কিনা তা আমি বুঝতে পারি তবে আপনার পরীক্ষাটি বরং ওভারকিল।

তবে, যদি আপনার পরীক্ষাটি এরকম কিছু করে:

public Person(Guid guid, DateTime dob)
{
  if(guid == default(Guid)) throw new ArgumentException("Guid is invalid");
  if(dob == default(DateTime)) throw new ArgumentException("Dob is invalid");

  this.Guid = guid;
  this.Dob = dob;
}

তারপরে আপনার পরীক্ষাটি আরও প্রাসঙ্গিক হয়ে ওঠে (আপনি প্রকৃতপক্ষে কোডের কোনও ব্যতিক্রম ছুঁড়ে মারছেন)

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

এ কারণে, যদি আপনার নির্মাণকারী পরীক্ষার উপযুক্ত হয় (কারণ প্রচুর যুক্তি দিয়ে চলেছে) তবে অন্য কিছু হতে পারে।

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

আপনার উদাহরণে:

public Person(Id id, DateTime dateOfBirth) :
        base(id)
    {
        if (dateOfBirth == null)
            throw new ArgumentNullException("Date of Birth");
        elseif (dateOfBith < new DateTime(1900,01,01)
            throw new ArgumentException("Date of Birth");
        DateOfBirth = dateOfBirth;
    }

আপনি কেবল বৈধতা দিচ্ছেন না, তবে আপনি বেস কনস্ট্রাক্টরকেও কল করছেন। আমার জন্য এটি এই পরীক্ষাগুলিগুলির আরও কারণ দেখায় কারণ তাদের কাছে কনস্ট্রাক্টর / বৈধতা যুক্তি এখন দুটি শ্রেণিতে বিভক্ত যা দৃশ্যমানতা হ্রাস করে এবং অপ্রত্যাশিত পরিবর্তনের ঝুঁকি বাড়ায়।

TLDR

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


@ লইথ, দয়া করে আমার প্রশ্নের আপডেটটি দেখুন
w0051977

আমি লক্ষ্য করেছি যে আপনি উদাহরণে একটি বেস কনস্ট্রাক্টরকে কল করছেন। আইএমএইচও এটি আপনার পরীক্ষার আরও মান যুক্ত করে, কনস্ট্রাক্টর লজিক এখন দুটি ক্লাসে বিভক্ত এবং তাই পরিবর্তনের আরও ঝুঁকি তাই এটি পরীক্ষা করার আরও কারণ দেয় giving
লিথ

"তবে, যদি আপনার পরীক্ষা ভালো কিছু করে:" <আপনি কি বলতে চান না "যদি আপনার কন্সট্রাকটর ভালো কিছু করে" ?
কোডোস জনসন

"এই পরীক্ষাগুলির কিছু মূল্য রয়েছে" - আকর্ষণীয়ভাবে যাইহোক আমার জন্য, মানটি দেখায় যে আমরা কোনও নতুন শ্রেণীর ব্যবহার করে ব্যক্তির দোব (যেমন PersonBirthdate) যা জন্ম বৈধতার তারিখটি সম্পাদন করে তা ব্যবহার করে এই পরীক্ষাটি রিডানড্যান্ট করতে পারি । একইভাবে Guidচেকটি Idক্লাসে প্রয়োগ করা যেতে পারে । এর অর্থ এই যে আপনার Personঅবৈধ ডেটা দিয়ে কোনওটি নির্মাণ করা সম্ভব না হওয়ায় - কনফ্রাক্টরের কাছে সত্যিকারের আর সেই বৈধতা যুক্তি থাকতে হবে না - nullরেফগুলি বাদে । অবশ্যই, আপনাকে অন্য দুটি শ্রেণির জন্য পরীক্ষা লিখতে হবে :)
স্টিফেন বাইর্ন

12

ইতিমধ্যে এখানে একটি ভাল উত্তর, তবে আমি মনে করি যে একটি অতিরিক্ত বিষয় উল্লেখযোগ্য।

"বই দ্বারা" টিডিডি করার সময় , প্রথমে একটি পরীক্ষা লিখতে হবে যা কনস্ট্রাক্টরকে কল করে, কনস্ট্রাক্টর বাস্তবায়নের আগেই। এই পরীক্ষাটি আসলে আপনি যেমন উপস্থাপন করেছেন তার মতো দেখতে পারা যায়, এমনকি যদি নির্মাতার বাস্তবায়নের ভিতরে শূন্য বৈধতা যুক্তিও থাকে।

আরও মনে রাখবেন যে টিডিডির জন্য প্রথমে অন্য একটি পরীক্ষা লিখতে হবে

  Assert.Throws<ArgumentException>(() => new Person(Guid.NewGuid(), 
        new DateTime(1572, 01, 01));

DateTime(1900,01,01)কনস্ট্রাক্টরের জন্য চেক যোগ করার আগে

টিডিডি প্রসঙ্গে, প্রদর্শিত পরীক্ষাটি পুরোপুরি অর্থবোধ করে।


ভাল কোণ আমি বিবেচনা না করতাম!
লিথ

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

এটি কি সত্যই বইটি দিয়ে টিডিডি করেছে? আমি উদাহরণ তৈরি করব এবং সাথে সাথে একটি কোডে এর পদ্ধতিটি কল করব। তারপরে আমি সেই পদ্ধতির জন্য পরীক্ষা লিখব, এবং এটি করে আমাকে সেই পদ্ধতির জন্য উদাহরণও তৈরি করতে হবে, সুতরাং কনস্ট্রাক্টর এবং পদ্ধতি উভয়ই সেই পরীক্ষায় আবৃত হবে। কনস্ট্রাক্টর না থাকলে কিছু যুক্তি রয়েছে, তবে সেই অংশটি লিথ দ্বারা আবৃত।
রাফা łużyński

@ রাফাউইসিস্কি: টিডিডি "বইয়ের" দ্বারা প্রথমে টেস্ট লেখার কথা । এর অর্থ হ'ল সর্বদা প্রথমে একটি ব্যর্থ পরীক্ষা লিখতে হবে (ব্যর্থতা হিসাবে গণনাও করা হয় না)। সুতরাং আপনি প্রথমে কনস্ট্রাক্টর না থাকলেও কনস্ট্রাক্টরকে কল করে একটি পরীক্ষা লিখুন । তারপরে আপনি সংকলন করার চেষ্টা করুন (যা ব্যর্থ হয়), তারপরে আপনি একটি খালি নির্মাতা বাস্তবায়ন করুন, সংকলন করুন, পরীক্ষাটি চালান, ফলাফল = সবুজ। তারপরে আপনি প্রথম ব্যর্থ পরীক্ষা লিখুন এবং এটিকে চালান - ফলাফল = লাল, তারপরে আপনি পরীক্ষাকে আবার "সবুজ" করার জন্য কার্যকারিতা যুক্ত করুন, এবং আরও অনেক কিছু।
ডক ব্রাউন 17

অবশ্যই. আমি বলতে চাইনি আমি প্রথমে বাস্তবায়ন লিখি, পরে পরীক্ষা করি test আমি কেবল উপরের স্তরে সেই কোডটির "ব্যবহার" লিখি, তারপরে সেই কোডটির জন্য পরীক্ষা করে, তারপরে আমি এটি প্রয়োগ করি। আমি সাধারণত "বাইরে টিডিডি" করি doing
রাফা łużyński
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.