পরীক্ষার সময় ডেটটাইম ওভাররাইট করার একটি ভাল উপায় কী?


116

আমি কিছু (সি #) কোড পেয়েছি যা ভবিষ্যতের জিনিসগুলি সঠিকভাবে গণনা করতে আজকের তারিখের উপর নির্ভর করে। আমি যদি পরীক্ষার মধ্যে আজকের তারিখটি ব্যবহার করি তবে আমাকে পরীক্ষায় গণনার পুনরাবৃত্তি করতে হবে, যা সঠিক মনে হচ্ছে না। পরীক্ষার মধ্যে একটি জ্ঞাত মানের জন্য তারিখটি নির্ধারণ করার সর্বোত্তম উপায় কী যাতে আমি পরীক্ষা করতে পারি যে ফলাফলটি একটি পরিচিত মান?

উত্তর:


157

আমার পছন্দটি এমন ক্লাসগুলিতে থাকে যা সময় ব্যবহার করে প্রকৃতপক্ষে কোনও ইন্টারফেসের উপর নির্ভর করে, যেমন

interface IClock
{
    DateTime Now { get; } 
}

একটি কংক্রিট বাস্তবায়ন সঙ্গে

class SystemClock: IClock
{
     DateTime Now { get { return DateTime.Now; } }
}

তারপরে আপনি যদি চান তবে আপনি পরীক্ষার জন্য অন্য যে কোনও ধরণের ঘড়ি সরবরাহ করতে পারেন, যেমন

class StaticClock: IClock
{
     DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}

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

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

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


2
আমরা আসলে xUnit.net এক্সটেনশনের একটিতে এটি আনুষ্ঠানিকভাবে তৈরি করেছি। আমাদের কাছে একটি ক্লক ক্লাস রয়েছে যা আপনি ডেটটাইমের পরিবর্তে স্ট্যাটিক হিসাবে ব্যবহার করেন এবং আপনি নির্দিষ্ট তারিখগুলি সহ ঘড়ির "হিমায়িত" এবং "গলিত" করতে পারেন। দেখুন is.gd/3xds এবং is.gd/3xdu
ব্র্যাড উইলসন

2
এটিও লক্ষণীয় যে আপনি যখন আপনার সিস্টেম ক্লক পদ্ধতিটি বিকল্প করতে চান - এটি ঘটবে, উদাহরণস্বরূপ, যখন বিস্তৃত সময় অঞ্চলগুলিতে শাখাগুলি সহ কোনও এন্টারপ্রাইজে গ্লোবাল ঘড়ি ব্যবহার করা হয় - এই পদ্ধতিটি আপনাকে পরিবর্তন করার মূল্যবান ব্যবসায়ের স্তরের স্বাধীনতা দেয় "এখন" এর অর্থ।
মাইক বার্টন

1
আইস্লক দৃষ্টান্তে যেতে নির্ভরতা ইনজেকশন ফ্রেমওয়ার্ক ব্যবহারের সাথে এইভাবে আমার পক্ষে খুব ভাল কাজ করে।
উইলকা

8
দুর্দান্ত উত্তর। কেবল এটি যুক্ত করতে চেয়েছিলেন যে প্রায় সমস্ত ক্ষেত্রে UtcNowব্যবহার করা উচিত এবং তারপরে কোডের উদ্বেগ অনুসারে যথাযথভাবে সামঞ্জস্য করা উচিত, যেমন ব্যবসায়িক যুক্তি, ইউআই ইত্যাদি etc. ইউটিসি সময়।
অ্যাডাম রাল্ফ

@ ব্র্যাড উইলসন Those লিঙ্কগুলি এখন ভেঙে গেছে। এগুলিকেও ওয়েব্যাকের উপরে টানতে পারেনি।

55

আয়েন্দে রাহিয়ান স্থিতিশীল পদ্ধতি ব্যবহার করেছেন যা বরং সহজ ...

public static class SystemTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
}

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

1
এটি স্টাইলের বিষয়। ইউনিট-পরীক্ষা-পরিবর্তনশীল সিস্টেমের সময় পাওয়ার জন্য এটি আপনি সবচেয়ে কম কাজ করতে পারেন।
অ্যান্থনি মাস্ট্রিয়ান

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

17

আমি মনে করি বর্তমান তারিখ পাওয়ার মতো সাধারণ কোনও কিছুর জন্য আলাদা ক্লক ক্লাস তৈরি করা কিছুটা ওভারকিল।

আপনি প্যারামিটার হিসাবে আজকের তারিখটি পাস করতে পারেন যাতে আপনি পরীক্ষায় একটি আলাদা তারিখ ইনপুট করতে পারেন। এতে আপনার কোডটিকে আরও নমনীয় করে তোলার অতিরিক্ত সুবিধা রয়েছে।


আপনার এবং ব্লেয়ারের উত্তরগুলিতে আমি +1 করেছি, যদিও তারা উভয়ই বিরোধিতা করছে। আমি মনে করি উভয় পন্থা বৈধ। আপনার পদ্ধতির আমি সম্ভবত এমন একটি প্রকল্প ব্যবহার করব যা ইউনিটির মতো কিছু ব্যবহার করে না।
রিচার্ডড

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

17

শিম তৈরি করতে মাইক্রোসফ্ট ফেকস ব্যবহার করা এটি করার একটি সহজ উপায়। ধরুন আমার নিম্নলিখিত ক্লাস ছিল:

public class MyClass
{
    public string WhatsTheTime()
    {
        return DateTime.Now.ToString();
    }

}

ভিজ্যুয়াল স্টুডিও ২০১২-তে আপনি যে ন্যাশনাল ফেকস / শিমস তৈরি করতে চান তার উপর ক্লিক করে এবং "ফেকস এসেম্বলি যোগ করুন" নির্বাচন করে আপনার টেস্ট প্রকল্পে একটি ফেকস অ্যাসেমব্লী যুক্ত করতে পারেন

ফেকস অ্যাসেম্বলি যুক্ত করা

পরিশেষে, পরীক্ষার ক্লাসটি কেমন দেখাচ্ছে তা এখানে:

using System;
using ConsoleApplication11;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DateTimeTest
{
[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestWhatsTheTime()
    {

        using(ShimsContext.Create()){

            //Arrange
            System.Fakes.ShimDateTime.NowGet =
            () =>
            { return new DateTime(2010, 1, 1); };

            var myClass = new MyClass();

            //Act
            var timeString = myClass.WhatsTheTime();

            //Assert
            Assert.AreEqual("1/1/2010 12:00:00 AM",timeString);

        }
    }
}
}

1
এটি ঠিক আমি যা খুঁজছিলাম ছিল। ধন্যবাদ! বিটিডাব্লু, ভিএস ২০১৩ তে একই কাজ করে
ডগলাস লুডলো

বা আজকাল, ভিএস 2015 এন্টারপ্রাইজ সংস্করণ। যা একটি লজ্জাজনক, যেমন একটি সেরা অনুশীলনের জন্য।
আরজেবি

12

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

এই ক্ষেত্রে, আপনার বাহ্যিকটি বর্তমান তারিখের সময়।

এখানে আমার পরামর্শটি হ'ল যুক্তিটি বের করা যা ডেটটাইমকে কোনও নতুন পদ্ধতি বা শ্রেণীর সাথে সম্পর্কিত করে বা আপনার ক্ষেত্রে যা কিছু বোঝায় তা ডেটটাইম পাস করে Now


10

মাইক্রোসফ্ট মোলস ব্যবহার করে অন্য একটি ( । নেট জন্য বিচ্ছিন্ন কাঠামো )।

MDateTime.NowGet = () => new DateTime(2000, 1, 1);

মোলগুলি কোনও প্রতিনিধি দ্বারা কোনও নেট নেট পদ্ধতি প্রতিস্থাপন করতে দেয়। মোলস স্থির বা অ-ভার্চুয়াল পদ্ধতিগুলিকে সমর্থন করে। মোলস পেক্স থেকে প্রোফাইলারের উপর নির্ভর করে।


এটি দুর্দান্ত, তবে এটির জন্য ভিজ্যুয়াল স্টুডিও 2010 দরকার! :-(
প্যান্ডিকাস

এটি ভিএস ২০০৮-তেও দুর্দান্ত কাজ করে। যদিও এটি এমএসটিস্টের সাথে সবচেয়ে ভাল কাজ করে। আপনি NUnit ব্যবহার করতে পারেন তবে আমার মনে হয় আপনাকে একটি বিশেষ পরীক্ষার রানার দিয়ে আপনার পরীক্ষা চালাতে হবে।
Torbjørn

সম্ভব হলে আমি মোলস (ওরফে মাইক্রোসফ্ট ফেকস) ব্যবহার করা এড়াতে চাই। আদর্শভাবে, এটি কেবলমাত্র লিগ্যাসি কোডের জন্য ব্যবহার করা উচিত যা নির্ভরতা ইনজেকশনের মাধ্যমে ইতিমধ্যে পরীক্ষাযোগ্য নয়।
brianpeiris

1
@ ব্রায়ানপেইরিস, মাইক্রোসফ্ট ফেকস ব্যবহারের জন্য ডাউনসাইডগুলি কী কী?
রায় চেং

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

5

আমি আইডিস্পোজেবল প্যাটার্ন ব্যবহার করার পরামর্শ দিই:

[Test] 
public void CreateName_AddsCurrentTimeAtEnd() 
{
    using (Clock.NowIs(new DateTime(2010, 12, 31, 23, 59, 00)))
    {
        string name = new ReportNameService().CreateName(...);
        Assert.AreEqual("name 2010-12-31 23:59:00", name);
    } 
}

বিস্তারিত বর্ণিত এখানে: http://www.lesnikowski.com/blog/index.php/testing-datetime- હવે/


3

2

আপনি ক্লাসটি পরীক্ষার জন্য ক্লাসের জন্য (আরও ভাল: পদ্ধতি / প্রতিনিধি ) ব্যবহার করতে পারেন DateTime.Now। হয়েছে DateTime.Nowডিফল্ট মান এবং শুধুমাত্র একটি ডামি পদ্ধতি যা আয় একটি ধ্রুবক মান পরীক্ষা করতে এটি সেট করা।

সম্পাদনা: ব্লেয়ার কনরাড কী বলেছেন (তার কিছু দেখার কোড রয়েছে)। ব্যতীত, আমি এর জন্য প্রতিনিধিদের পছন্দ করতে চাই, কারণ তারা আপনার ক্লাসের শ্রেণিবিন্যাসকে এ জাতীয় স্টাফ দিয়ে ঝাঁকুনি দেয় না IClock...


1

আমি প্রায়শই এই পরিস্থিতির মুখোমুখি হয়েছিলাম যে আমি একটি সহজ নুগেট তৈরি করেছি যা ইন্টারফেসের মাধ্যমে নাও সম্পত্তি প্রকাশ করে ।

public interface IDateTimeTools
{
    DateTime Now { get; }
}

বাস্তবায়ন অবশ্যই খুব সোজা

public class DateTimeTools : IDateTimeTools
{
    public DateTime Now => DateTime.Now;
}

সুতরাং আমার প্রকল্পে নুগেট যুক্ত করার পরে আমি এটি ইউনিট পরীক্ষায় ব্যবহার করতে পারি

এখানে চিত্র বর্ণনা লিখুন

আপনি জিইউআই নুগেট প্যাকেজ ম্যানেজারের কাছ থেকে বা কমান্ডটি ব্যবহার করে মডিউলটি ইনস্টল করতে পারেন:

Install-Package -Id DateTimePT -ProjectName Project

এবং নুগেটের জন্য কোড এখানে

অটোফ্যাকের সাথে ব্যবহারের উদাহরণটি এখানে পাওয়া যাবে


-11

আপনি কি ডিবাগ / স্থাপনার সময় কী ঘটে তা নিয়ন্ত্রণ করতে শর্তসাপেক্ষ সংকলনটি ব্যবহার করার বিষয়টি বিবেচনা করেছেন?

যেমন

DateTime date;
#if DEBUG
  date = new DateTime(2008, 09, 04);
#else
  date = DateTime.Now;
#endif

এটি ব্যর্থ হয়ে আপনি সম্পত্তিটি প্রকাশ করতে চান যাতে আপনি এটি ব্যবহার করতে পারেন, এটি টেস্টেবল কোড লেখার চ্যালেঞ্জের সমস্ত অংশ , যা আমি বর্তমানে নিজেকে কুস্তি করছি: ডি

সম্পাদন করা

আমার একটি বড় অংশ ব্লেয়ারের পদ্ধতির পছন্দ করবে । এটি আপনাকে পরীক্ষার ক্ষেত্রে সহায়তা করার জন্য কোডের কিছু অংশ "হট প্লাগ" করতে দেয়। এটি সমস্ত পরিবর্তিত হয় নকশা নীতি encapsulate অনুসরণ করে টেস্ট কোডে হয় উত্পাদন কোডের চেয়ে আলাদা নয়, কেবল এটি বাহ্যিকভাবে কেউ দেখে না।

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


বাহ এই উত্তর আপনি খুব আঘাত পেয়েছি। আমি, কি করছেন, যদিও একটি স্থান, যেখানে আমি পদ্ধতি প্রতিস্থাপন কলে রয়েছেন DateTime'র Nowএবং Todayইত্যাদি
ডেভ Cousineau
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.