كيفية إيقاف جميع الاختبارات من داخل الاختبار أو الإعداد باستخدام Unittest؟
-
25-09-2019 - |
سؤال
أقوم بتمديد بيثون 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'