اختبار قيمة الإرجاع من الأسلوب الذي يتسبب خطأ مع PHPUnit

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

سؤال

هذا السؤال محددة باستخدام PHPUnit.

PHPUnit تلقائيا بتحويل php أخطاء الاستثناءات. هل هناك طريقة لاختبار قيمة العائد من الطريقة التي يحدث أن يؤدي خطأ php (إما المدمج في أخطاء أو المستخدم ولدت الأخطاء عبر trigger_error)?

مثال على كود الاختبار:

function load_file ($file)
{
    if (! file_exists($file)) {
        trigger_error("file {$file} does not exist", E_USER_WARNING);
        return false;
    }
    return file_get_contents($file);
}

هذا هو نوع من اختبار أريد أن أكتب:

public function testLoadFile ()
{
    $this->assertFalse(load_file('/some/non-existent/file'));
}

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

هذا المثال لا يعمل:

public function testLoadFile ()
{
    $this->setExpectedException('Exception');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

أي أفكار كيف يمكن تحقيق ذلك ؟

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

المحلول

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

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

وربما هذا هو أسهل مع مثال, إذا, هنا ما اختبارين يجب أن تبدو مثل:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    $result = load_file('/some/non-existent/file');

}

public function testLoadFileRetunsFalseWhenFileNotFound()
{
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
    $result = load_file('/some/non-existent/file');

    $this->assertFalse($result);
}

هذا أيضا مكافأة إضافية من إجراء اختبارات أكثر وضوحا ، نظافة النفس توثيق.

Re:التعليق: هذا هو السؤال الكبير ، لم يكن لدي أي فكرة حتى لقد أجريت عدة اختبارات.يبدو كما لو أنه سوف لا استعادة الافتراضي/القيمة الأصلية, على الأقل من PHPUnit 3.3.17 (الحالية الإصدار المستقر الآن).

لذلك أنا في الواقع تعديل أعلاه أن تبدو مثل ذلك:

public function testLoadFileRetunsFalseWhenFileNotFound()
{
    $warningEnabledOrig = PHPUnit_Framework_Error_Warning::$enabled;
    PHPUnit_Framework_Error_Warning::$enabled = false;

    $result = load_file('/some/non-existent/file');

    $this->assertFalse($result);

    PHPUnit_Framework_Error_Warning::$enabled = $warningEnabledOrig;
}

Re:التعليق الثاني:

هذا ليس صحيحا تماما.أنا أبحث في PHPUnit خطأ معالج, ويعمل على النحو التالي:

  • إذا كان E_WARNING, استخدام PHPUnit_Framework_Error_Warning استثناء فئة.
  • إذا كان E_NOTICE أو E_STRICT خطأ, استخدام PHPUnit_Framework_Error_Notice
  • آخر استخدام PHPUnit_Framework_Error كما الاستثناء الدرجة.

لذا, نعم, أخطاء E_USER_* لا تحول إلى PHPUnit هو *_Warning أو *_Notice الصف أنها لا تزال تتحول إلى عام PHPUnit_Framework_Error الاستثناء.

مزيد من الأفكار

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

نصائح أخرى

استخدام phpunit.xml ملف التكوين و تعطيل إشعار/إنذار/خطأ استثناء التحويل.المزيد التفاصيل في دليل.انها في الاساس شيء من هذا القبيل:

<phpunit convertErrorsToExceptions="false"
         convertNoticesToExceptions="false"
         convertWarningsToExceptions="false">
</phpunit>

بدلا من تتوقع عامة "Exception"ماذا عن أتوقع "PHPUnit_Framework_Error" ?

شيء من هذا القبيل قد تفعل :

/**
 * @expectedException PHPUnit_Framework_Error
 */
public function testFailingInclude()
{
    include 'not_existing_file.php';
}

و أفترض أن ذلك قد يكون أيضا كما هو مكتوب :

public function testLoadFile ()
{
    $this->setExpectedException('PHPUnit_Framework_Error');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

لمزيد من المعلومات, انظر اختبار الأخطاء PHP
خصوصا أنه يقول (نقلا عن) :

PHPUnit_Framework_Error_Notice و PHPUnit_Framework_Error_Warning تمثل PHP إشعارات الإنذار ، على التوالي.


أنظر /usr/share/php/PHPUnit/TextUI/TestRunner.php الملف لدي على نظام أرى هذا (خط 198 وما بعدها) :

if (!$arguments['convertNoticesToExceptions']) {
    PHPUnit_Framework_Error_Notice::$enabled = FALSE;
}

if (!$arguments['convertWarningsToExceptions']) {
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
}

لذلك ربما سيكون لديك لتمرير بعض نوع من المعلمة إلى تفعيل هذا السلوك ؟ ولكن يبدو أن تمكين افتراضيا...

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

عليك فقط أن تفعل ما يلي:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->assertFalse(@load_file('/some/non-existent/file'));

    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    load_file('/some/non-existent/file');
}

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

ما لا تستطيع القيام به هو اختبار استثناءات متعددة داخل وحدة اختبار.

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