كيفية إيقاف جميع الاختبارات من داخل الاختبار أو الإعداد باستخدام Unittest؟

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

سؤال

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

لقد لاحظت أن TestResult لديه ملف shouldStop السمة ، و stop() الطريقة ، لكنني لست متأكدًا من كيفية الوصول إلى ذلك داخل الاختبار.

هل لدى أي شخص أي أفكار؟ هل هناك طريقة أفضل؟

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

المحلول 2

إليك إجابة أخرى توصلت إليها بعد فترة:

أولاً ، أضفت استثناء جديد:

class StopTests(Exception):
"""
Raise this exception in a test to stop the test run.

"""
    pass

ثم أضفت جديد assert إلى فصل اختبار طفلي:

def assertStopTestsIfFalse(self, statement, reason=''):
    try:
        assert statement            
    except AssertionError:
        result.addFailure(self, sys.exc_info())

وأخيراً تجاوزت run وظيفة لتضمين هذا مباشرة أدناه testMethod() يتصل:

except StopTests:
    result.addFailure(self, sys.exc_info())
    result.stop()

يعجبني هذا بشكل أفضل لأن أي اختبار لديه الآن القدرة على إيقاف جميع الاختبارات ، ولا يوجد رمز خاص بـ Cpython.

نصائح أخرى

في حال كنت مهتمًا ، إليك مثال بسيط كيف يمكنك اتخاذ قرار بشأن الخروج من مجموعة اختبار نظيفة مع Py.Test:

# content of test_module.py
import pytest
counter = 0
def setup_function(func):
    global counter
    counter += 1
    if counter >=3:
        pytest.exit("decided to stop the test run")

def test_one():
    pass
def test_two():
    pass
def test_three():
    pass

وإذا قمت بتشغيل هذا ، فستحصل على:

$ pytest test_module.py 
============== test session starts =================
platform linux2 -- Python 2.6.5 -- pytest-1.4.0a1
test path 1: test_module.py

test_module.py ..

!!!! Exit: decided to stop the test run !!!!!!!!!!!!
============= 2 passed in 0.08 seconds =============

يمكنك أيضا وضع py.test.exit() اتصل داخل اختبار أو في البرنامج المساعد الخاص بالمشروع.

ملاحظة جانبية: py.test يدعم أصلاً py.test --maxfail=NUM لتنفيذ التوقف بعد فشل NUM.

Sidenote2: py.test لديه دعم محدود فقط لإجراء اختبارات في التقليدية unittest.TestCase نمط.

حاليا ، يمكنك فقط إيقاف الاختبارات على مستوى الجناح. بمجرد أن تكون في TestCase, ، ال stop() طريقة ل TestResult لا يستخدم عند التكرار من خلال الاختبارات.

مرتبط إلى حد ما بسؤالك ، إذا كنت تستخدم Python 2.7 ، يمكنك استخدام -f/--failfast العلم عند الاتصال باختبارك مع python -m unittest. هذا سيوقف الاختبار عند الفشل الأول.

يرى 25.3.2.1. Failfast ، خيارات سطر الأوامر المشتركة والمخزن المؤقت

يمكنك أيضًا التفكير في استخدام أنف لتشغيل الاختبارات الخاصة بك واستخدام -x, --stop علَم لوقف الاختبار في وقت مبكر.

في حلقة اختبار unittest.TestSuite, ، هناك break الحالة في البداية:

class TestSuite(BaseTestSuite):

    def run(self, result, debug=False):
        topLevel = False
        if getattr(result, '_testRunEntered', False) is False:
            result._testRunEntered = topLevel = True

        for test in self:
            if result.shouldStop:
                break

لذلك أنا أستخدم جناح اختبار مخصص مثل هذا:

class CustomTestSuite(unittest.TestSuite):
    """ This variant registers the test result object with all ScriptedTests,
        so that a failed Loign test can abort the test suite by setting result.shouldStop
        to True
    """
    def run(self, result, debug=False):
        for test in self._tests:
            test.result = result

        return super(CustomTestSuite, self).run(result, debug)

مع فئة نتائج اختبار مخصصة مثل هذا:

class CustomTestResult(TextTestResult):
    def __init__(self, stream, descriptions, verbosity):
        super(CustomTestResult, self).__init__(stream, descriptions, verbosity)
        self.verbosity = verbosity
        self.shouldStop = False

وفصول الاختبار الخاصة بي مثل:

class ScriptedTest(unittest.TestCase):
    def __init__(self, environment, test_cfg, module, test):
        super(ScriptedTest, self).__init__()
        self.result = None

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

    try:
        test_case.execute_script(test_command_list)
    except AssertionError as e:
        if test_case.module == 'session' and test_case.test == 'Login':
            test_case.result.shouldStop = True
            raise TestFatal('Login failed, aborting test.')
        else:
            raise sys.exc_info()

ثم أستخدم مجموعة الاختبار بالطريقة التالية:

    suite = CustomTestSuite()

    self.add_tests(suite)

    result = unittest.TextTestRunner(verbosity=self.environment.verbosity, stream=UnitTestLoggerStream(self.logger),
                                     resultclass=CustomTestResult).run(suite)

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

نظرت إلى TestCase الفصل وقررت فئة فرعية. الفصل يتجاوز فقط run(). لقد قمت بنسخ الطريقة والبدء في السطر 318 في الفئة الأصلية أضافت هذا:

# this is CPython specific. Jython and IronPython may do this differently
if testMethod.func_code.co_argcount == 2:
    testMethod(result)
else:
    testMethod()

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

على الرغم من أنك لن تحصل على تقارير الاختبار المعتادة للاختبارات التي يتم تشغيلها حتى الآن ، إلا أن هناك طريقة سهلة للغاية لإيقاف الاختبار من داخل TestCase الطريقة ببساطة للتربية KeyboardInterrupt داخل الطريقة.

يمكنك أن ترى كيف فقط KeyboardInterrupt يُسمح له بالفقاعة في الداخل unittestعداء اختبار من خلال النظر في رمز Cpython هنا داخل testPartExecutor().

يستخدم:

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