سؤال

لأغراض اختبار الوحدة، أحتاج إلى محاكاة استجابة الشبكة.عادة ما تكون الاستجابة عبارة عن دفق بايت، يتم تخزينه كملف const vector<uint8_t>.ومع ذلك، بالنسبة لاختبار الوحدة، أرغب في إنتاج المتجه ببيانات إما مشفرة في ملف CPP أو مقروءة من ملف في نفس الحل.بيانات المثال الخاص بي تبلغ حوالي 6 كيلو بايت.ما هو التوجيه العام حول مكان وضع البيانات عند الاستخدام com.googletest?

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

المحلول

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

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

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

يوضح البرنامج التالي لاعبا اساسيا يوفر كل من البيانات القابلة للتغيير لكل حالة وبيانات ثابتة عالمية المكتسبة من الملفات.

#include <vector>
#include <fstream>
#include <stdexcept>
#include "gtest/gtest.h"

class foo_test : public ::testing::Test
{
protected:
    virtual void SetUp() {
        std::ifstream in("path/to/case_data");
        if (!in) {
            throw std::runtime_error("Could not open \"path/to/case_data\" for input");
        }
        _case_data.assign(
            std::istream_iterator<char>(in),std::istream_iterator<char>());
        if (_global_data.empty()) {
            std::ifstream in("path/to/global_data");
            if (!in) {
                throw std::runtime_error(
                    "Could not open \"path/to/global_data\" for input");
            }
            _global_data.assign(
                std::istream_iterator<char>(in),std::istream_iterator<char>());
        }
    }
    // virtual void TearDown() {}   
    std::vector<char> & case_data() {
        return _case_data;
    }
    static std::vector<char> const & global_data() {
        return _global_data;
    }

private:
    std::vector<char> _case_data;
    static std::vector<char> _global_data;

};

std::vector<char> foo_test::_global_data;

TEST_F(foo_test, CaseDataWipe) {
  EXPECT_GT(case_data().size(),0);
  case_data().resize(0);
  EXPECT_EQ(case_data().size(),0);
}

TEST_F(foo_test, CaseDataTrunc) {
  EXPECT_GT(case_data().size(),0);
  case_data().resize(1);
  EXPECT_EQ(case_data().size(),1);
}

TEST_F(foo_test, HaveGlobalData) {
  EXPECT_GT(global_data().size(),0);
}


int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

بالنسبة للحالة (أ)، قد تفكر أيضًا في الحصول على البيانات في ملف الإعداد العالميوظيفة العضو من خلال فئة فرعية ::testing::Environment, ، لكنني لا أرى أي سبب عام لفضح القيام بذلك بهذه الطريقة.

... أم أنه من الصعب رمز ذلك؟

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

كمسألة عامة ، هذه مسألة من الحكم على الحكم ، ولا أعتقد أن استخدام Googletest نصائح المقاييس ماديًا.أعتقد أن الاعتبار الرئيسي هو: هل من المستحسن أن تكون قادرًا على تغيير عنصر من عمليات الاختبار دون إعادة بناء مجموعة الاختبار؟

قل إعادة بناء مجموعة الاختبار لتغيير هذا العنصر هو تكلفة غير مؤهلة وتتوقع أن يختلف محتوى العنصر في المستقبل بشكل مستقل عن رمز الاختبار المرتبط به.أو يمكن أن تختلف ، بشكل مستقل عن رمز الاختبار المرتبط ، لتكوينات مختلفة للنظام قيد الاختبار.في هذه الحالة ، من الأفضل الحصول على العنصر من ملف أو مصدر آخر يمكن تحديده بواسطة معلمات وقت التشغيل في مجموعة الاختبار.في googletest، فئة فرعية class ::testing::Environment هو منشأة مصممة لاكتساب موارد جناح الاختبار.

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

إذا كان محتوى عنصر بيانات الاختبار يكون إلى جانب راسخ رمز الاختبار المرتبط به ، فأنا متحيزًا لأدخله الثابت بدلاً من استخراجه من ملف بيانات.مجرد منحازة، وليس ملتزمة عقائديا.ربما يستخدم جناح الاختبار الخاص بك مرافق مكتبة قوية لتهيئة بيانات اختبار API العامة من ملفات XML التي يتم ربطها أيضًا في إدارة الاختبار وإدارة العيوب.بخير!

أعتبر أنه من المرغوب فيه بوضوح أنه إذا كان ملف بيانات الاختبار هو مورد اختبار أساسي - وهو واحد لا يمكن لجنة الاختبار توليدها - عندها كان محتوىه أفضل بيانات نصية يمكن لمحشر مختص أن يفهمها بسهولة ومعالجتها.في هذا الإعداد ، سأفكر بالطبع أن قائمة ثوابت C/C ++ Hex ، على سبيل المثال ، هي قائمة البيانات النصية - إنه رمز المصدر.إذا كان ملف الاختبار يحتوي على بيانات ثنائية أو مثيرة للآلة ، فإن مجموعة الاختبار قد تحتوي على أفضل حالات إنتاجها من الموارد الأولية المقروءة.في بعض الأحيان لا يمكن تجنبها بالنسبة لمجموعة الاختبار أن تعتمد على الثنائيات "النموذجية" من مصادر خارجيًا ، لكنها تستلزم حتماً المشهد القاتم لمهندسي الاختبار وتوليد الأخطاء التي تتحول إلى اللون الرمادي أمام الحوايات السداسية.

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

تخيل أن تسلسلًا معينًا من 4096 من أعداد صحيحة غير موقعة 64 بت (الجدول السحري الكبير) مطلوب لاختبار البرنامج الخاص بك ويتم ربطه بإحكام برمز الاختبار المرتبط به.يمكن ترميزها بقوة كقائمة تهيئة ضخمة أو مصفوفة في بعض الملفات المصدر لمجموعة الاختبار.يمكن استخلاصه بواسطة جناح الاختبار من ملف بيانات يتم الاحتفاظ به بتنسيق CSV أو في خطوط CSV المغطاة.

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

ولكن يمكن مواجهة كلتا هاتين النقطتين مع ملاحظة أن الإعلان المحدد لـ BMT قد يتم ترميزه في ملف مصدر خاص به.يمكن أن تكون سياسة مراجعة التعليمات البرمجية لمجموعة الاختبار التي تهيئة بيانات الاختباريجب كن مشفرًا جدًا - وربما في الملفات التي تلتزم باتفاقية تسمية مميزة.سياسة متعصب ، بالتأكيد ، ولكن ليس أكثر متعصبة من سياسة من شأنها أن تصر على أنه يجب استخراج جميع أجهزة تهيئة بيانات الاختبار من الملفات.إذا كان المشرف ملزماً بمسح BMT في أي ملف يحتوي عليه ، فلن يحدث أي فرق عما إذا كان تمديد الملف هو .cpp, .dat أو أيا كان:كل ما يهم هو فهم "الكود".

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

في حالة أطر googletest والوظيفية المتشابهة ، يمكن مواجهة هذه النقطة ، إلى حد ما ، من خلال الإعلان عن فئات قاعدة التثبيت متعددة الأشكال مثل ::testing::Test و ::testing::Environment.هذه تسهل مطور الاختبار في تغليف اكتساب موارد الاختبار في حالة الاختبار أو تهيئة اختبار الاختبار بحيث ينتهي كل شيء ، إما بنجاح أو مع فشل تم تشخيصه ، قبل إجراء اختبارات المكونة لأي حالة اختبار.يمكن أن يحافظ RAII على فجوة غير مثيرة للمشاكل بين حالات فشل الإعداد والفشل الحقيقي.

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

منذ ملفات المصدر يمكن أن تغلف تهيئة بيانات الاختبار بشكل صحي لتتبع المراجعة ، يمكن أن يكون الترميز الثابت مساويًا للاستخراج من ملف ، مع قيام المعالج المسبق بالاستخراج كمنتج ثانوي للتجميع.وفي ضوء ذلك، لماذا نستخدم آلات أخرى، مع مسؤوليات إضافية، لاستخراجها؟قد تكون هناك إجابات جيدة ، مثل واجهة XML المقترحة مع إدارة الاختبار ، وأنظمة إدارة العيوب ، ولكن "بيانات الاختبار ، لذلك لا ترحمها" ليست جيدة.

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

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

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

الحد الأدنى:إذا كنت تريد أن تكون قادرًا على تشغيل نفس بناء مجموعة الاختبار الخاصة بك لمجموعة متنوعة من استجابات الشبكة الوهمية هذه ، فاقرأها من ملف.إذا كان من ناحية أخرى ، فهو ثابت أو متغير مع تكوينات بناء جناح الاختبار ، ولم لا؟ رمز صعب؟

نصائح أخرى

(تحذير - هذه الإجابة عامة إلى أي إطار اختبار الوحدة)

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

  • يمكنك رمز اختبار الوحدة لقبول أي ملفات بيانات متعددة لاختبار مجموعة متنوعة من المواقف
  • يمكنك تتبع التغييرات في البيانات حسب الحاجة

إذا كنت لا تريد تنفيذ اختبار الوحدة عندئذ ملف بيانات يمكن أن يكون شرطا ضروريا في بعض المواقف، فقد تختار كتابة برنامج أو برنامج نصي يقوم بإنشاء رمز C ++ الذي يتخبط متجه في إعداد FEXTURE.

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