سؤال

أنا أكتب مكون بالنظر إلى ملف مضغوط يحتاج إلى:

  1. قم بفك ضغط الملف.
  2. العثور على dll معينة بين فك ضغط الملفات.
  3. تحميل dll من خلال التفكير و استدعاء الأسلوب على ذلك.

أود أن وحدة اختبار هذا المكون.

أنا يميل إلى كتابة التعليمات البرمجية التي تتعامل مباشرة مع نظام الملفات:

void DoIt()
{
   Zip.Unzip(theZipFile, "C:\\foo\\Unzipped");
   System.IO.File myDll = File.Open("C:\\foo\\Unzipped\\SuperSecret.bar");
   myDll.InvokeSomeSpecialMethod();
}

ولكن الناس كثيرا ما يقولون: "لا تكتب وحدة الاختبارات التي تعتمد على نظام الملفات, قاعدة البيانات, شبكة, إلخ."

إذا كان لي أن أكتب هذا في وحدة الاختبار بطريقة ودية ، أعتقد أنها تبدو مثل هذا:

void DoIt(IZipper zipper, IFileSystem fileSystem, IDllRunner runner)
{
   string path = zipper.Unzip(theZipFile);
   IFakeFile file = fileSystem.Open(path);
   runner.Run(file);
}

ياي!الآن انها قابلة للاختبار;أستطيع إطعام في اختبار الزوجي (يسخر) إلى DoIt الأسلوب.ولكن ما هو الثمن ؟ لقد كان تحديد 3 واجهات جديدة إلى أن تكون قابلة للاختبار.و ما أنا الاختبار ؟ أنا اختبار بلدي DoIt تعمل بشكل صحيح يتفاعل مع تبعياته.لا اختبار هذا الملف zip فك ضغط بشكل صحيح ، وما إلى ذلك.

لا أشعر أنني اختبار وظيفة بعد الآن.فإنه يشعر وكأنه أنا مجرد اختبار الفصل التفاعلات.

سؤالي هو:ما هي الطريقة الصحيحة لاختبار وحدة الشيء يعتمد على ملفات النظام ؟

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

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

المحلول

لا يوجد شيء خاطئ مع هذا, انها مجرد مسألة ما إذا كانت تسميه وحدة اختبار أو اختبار التكامل.لديك فقط للتأكد من أن إذا كنت لا تتفاعل مع نظام الملفات ، هناك أي آثار جانبية غير مقصودة.على وجه التحديد, تأكد من تنظيف بعد نفسك -- حذف أي ملفات مؤقتة قمت بإنشائه-وأن كنت لا بطريق الخطأ الكتابة فوق الملف الموجود حدث لها نفس اسم الملف باسم ملف مؤقت كنت تستخدم.دائما استخدام المسارات النسبية وليس المطلقة مسارات.

كما سيكون فكرة جيدة chdir() في دليل مؤقت قبل تشغيل الاختبار الخاصة بك ، chdir() مرة أخرى بعد ذلك.

نصائح أخرى

ياي!الآن انها قابلة للاختبار;أستطيع إطعام في اختبار الزوجي (يسخر) إلى DoIt الأسلوب.ولكن ما هو الثمن ؟ لقد كان تحديد 3 واجهات جديدة إلى أن تكون قابلة للاختبار.و ما أنا الاختبار ؟ أنا اختبار بلدي DoIt تعمل بشكل صحيح يتفاعل مع تبعياته.لا اختبار هذا الملف zip فك ضغط بشكل صحيح ، وما إلى ذلك.

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

السؤال يعرض واحدة من أصعب أجزاء من الاختبار للمطورين فقط الدخول في ذلك:

"ماذا يمكنني الاختبار؟"

المثال الخاص بك ليست مثيرة جدا للاهتمام لأنه يلصق بعض المكالمات API معا حتى إذا كنت تريد كتابة اختبار الوحدة من أجل ذلك كنت في نهاية المطاف مجرد مؤكدا أن الطرق كانت تسمى.الاختبارات مثل هذا بإحكام الزوجين الخاص بك تفاصيل تنفيذ الاختبار.هذا أمر سيء لأنه الآن لديك لتغيير الاختبار في كل مرة قمت بتغيير تفاصيل تنفيذ الأسلوب الخاص بك بسبب تغيير تفاصيل تنفيذ فواصل الاختبار الخاص بك(ق)!

بعد سوء الاختبارات هو في الواقع أسوأ من عدم وجود اختبارات في جميع.

في المثال الخاص بك:

void DoIt(IZipper zipper, IFileSystem fileSystem, IDllRunner runner)
{
   string path = zipper.Unzip(theZipFile);
   IFakeFile file = fileSystem.Open(path);
   runner.Run(file);
}

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

// Assuming that zipper, fileSystem, and runner are mocks
void testDoIt()
{
  // mock behavior of the mock objects
  when(zipper.Unzip(any(File.class)).thenReturn("some path");
  when(fileSystem.Open("some path")).thenReturn(mock(IFakeFile.class));

  // run the test
  someObject.DoIt(zipper, fileSystem, runner);

  // verify things were called
  verify(zipper).Unzip(any(File.class));
  verify(fileSystem).Open("some path"));
  verify(runner).Run(file);
}

تهانينا, أنت في الأساس نسخ-لصق تنفيذ تفاصيل DoIt() الطريقة في الاختبار.سعيدة المحافظة.

عند كتابة الاختبارات كنت ترغب في اختبار ما وليس كيف. انظر اختبار الصندوق الأسود لمزيد من.

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

التفكير في الأمر بهذه الطريقة ، اسأل نفسك:

"إذا قمت بتغيير تفاصيل تنفيذ هذا الأسلوب (دون تغيير العقود العامة) وسوف كسر بلدي اختبار(ق)؟"

إذا كان الجواب نعم ، أنت اختبار كيف وليس ما.

للإجابة على سؤال محدد حول اختبار التعليمات البرمجية مع نظام الملفات تبعيات دعنا نقول أن لديك شيئا قليلا أكثر إثارة للاهتمام يحدث مع الملف و أردت حفظ Base64 في ترميز محتويات byte[] إلى ملف.يمكنك استخدام تيارات لهذا لاختبار الخاص بك التعليمات البرمجية يفعل الشيء الصحيح دون الحاجة إلى مراجعة كيف فإنه يفعل ذلك.مثال واحد قد يكون شيئا من هذا القبيل (Java):

interface StreamFactory {
    OutputStream outStream();
    InputStream inStream();
}

class Base64FileWriter {
    public void write(byte[] contents, StreamFactory streamFactory) {
        OutputStream outputStream = streamFactory.outStream();
        outputStream.write(Base64.encodeBase64(contents));
    }
}

@Test
public void save_shouldBase64EncodeContents() {
    OutputStream outputStream = new ByteArrayOutputStream();
    StreamFactory streamFactory = mock(StreamFactory.class);
    when(streamFactory.outStream()).thenReturn(outputStream);

    // Run the method under test
    Base64FileWriter fileWriter = new Base64FileWriter();
    fileWriter.write("Man".getBytes(), streamFactory);

    // Assert we saved the base64 encoded contents
    assertThat(outputStream.toString()).isEqualTo("TWFu");
}

اختبار يستخدم ByteArrayOutputStream ولكن في التطبيق (باستخدام حقن التبعية) الحقيقي StreamFactory (ربما يسمى FileStreamFactory) سيعود FileOutputStream من outputStream() و أن يكتب إلى File.

ما كان مثيرا للاهتمام حول write طريقة هنا هو أنه كان يكتب المحتويات ترميز Base64, وهذا ما نحن اختبار.الخاص بك DoIt() الأسلوب هذا من شأنه أن يكون من الأنسب اختبار مع اختبار التكامل.

أنا متحفظا إلى تلوث قانون بلدي مع أنواع والمفاهيم التي توجد فقط لتسهيل اختبار وحدة.بالتأكيد, إذا كان يجعل التصميم النظيف وأفضل عظيم ، ولكن أعتقد أن هذا هو الحال في كثير من الأحيان.

بلدي يأخذ على هذا هو أن وحدة الاختبارات أن تفعل بقدر ما يمكن التي قد لا تكون 100% التغطية.في الواقع, قد يكون فقط 10%.النقطة هي وحدة الاختبارات يجب أن تكون سريعة ولا التبعيات الخارجية.قد اختبار الحالات مثل "هذا الأسلوب يلقي ArgumentNullException عند تمرير null لهذه المعلمة".

ثم أود أن أضيف اختبارات التكامل (أيضا الآلي و ربما باستخدام نفس اختبار وحدة الإطار) التي يمكن أن يكون لها تبعيات خارجية و اختبار نهاية إلى نهاية سيناريوهات مثل هذه.

عند قياس مدونة التغطية أنا قياس كل وحدة و تكامل الاختبارات.

لا يوجد شيء خاطئ مع ضرب نظام الملفات فقط نعتبره اختبار التكامل بدلا من اختبار الوحدة.كنت مبادلة المسار الثابت ترميز مع مسار نسبي وخلق TestData فرعي تحتوي على الكود البريدية من أجل وحدة الاختبارات.

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

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

طريقة واحدة أن تكتب بفك طريقة اتخاذ InputStreams.ثم اختبار وحدة يمكن بناء مثل هذا InputStream من صفيف بايت باستخدام ByteArrayInputStream.محتويات هذا صفيف بايت يمكن أن تكون ثابتة في اختبار الوحدة البرمجية.

هذا يبدو أن يكون أكثر من اختبار التكامل كما كنت اعتمادا على التفاصيل المحددة (نظام الملفات) التي يمكن أن تغير من الناحية النظرية.

أنا مجردة الكود الذي يتعامل مع نظام التشغيل إلى أنها تملك وحدة (الدرجة, الجمعية, جرة, أيا كان).في حال كنت ترغب في تحميل DLL معينة إذا وجدت ، لذا جعل IDllLoader واجهة DllLoader الدرجة.يكون التطبيق الخاص بك الحصول على دلل من DllLoader باستخدام واجهة اختبار ..أنت لست مسؤولا عن بفك رمز أنس الحق ؟

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

يجب أن لا فئة اختبار التفاعل وظيفة الدعوة.بدلا من ذلك يجب عليك أن تنظر اختبار التكامل.اختبار النتيجة المطلوبة وليس ملف التحميل العملية.

من أجل اختبار وحدة وأود أن أقترح عليك أن تشمل اختبار ملف في المشروع(الأذن الملف أو ما يعادلها) ثم استخدام مسار نسبي في وحدة الاختبارات أي"../testdata/testfile".

طالما المشروع الخاص بك بشكل صحيح تصدير/استيراد من وحدة اختبار يجب أن تعمل.

كما قال آخرون ، الأول هو بخير بمثابة اختبار التكامل.الثاني الاختبارات فقط ما هي وظيفة من المفترض أن تفعل في الواقع ، وهو كل وحدة اختبار ينبغي القيام به.

كما هو موضح في المثال الثاني يبدو قليلا غير المجدي ، ولكنها تعطيك الفرصة لاختبار مدى الدالة يستجيب أخطاء في أي من الخطوات.لم يكن لديك أي تدقيق الأخطاء في المثال ، ولكن في النظام الحقيقي قد يكون لديك, و حقن التبعية سوف تمكنك من اختبار جميع الردود على أي أخطاء.ثم التكلفة سوف يكون يستحق ذلك.

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