Gilus Django testavimo sistemos nagrinėjimas, lyginant ir kontrastingai pateikiant TestCase ir TransactionTestCase, siekiant padėti jums rašyti efektyvesnius ir patikimesnius testus.
Python Django Testavimas: TestCase prieš TransactionTestCase
Testavimas yra itin svarbus programinės įrangos kūrimo aspektas, užtikrinantis, kad jūsų programa veiktų taip, kaip tikėtasi, ir išliktų patikima ilgainiui. Django, populiarus Python žiniatinklio karkasas, suteikia galingą testavimo sistemą, padedančią rašyti efektyvius testus. Šiame tinklaraščio įraše gilinsimės į du pagrindinius Django testavimo sistemos klases: TestCase
ir TransactionTestCase
. Nagrinėsime jų skirtumus, naudojimo atvejus ir pateiksime praktinius pavyzdžius, padėsiančius pasirinkti tinkamą klasę jūsų testavimo poreikiams.
Kodėl testavimas svarbus Django
Prieš gilindamiesi į TestCase
ir TransactionTestCase
ypatybes, trumpai aptarkime, kodėl testavimas yra toks svarbus Django kūrimo procese:
- Užtikrina kodo kokybę: Testai padeda anksti aptikti klaidas kūrimo procese, neleisdami joms patekti į gamybos aplinką.
- Palengvina refaktoringą: Turėdami išsamų testų rinkinį, galite užtikrintai refaktoruoti savo kodą, žinodami, kad testai įspės jus, jei įdiegsite kokių nors regresijų.
- Tobulina bendradarbiavimą: Gerai parašyti testai tarnauja kaip jūsų kodo dokumentacija, palengvindami kitų kūrėjų supratimą ir prisidėjimą.
- Palaiko testais pagrįstą kūrimą (TDD): TDD yra kūrimo metodas, kai testai rašomi prieš rašant faktinį kodą. Tai verčia jus iš anksto apgalvoti norimą jūsų programos elgesį, todėl kodas tampa švaresnis ir lengviau prižiūrimas.
Django testavimo sistema: greita apžvalga
Django testavimo sistema yra sukurta remiantis Python integruotu unittest
moduliu. Ji suteikia keletą funkcijų, palengvinančių Django programų testavimą, įskaitant:
- Testų atradimas: Django automatiškai atranda ir paleidžia testus jūsų projekte.
- Testų vykdytojas: Django suteikia testų vykdytoją, kuris paleidžia jūsų testus ir praneša rezultatus.
- Patvirtinimo metodai: Django suteikia patvirtinimo metodų rinkinį, kurį galite naudoti tikrindami numatomą jūsų kodo elgesį.
- Klientas: Django testavimo klientas leidžia simuliuoti vartotojo sąveiką su jūsų programa, pavyzdžiui, pateikiant formas ar atliekant API užklausas.
- TestCase ir TransactionTestCase: Tai dvi pagrindinės klasės rašant testus Django, kurias išsamiai nagrinėsime.
TestCase: Greitas ir efektyvus vienetinių testų rašymas
TestCase
yra pagrindinė klasė vienetiniams testams rašyti Django. Ji suteikia švarią duomenų bazės aplinką kiekvienam testų atvejui, užtikrindama, kad testai būtų izoliuoti ir vieni kitų netrukdytų.
Kaip veikia TestCase
Kai naudojate TestCase
, Django atlieka šiuos veiksmus kiekvienam testų metodui:
- Sukuriamas testavimo duomenų bazė: Django sukuriama atskira testavimo duomenų bazė kiekvienam testų paleidimui.
- Duomenų bazė išvaloma: Prieš kiekvieną testų metodą Django išvalo testavimo duomenų bazę, pašalindama visus esamus duomenis.
- Vykdomas testų metodas: Django paleidžia jūsų apibrėžtą testų metodą.
- Sandoris atšaukiamas: Po kiekvieno testų metodo Django atšaukia sandorį, efektyviai atšaukdama visus duomenų bazės pakeitimus, padarytus testo metu.
Šis metodas užtikrina, kad kiekvienas testų metodas prasideda nuo švaraus lapo ir kad visi duomenų bazės pakeitimai automatiškai atšaukiami. Tai daro TestCase
idealų vienetiniams testams, kai norite atskirai testuoti atskirus jūsų programos komponentus.
Pavyzdys: Paprasto modelio testavimas
Apsvarstykite paprastą Django modelio testavimo pavyzdį naudojant TestCase
:
from django.test import TestCase
from .models import Product
class ProductModelTest(TestCase):
def test_product_creation(self):
product = Product.objects.create(name="Test Product", price=10.00)
self.assertEqual(product.name, "Test Product")
self.assertEqual(product.price, 10.00)
self.assertTrue(isinstance(product, Product))
Šiame pavyzdyje testuojame Product
modelio egzemplioriaus sukūrimą. test_product_creation
metodas sukuria naują produktą, o tada naudoja patvirtinimo metodus, kad patikrintų, ar produkto atributai tinkamai nustatyti.
Kada naudoti TestCase
TestCase
paprastai yra pageidaujamas pasirinkimas daugeliui Django testavimo scenarijų. Jis greitas, efektyvus ir suteikia švarią duomenų bazės aplinką kiekvienam testui. Naudokite TestCase
, kai:
- Testuojate atskirus modelius, vaizdus ar kitus jūsų programos komponentus.
- Norite užtikrinti, kad jūsų testai būtų izoliuoti ir vieni kitų netrukdytų.
- Nereikia testuoti sudėtingų duomenų bazės sąveikų, apimančių kelis sandorius.
TransactionTestCase: Sudėtingų duomenų bazės sąveikų testavimas
TransactionTestCase
yra dar viena klasė testams rašyti Django, tačiau ji skiriasi nuo TestCase
tuo, kaip tvarko duomenų bazės sandorius. Vietoj sandorio atšaukimo po kiekvieno testų metodo, TransactionTestCase
sandorį patvirtina. Tai daro jį tinkamu sudėtingoms duomenų bazės sąveikoms, apimančioms kelis sandorius, pavyzdžiui, su signalais ar atominiais sandoriais, testuoti.
Kaip veikia TransactionTestCase
Kai naudojate TransactionTestCase
, Django atlieka šiuos veiksmus kiekvienam testų atvejui:
- Sukuriamas testavimo duomenų bazė: Django sukuriama atskira testavimo duomenų bazė kiekvienam testų paleidimui.
- Duomenų bazė NEišvaloma: TransactionTestCase *neišvalo* automatiškai duomenų bazės prieš kiekvieną testą. Jis tikisi, kad duomenų bazė bus nuosekli būklė prieš paleidžiant kiekvieną testą.
- Vykdomas testų metodas: Django paleidžia jūsų apibrėžtą testų metodą.
- Sandoris patvirtinamas: Po kiekvieno testų metodo Django patvirtina sandorį, padarydamas pakeitimus nuolatinius testavimo duomenų bazėje.
- Lentelės ištrinamos: Visų TransactionTestCase testų *pabaigoje* lentelės ištrinamos, kad išvalytumėte duomenis.
Kadangi TransactionTestCase
patvirtina sandorį po kiekvieno testų metodo, svarbu užtikrinti, kad jūsų testai nepaliktų duomenų bazės nuoseklioje būklėje. Gali tekti rankiniu būdu išvalyti visus testo metu sukurtus duomenis, kad nebūtų trukdoma vėlesniems testams.
Pavyzdys: Signalų testavimas
Apsvarstykite Django signalų testavimo pavyzdį naudojant TransactionTestCase
:
from django.test import TransactionTestCase
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Product, ProductLog
@receiver(post_save, sender=Product)
def create_product_log(sender, instance, created, **kwargs):
if created:
ProductLog.objects.create(product=instance, action="Created")
class ProductSignalTest(TransactionTestCase):
def test_product_creation_signal(self):
product = Product.objects.create(name="Test Product", price=10.00)
self.assertEqual(ProductLog.objects.count(), 1)
self.assertEqual(ProductLog.objects.first().product, product)
self.assertEqual(ProductLog.objects.first().action, "Created")
Šiame pavyzdyje testuojame signalą, kuris sukuria ProductLog
egzempliorių, kai sukuriama nauja Product
egzempliorius. test_product_creation_signal
metodas sukuria naują produktą, o tada patikrina, ar atitinkamas produktų žurnalo įrašas yra sukurtas.
Kada naudoti TransactionTestCase
TransactionTestCase
paprastai naudojamas specifiniuose scenarijuose, kai reikia testuoti sudėtingas duomenų bazės sąveikas, apimančias kelis sandorius. Apsvarstykite TransactionTestCase
naudojimą, kai:
- Testuojate signalus, kuriuos sukelia duomenų bazės operacijos.
- Testuojate atominius sandorius, apimančius kelias duomenų bazės operacijas.
- Reikia patikrinti duomenų bazės būklę po eilės susijusių operacijų.
- Naudojate kodą, kuris remiasi automatiškai didėjančiu ID, kad jis išliktų tarp testų (nors tai paprastai laikoma bloga praktika).
Svarbūs aspektai naudojant TransactionTestCase
Kadangi TransactionTestCase
patvirtina sandorius, svarbu žinoti šiuos aspektus:
- Duomenų bazės valymas: Gali tekti rankiniu būdu išvalyti visus testo metu sukurtus duomenis, kad būtų išvengta trikdžių vėlesniems testams. Apsvarstykite
setUp
irtearDown
metodų naudojimą testavimo duomenims tvarkyti. - Testų izoliacija:
TransactionTestCase
nesuteikia tokio paties izoliacijos lygio kaipTestCase
. Turėkite omenyje galimus testų sąveikavimus ir užtikrinkite, kad jūsų testai nesiremtų duomenų bazės būkle iš ankstesnių testų. - Našumas:
TransactionTestCase
gali būti lėtesnis neiTestCase
, nes apima sandorių patvirtinimą. Naudokite jį protingai ir tik tada, kai būtina.
Geriausios Django testavimo praktikos
Štai keletas geriausių praktikų, kurių verta laikytis rašant testus Django:
- Rašykite aiškius ir glaustus testus: Testai turėtų būti lengvai suprantami ir prižiūrimi. Naudokite apibūdinamuosius pavadinimus testų metodams ir patvirtinimams.
- Testuokite po vieną dalyką: Kiekvienas testų metodas turėtų būti sutelktas į vieno jūsų kodo aspekto testavimą. Tai palengvina gedimo šaltinio nustatymą, kai testas nepavyksta.
- Naudokite prasmingus patvirtinimus: Naudokite patvirtinimo metodus, kurie aiškiai išreiškia numatomą jūsų kodo elgesį. Django suteikia daugybę patvirtinimo metodų įvairiems scenarijams.
- Laikykitės Arrange-Act-Assert modelio: Struktūruokite savo testus pagal Arrange-Act-Assert modelį: paruoškite testavimo duomenis, atlikite veiksmą su testuojamu kodu ir patvirtinkite numatomą rezultatą.
- Laikykite testus greitus: Lėti testai gali atgrasyti kūrėjus nuo jų dažno paleidimo. Optimizuokite testus, kad sumažintumėte vykdymo laiką.
- Naudokite išvedimus testavimo duomenims: Išvedimai yra patogus būdas įkelti pradinius duomenis į jūsų testavimo duomenų bazę. Naudokite išvedimus, kad sukurtumėte nuoseklius ir daugkartinius testavimo duomenis. Apsvarstykite galimybę naudoti natūralius raktus išvedimuose, kad išvengtumėte sukietintų ID.
- Apsvarstykite galimybę naudoti testavimo biblioteką, pvz., pytest: Nors Django integruota testavimo sistema yra galinga, bibliotekos, tokios kaip pytest, gali pasiūlyti papildomų funkcijų ir lankstumo.
- Siekti aukštos testavimo aprėpties: Siekite aukštos testavimo aprėpties, kad užtikrintumėte, jog jūsų kodas yra kruopščiai ištirtas. Naudokite aprėpties įrankius, kad išmatuotumėte savo testavimo aprėptį ir nustatytumėte sritis, kurioms reikia daugiau testavimo.
- Integruokite testus į savo CI/CD procesą: Paleiskite savo testus automatiškai kaip dalį savo nuolatinio integravimo ir nuolatinio diegimo (CI/CD) proceso. Tai užtikrina, kad bet kokios regresijos bus aptiktos anksti kūrimo procese.
- Rašykite testus, atspindinčius realaus pasaulio scenarijus: Testuokite savo programą taip, kaip vartotojai ją faktiškai naudotų. Tai padės jums aptikti klaidas, kurios gali pasireikšti paprastuose vienetiniuose testuose. Pavyzdžiui, testuodami formas, apsvarstykite tarptautinių adresų ir telefono numerių įvairovę.
Internacionalizacija (i18n) ir testavimas
Kuriant Django programas tarptautinei auditorijai, būtina atsižvelgti į internacionalizaciją (i18n) ir lokalizaciją (l10n). Užtikrinkite, kad jūsų testai apimtų skirtingas kalbas, datos formatus ir valiutos simbolius. Štai keletas patarimų:
- Testuokite su skirtingais kalbos nustatymais: Naudokite Django
override_settings
dekoratorių, kad testuotumėte savo programą su skirtingais kalbos nustatymais. - Naudokite lokalizuotus duomenis savo testuose: Naudokite lokalizuotus duomenis savo testų išvedimuose ir testų metodose, kad užtikrintumėte, jog jūsų programa tinkamai tvarko skirtingus datos formatus, valiutos simbolius ir kitus lokalės specifinius duomenis.
- Testuokite savo vertimo eilutes: Patikrinkite, ar jūsų vertimo eilutės yra tinkamai išverstos ir ar jos tinkamai pateikiamos skirtingomis kalbomis.
- Naudokite
localize
šablonų žymą: Šablonuose naudokitelocalize
šablonų žymą, kad formatuotumėte datas, skaičius ir kitus lokalės specifinius duomenis pagal vartotojo dabartinę lokalę.
Pavyzdys: Testavimas su skirtingais kalbos nustatymais
from django.test import TestCase
from django.utils import translation
from django.conf import settings
class InternationalizationTest(TestCase):
def test_localized_date_format(self):
original_language = translation.get_language()
try:
translation.activate('de') # Activate German language
with self.settings(LANGUAGE_CODE='de'): # Set the language in settings
from django.utils import formats
from datetime import date
d = date(2024, 1, 20)
formatted_date = formats.date_format(d, 'SHORT_DATE_FORMAT')
self.assertEqual(formatted_date, '20.01.2024')
finally:
translation.activate(original_language) # Restore original language
Šis pavyzdys demonstruoja, kaip testuoti datos formatavimą su skirtingais kalbos nustatymais, naudojant Django translation
ir formats
modulius.
Išvada
Suprasti TestCase
ir TransactionTestCase
skirtumus yra būtina norint rašyti efektyvius ir patikimus testus Django. TestCase
paprastai yra pageidaujamas pasirinkimas daugeliui testavimo scenarijų, suteikiantis greitą ir efektyvų būdą atskirai testuoti jūsų programos komponentus. TransactionTestCase
naudingas testuojant sudėtingas duomenų bazės sąveikas, apimančias kelis sandorius, pavyzdžiui, su signalais ar atominiais sandoriais. Laikydamiesi geriausių praktikų ir atsižvelgdami į internacionalizacijos aspektus, galite sukurti tvirtą testų rinkinį, kuris užtikrins jūsų Django programų kokybę ir prižiūrimumą.