ما هي الطريقة الجيدة إلى الكتابة فوق التاريخ والوقت.الآن أثناء الاختبار ؟

StackOverflow https://stackoverflow.com/questions/43711

سؤال

لقد حصلت على بعض (C#) التعليمات البرمجية التي تعتمد على تاريخ اليوم بشكل صحيح لحساب الأشياء في المستقبل.إذا كنت تستخدم اليوم في الاختبار ، علي أن أعيد حساب في الاختبار الذي لا يشعر الحق.ما هي أفضل طريقة لتحديد موعد قيمة معروفة في الاختبار حتى أستطيع أن الاختبار أن النتيجة معروفة القيمة ؟

هل كانت مفيدة؟

المحلول

أفضله هو أن الطبقات التي تستخدم الوقت في الواقع تعتمد على واجهة مثل

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 بما في ذلك في الحسابات الخاصة بك لا فقط لا يشعر الحق - أنه ينسلخ من القدرة على اختبار معين مرات ، على سبيل المثال إذا كنت اكتشاف الخلل الذي لا يحدث إلا قرب منتصف الليل الحدود ، أو يوم الثلاثاء.استخدام الوقت الحالي لن تسمح لك لاختبار تلك السيناريوهات.أو على الأقل ليس وقتما تشاء.

نصائح أخرى

Ayende Rahien يستخدم ثابت طريقة بسيطة نوعا ما...

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

أعتقد إنشاء منفصلة على مدار الساعة فئة شيء بسيط مثل الحصول على التاريخ الحالي هو مبالغة بعض الشيء.

يمكنك تمرير تاريخ اليوم كمعلمة بحيث يمكنك إدخال تاريخ مختلف في الاختبار.وهذا له فائدة إضافية لجعل التعليمات البرمجية الخاصة بك أكثر مرونة.

باستخدام Microsoft مزيفة لإنشاء شيم هو حقا وسيلة سهلة للقيام بذلك.لنفترض أن لدي فئة التالية:

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

}

في Visual Studio 2012 يمكنك إضافة مزيفة الجمعية إلى اختبار المشروع عن طريق النقر على الحق في التجمع كنت ترغب في إنشاء مزيفة/الحشوات عن طريق اختيار "إضافة مزيفة الجمعية"

Adding Fakes Assembly

أخيرا, هنا هو ما الطبقة اختبار تبدو مثل:

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);

        }
    }
}
}

مفتاح النجاح في اختبار وحدة هو فصل.عليك أن تفصل للاهتمام الخاص بك رمز من التبعيات الخارجية ، لذلك يمكن اختبارها في عزلة.(لحسن الحظ, تطوير اختبار يحركها تنتج تنفصل رمز.)

في هذه الحالة الخارجي الخاص بك هو التاريخ والوقت الحالي.

نصيحتي هنا هو استخراج المنطق الذي يتعامل مع التاريخ والوقت إلى طريقة جديدة أو فئة أو أيا كان من المنطقي في حالة تمرير التاريخ والوقت في.إن وحدة اختبار يمكن أن تمر التعسفي التاريخ والوقت في أن تنتج نتائج يمكن التنبؤ بها.

واحد آخر باستخدام Microsoft الشامات (العزلة الإطار .صافي).

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

الشامات يسمح استبدال أي .صافي الأسلوب مع مندوب.الشامات يدعم ثابت أو غير ظاهري الأساليب.الشامات يعتمد على التعريف من البورصة.

أقترح استخدام IDisposable نمط:

[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-now/

الإجابة بسيطة:خندق النظام.التاريخ والوقت :) بدلا من, استخدام NodaTime و هو اختبار المكتبة: NodaTime.اختبار.

مزيد من القراءة:

هل يمكن حقن فئة (أفضل:الطريقة/مندوب) استخدام DateTime.Now في الطبقة التي يجري اختبارها.لديك DateTime.Now تكون القيمة الافتراضية فقط وضعه في اختبار دمية الأسلوب بإرجاع قيمة ثابتة.

تحرير: ما بلير كونراد قال (لديه بعض التعليمات البرمجية للنظر في).إلا أنني أميل إلى تفضيل المندوبين على هذا ، كما أنهم لا فوضى حتى الصف الهرمي مع الاشياء مثل IClock...

أنا واجهت هذا الوضع في كثير من الأحيان ، التي خلقت بسيطة nuget الذي يعرض الآن الملكية من خلال واجهة.

public interface IDateTimeTools
{
    DateTime Now { get; }
}

تنفيذ بالطبع واضحة جدا

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

حتى بعد إضافة nuget إلى المشروع الذي يمكن استخدامه في وحدة الاختبارات

enter image description here

يمكنك تثبيت وحدة الحق من واجهة المستخدم الرسومية Nuget مدير الحزم أو باستخدام الأمر:

Install-Package -Id DateTimePT -ProjectName Project

و رمز Nuget هو هنا.

مثال الاستخدام مع Autofac يمكن العثور عليها هنا.

هل يعتبر استخدام الشرطية إلى السيطرة على ما يحدث أثناء التصحيح/نشر الصور ؟

على سبيل المثال

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

إذا تعذر ذلك, تريد أن تعرض المنشأة حتى يمكن التعامل مع ذلك ، هذا هو كل جزء من التحدي من الكتابة قابلة للاختبار رمز وهو شيء أنا حاليا المصارعة نفسي :D

تحرير

جزء كبير مني أن تفضيل بلير النهج.هذا يسمح لك أن "المكونات الساخنة" أجزاء من التعليمات البرمجية للمساعدة في الاختبار.كل شيء يتبع مبدأ التصميم تغلف ما يختلف اختبار رمز لا يختلف عن رمز الإنتاج فقط لا أحد يرى خارجيا.

إنشاء واجهة قد يبدو مثل الكثير من العمل من أجل هذا المثال على الرغم من (والذي هو السبب في أنني اختار الشرطية).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top