Django 2.1 - Writing and running tests

लेखन और परीक्षण चल रहा है




django

लेखन और परीक्षण चल रहा है

यह दस्तावेज़ दो प्राथमिक वर्गों में विभाजित है। सबसे पहले, हम समझाते हैं कि Django के साथ परीक्षण कैसे लिखें। फिर, हम बताते हैं कि उन्हें कैसे चलाना है।

लेखन परीक्षण

Django की इकाई परीक्षण एक पायथन मानक पुस्तकालय मॉड्यूल का उपयोग करते हैं: unittest । यह मॉड्यूल क्लास-आधारित दृष्टिकोण का उपयोग करके परीक्षणों को परिभाषित करता है।

यहाँ एक उदाहरण है जो django.test.TestCase से उप-वर्ग django.test.TestCase , जो कि unittest.TestCase का एक उपवर्ग है django.test.TestCase जो अलगाव प्रदान करने के लिए लेनदेन के अंदर प्रत्येक परीक्षण चलाता है:

from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
    def setUp(self):
        Animal.objects.create(name="lion", sound="roar")
        Animal.objects.create(name="cat", sound="meow")

    def test_animals_can_speak(self):
        """Animals that can speak are correctly identified"""
        lion = Animal.objects.get(name="lion")
        cat = Animal.objects.get(name="cat")
        self.assertEqual(lion.speak(), 'The lion says "roar"')
        self.assertEqual(cat.speak(), 'The cat says "meow"')

जब आप अपने परीक्षण चलाते हैं , तो परीक्षण उपयोगिता का डिफ़ॉल्ट व्यवहार किसी भी फ़ाइल में सभी परीक्षण मामलों (यानी, unittest.TestCase उपवर्ग) को खोजने के लिए होता है, जिसका नाम test शुरू होता है, स्वचालित रूप से उन परीक्षण मामलों से बाहर एक परीक्षण सूट का निर्माण करता है, और उस सुइट को चलाएं।

unittest बारे में अधिक जानकारी के लिए, पायथन प्रलेखन देखें।

परीक्षण कहाँ रहना चाहिए?

नए ऐप्लीकेशन में डिफ़ॉल्ट tests.py टेम्प्लेट में एक tests.py फाइल tests.py । यह ठीक हो सकता है यदि आपके पास केवल कुछ परीक्षण हैं, लेकिन जैसा कि आपका परीक्षण सूट बढ़ता है, आप संभवतः इसे एक परीक्षण पैकेज में पुनर्गठित करना चाहेंगे, ताकि आप अपने परीक्षणों को अलग-अलग test_models.py जैसे test_models.py , test_views.py , test_forms.py में विभाजित कर test_views.pytest_forms.py , आदि जो भी संगठनात्मक योजना आपको पसंद है उसे लेने के लिए स्वतंत्र महसूस करें।

पुन: प्रयोज्य अनुप्रयोगों का परीक्षण करने के लिए Django परीक्षण धावक का उपयोग करना भी देखें।

चेतावनी

यदि आपके परीक्षण डेटाबेस एक्सेस पर निर्भर करते हैं जैसे कि मॉडल बनाना या क्वेरी करना, तो अपने टेस्ट क्लासेस को unittest.TestCase बजाय django.test.TestCase उपवर्ग के रूप में बनाना सुनिश्चित करें।

unittest.TestCase का उपयोग लेनदेन में प्रत्येक परीक्षण को चलाने और डेटाबेस को फ्लश करने से बचाता है, लेकिन यदि आपके परीक्षण डेटाबेस के साथ बातचीत करते हैं, तो उनका व्यवहार इस क्रम के आधार पर अलग-अलग होगा कि परीक्षण धावक उन्हें निष्पादित करता है। इससे यूनिट टेस्ट हो सकते हैं जो अलग-थलग पड़ने पर गुजरते हैं लेकिन सूट में चलने पर असफल हो जाते हैं।

परीक्षण चल रहा है

एक बार जब आप परीक्षण लिख चुके होते हैं, तो उन्हें अपनी परियोजना की manage.py के test कमांड का उपयोग करके चलाएं:

$ ./manage.py test

परीक्षण की खोज, यूनिस्टेस्ट मॉड्यूल की अंतर्निहित परीक्षण खोज पर आधारित है। डिफ़ॉल्ट रूप से, यह वर्तमान कार्यशील निर्देशिका के तहत "परीक्षण * .py" नामक किसी भी फ़ाइल में परीक्षणों की खोज करेगा।

आप किसी भी संख्या में "परीक्षण लेबल" ./manage.py test आपूर्ति करके चलाने के लिए विशेष परीक्षण निर्दिष्ट कर सकते हैं। प्रत्येक परीक्षण लेबल एक पैकेज, मॉड्यूल, TestCase उपवर्ग या परीक्षण विधि के लिए पूर्ण पायथन डॉटेड पथ हो सकता है। उदाहरण के लिए:

# Run all the tests in the animals.tests module
$ ./manage.py test animals.tests

# Run all the tests found within the 'animals' package
$ ./manage.py test animals

# Run just one test case
$ ./manage.py test animals.tests.AnimalTestCase

# Run just one test method
$ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak

आप उस निर्देशिका के नीचे परीक्षण खोजने के लिए एक निर्देशिका को एक मार्ग प्रदान कर सकते हैं:

$ ./manage.py test animals/

यदि आप अपने परीक्षण फ़ाइलों को test*.py प्रतिमान से अलग नाम देते हैं, तो आप ( --pattern ) विकल्प का उपयोग करके एक कस्टम फ़ाइल नाम पैटर्न मैच निर्दिष्ट कर सकते हैं test*.py

$ ./manage.py test --pattern="tests_*.py"

यदि आप परीक्षण चला रहे हैं, तो आप Ctrl-C दबाते हैं, तो परीक्षण धावक वर्तमान में चल रहे परीक्षण के पूरा होने और फिर इनायत से बाहर निकलने का इंतजार करेगा। एक ग्रेसफुल एग्जिट के दौरान टेस्ट रनर किसी भी टेस्ट फेलियर का डिटेल आउटपुट करेगा, कितने टेस्ट चलाए गए और कितने एरर और फेलियर सामने आए, इस पर रिपोर्ट करें और हमेशा की तरह किसी भी टेस्ट डेटाबेस को नष्ट कर दें। इस प्रकार, Ctrl-C दबाने पर बहुत उपयोगी हो सकता है यदि आप --failfast विकल्प को पास करना भूल जाते हैं, तो ध्यान दें कि कुछ परीक्षण अप्रत्याशित रूप से विफल हो रहे हैं और पूर्ण परीक्षण रन का इंतजार किए बिना विफलताओं पर विवरण प्राप्त करना चाहते हैं।

यदि आप वर्तमान में चल रहे परीक्षण के समाप्त होने की प्रतीक्षा नहीं करना चाहते हैं, तो आप दूसरी बार Ctrl-C दबा सकते हैं और परीक्षण रन तुरंत रुक जाएगा, लेकिन इनायत नहीं। रुकावट से पहले चलाए जाने वाले परीक्षणों का कोई विवरण नहीं दिया जाएगा, और रन द्वारा बनाए गए किसी भी परीक्षण डेटाबेस को नष्ट नहीं किया जाएगा।

चेतावनियों के साथ परीक्षण सक्षम

पायथन चेतावनी के साथ अपने परीक्षणों को चलाने के लिए यह एक अच्छा विचार है: python -Wa manage.py test-Wa ध्वज पायथन को -Wa चेतावनी प्रदर्शित करने के लिए कहता है। कई अन्य पायथन पुस्तकालयों की तरह, Django इन चेतावनियों का उपयोग करता है जब ध्वज दूर जा रहे हैं। यह आपके कोड में उन क्षेत्रों को भी ध्वजांकित कर सकता है जो कड़ाई से गलत नहीं हैं लेकिन बेहतर कार्यान्वयन से लाभान्वित हो सकते हैं।

परीक्षण डेटाबेस

एक डेटाबेस (अर्थात्, मॉडल परीक्षण) की आवश्यकता वाले टेस्ट आपके "वास्तविक" (उत्पादन) डेटाबेस का उपयोग नहीं करेंगे। परीक्षणों के लिए अलग, रिक्त डेटाबेस बनाए जाते हैं।

भले ही परीक्षण पास हों या असफल हों, सभी परीक्षण निष्पादित किए जाने पर परीक्षण डेटाबेस नष्ट हो जाते हैं।

आप परीक्षण डेटाबेस को test --keepdb विकल्प का उपयोग करके नष्ट होने से रोक सकते हैं। यह रन के बीच परीक्षण डेटाबेस को संरक्षित करेगा। यदि डेटाबेस मौजूद नहीं है, तो इसे पहले बनाया जाएगा। इसे जारी रखने के लिए कोई भी माइग्रेशन भी लागू किया जाएगा।

डिफ़ॉल्ट परीक्षण डेटाबेस नाम DATABASES में प्रत्येक NAME के मान के लिए test_ prepending द्वारा बनाए जाते हैं। SQLite का उपयोग करते समय, परीक्षण डिफ़ॉल्ट रूप से एक-इन-मेमोरी डेटाबेस का उपयोग करेंगे (यानी, डेटाबेस को मेमोरी में बनाया जाएगा, पूरी तरह से फाइल सिस्टम को दरकिनार करके!)। DATABASES में TEST शब्दकोश आपके परीक्षण डेटाबेस को कॉन्फ़िगर करने के लिए कई सेटिंग्स प्रदान करता है। उदाहरण के लिए, यदि आप एक अलग डेटाबेस नाम का उपयोग करना चाहते हैं, तो DATABASES में किसी भी दिए गए डेटाबेस के लिए TEST शब्दकोश में NAME निर्दिष्ट करें।

PostgreSQL पर, USER को अंतर्निहित postgres डेटाबेस तक रीड एक्सेस की भी आवश्यकता होगी।

एक अलग डेटाबेस का उपयोग करने के अलावा, परीक्षण धावक अन्यथा आपकी सेटिंग फ़ाइल में आपके पास समान डेटाबेस सेटिंग्स का उपयोग करेगा: ENGINE , USER , HOST , आदि। परीक्षण डेटाबेस USER द्वारा निर्दिष्ट उपयोगकर्ता द्वारा बनाया गया है, इसलिए आप करेंगे यह सुनिश्चित करने की आवश्यकता है कि सिस्टम पर एक नया डेटाबेस बनाने के लिए दिए गए उपयोगकर्ता खाते में पर्याप्त विशेषाधिकार हैं।

अपने परीक्षण डेटाबेस के वर्ण एन्कोडिंग पर ठीक-ठीक नियंत्रण के लिए, CHARSET TEST विकल्प का उपयोग करें। यदि आप MySQL का उपयोग कर रहे हैं, तो आप परीक्षण डेटाबेस द्वारा उपयोग किए जाने वाले विशेष कॉलेशन को नियंत्रित करने के लिए COLLATION विकल्प का उपयोग भी कर सकते हैं। इन और अन्य उन्नत सेटिंग्स के विवरण के लिए सेटिंग्स प्रलेखन देखें।

यदि SQLite के साथ SQLite-in-memory डेटाबेस का उपयोग किया जाता है, तो साझा कैश सक्षम है, इसलिए आप थ्रेड्स के बीच डेटाबेस को साझा करने की क्षमता के साथ परीक्षण लिख सकते हैं।

परीक्षण चलाते समय अपने उत्पादन डेटाबेस से डेटा ढूँढना?

यदि आपका कोड डेटाबेस को एक्सेस करने का प्रयास करता है, जब उसके मॉड्यूल संकलित किए जाते हैं, तो यह संभावित अप्रत्याशित परिणामों के साथ, परीक्षण डेटाबेस सेट होने से पहले होगा। उदाहरण के लिए, यदि आपके पास मॉड्यूल-स्तरीय कोड में एक डेटाबेस क्वेरी है और एक वास्तविक डेटाबेस मौजूद है, तो उत्पादन डेटा आपके परीक्षणों को प्रदूषित कर सकता है। आपके कोड में इस तरह के आयात-समय डेटाबेस क्वेरी रखना एक बुरा विचार है - अपने कोड को फिर से लिखना ताकि यह ऐसा न करे।

यह ready() अनुकूलित कार्यान्वयन पर भी लागू होता है।

आदेश जिसमें परीक्षण निष्पादित किए जाते हैं

यह सुनिश्चित करने के लिए कि सभी TestCase कोड एक साफ डेटाबेस के साथ शुरू होता है, Django टेस्ट रनर फिर से परीक्षण करता है:

  • सभी django.test.TestCase उपवर्ग पहले चलाए जाते हैं।
  • फिर, अन्य सभी Django- आधारित परीक्षण ( SimpleTestCase पर आधारित परीक्षण के मामले, जिसमें TransactionTestCase भी शामिल है) को किसी विशेष आदेश की गारंटी के साथ नहीं चलाया जाता है और न ही उनके बीच लागू किया जाता है।
  • फिर किसी भी अन्य unittest.TestCase परीक्षण (सिद्धांत सहित) जो डेटाबेस को उसकी मूल स्थिति में पुनर्स्थापित किए बिना बदल सकता है।

ध्यान दें

परीक्षणों के नए आदेश से परीक्षण मामले के आदेश पर अप्रत्याशित निर्भरता प्रकट हो सकती है। यह उन मामलों के साथ है, जो किसी दिए गए TransactionTestCase परीक्षण द्वारा डेटाबेस में छोड़ी गई अवस्था पर निर्भर हैं, उन्हें स्वतंत्र रूप से चलाने में सक्षम होने के लिए अद्यतन किया जाना चाहिए।

आप test --reverse विकल्प का उपयोग करके समूहों के अंदर निष्पादन आदेश को उलट सकते हैं। यह सुनिश्चित करने में मदद कर सकता है कि आपके परीक्षण एक-दूसरे से स्वतंत्र हैं।

रोलबैक एमुलेशन

माइग्रेशनों में लोड किया गया कोई भी आरंभिक डेटा केवल TestCase परीक्षणों में उपलब्ध होगा और TransactionTestCase परीक्षणों में नहीं, और इसके अतिरिक्त केवल उन बैकेंड्स पर, जहाँ लेनदेन समर्थित हैं (सबसे महत्वपूर्ण अपवाद MyISAM है)। यह उन परीक्षणों के लिए भी सही है, जो LiveServerTestCase और StaticLiveServerTestCase जैसे TransactionTestCase पर निर्भर हैं।

Django उस डेटा को आपके लिए प्रति-परीक्षण के आधार पर TestCase या TransactionTestCase के TestCase में True serialized_rollback विकल्प सेट करके सेट कर सकता है, लेकिन ध्यान दें कि यह उस परीक्षण सूट को लगभग 3x तक धीमा कर देगा।

तृतीय-पक्ष एप्लिकेशन या MyISAM के खिलाफ विकास करने वालों को इसे सेट करने की आवश्यकता होगी; सामान्य तौर पर, हालांकि, आपको एक लेनदेन डेटाबेस के खिलाफ अपनी खुद की परियोजनाएं विकसित करनी चाहिए और अधिकांश परीक्षणों के लिए TestCase का उपयोग करना चाहिए, और इस तरह इस सेटिंग की आवश्यकता नहीं है।

प्रारंभिक क्रमांकन आमतौर पर बहुत जल्दी होता है, लेकिन अगर आप कुछ ऐप्स को इस प्रक्रिया से बाहर करना चाहते हैं (और परीक्षण को थोड़ा तेज करें), तो आप उन ऐप्स को TEST_NON_SERIALIZED_APPS जोड़ सकते हैं।

क्रमबद्ध डेटा को दो बार लोड होने से रोकने के लिए, serialized_rollback=True सेट करना serialized_rollback=True परीक्षण डेटाबेस को post_migrate करने पर post_migrate सिग्नल को serialized_rollback=True अक्षम करता है।

अन्य परीक्षण की स्थिति

आपके कॉन्फ़िगरेशन फ़ाइल में DEBUG सेटिंग के मान के बावजूद, सभी Django परीक्षण DEBUG = गलत के साथ चलते हैं। यह सुनिश्चित करना है कि आपके कोड का अवलोकन किया गया उत्पादन किसी सेटिंग में देखा जाएगा।

प्रत्येक परीक्षण के बाद कैश को साफ़ नहीं किया जाता है, और "मैनेजडोमेटो टेस्ट फूप" चलाने से परीक्षणों का डेटा एक लाइव सिस्टम के कैश में डाला जा सकता है यदि आप उत्पादन में अपने परीक्षण चलाते हैं क्योंकि, डेटाबेस के विपरीत, एक अलग "टेस्ट कैश" नहीं है। उपयोग किया गया। यह व्यवहार भविष्य में बदल सकता है

परीक्षण आउटपुट को समझना

जब आप अपने परीक्षण चलाते हैं, तो आपको कई संदेश दिखाई देंगे, क्योंकि परीक्षण धावक खुद को तैयार करता है। आप कमांड लाइन पर verbosity विकल्प के साथ इन संदेशों के विस्तार के स्तर को नियंत्रित कर सकते हैं:

Creating test database...
Creating table myapp_animal
Creating table myapp_mineral

यह आपको बताता है कि परीक्षण धावक एक परीक्षण डेटाबेस बना रहा है, जैसा कि पिछले भाग में बताया गया है।

एक बार परीक्षण डेटाबेस बन जाने के बाद, Django आपके परीक्षण चलाएगा। यदि सब कुछ ठीक रहा, तो आपको कुछ इस तरह दिखाई देगा:

----------------------------------------------------------------------
Ran 22 tests in 0.221s

OK

यदि परीक्षण में असफलताएँ हैं, हालाँकि, आपको पूर्ण विवरण दिखाई देगा कि कौन से परीक्षण विफल हुए:

======================================================================
FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_poll
    self.assertIs(future_poll.was_published_recently(), False)
AssertionError: True is not False

----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (failures=1)

इस त्रुटि आउटपुट का पूर्ण विवरण इस दस्तावेज़ के दायरे से परे है, लेकिन यह बहुत सहज है। आप विवरण के लिए पायथन के सबसे unittest पुस्तकालय के प्रलेखन से परामर्श कर सकते हैं।

नोट करें कि परीक्षण-रनर स्क्रिप्ट के लिए रिटर्न कोड किसी भी असफल और गलत परीक्षण के लिए 1 है। यदि सभी परीक्षण पास हो जाते हैं, तो रिटर्न कोड 0. है। यदि आप किसी शेल स्क्रिप्ट में टेस्ट-रनर स्क्रिप्ट का उपयोग कर रहे हैं और उस स्तर पर सफलता या विफलता के लिए परीक्षण करने की आवश्यकता है तो यह सुविधा उपयोगी है।

परीक्षणों को गति देना

समानांतर में परीक्षण चल रहा है

जब तक आपके परीक्षण ठीक से अलग नहीं हो जाते, तब तक आप उन्हें मल्टी-कोर हार्डवेयर पर गति प्राप्त करने के लिए समानांतर में चला सकते हैं। test --parallel देखें - test --parallel

पासवर्ड हैशिंग

डिफ़ॉल्ट पासवर्ड हैशर डिजाइन के बजाय धीमा है। यदि आप अपने परीक्षणों में कई उपयोगकर्ताओं को प्रमाणित कर रहे हैं, तो आप एक कस्टम सेटिंग फ़ाइल का उपयोग करना चाहते हैं और PASSWORD_HASHERS सेटिंग को तेज़ हैशिंग एल्गोरिथ्म में सेट कर सकते हैं:

PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.MD5PasswordHasher',
]

PASSWORD_HASHERS में शामिल किसी भी हैशिंग एल्गोरिथ्म को जुड़नार में उपयोग करना न भूलें, यदि कोई हो।

परीक्षण डेटाबेस का संरक्षण

परीक्षण रन के बीच परीक्षण डेटाबेस test --keepdb विकल्प को संरक्षित करता है। यह कार्यों को बनाने और नष्ट करने को रोक देता है जो परीक्षणों को चलाने के लिए बहुत कम कर सकता है।