যখন দৃ .়তা ব্যর্থ হয় পাইথনের ইউনিটেস্টে চালিয়ে যাওয়া


84

সম্পাদনা: আরও ভাল উদাহরণে পরিবর্তন করা হয়েছে এবং কেন এটি আসল সমস্যা তা স্পষ্ট করে জানিয়েছে।

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

class Car(object):
  def __init__(self, make, model):
    self.make = make
    self.model = make  # Copy and paste error: should be model.
    self.has_seats = True
    self.wheel_count = 3  # Typo: should be 4.

class CarTest(unittest.TestCase):
  def test_init(self):
    make = "Ford"
    model = "Model T"
    car = Car(make=make, model=model)
    self.assertEqual(car.make, make)
    self.assertEqual(car.model, model)  # Failure!
    self.assertTrue(car.has_seats)
    self.assertEqual(car.wheel_count, 4)  # Failure!

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

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

তুলনার জন্য, গুগলের সি ++ ইউনিট পরীক্ষার কাঠামো অ-মারাত্মক বক্তব্য এবং মারাত্মক বক্তব্যগুলির মধ্যে পার্থক্য করে :EXPECT_*ASSERT_*

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

EXPECT_*পাইথন-এর মতো আচরণ করার কোনও উপায় আছে কি unittest? যদি না থাকে unittest, তবে অন্য পাইথন ইউনিট পরীক্ষার কাঠামো রয়েছে যা এই আচরণকে সমর্থন করে?


ঘটনাচক্রে, আমি কৌতূহলী ছিলাম যে কতগুলি বাস্তব-জীবনের পরীক্ষাগুলি অ-মারাত্মক বক্তব্যগুলি থেকে উপকৃত হতে পারে, তাই আমি কয়েকটি কোড উদাহরণগুলিতে (গুগল কোড অনুসন্ধান, আরআইপি পরিবর্তে সার্চকোড ব্যবহার করতে 2014-08-19 সম্পাদিত) তাকালাম। প্রথম পৃষ্ঠা থেকে এলোমেলোভাবে নির্বাচিত ফলাফলগুলির মধ্যে 10 টিতে একই পরীক্ষা পদ্ধতিতে একাধিক স্বতন্ত্র জোর দিয়েছিল এমন সমস্ত পরীক্ষা রয়েছে। অ-মারাত্মক বক্তব্যগুলি থেকে সকলেই উপকৃত হবেন।


4
আপনি কি শেষ করেছেন? আমি এই বিষয়ে আগ্রহী (সম্পূর্ণ ভিন্ন কারণে যা আমি মন্তব্যের চেয়ে আরও প্রশস্ত জায়গায় আলোচনা করে খুশি হতে পারি) এবং আপনার অভিজ্ঞতা জানতে চাই। যাইহোক, "কোড উদাহরণগুলি" লিঙ্কটি "দুঃখের সাথে, এই পরিষেবাটি বন্ধ হয়ে গেছে" দিয়ে শেষ হয়, সুতরাং আপনার যদি এটির ক্যাশেড সংস্করণ থাকে তবে আমি এটিও দেখতে আগ্রহী হব।
ডেভিড

ভবিষ্যতে উল্লেখের জন্য, আমি বিশ্বাস করি এই বর্তমান সিস্টেমে সমতুল্য অনুসন্ধান, কিন্তু ফলাফল আর উপরে বর্ণিত আছে।
জ্যাড-ম্যান

4
@ ডেভিড, আমি কিছু করতে শেষ করিনি। "পদ্ধতি অনুসারে কেবলমাত্র একটি দৃ make়তা তৈরি করুন" পদ্ধতির বিষয়টি আমার কাছে খুব কঠোরভাবে মনে হচ্ছে না, তবে একমাত্র কার্যক্ষম (এবং রক্ষণাবেক্ষণযোগ্য) সমাধানটি মনে হয় অ্যান্টনির "ধরা এবং সংযোজন" পরামর্শ। যদিও এটি আমার পক্ষে খুব কুরুচিপূর্ণ, সুতরাং আমি কেবল পদ্ধতি অনুসারে একাধিক দৃ with়তার সাথে আটকেছি এবং সমস্ত ব্যর্থতা খুঁজে পাওয়ার জন্য আমাকে চলমান পরীক্ষাগুলির সাথে আরও অনেকবার বেঁচে থাকতে হবে।
ব্রুস ক্রিস্টেনসেন

পাইটেষ্ট নামক পাইথন টেস্টিং ফ্রেমওয়ার্কটি বেশ স্বজ্ঞাত এবং ডিফল্টরূপে সমস্ত দৃsert় ব্যর্থতা দেখায়। এটি আপনি যে সমস্যার মুখোমুখি হচ্ছেন সেটি প্রায় কাজ করতে পারে।
সূর্য শেখর চক্রবর্তী

উত্তর:


9

আপনি সম্ভবত যা করতে চাইবেন তা হ'ল unittest.TestCaseযেহেতু সেই ক্লাসটি যা ছুঁড়ে ফেলা হয় যখন দৃ as়তা ব্যর্থ হয়। আপনার TestCaseনিক্ষেপ না করার জন্য আপনাকে পুনর্নির্মাণ করতে হবে (পরিবর্তে ব্যর্থতার একটি তালিকা রাখবেন)) রি-আর্কিটেকিং স্টাফ আপনাকে সমাধান করতে হবে এমন অন্যান্য সমস্যাগুলির কারণ হতে পারে। উদাহরণস্বরূপ, আপনার নিজের TestSuiteপরিবর্তিত পরিবর্তনের সমর্থনে পরিবর্তন আনার প্রয়োজন হতে পারে TestCase


4
আমি অনুভব করেছি যে এটি সম্ভবত শেষ উত্তর হতে পারে তবে আমি আমার ঘাঁটিগুলি coverাকতে চাই এবং আমি কিছু মিস করছি কিনা তা দেখতে চেয়েছিলাম। ধন্যবাদ!
ব্রুস ক্রিস্টেনসেন

4
আমি বলব যে TestCaseনরম দৃ implementing়তা বাস্তবায়নের স্বার্থে ওভাররাইড করা ওভারকিল - এগুলি অজগর তৈরি করা বিশেষত সহজ: আপনার AssertionErrorসমস্তগুলি (সম্ভবত একটি সাধারণ লুপে) ধরুন এবং সেগুলি একটি তালিকা বা একটি সেটে সঞ্চয় করুন , তারপরে একবারে সমস্ত ব্যর্থ করুন। সুনির্দিষ্ট জন্য অ্যান্থনি ব্যাচেলর এর উত্তর দেখুন।
dcsordas

4
@dscordas এটি নির্ভর করে যদি এটি এক পরীক্ষার বাইরে থাকে বা আপনি যদি বেশিরভাগ পরীক্ষার জন্য এই ক্ষমতা অর্জন করতে চান।
ডায়েটবুদ্ধ

44

অ-মারাত্মক দৃser়তা থাকার আরেকটি উপায় হ'ল দৃ exception় ব্যতিক্রম ক্যাপচার এবং ব্যতিক্রমগুলি একটি তালিকায় সংরক্ষণ করে। তারপরে দৃsert়ভাবে দাবি করুন যে টিয়ারডাউন অংশ হিসাবে সেই তালিকাটি খালি।

import unittest

class Car(object):
  def __init__(self, make, model):
    self.make = make
    self.model = make  # Copy and paste error: should be model.
    self.has_seats = True
    self.wheel_count = 3  # Typo: should be 4.

class CarTest(unittest.TestCase):
  def setUp(self):
    self.verificationErrors = []

  def tearDown(self):
    self.assertEqual([], self.verificationErrors)

  def test_init(self):
    make = "Ford"
    model = "Model T"
    car = Car(make=make, model=model)
    try: self.assertEqual(car.make, make)
    except AssertionError, e: self.verificationErrors.append(str(e))
    try: self.assertEqual(car.model, model)  # Failure!
    except AssertionError, e: self.verificationErrors.append(str(e))
    try: self.assertTrue(car.has_seats)
    except AssertionError, e: self.verificationErrors.append(str(e))
    try: self.assertEqual(car.wheel_count, 4)  # Failure!
    except AssertionError, e: self.verificationErrors.append(str(e))

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

4
খুব নিশ্চিত যে আমি আপনার সাথে একমত। পাইথন ব্যাকএন্ডে সেলেনিয়াম যাচাইকরণের ত্রুটিগুলির সাথে এটি পরিচালনা করে।
অ্যান্টনি ব্যাচেলর

হ্যাঁ, এই সমাধানটির সাথে সমস্যাটি হ'ল সমস্ত দাবিগুলি ত্রুটি হিসাবে গণ্য করা হয় (ব্যর্থ হয় না) এবং ত্রুটিগুলি রেন্ডার করার উপায়টি আসলে ব্যবহারযোগ্য নয়। যাইহোক একটি উপায় এবং রেন্ডার ফাংশনটি সহজেই উন্নত করা যেতে পারে
eMarine

আমি এই সমাধানটি ডায়েটবুদ্ধার উত্তরের সাথে মিশ্রণে ব্যবহার করে unittest.TestCaseচেষ্টা করছি / ব্লকগুলি ব্যতীত সমস্ত দাবিগুলি ওভাররাইড করে।
থোডিক

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

এটি অত্যন্ত চতুর, তাই আপনার কাছে টুপিগুলি।
আদালতগণ

31

একটি বিকল্প টিউপল হিসাবে একবারে সমস্ত মানগুলিতে দৃsert় থাকে।

উদাহরণ স্বরূপ:

class CarTest(unittest.TestCase):
  def test_init(self):
    make = "Ford"
    model = "Model T"
    car = Car(make=make, model=model)
    self.assertEqual(
            (car.make, car.model, car.has_seats, car.wheel_count),
            (make, model, True, 4))

এই পরীক্ষাগুলি থেকে আউটপুট হবে:

======================================================================
FAIL: test_init (test.CarTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\temp\py_mult_assert\test.py", line 17, in test_init
    (make, model, True, 4))
AssertionError: Tuples differ: ('Ford', 'Ford', True, 3) != ('Ford', 'Model T', True, 4)

First differing element 1:
Ford
Model T

- ('Ford', 'Ford', True, 3)
?           ^ -          ^

+ ('Ford', 'Model T', True, 4)
?           ^  ++++         ^

এটি দেখায় যে মডেল এবং চাকা গণনা উভয়ই ভুল।


এটি স্মার্ট। আমি এখনও অবধি সেরা সমাধান খুঁজে পেয়েছি।
চেন নি

8

পাইথন ৩.৪ থেকে আপনি সাবসেটগুলিও ব্যবহার করতে পারেন :

def test_init(self):
    make = "Ford"
    model = "Model T"
    car = Car(make=make, model=model)
    with self.subTest(msg='Car.make check'):
        self.assertEqual(car.make, make)
    with self.subTest(msg='Car.model check'):
        self.assertEqual(car.model, model)
    with self.subTest(msg='Car.has_seats check'):
        self.assertTrue(car.has_seats)
    with self.subTest(msg='Car.wheel_count check'):
        self.assertEqual(car.wheel_count, 4)

( msgকোন পরীক্ষায় ব্যর্থ হয়েছে তা আরও সহজে নির্ধারণ করতে প্যারামিটার ব্যবহার করা হয়))

আউটপুট:

======================================================================
FAIL: test_init (__main__.CarTest) [Car.model check]
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 23, in test_init
    self.assertEqual(car.model, model)
AssertionError: 'Ford' != 'Model T'
- Ford
+ Model T


======================================================================
FAIL: test_init (__main__.CarTest) [Car.wheel_count check]
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 27, in test_init
    self.assertEqual(car.wheel_count, 4)
AssertionError: 3 != 4

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=2)

4
বিদ্যমান কোডে ড্রপ করা সবচেয়ে সহজ হিসাবে এটি এখন গ্রহণযোগ্য উত্তর হওয়া উচিত।
মাইকেল স্কট কুথবার্ট

7

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

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


4
@ ব্রুস: একটি দৃsert় ব্যর্থতা বা সফল হওয়া উচিত। মাঝে কখনও কিছু হয় না। পরীক্ষাটি বিশ্বাসযোগ্য, পাঠযোগ্য এবং রক্ষণাবেক্ষণযোগ্য হওয়া উচিত। পরীক্ষায় ব্যর্থ হয় না এমন একটি ব্যর্থতার দাবি একটি খারাপ ধারণা। এটি আপনার পরীক্ষাগুলিকে অত্যধিক জটিল করে তোলে (যা পাঠযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা হ্রাস করে) এবং 'ব্যর্থ হওয়ার অনুমতি দেওয়া' পরীক্ষাগুলি তাদের এড়িয়ে যাওয়া সহজ করে দেয়, যার অর্থ তারা বিশ্বাসযোগ্য নয়।
স্টিভেন

8
বাকি পরীক্ষা কেন চালাতে না পারে তার কারণ এবং এটি এখনও মারাত্মক। আমি মনে করি আপনি যে কোনও সম্ভাব্য ব্যর্থতা সংঘটিত হওয়ার পক্ষে কোথাও ব্যর্থতা ফিরে আসতে বিলম্ব করতে পারেন।
ডায়েটবুদ্ধ

4
আমি মনে করি আমরা দুজনেই একই কথা বলছি। আমি চাই প্রতি পরীক্ষায় ব্যর্থ হওয়ার জন্য প্রতিটি ব্যর্থতার দাবি; @ ডায়েটবুদ্ধ যেমন উল্লেখ করেছেন, দাবী পরীক্ষার সাথে সাথে পরীক্ষার পদ্ধতিটি ফিরে আসার চেয়ে তাত্ক্ষণিকভাবে ফিরে আসার চেয়ে ব্যর্থতাটি ঘটতে চাই তা ঠিক। এটি পদ্ধতিতে সমস্ত সম্পদ পরীক্ষা করার অনুমতি দেবে , যাতে আমি একটি শটে সমস্ত ব্যর্থতা দেখতে (এবং ঠিক করতে) পারি। পরীক্ষাটি এখনও বিশ্বাসযোগ্য, পাঠযোগ্য এবং রক্ষণাবেক্ষণযোগ্য (আরও বেশি, আসলে)।
ব্রুস ক্রিস্টেনসেন

10
তিনি বলছেন না যে আপনি দৃ hit়তার সাথে আঘাত করলে পরীক্ষা ব্যর্থ হওয়া উচিত নয়, তিনি বলছেন যে ব্যর্থতা অন্য চেকগুলিকে আটকাতে হবে না। উদাহরণস্বরূপ, এই মুহুর্তে আমি পরীক্ষা করছি যে নির্দিষ্ট ডিরেক্টরিগুলি ব্যবহারকারী, গোষ্ঠী এবং অন্যান্য লিখনযোগ্য writ প্রতিটি পৃথক দৃ as়। তিনটি কেসই ব্যর্থ হচ্ছে কিনা তা পরীক্ষার আউটপুট থেকে জেনে রাখা কার্যকর হবে, সুতরাং "পথটি ব্যবহারকারী-লেখার যোগ্য নয়," আবার পরীক্ষা চালিয়ে "পাথ পাওয়ার জন্য" পাওয়ার পরিবর্তে আমি একটি chmod কল দিয়ে এগুলি ঠিক করতে পারি " গ্রুপ-লিখনযোগ্য নয় "ইত্যাদি and যদিও আমি অনুমান করি আমি কেবল যুক্তি দিয়েছিলাম যে তাদের পৃথক পরীক্ষা হওয়া উচিত ...
টিম কেটিং

8
লাইব্রেরিটিকে ইউনিটেস্ট বলা হয় বলে এর অর্থ এই নয় যে পরীক্ষাটি একটি বিচ্ছিন্ন ইউনিট পরীক্ষা। ইউনিটেস্ট মডিউল পাশাপাশি পাইস্টেস্ট এবং নাক এবং অন্যান্যরা সিস্টেম টেস্ট, ইন্টিগ্রেশন টেস্ট ইত্যাদির জন্য দুর্দান্ত কাজ করে etc. এটা সত্যিই বিরক্তিকর। আমি সত্যিই সমস্ত আসক্তি ফাংশন দেখতে চাই যে হয় হয় এমন একটি পরামিতি যুক্ত করে যা আপনাকে ব্যর্থতা অবিরত করতে দেয়, বা প্রত্যাশী ব্লাড নামে সঞ্চারিত ফাংশনগুলির একটি সদৃশ যা এ জাতীয় কাজ করে। তারপরে ইউনিটেস্টের সাথে বৃহত্তর ফাংশনাল টেস্টগুলি লেখার পক্ষে আরও সহজ উপায় হবে।
Okken

5

প্রতিটি দৃsert় পৃথক পদ্ধতিতে করুন।

class MathTest(unittest.TestCase):
  def test_addition1(self):
    self.assertEqual(1 + 0, 1)

  def test_addition2(self):
    self.assertEqual(1 + 1, 3)

  def test_addition3(self):
    self.assertEqual(1 + (-1), 0)

  def test_addition4(self):
    self.assertEqaul(-1 + (-1), -1)

4
আমি বুঝতে পারি যে এটি একটি সম্ভাব্য সমাধান, তবে এটি সর্বদা ব্যবহারিক নয়। আমি এমন কিছু সন্ধান করছি যা একটি পূর্ববর্তী সহজাত পরীক্ষাটি কয়েকটি ছোট্ট পদ্ধতিতে না ভেঙে কাজ করে।
ব্রুস ক্রিস্টেনসেন

@ ব্রুস ক্রিস্টেনসেন: তারা যদি এত সংহত হয় তবে সম্ভবত তারা কোনও গল্প গঠন করবে? এবং তারপরে এগুলিকে নথি তৈরি করা যেতে পারে যা ব্যর্থতার পরেও অব্যাহত থাকবে
লেনার্ট রেজেব্রো

4
আমার পরীক্ষাগুলির একটি সেট রয়েছে, এরকম কিছু: ১. ডেটা লোড করুন, ২. সঠিকভাবে লোড হওয়া ডেটা জোড় করুন, ৩. তথ্য পরিবর্তন করুন, ৪. সংশোধন সঠিকভাবে কাজ করেছেন, ৫. পরিবর্তিত ডেটা সংরক্ষণ করুন, data. সঠিকভাবে সংরক্ষণ করা তথ্য সংরক্ষণ করুন। এই পদ্ধতিটি দিয়ে আমি কীভাবে এটি করতে পারি? এটিতে ডেটা লোড করা কোনও অর্থবোধ করে না setup(), কারণ এটি পরীক্ষার মধ্যে একটি। তবে আমি যদি প্রতিটি প্রতিবেদনের নিজস্ব ফাংশনটিতে রাখি, তবে আমাকে 3 বার ডেটা লোড করতে হবে এবং এটি সম্পদের বিশাল অপচয়। এমন পরিস্থিতি মোকাবিলার সর্বোত্তম উপায় কোনটি?
nnot101

ঠিক আছে, নির্দিষ্ট সিকোয়েন্স পরীক্ষা করে এমন পরীক্ষাগুলি একই পরীক্ষা পদ্ধতিতে হওয়া উচিত।
লেনার্ট রেজেব্রো

4

পিপিআইতে একটি নরম দৃ as় প্যাকেজ রয়েছে softestযা আপনার প্রয়োজনীয়তাগুলি পরিচালনা করবে। এটি ব্যর্থতা সংগ্রহ করে, ব্যতিক্রম এবং স্ট্যাক ট্রেস ডেটা সমন্বিত করে এবং সাধারণ unittestআউটপুটটির অংশ হিসাবে এগুলি সব প্রতিবেদন করে কাজ করে ।

উদাহরণস্বরূপ, এই কোড:

import softest

class ExampleTest(softest.TestCase):
    def test_example(self):
        # be sure to pass the assert method object, not a call to it
        self.soft_assert(self.assertEqual, 'Worf', 'wharf', 'Klingon is not ship receptacle')
        # self.soft_assert(self.assertEqual('Worf', 'wharf', 'Klingon is not ship receptacle')) # will not work as desired
        self.soft_assert(self.assertTrue, True)
        self.soft_assert(self.assertTrue, False)

        self.assert_all()

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

... এই কনসোল আউটপুট উত্পাদন করে:

======================================================================
FAIL: "test_example" (ExampleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\...\softest_test.py", line 14, in test_example
    self.assert_all()
  File "C:\...\softest\case.py", line 138, in assert_all
    self.fail(''.join(failure_output))
AssertionError: ++++ soft assert failure details follow below ++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The following 2 failures were found in "test_example" (ExampleTest):
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Failure 1 ("test_example" method)
+--------------------------------------------------------------------+
Traceback (most recent call last):
  File "C:\...\softest_test.py", line 10, in test_example
    self.soft_assert(self.assertEqual, 'Worf', 'wharf', 'Klingon is not ship receptacle')
  File "C:\...\softest\case.py", line 84, in soft_assert
    assert_method(*arguments, **keywords)
  File "C:\...\Python\Python36-32\lib\unittest\case.py", line 829, in assertEqual
    assertion_func(first, second, msg=msg)
  File "C:\...\Python\Python36-32\lib\unittest\case.py", line 1203, in assertMultiLineEqual
    self.fail(self._formatMessage(msg, standardMsg))
  File "C:\...\Python\Python36-32\lib\unittest\case.py", line 670, in fail
    raise self.failureException(msg)
AssertionError: 'Worf' != 'wharf'
- Worf
+ wharf
 : Klingon is not ship receptacle

+--------------------------------------------------------------------+
Failure 2 ("test_example" method)
+--------------------------------------------------------------------+
Traceback (most recent call last):
  File "C:\...\softest_test.py", line 12, in test_example
    self.soft_assert(self.assertTrue, False)
  File "C:\...\softest\case.py", line 84, in soft_assert
    assert_method(*arguments, **keywords)
  File "C:\...\Python\Python36-32\lib\unittest\case.py", line 682, in assertTrue
    raise self.failureException(msg)
AssertionError: False is not true


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

FAILED (failures=1)

দ্রষ্টব্য : আমি তৈরি এবং রক্ষণাবেক্ষণ softest


3

প্রত্যাশা গেষ্টে খুব দরকারী। এই পাইথন উপায় সারকথা , এবং কোড:

import sys
import unittest


class TestCase(unittest.TestCase):
    def run(self, result=None):
        if result is None:
            self.result = self.defaultTestResult()
        else:
            self.result = result

        return unittest.TestCase.run(self, result)

    def expect(self, val, msg=None):
        '''
        Like TestCase.assert_, but doesn't halt the test.
        '''
        try:
            self.assert_(val, msg)
        except:
            self.result.addFailure(self, sys.exc_info())

    def expectEqual(self, first, second, msg=None):
        try:
            self.failUnlessEqual(first, second, msg)
        except:
            self.result.addFailure(self, sys.exc_info())

    expect_equal = expectEqual

    assert_equal = unittest.TestCase.assertEqual
    assert_raises = unittest.TestCase.assertRaises


test_main = unittest.main

2

আমি অ্যান্থনি-ব্যাচেলর দ্বারা দৃser়পদ পছন্দ করেছি, AssertionError ব্যতিক্রম ক্যাপচার করতে। তবে সাজসজ্জার ব্যবহার করে এই পদ্ধতির সামান্যতম পার্থক্য এবং পাস / ব্যর্থতার সাথে পরীক্ষাগুলির ক্ষেত্রে রিপোর্ট করার একটি উপায়।

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest

class UTReporter(object):
    '''
    The UT Report class keeps track of tests cases
    that have been executed.
    '''
    def __init__(self):
        self.testcases = []
        print "init called"

    def add_testcase(self, testcase):
        self.testcases.append(testcase)

    def display_report(self):
        for tc in self.testcases:
            msg = "=============================" + "\n" + \
                "Name: " + tc['name'] + "\n" + \
                "Description: " + str(tc['description']) + "\n" + \
                "Status: " + tc['status'] + "\n"
            print msg

reporter = UTReporter()

def assert_capture(*args, **kwargs):
    '''
    The Decorator defines the override behavior.
    unit test functions decorated with this decorator, will ignore
    the Unittest AssertionError. Instead they will log the test case
    to the UTReporter.
    '''
    def assert_decorator(func):
        def inner(*args, **kwargs):
            tc = {}
            tc['name'] = func.__name__
            tc['description'] = func.__doc__
            try:
                func(*args, **kwargs)
                tc['status'] = 'pass'
            except AssertionError:
                tc['status'] = 'fail'
            reporter.add_testcase(tc)
        return inner
    return assert_decorator



class DecorateUt(unittest.TestCase):

    @assert_capture()
    def test_basic(self):
        x = 5
        self.assertEqual(x, 4)

    @assert_capture()
    def test_basic_2(self):
        x = 4
        self.assertEqual(x, 4)

def main():
    #unittest.main()
    suite = unittest.TestLoader().loadTestsFromTestCase(DecorateUt)
    unittest.TextTestRunner(verbosity=2).run(suite)

    reporter.display_report()


if __name__ == '__main__':
    main()

কনসোল থেকে আউটপুট:

(awsenv)$ ./decorators.py 
init called
test_basic (__main__.DecorateUt) ... ok
test_basic_2 (__main__.DecorateUt) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
=============================
Name: test_basic
Description: None
Status: fail

=============================
Name: test_basic_2
Description: None
Status: pass

1

@ অ্যান্টনি ব্যাচেলর এর উত্তর নিয়ে আমার সমস্যা ছিল কারণ এটি আমাকে try...catchআমার ইউনিট পরীক্ষার অভ্যন্তরে ব্যবহার করতে বাধ্য করেছিল । পরিবর্তে, আমি পদ্ধতির try...catchএকটি ওভাররাইডে যুক্তিটি encapsulate করেছি TestCase.assertEqual। কোডটি এখানে:

import unittest
import traceback

class AssertionErrorData(object):

    def __init__(self, stacktrace, message):
        super(AssertionErrorData, self).__init__()
        self.stacktrace = stacktrace
        self.message = message

class MultipleAssertionFailures(unittest.TestCase):

    def __init__(self, *args, **kwargs):
        self.verificationErrors = []
        super(MultipleAssertionFailures, self).__init__( *args, **kwargs )

    def tearDown(self):
        super(MultipleAssertionFailures, self).tearDown()

        if self.verificationErrors:
            index = 0
            errors = []

            for error in self.verificationErrors:
                index += 1
                errors.append( "%s\nAssertionError %s: %s" % ( 
                        error.stacktrace, index, error.message ) )

            self.fail( '\n\n' + "\n".join( errors ) )
            self.verificationErrors.clear()

    def assertEqual(self, goal, results, msg=None):

        try:
            super( MultipleAssertionFailures, self ).assertEqual( goal, results, msg )

        except unittest.TestCase.failureException as error:
            goodtraces = self._goodStackTraces()
            self.verificationErrors.append( 
                    AssertionErrorData( "\n".join( goodtraces[:-2] ), error ) )

    def _goodStackTraces(self):
        """
            Get only the relevant part of stacktrace.
        """
        stop = False
        found = False
        goodtraces = []

        # stacktrace = traceback.format_exc()
        # stacktrace = traceback.format_stack()
        stacktrace = traceback.extract_stack()

        # /programming/54499367/how-to-correctly-override-testcase
        for stack in stacktrace:
            filename = stack.filename

            if found and not stop and \
                    not filename.find( 'lib' ) < filename.find( 'unittest' ):
                stop = True

            if not found and filename.find( 'lib' ) < filename.find( 'unittest' ):
                found = True

            if stop and found:
                stackline = '  File "%s", line %s, in %s\n    %s' % ( 
                        stack.filename, stack.lineno, stack.name, stack.line )
                goodtraces.append( stackline )

        return goodtraces

# class DummyTestCase(unittest.TestCase):
class DummyTestCase(MultipleAssertionFailures):

    def setUp(self):
        self.maxDiff = None
        super(DummyTestCase, self).setUp()

    def tearDown(self):
        super(DummyTestCase, self).tearDown()

    def test_function_name(self):
        self.assertEqual( "var", "bar" )
        self.assertEqual( "1937", "511" )

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

ফলাফল আউটপুট:

F
======================================================================
FAIL: test_function_name (__main__.DummyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:\User\Downloads\test.py", line 77, in tearDown
    super(DummyTestCase, self).tearDown()
  File "D:\User\Downloads\test.py", line 29, in tearDown
    self.fail( '\n\n' + "\n\n".join( errors ) )
AssertionError: 

  File "D:\User\Downloads\test.py", line 80, in test_function_name
    self.assertEqual( "var", "bar" )
AssertionError 1: 'var' != 'bar'
- var
? ^
+ bar
? ^
 : 

  File "D:\User\Downloads\test.py", line 81, in test_function_name
    self.assertEqual( "1937", "511" )
AssertionError 2: '1937' != '511'
- 1937
+ 511
 : 

সঠিক স্ট্যাকট্রেস ক্যাপচারের জন্য আরও বিকল্প সমাধান পোস্ট টেস্ট করা যেতে পারে কীভাবে সঠিকভাবে স্ট্যাকট্র্যাস উত্পাদন করে টেস্ট কেস.এসার্টএকুয়াল () কে ওভাররাইড করা যায়?


0

পাইউনিট দিয়ে এটি করার কোনও উপায় আছে বলে আমি মনে করি না এবং পাইউনিটকে এইভাবে প্রসারিত দেখতে চাই না।

আমি পরীক্ষার ক্রিয়াকলাপের প্রতি একটি দৃser়তার সাথে লেগে থাকতে পছন্দ করি ( বা আরও নির্দিষ্টভাবে পরীক্ষা প্রতি একটি ধারণা জোর দিয়েছি ) এবং test_addition()চারটি পৃথক পরীক্ষা ফাংশন হিসাবে আবার লিখতে চাই । এটি ব্যর্থতার উপর আরও দরকারী তথ্য দেয়, যেমন :

.FF.
======================================================================
FAIL: test_addition_with_two_negatives (__main__.MathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_addition.py", line 10, in test_addition_with_two_negatives
    self.assertEqual(-1 + (-1), -1)
AssertionError: -2 != -1

======================================================================
FAIL: test_addition_with_two_positives (__main__.MathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_addition.py", line 6, in test_addition_with_two_positives
    self.assertEqual(1 + 1, 3)  # Failure!
AssertionError: 2 != 3

----------------------------------------------------------------------
Ran 4 tests in 0.000s

FAILED (failures=2)

আপনি যদি সিদ্ধান্ত নেন যে এই পদ্ধতিটি আপনার পক্ষে নয় তবে আপনি এই উত্তরটি সহায়ক বলে মনে করতে পারেন ।

হালনাগাদ

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

দ্বিতীয় ধারণাটি আরও প্রশ্নবিদ্ধ ... আপনি ডিফল্ট মানগুলি আরম্ভ করা আছে কিনা তা পরীক্ষা করছেন। কেন ? এই মানগুলি এই স্থানে পরীক্ষা করা আরও কার্যকর হবে যে সেগুলি প্রকৃতপক্ষে ব্যবহৃত হয় (এবং যদি সেগুলি ব্যবহার না করা হয় তবে তারা কেন সেখানে রয়েছে?)।

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

FF
======================================================================
FAIL: test_creation_defaults (__main__.CarTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_car.py", line 25, in test_creation_defaults
    self.assertEqual(self.car.wheel_count, 4)  # Failure!
AssertionError: 3 != 4

======================================================================
FAIL: test_creation_parameters (__main__.CarTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_car.py", line 20, in test_creation_parameters
    self.assertEqual(self.car.model, self.model)  # Failure!
AssertionError: 'Ford' != 'Model T'

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (failures=2)

সুতরাং আপনি Car.test_init চারটি ফাংশনে বিভক্ত করবেন?
ব্রুস ক্রিস্টেনসেন

@ ব্রুস ক্রিস্টেনসেন: আমি সম্ভবত এটি দুই ভাগে বিভক্ত করব। তবে তারপরেও আমি নিশ্চিত নই যে আপনার বক্তব্যগুলি কার্যকর are উত্তর জানার জন্য আপডেট দেখুন।
জনসয়েব

0

আমি বুঝতে পারি যে এই প্রশ্নটি বছর কয়েক আগে আক্ষরিক জিজ্ঞাসা করা হয়েছিল, তবে এখন দুটি (কমপক্ষে) দুটি পাইথন প্যাকেজ রয়েছে যা আপনাকে এটি করতে দেয়।

একটি হল সবচেয়ে নরম: https://pypi.org/project/softest/

অন্যটি পাইথন-বিলম্বিত-সংস্থান: https://github.com/pr4bh4sh/python-delayed-assert

আমিও ব্যবহার করিনি, তবে তারা আমার সাথে দেখতে অনেকটা মিল similar

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.