পাইথন ফাংশন একটি ব্যতিক্রম ছুঁড়ে ফেলেছে তা আপনি কীভাবে পরীক্ষা করবেন?


উত্তর:


679

ইউনিটেটেস্ট মডিউল থেকে TestCase.assertRaises(বা TestCase.failUnlessRaises) ব্যবহার করুন , উদাহরণস্বরূপ:

import mymod

class MyTestCase(unittest.TestCase):
    def test1(self):
        self.assertRaises(SomeCoolException, mymod.myfunc)

9
এর বিপরীত করার কোন উপায় আছে? এটির মতো ব্যর্থ হয় কেবল যদি ফাংশনটি ব্যতিক্রম ছুঁড়ে ফেলে?
বুইআইভেনভেন্ট

67
নোট করুন যে আপনাকে আর্গুমেন্টগুলি পাস myfuncকরার জন্য সেগুলি অ্যাসেটরাইজস কলটিতে যুক্তি হিসাবে যুক্ত করা দরকার to ড্যারিল স্পিজিটরের উত্তর দেখুন।
cbron

1
একাধিক ব্যতিক্রম ধরণের অনুমতি দেওয়ার কোনও উপায় আছে কি?
দিনেশ

1
দাবীটি দ্রুত পরীক্ষা করতে আপনি পাইথনের বিল্ট-ইন ব্যতিক্রমগুলি ব্যবহার করতে পারেন; @ উদাহরণস্বরূপ উপরে মো এর উত্তর ব্যবহার করছে: self.assertRaises(TypeError, mymod.myfunc)। আপনি এখানে অন্তর্নির্মিত ব্যতিক্রমগুলির একটি সম্পূর্ণ তালিকা পেতে পারেন: ডকস.পিথথন.আর
রায়মন্ড ওয়াচাগা

3
শ্রেণি নির্মাণকারীদের পরীক্ষার জন্য একই জিনিস:self.assertRaises(SomeCoolException, Constructor, arg1)
tschmann

475

পাইথন ২.7 যেহেতু আপনি ফেলে দেওয়া প্রকৃত ব্যতিক্রমী অবজেক্টটির প্রাপ্যতা পেতে প্রসঙ্গ পরিচালক ব্যবহার করতে পারেন:

import unittest

def broken_function():
    raise Exception('This is broken')

class MyTestCase(unittest.TestCase):
    def test(self):
        with self.assertRaises(Exception) as context:
            broken_function()

        self.assertTrue('This is broken' in context.exception)

if __name__ == '__main__':
    unittest.main()

http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises


ইন পাইথন 3.5 , আপনি মোড়ানো আছে context.exceptionমধ্যে str, অন্যথায় আপনি একটি পাবেনTypeError

self.assertTrue('This is broken' in str(context.exception))

6
আমি পাইথন ২.7.১০ ব্যবহার করছি এবং উপরেরটি কাজ করে না; context.exceptionবার্তা দেয় না; এটা এক প্রকার
লেটকোডার

6
পাইথন ২.7 এ (কমপক্ষে আমার ২.7..6 এর মধ্যে) ব্যবহার করেও import unittest2আপনার ব্যবহার করা দরকার str(), যেমন self.assertTrue('This is broken' in str(context.exception))
সোহেল সি

4
দুটি জিনিস: 1. আপনি assertTrue এর পরিবর্তে assertIn ব্যবহার করতে পারেন। উদাহরণস্বরূপ self.assertIn ('এটি ভাঙা', প্রসঙ্গ। এক্সসেপশন) ২. আমার ক্ষেত্রে, ২.7.১০ ব্যবহার করে, প্রসঙ্গটি.অ্যাসেপশন অক্ষরের অ্যারে হিসাবে উপস্থিত বলে মনে হচ্ছে। Str ব্যবহার করে কাজ হয় না। আমি এটি শেষ করে দিয়েছি: '' .জয়েন (প্রসঙ্গ। এক্সসেপশন) সুতরাং, একসাথে রাখুন: self.assertIn ('এটি ভেঙে গেছে', '' .জয়েন (প্রসঙ্গ। এক্সসেপশন))
ব্লকসিফার

1
আপনার পদ্ধতিটি ব্যতিক্রমের ট্রেসব্যাকের সাহায্যে পরীক্ষার কনসোলটি বন্ধ করে দেওয়া কি স্বাভাবিক? আমি কীভাবে এটি ঘটতে রোধ করব?
ম্যাডফিসিসিস্ট

1
পরে আমি এই ব্যতিক্রমটি হিসাবে বার্তাটি পাওয়ার আরও একটি উপায় খুঁজে পেয়েছি, এটি ত্রুটিযুক্ত = প্রসঙ্গ ex এক্সসেপশন.মেসেজ। এবং তারপরে পরীক্ষার জন্য স্ব.অ্যাসেটএকুয়াল (ভুল, 'এটি ভাঙা') ব্যবহার করতে পারেন।
zhihong

326

আমার আগের উত্তরের কোডটি এখানে সরল করা যেতে পারে:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction)

এবং যদি কার্যকারিতাটি আর্গুমেন্ট নেয়, কেবল তাদের এন্টারট্রেস রাইজেস করুন:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction, arg1, arg2)

17
যুক্তিটি পাস হওয়ার পরে দ্বিতীয়টি কীভাবে করা উচিত তা সত্যিই সহায়ক ছিল।
সব্যসাচি

আমি ব্যবহার করছি 2.7.15। তাহলে afunctionself.assertRaises(ExpectedException, afunction, arg1, arg2)বর্গ সূচনাকারী হয়, তাহলে আপনি পাস করতে হবে selfপ্রথম আর্গুমেন্ট যেমন, যেমন self.assertRaises(ExpectedException, Class, self, arg1, arg2)
মিন Tran

128

পাইথন ফাংশন একটি ব্যতিক্রম ছুঁড়ে ফেলেছে তা আপনি কীভাবে পরীক্ষা করবেন?

কোনও ফাংশন প্রত্যাশিত ব্যতিক্রম না ছুঁড়লে কেবলমাত্র কীভাবে একটি পরীক্ষা লিখবে?

সংক্ষিপ্ত উত্তর:

self.assertRaisesপ্রসঙ্গ পরিচালক হিসাবে পদ্ধতিটি ব্যবহার করুন :

    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'

প্রদর্শন

পাইথন শেলটিতে সর্বোত্তম অনুশীলনের পদ্ধতির প্রদর্শন করা মোটামুটি সহজ।

unittestগ্রন্থাগার

পাইথন ২.7 বা 3 তে:

import unittest

পাইথন ২.6-এ, আপনি ইউনিটএস্ট 2unittest নামে পরিচিত 2.7 এর লাইব্রেরির একটি ব্যাকপোর্ট ইনস্টল করতে পারেন এবং কেবল এটির নাম হিসাবে unittest:

import unittest2 as unittest

উদাহরণ পরীক্ষা

পাইথনের টাইপ-সুরক্ষার জন্য নিম্নলিখিত পরীক্ষাটি এখন আপনার পাইথন শেলটিতে আটকান:

class MyTestCase(unittest.TestCase):
    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'
    def test_2_cannot_add_int_and_str(self):
        import operator
        self.assertRaises(TypeError, operator.add, 1, '1')

পরীক্ষার এক ব্যবহার assertRaises প্রসঙ্গ পরিচালক হিসাবে করে, যা নিশ্চিত করে যে ত্রুটিটি সঠিকভাবে ধরা হয়েছে এবং রেকর্ড করার সময় পরিষ্কার হয়েছে।

আমরা প্রসঙ্গ পরিচালক ছাড়া এটি লিখতেও পারি, পরীক্ষা দুটি দেখুন। প্রথম যুক্তিটি হ'ল আপনি যে ত্রুটিটি উত্থাপনের প্রত্যাশা করছেন সেটি, দ্বিতীয় যুক্তি, আপনি যে ফাংশনটি পরীক্ষা করছেন এবং বাকি আরগস এবং কীওয়ার্ড আরগগুলি সেই ফাংশনে পাঠানো হবে।

আমি মনে করি এটি কেবল প্রসঙ্গ ব্যবস্থাপককে ব্যবহার করার জন্য আরও সহজ, পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য।

পরীক্ষা চলছে

পরীক্ষা চালাতে:

unittest.main(exit=False)

পাইথন ২.6 এ আপনার সম্ভবত নিম্নলিখিতগুলির প্রয়োজন হবে :

unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

এবং আপনার টার্মিনালটি নিম্নলিখিত আউটপুট করা উচিত:

..
----------------------------------------------------------------------
Ran 2 tests in 0.007s

OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>

এবং আমরা দেখতে পাচ্ছি যে আমরা প্রত্যাশা মতো একটি যুক্ত করার চেষ্টা করেছি 1এবং এর '1'ফলে একটি TypeError


আরও ভার্বোজ আউটপুট জন্য, এই চেষ্টা করুন:

unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

56

আপনার কোডটি এই প্যাটার্নটি অনুসরণ করবে (এটি এককতম মডিউল শৈলীর পরীক্ষা):

def test_afunction_throws_exception(self):
    try:
        afunction()
    except ExpectedException:
        pass
    except Exception:
       self.fail('unexpected exception raised')
    else:
       self.fail('ExpectedException not raised')

পাইথন <2.7 এ এই নির্মাণটি প্রত্যাশিত ব্যতিক্রমগুলিতে সুনির্দিষ্ট মানগুলি পরীক্ষা করার জন্য দরকারী। ইউনিটেটেস্ট ফাংশনটি assertRaisesকেবলমাত্র তার ব্যতিক্রম উত্থাপিত হয়েছিল কিনা তা পরীক্ষা করে।


3
এবং মেথড.ফয়েল কেবল একটি যুক্তি নেয়
এমডব

3
এটি কোনও ফাংশন ব্যতিক্রম ছুঁড়ে ফেললে পরীক্ষার জন্য এটি অত্যধিক জটিল বলে মনে হয়। যেহেতু ব্যতিক্রম ব্যতীত অন্য কোনও ব্যতিক্রম পরীক্ষায় ত্রুটি ঘটবে এবং একটি ব্যতিক্রম না ছোঁড়লে পরীক্ষায় ব্যর্থ হবে, তবে এটির মতই হ'ল একমাত্র পার্থক্য হ'ল আপনি যদি আলাদা ব্যতিক্রম পেয়ে থাকেন তবে একটি ব্যর্থতার assertRaisesপরিবর্তে একটি ত্রুটি পাবেন।
55-15

24

থেকে: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/

প্রথমত, এখানে dum_function.py ফাইলের সম্পর্কিত (এখনও ডাম: পি) ফাংশনটি দিচ্ছি:

def square_value(a):
   """
   Returns the square value of a.
   """
   try:
       out = a*a
   except TypeError:
       raise TypeError("Input should be a string:")

   return out

এখানে পরীক্ষাটি করা হবে (কেবলমাত্র এই পরীক্ষাটি সন্নিবেশ করা হয়েছে):

import dum_function as df # import function module
import unittest
class Test(unittest.TestCase):
   """
      The class inherits from unittest
      """
   def setUp(self):
       """
       This method is called before each test
       """
       self.false_int = "A"

   def tearDown(self):
       """
       This method is called after each test
       """
       pass
      #---
         ## TESTS
   def test_square_value(self):
       # assertRaises(excClass, callableObj) prototype
       self.assertRaises(TypeError, df.square_value(self.false_int))

   if __name__ == "__main__":
       unittest.main()

আমরা এখন আমাদের ফাংশন পরীক্ষা করতে প্রস্তুত! পরীক্ষা চালানোর চেষ্টা করার পরে যা ঘটে তা এখানে:

======================================================================
ERROR: test_square_value (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dum_function.py", line 22, in test_square_value
    self.assertRaises(TypeError, df.square_value(self.false_int))
  File "/home/jlengrand/Desktop/function.py", line 8, in square_value
    raise TypeError("Input should be a string:")
TypeError: Input should be a string:

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

TypeError হল অ্যাক্টুল্লে উত্থাপিত, এবং একটি পরীক্ষায় ব্যর্থতা উত্পন্ন করে। সমস্যাটি হ'ল এটি হ'ল আমাদের ঠিক আচরণ: এস।

এই ত্রুটিটি এড়াতে, পরীক্ষা কলটিতে ল্যাম্বদা ব্যবহার করে কেবল ফাংশনটি চালান:

self.assertRaises(TypeError, lambda: df.square_value(self.false_int))

চূড়ান্ত আউটপুট:

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

পারফেক্ট!

... এবং আমার জন্যও নিখুঁত !!

থানস্ক অনেক মিঃ জুলিয়েন লেনগ্র্যান্ড-ল্যামবার্ট


এই পরীক্ষার দাবী আসলে একটি মিথ্যা ধনাত্মক ফেরত দেয় । এটি ঘটে কারণ 'অ্যাসেটরাইজেস' এর ভিতরে থাকা ল্যাম্বদা হ'ল একক যা পরীক্ষিত ক্রিয়াকলাপটি নয়, তবে টাইপ ত্রুটি উত্থাপন করে।


10
কেবল একটি নোট, আপনার ল্যাম্বডা লাগবে না। লাইনটি self.assertRaises(TypeError, df.square_value(self.false_int))পদ্ধতিটিতে কল করে ফলাফলটি দেয়। আপনি যা চান তা হ'ল পদ্ধতি এবং কোনও যুক্তি পাস করা এবং একককে এটি কল করতে দিন:self.assertRaises(TypeError, df.square_value, self.false_int)
রোমান কুতলাক

অনেক ধন্যবাদ. পুরোপুরি কাজ করে
চন্দন কুমার

14

contextmanagerব্যতিক্রমটি উত্থাপিত হয়েছে কিনা তা পরীক্ষা করতে আপনি নিজের তৈরি করতে পারেন।

import contextlib

@contextlib.contextmanager
def raises(exception):
    try:
        yield 
    except exception as e:
        assert True
    else:
        assert False

এবং তারপরে আপনি এটির raisesমতো ব্যবহার করতে পারেন :

with raises(Exception):
    print "Hola"  # Calls assert False

with raises(Exception):
    raise Exception  # Calls assert True

আপনি যদি ব্যবহার করে থাকেন তবে pytestএই জিনিসটি ইতিমধ্যে কার্যকর করা হয়েছে। আপনি করতে পারেন pytest.raises(Exception):

উদাহরণ:

def test_div_zero():
    with pytest.raises(ZeroDivisionError):
        1/0

এবং ফলাফল:

pigueiras@pigueiras$ py.test
================= test session starts =================
platform linux2 -- Python 2.6.6 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python
collected 1 items 

tests/test_div_zero.py:6: test_div_zero PASSED

1
unittestমডিউলটির প্রয়োজন নেই এমন উত্তর পোস্ট করার জন্য ধন্যবাদ !
শেরউড ক্যালওয়ে

10

আমি ডক্টেস্ট ব্যবহার করি প্রায় সর্বত্র [1] কারণ আমি একই সাথে আমার ফাংশনগুলি নথিভুক্ত ও পরীক্ষা করি তা পছন্দ করি।

এই কোডটি একবার দেখুন:

def throw_up(something, gowrong=False):
    """
    >>> throw_up('Fish n Chips')
    Traceback (most recent call last):
    ...
    Exception: Fish n Chips

    >>> throw_up('Fish n Chips', gowrong=True)
    'I feel fine!'
    """
    if gowrong:
        return "I feel fine!"
    raise Exception(something)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

যদি আপনি এই উদাহরণটি একটি মডিউলে রাখেন এবং কমান্ড লাইন থেকে চালান তবে উভয় পরীক্ষার কেসগুলি মূল্যায়ন করে পরীক্ষা করা হয়।

[1] পাইথন ডকুমেন্টেশন: ২৩.২ ডক্টেস্ট - টেস্ট ইন্টারেক্টিভ পাইথনের উদাহরণ


4
আমি ডক্টেস্ট পছন্দ করি তবে আমি এটি ইউনিটএস্টের পরিবর্তে পরিপূরক খুঁজে পাই।
টিমোথিউজম্যান

2
স্বয়ংক্রিয় রিফ্যাক্টরিংয়ের সাথে ডক্টেস্ট কি কম খেলার সম্ভাবনা কম? আমি মনে করি পাইথনের জন্য ডিজাইন করা একটি রিফ্যাক্টরিং সরঞ্জাম ডকাস্ট্রিং সম্পর্কে সচেতন হওয়া উচিত । তাদের অভিজ্ঞতা থেকে কেউ মন্তব্য করতে পারেন?
kdbanman

6

আমি সবেমাত্র আবিষ্কার করেছি যে মক গ্রন্থাগারটি একটি assertRaisesWithMessage () পদ্ধতি সরবরাহ করে (তার ইউনিটেস্টে est টেস্টকেস সাবক্লাসে), যা কেবল প্রত্যাশিত ব্যতিক্রম উত্থাপিত নয় তা পরীক্ষা করে দেখবে, তবে এটি প্রত্যাশিত বার্তার সাথেও উত্থাপিত হয়েছে:

from testcase import TestCase

import mymod

class MyTestCase(TestCase):
    def test1(self):
        self.assertRaisesWithMessage(SomeCoolException,
                                     'expected message',
                                     mymod.myfunc)

দুর্ভাগ্যবশত, এটা আর উপলব্ধ করা হয় না .. কিন্তু @Art (এর উপরে উত্তর stackoverflow.com/a/3166985/1504046 ) একই ফলাফল দেয়
Rmatt

6

এখানে অনেক উত্তর আছে। কোডটি দেখায় যে আমরা কীভাবে একটি ব্যতিক্রম তৈরি করতে পারি, কীভাবে আমরা আমাদের পদ্ধতিগুলিতে সেই ব্যতিক্রমটি ব্যবহার করতে পারি এবং শেষ পর্যন্ত কীভাবে আপনি ইউনিট পরীক্ষায় যাচাই করতে পারেন, সঠিক ব্যতিক্রমগুলি উত্থাপিত হচ্ছে।

import unittest

class DeviceException(Exception):
    def __init__(self, msg, code):
        self.msg = msg
        self.code = code
    def __str__(self):
        return repr("Error {}: {}".format(self.code, self.msg))

class MyDevice(object):
    def __init__(self):
        self.name = 'DefaultName'

    def setParameter(self, param, value):
        if isinstance(value, str):
            setattr(self, param , value)
        else:
            raise DeviceException('Incorrect type of argument passed. Name expects a string', 100001)

    def getParameter(self, param):
        return getattr(self, param)

class TestMyDevice(unittest.TestCase):

    def setUp(self):
        self.dev1 = MyDevice()

    def tearDown(self):
        del self.dev1

    def test_name(self):
        """ Test for valid input for name parameter """

        self.dev1.setParameter('name', 'MyDevice')
        name = self.dev1.getParameter('name')
        self.assertEqual(name, 'MyDevice')

    def test_invalid_name(self):
        """ Test to check if error is raised if invalid type of input is provided """

        self.assertRaises(DeviceException, self.dev1.setParameter, 'name', 1234)

    def test_exception_message(self):
        """ Test to check if correct exception message and code is raised when incorrect value is passed """

        with self.assertRaises(DeviceException) as cm:
            self.dev1.setParameter('name', 1234)
        self.assertEqual(cm.exception.msg, 'Incorrect type of argument passed. Name expects a string', 'mismatch in expected error message')
        self.assertEqual(cm.exception.code, 100001, 'mismatch in expected error code')


if __name__ == '__main__':
    unittest.main()

3

আপনি ইউনিটতম মডিউল থেকে assertRaises ব্যবহার করতে পারেন

import unittest

class TestClass():
  def raises_exception(self):
    raise Exception("test")

class MyTestCase(unittest.TestCase):
  def test_if_method_raises_correct_exception(self):
    test_class = TestClass()
    # note that you dont use () when passing the method to assertRaises
    self.assertRaises(Exception, test_class.raises_exception)

-5

যদিও সমস্ত উত্তর পুরোপুরি ঠিক আছে, আমি পরীক্ষার একটি উপায় খুঁজছিলাম যদি কোনও ফাংশন ইউনিট টেস্টিং ফ্রেমওয়ার্কের উপর নির্ভর না করে এবং পরীক্ষার ক্লাস না লিখে ব্যতিক্রম করে তোলে।

আমি নিম্নলিখিত লেখা শেষ:

def assert_error(e, x):
    try:
        e(x)
    except:
        return
    raise AssertionError()

def failing_function(x):
    raise ValueError()

def dummy_function(x):
    return x

if __name__=="__main__":
    assert_error(failing_function, 0)
    assert_error(dummy_function, 0)

এবং এটি ডান লাইনে ব্যর্থ:

Traceback (most recent call last):
  File "assert_error.py", line 16, in <module>
    assert_error(dummy_function, 0)
  File "assert_error.py", line 6, in assert_error
    raise AssertionError()
AssertionError
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.