目次
- 1 1. Mis on Python unittest?
- 2 2. unittesti põhiline kasutamine
- 3 3. setUp() ja tearDown() kasutamine
- 4 4. Sõltuvuste testimine mokkide abil
- 5 5. Erandite käsitlemine ja kohandatud väide
- 6 6. unittesti testide avastamise funktsioon
- 7 7. unittesti kasutamise näpunäited jõudluse parandamiseks
- 8 8. Kokkuvõte ja järgmised sammud
1. Mis on Python unittest?
unittest
on Pythoni standardraamatukogus sisalduv üksustestimise raamistik, mis on oluline tööriist koodi kvaliteedi tagamiseks. See võimaldab arendajatel testida koodi iga osa eraldi ja avastada vead varakult. Samuti aitab see pideva arenduse käigus veenduda, et koodi muudatused ei riku olemasolevaid funktsioone.Üksustestimise tähtsus
Kood muutudes keerukamaks, muutub järjest keerulisemaks kontrollida, kas erinevad osad töötavad õigesti koos. Üksustestide kasutuselevõtt aitab vältida ootamatuid vigu väikeste muudatuste tõttu ja säilitada kogu programmi stabiilsust.2. unittesti põhiline kasutamine
unittest
i põhiline on luua klass, mis pärib unittest.TestCase
i, ning määratleda selles testmeetodid. Testmeetodites kasutatakse selliseid väite meetodeid nagu assertEqual()
, et võrrelda oodatud tulemust tegeliku tulemusega.Põhiline testinäide
Järgmine kood on lihtne näideadd(a, b)
funktsiooni testimiseks.import unittest
# Testitav kood
def add(a, b):
return a + b
# Testiklass
class TestAddFunction(unittest.TestCase):
def test_add_integers(self):
result = add(2, 3)
self.assertEqual(result, 5)
if __name__ == '__main__':
unittest.main()
Selles koodis testitakse, kas add()
funktsioon töötab õigesti. assertEqual()
meetod kontrollib, et oodatav väärtus ja tegelik tulemus on võrdsed. Sel viisil saab kinnitada, et funktsioon töötab õigesti mitmes olukorras.Testi laiendamine
Saab kasutada mitut testmeetodit, et testida funktsiooni käitumist erinevate sisendite korral. Näiteks on võimalik testida ujukomaarvude või stringide ühendamist.def test_add_floats(self):
result = add(2.5, 3.5)
self.assertAlmost(result, 6.0, places=2)
def test_add_strings(self):
result = add("Hello, ", "World!")
self.assertEqual(result, "Hello, World!")
Nii saab testides funktsiooni käitumist erinevate andmetüüpide korral kinnitada, et funktsioon töötab õigesti erinevates olukordades.
3. setUp() ja tearDown() kasutamine
Testide enne ja pärast teatud toimingute automaatseks käivitamiseks kasutataksesetUp()
ja tearDown()
meetodeid. Sellega saab testide käivitamise eelnevalt teha vajalikud ettevalmistused ja testide lõpus teha puhastust.setUp() näide
setUp()
meetod kutsutakse alati enne iga testimeetodi käivitamist ning seda saab kasutada ühiste initsialiseerimistoimingute koondamiseks.def setUp(self):
self.temp_value = 42
tearDown() näide
tearDown()
meetod käivitatakse iga testimeetodi järel ning see teostab järeltoiminguid ja ressursside vabastamist. Näiteks saab seda kasutada andmebaasiühenduse sulgemiseks või ajutiste failide kustutamiseks.def tearDown(self):
self.temp_value = None
Nii saab vähendada testkoodi üleküllust ja säilitada puhtamat koodi.4. Sõltuvuste testimine mokkide abil
Kui testitav kood sõltub välistest ressurssidest (andmebaas, API jne), saab sõltuvuse osad asendada mokkidega, mis parandab testide käivitamise kiirust ja võimaldab ennustatavaid teste. Kui kasutada Python’iunittest.mock
moodulit, on see lihtne teostada.Mokkide näide
Allolevas koodis asendataksetime_consuming_function()
nimega pikaajaline funktsioon mokiga.from unittest.mock import patch
class TestAddFunction(unittest.TestCase):
@patch('my_module.time_consuming_function')
def test_add_with_mock(self, mock_func):
mock_func.return_value = 0
result = add(2, 3)
self.assertEqual(result, 5)
Selles näites kasutatakse mokki, et testida ilma time_consuming_function
kutsumata. Sellega saab testimise aega lühendada ja saada täpseid tulemusi.
5. Erandite käsitlemine ja kohandatud väide
unittest
-is on võimalik ka erandite käitlemist testida. Näiteks, et kindlaks teha, et erand tekib õigesti teatud olukorras, kasutatakse assertRaises()
.Erandite käitlemise test
Järgnevas näites kontrollitakse, etZeroDivisionError
tekib.def test_divide_by_zero(self):
with self.assertRaises(ZeroDivisionError):
divide(1, 0)
See kood testib, et divide(1, 0)
kutsutud ajal tekib ZeroDivisionError
.Kohandatud väite loomine
Kui standardne väide ei kata teatud juhtumeid, saate luua oma kohandatud väite meetodi.def assertIsPositive(self, value):
self.assertTrue(value > 0, f'{value} is not positive')
Kohandatud väite kasutamisega saate toetada spetsiifilisemaid teststsenaariume.6. unittesti testide avastamise funktsioon
unittest
testide avastamise funktsiooni kasutades saab projekti sees olevad kõik testfailid automaatselt leida ja käivitada. See funktsioon on eriti kasulik suurte projektide puhul.Testide avastamise kasutamine
Testide avastamise käivitamiseks kasutatakse järgmist käsku.python -m unittest discover
Selle tulemusena käivitatakse kõik määratud kataloogis olevad test_*.py
failid. Kui soovite määrata failid või kataloogid, kasutage järgmist valikut.python -m unittest discover -s tests -p "test_*.py"
Selle funktsiooni kasutamisega saate vältida testifailide eraldi määramise vaeva ja hallata teste tõhusalt ka suurtes projektides.7. unittesti kasutamise näpunäited jõudluse parandamiseks
Kui testide käivitamise kiirus on aeglane, väheneb arendustõhusus. Siin tutvustame mõningaid näpunäiteid, kuidas parandadaunittest
i kasutavate testide jõudlust.Faili I/O optimeerimine
Testid, mis nõuavad failide lugemist ja kirjutamist, saab kiirendada, kui need töötavad mälus.StringIO
abil saab luua objektid, mis käituvad mälus nagu failid, vältides kettal I/O-d.from io import StringIO
class TestFileOperations(unittest.TestCase):
def test_write_to_memory(self):
output = StringIO()
output.write('Hello, World!')
self.assertEqual(output.getvalue(), 'Hello, World!')
Selle meetodiga saab isegi testide, mis vajavad failidele juurdepääsu, kiirust märkimisväärselt parandada.Mokkide kasutamine
Mokkide kasutamine võimaldab testide kiirust suurendada, vähendades väliste ressursside juurdepääsu. See aitab vältida võrgu ja andmebaasi viivitusi ning lühendada testide käivitusaega. Järgnevas näites asendatakse API-kõne mokiga.from unittest.mock import MagicMock
class TestApiCall(unittest.TestCase):
def test_api_response(self):
mock_api = MagicMock(return_value={'status': 'success'})
response = mock_api()
self.assertEqual(response['status'], 'success')
Nii saab funktsioone testida ilma väliste ressursside sõltuvuseta, luues kiirema ja stabiilsema testikeskkonna.8. Kokkuvõte ja järgmised sammud
Selles artiklis käsitlesime põhialuseid Python’iunittest
kasutades üksustestide tegemiseks, sealhulgas seadistuse ja lõpetamise (setup/teardown) kasutamist, mokkide abil sõltuvuste testimist ning tehnikaid, mis parandavad testide jõudlust.Peamised punktid kokkuvõttes
- Aluskasutus:
unittest.TestCase
pärandades ja väite meetodite kasutamisega testide loomiseks. - setUp() / tearDown(): ühiste toimingute haldamine testide enne ja pärast suurendab koodi taaskasutatavust ja loetavust.
- Mokkide kasutamine: võimaldab funktsioone testida ilma väliste ressursside sõltuvuseta, mis suurendab testimise tõhusust märkimisväärselt.
- Testide avastamine: kasulik funktsioon, mis lihtsustab testide haldamist suurtes projektides.
- Jõudluse parandamise tehnikad: mälus töötamine ja mokkide kasutamine võimaldavad testide käivitusaega vähendada.
Järgmised sammud
unittest
põhialuste omandamisel proovi keerukamaid testimismeetodeid. Näiteks parameetrilised testid, mis võimaldavad korraga testida mitut sisendandmestikku, või koodikate tööriistade kasutamine testide ulatuse kontrollimiseks, tugevdavad kogu projekti testimisstrateegiat. Samuti on hea vaadata teisi testiraamistikke, nagu pytest
, et laiendada valikuid vastavalt vajadustele. Testimine on arenduse oluline osa. Avasta vead varakult ja säilita koodi kvaliteet, võttes testimise aktiivselt kasutusele.