ইউনিট পরীক্ষার প্রত্যাশিত ফলাফলগুলি হার্ডকোড করা উচিত?


29

ইউনিট পরীক্ষার প্রত্যাশিত ফলাফলগুলি হার্ডকোড করা উচিত, না সেগুলি প্রাথমিক ভেরিয়েবলের উপর নির্ভরশীল হতে পারে? হার্ডকোডযুক্ত বা গণনা করা ফলাফলগুলি কি ইউনিট পরীক্ষায় ত্রুটিগুলি প্রবর্তনের ঝুঁকি বাড়ায়? অন্যান্য বিষয়গুলিও আমি বিবেচনা করি নি?

উদাহরণস্বরূপ, এই দুটির মধ্যে কোনটি আরও নির্ভরযোগ্য ফর্ম্যাট?

[TestMethod]
public void GetPath_Hardcoded()
{
    MyClass target = new MyClass("fields", "that later", "determine", "a folder");
    string expected = "C:\\Output Folder\\fields\\that later\\determine\\a folder";
    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

[TestMethod]
public void GetPath_Softcoded()
{
    MyClass target = new MyClass("fields", "that later", "determine", "a folder");
    string expected = "C:\\Output Folder\\" + string.Join("\\", target.Field1, target.Field2, target.Field3, target.Field4);
    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

সম্পাদনা 1: ডিএক্সএম এর উত্তরের প্রতিক্রিয়াতে, বিকল্প 3 কি পছন্দসই সমাধান?

[TestMethod]
public void GetPath_Option3()
{
    string field1 = "fields";
    string field2 = "that later";
    string field3 = "determine";
    string field4 = "a folder";
    MyClass target = new MyClass(field1, field2, field3, field4);
    string expected = "C:\\Output Folder\\" + string.Join("\\", field1, field2, field3, field4);
    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

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

আমি তৃতীয় বিকল্পটি ব্যবহার করতে চাই তা সম্মত করব। আপনি সংকলনের কারসাজি অপসারণ করার কারণে 1 বিকল্পটি ক্ষতিগ্রস্থ হবে বলে আমি মনে করি না।
kwelch

আপনার দুটি অপশনই হার্ডকোডিং ব্যবহার করেছে যদিও এবং সি: on
কিওয়ার্টি

উত্তর:


27

আমি মনে করি গণিত প্রত্যাশিত মান ফলাফল আরও শক্তিশালী এবং নমনীয় পরীক্ষা ক্ষেত্রে। এছাড়াও প্রত্যাশিত ফলাফল গণনা করে এমন অভিব্যক্তিতে ভাল পরিবর্তনশীল নাম ব্যবহার করে, প্রত্যাশিত ফলাফলটি প্রথম স্থান থেকে এসেছে তা আরও অনেক স্পষ্ট।

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

আমার পরামর্শটি প্রত্যাশিত মান গণনা করা হবে যেখানে এটি অর্থবোধ করে, তবে নিশ্চিত হয়ে নিন যে গণনাটি নিজেই কোনও কোডের উপর নির্ভর করে না UT

আমার প্রতিক্রিয়ায় ওপির আপডেটের প্রতিক্রিয়া:

হ্যাঁ, আমার জ্ঞানের ভিত্তিতে তবে টিডিডি করার ক্ষেত্রে কিছুটা সীমিত অভিজ্ঞতার ভিত্তিতে আমি # 3 বিকল্পটি বেছে নেব।


1
ভাল যুক্তি! পরীক্ষায় যাচাই করা হয়েছে না যাচাইকৃত বস্তুর উপর নির্ভর করবেন না।
হ্যান্ড-ই-ফুড

এটি কি এসইউটি কোডের সদৃশ নয়?
অ্যাবিক্স

1
এটি একরকম, তবে আপনি কীভাবে যাচাই করবেন যে SUT কাজ করছে। যদি আমরা একই কোড ব্যবহার করি এবং এটি ফাঁস হয়ে যায় তবে আপনি কখনই জানতে পারবেন না। অবশ্যই, যদি গণনাটি সম্পাদন করতে হয়, আপনাকে প্রচুর SUT নকল করতে হবে, তবে বিকল্প # 1 আরও ভাল হয়ে উঠবে, কেবল মানটিকে হার্ডকোড করুন।
DXM

16

কোডটি যদি নিম্নরূপ হয় তবে কী হবে:

MyTarget() // constructor
{
   Field1 = Field2 = Field3 = Field4 = "";
}

আপনার দ্বিতীয় উদাহরণটি বাগটি ধরবে না, তবে প্রথম উদাহরণটি।

সাধারণভাবে, আমি সফট কোডিংয়ের বিরুদ্ধে সুপারিশ করব কারণ এটি বাগগুলি লুকিয়ে রাখতে পারে। উদাহরণ স্বরূপ:

string expected = "C:\\Output Folder" + string.Join("\\", target.Field1, target.Field2, target.Field3, target.Field4);

আপনি সমস্যা স্পট করতে পারেন? আপনি হার্ড কোডিং সংস্করণে একই ভুল করবেন না। হার্ড-কোডড মানগুলির চেয়ে গণনাগুলি সঠিকভাবে পাওয়া শক্ত। এ কারণেই আমি নরম কোডেড মানগুলির চেয়ে হার্ড কোডিং মানগুলির সাথে কাজ করতে পছন্দ করি।

তবে ব্যতিক্রমও রয়েছে। যদি আপনার কোডটি উইন্ডোজ এবং লিনাক্সে চালিত হয়? পাথটি কেবল আলাদা হতে হবে না, এর জন্য পৃথক পৃথক পৃথক পৃথক ব্যবহার করতে হবে! ফাংশনগুলি ব্যবহার করে পাথের গণনা করা হচ্ছে যেগুলির মধ্যে পার্থক্যটিকে বিমূর্ত করে সেই প্রসঙ্গে বোধগম্য হতে পারে।


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

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

আমি নিশ্চিত না যে আমি অনুসরণ করি। আমি যে উদাহরণ দিয়েছি তা নিখুঁত অনুমানমূলক, দৃশ্যের বোঝার পক্ষে সহজ। ক্লাস এবং অবজেক্টের সর্বজনীন সদস্যদের পরীক্ষা করার জন্য আমি ইউনিট পরীক্ষা লিখছি। এগুলি ব্যবহারের সঠিক উপায় কি?
হ্যান্ড-ই-ফুড

@ হ্যান্ড-ই-ফুড, যদি আমি আপনাকে সঠিকভাবে বুঝতে পারি তবে আপনার পরীক্ষা কনস্ট্রাক্টশল্ডকারেক্টিআইনিটালাইসফিল্ডগুলি কনস্ট্রাক্টরকে অনুরোধ করবে এবং তারপরে দৃ as়ভাবে জানায় যে ক্ষেত্রগুলি সঠিকভাবে সেট করা আছে। তবে আপনার এটি করা উচিত নয়। অভ্যন্তরীণ ক্ষেত্রগুলি কী করছে তা আপনার যত্ন নেওয়া উচিত নয়। আপনার কেবলমাত্র দৃsert়ভাবে বলা উচিত যে বস্তুর বাহ্যিক আচরণ সঠিক। অন্যথায়, এমন দিন আসতে পারে যখন আপনাকে অভ্যন্তরীণ বাস্তবায়ন প্রতিস্থাপন করতে হবে। আপনি যদি অভ্যন্তরীণ পরিস্থিতি সম্পর্কে জোর দিয়ে থাকেন তবে আপনার সমস্ত পরীক্ষাগুলি ভেঙে যাবে। তবে আপনি যদি কেবলমাত্র বাহ্যিক আচরণ সম্পর্কে দৃ made় প্রতিজ্ঞাগুলি তৈরি করেন তবে সমস্ত কিছু এখনও কাজ করবে।
উইনস্টন ইওয়ার্ট

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

4

আমার মতে, আপনার উভয় পরামর্শই আদর্শের চেয়ে কম। এটি করার আদর্শ উপায় হ'ল:

[TestMethod]
public void GetPath_Hardcoded()
{
    const string f1 = "fields"; const string f2 = "that later"; 
    const string f3 = "determine"; const string f4 = "a folder";

    MyClass target = new MyClass( f1, f2, f3, f4 );
    string expected = "C:\\Output Folder\\" + string.Join("\\", f1, f2, f3, f4);
    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

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


1
সমস্ত পদ্ধতি কার্যকরী নয় - অনেকেরই সঠিকভাবে পার্শ্ব প্রতিক্রিয়া রয়েছে যা কিছু অবজেক্ট বা বস্তুর অবস্থাকে পরিবর্তন করে। পার্শ্ব প্রতিক্রিয়াযুক্ত একটি পদ্ধতির জন্য একক পরীক্ষার জন্য সম্ভবত পদ্ধতি দ্বারা প্রভাবিত বস্তুর (গুলি) অবস্থা মূল্যায়ন করা প্রয়োজন need
ম্যাথু ফ্লাইন

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

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

@ ম্যাথিউফ্লিন, কেবল স্পষ্ট করে বলতে গেলে, এটি দেখানো উদাহরণের সাথে কি অন্য ইউনিট পরীক্ষার জন্য বিবেচনা করার মতো অন্য কিছু? আমি দেখতে পেলাম যে বিষয়টির মতো target.Dispose(); Assert.IsTrue(target.IsDisposed);(খুব সাধারণ উদাহরণ for )
হ্যান্ড-ই-ফুড

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

2

আলোচনার দুটি দিক রয়েছে:

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

২. হার্ডকোডিংয়ের
আপনার হার্ড কোড করা উচিত ? আবার উত্তরটি হ'ল না । কারণ যে কোনও সফ্টওয়্যারের মতো - যখন তথ্য বিকশিত হয় তখন তার তথ্যের হার্ড কোডিং কঠিন হয়ে যায়। উদাহরণস্বরূপ, আপনি যখন উপরের পাথটি আবার সংশোধন করতে চান তখন আপনাকে অতিরিক্ত ইউনিট লিখতে হবে বা সংশোধন করতে হবে। একটি আরও ভাল পদ্ধতি হ'ল সহজেই মানিয়ে নেওয়া যায় এমন পৃথক কনফিগারেশন থেকে প্রাপ্ত ইনপুট এবং মূল্যায়নের তারিখটি রাখা।

উদাহরণস্বরূপ এখানে আমি পরীক্ষার স্টাবটি কীভাবে সঠিক করব।

[TestMethod]
public void GetPath_Tested(int CaseId)
{
    testParams = GetTestConfig(caseID,"testConfig.txt"); // some wrapper that does read line and chops the field. 
    MyClass target = new MyClass(testParams.field1, testParams.field2);
    string expected = testParams.field5;
    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

0

অনেকগুলি ধারণা সম্ভব, পার্থক্যটি দেখার জন্য কয়েকটি উদাহরণ তৈরি করেছেন

[TestMethod]
public void GetPath_Softcoded()
{
    //Hardcoded since you want to see what you expect is most simple and clear
    string expected = "C:\\Output Folder\\fields\\that later\\determine\\a folder";

    //If this test should also use a mocked filesystem it might be that you want to use
    //some base directory, which you could set in the setUp of your test class
    //that is usefull if you you need to run the same test on different environments
    string expected = this.outputPath + "fields\\that later\\determine\\a folder";


    //another readable way could be interesting if you have difficult variables needed to test
    string fields = "fields";
    string thatLater = "that later";
    string determine = "determine";
    string aFolder = "a folder";
    string expected = this.outputPath + fields + "\\" + thatLater + "\\" + determine + "\\" + aFolder;
    MyClass target = new MyClass(fields, thatLater, determine, aFolder);

    //in general testing with real words is not needed, so code could be shorter on that
    //for testing difficult folder names you write a separate test anyway
    string f1 = "f1";
    string f2 = "f2";
    string f3 = "f3";
    string f4 = "f4";
    string expected = this.outputPath + f1 + "\\" + f2 + "\\" + f3 + "\\" + f4;
    MyClass target = new MyClass(f1, f2, f3, f4);

    //so here we start to see a structure, it looks more like an array of fields
    //so what would make testing more interesting with lots of variables is the use of a data provider
    //the data provider will re-use your test with many different kinds of inputs. That will reduce the amount of duplication of code for testing
    //http://msdn.microsoft.com/en-us/library/ms182527.aspx


    The part where you compare already seems correct
    MyClass target = new MyClass(fields, thatLater, determine, aFolder);

    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

সংক্ষিপ্তসার হিসাবে: সাধারণভাবে আপনার প্রথম হার্ডকডযুক্ত পরীক্ষাটি আমার কাছে সবচেয়ে বেশি অর্থবোধ করে কারণ এটি সরল, সোজা বিষয় etc. ইত্যাদি you

ভবিষ্যতের আরও কাঠামোগত পরীক্ষার জন্য আমি ডাটাসোর্সগুলি পরীক্ষা করে দেখতে যাব যাতে আপনার আরও পরীক্ষার পরিস্থিতির প্রয়োজন হলে আপনি কেবল আরও ডেটা সারি যুক্ত করতে পারেন।


0

আধুনিক পরীক্ষার ফ্রেমওয়ার্কগুলি আপনাকে আপনার পদ্ধতিতে পরামিতি সরবরাহ করতে দেয়। আমি এগুলি উপার্জন করতে চাই:

[TestCase("fields", "that later", "determine", "a folder", @"C:\Output Folder\fields\that later\determine\a folder")]
public void GetPathShouldReturnFullDirectoryPathBasedOnItsFields(
    string field1, string field2, string field3, string field,
    string expected)
{
    MyClass target = new MyClass(field1, field2, field3, field4);
    string actual = target.GetPath();
    Assert.AreEqual(expected, actual,
        "GetPath should return a full directory path based on its fields.");
}

আমার দৃষ্টিতে এটির বেশ কয়েকটি সুবিধা রয়েছে:

  1. বিকাশকারীরা প্রায়শই কোডগুলির আপাতদৃষ্টিতে সহজ অংশগুলি তাদের ইউনিট পরীক্ষায় SUT থেকে অনুলিপি করতে প্ররোচিত হন। উইনস্টন যেমন উল্লেখ করেছে , সেগুলিতে এখনও ছদ্মবেশী বাগ লুকানো থাকতে পারে। "হার্ড-কোডিং" প্রত্যাশিত ফলাফল এমন পরিস্থিতিতে এড়াতে সহায়তা করে যেখানে আপনার পরীক্ষার কোডটি একই কারণে আপনার আসল কোডটি ভুল বলে ভুল হয়। তবে যদি প্রয়োজনীয়তার কোনও পরিবর্তন আপনাকে কয়েক ডজন পরীক্ষার পদ্ধতির অভ্যন্তরে হার্ড-কোডড স্ট্রিংগুলি সন্ধান করতে বাধ্য করে, যা বিরক্তিকর হতে পারে। আপনার পরীক্ষার যুক্তির বাইরে, সমস্ত হার্ড-কোডড মানগুলি এক জায়গায় রাখলে আপনাকে উভয় দুনিয়ার সেরা দেয়।
  2. আপনি কোডের একক লাইন সহ বিভিন্ন ইনপুট এবং প্রত্যাশিত আউটপুটগুলির জন্য পরীক্ষা যোগ করতে পারেন। এটি আপনাকে টেস্ট কোড ডিআরওয়াই এবং বজায় রাখা সহজ রাখার সময় আরও পরীক্ষা লিখতে উত্সাহ দেয়। আমি দেখতে পেলাম যে এটি টেস্ট যুক্ত করার পক্ষে এত সস্তা, আমার মন নতুন পরীক্ষার কেসগুলিতে উন্মুক্ত হয়ে গেছে আমি তাদের জন্য যদি একটি সম্পূর্ণ নতুন পদ্ধতি লিখতে হত তবে আমি ভেবে দেখতাম না। উদাহরণস্বরূপ, যদি কোনও ইনপুট এতে বিন্দু থাকে তবে আমি কোন আচরণের প্রত্যাশা করব? একটা ব্যাকস্ল্যাশ? কেউ যদি খালি থাকে? নাকি হোয়াইটস্পেস? বা সাদা বা স্পেস স্পেস দিয়ে শেষ হয়েছে?
  3. পরীক্ষার কাঠামোটি প্রতিটি টেস্টকেসকে তার নিজস্ব পরীক্ষা হিসাবে বিবেচনা করে, এমনকি প্রদত্ত ইনপুট এবং আউটপুটকে পরীক্ষার নামে রাখে। সমস্ত টেস্ট কেস যদি একটি করে পাস করে তবে কোনটি ভেঙে গেছে এবং অন্য সমস্তের থেকে এটি কীভাবে আলাদা তা দেখতে খুব সহজ।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.