- Käyttöönotto
- unittest.,pilkata tai pilkata
- Sisustusarkkitehti
- Resurssien sijainti
- Mock return_value vs side_effect
- Mock Sisäkkäisiä Puhelut
- Tarkista Poikkeukset
- Selvitys-lru_cache
- Mock-Moduuli Taso/Globaaleja Muuttujia
- Mock Esimerkiksi Menetelmä
- Mock-Luokan Menetelmä
- Mock Koko Luokka
- Mock Async Puhelut
- Mock Esimerkiksi Tyypit
- Mock builtin
opentoiminto - Johtopäätös
Johdanto
Pilkaten resursseja, kun kirjoitat testit Python voi olla hämmentävää, jos et tunne tehdä tällaisia asioita., Tässä postitse aion kattaa eri näkökohtia pilkaten koodi, joka on toivottavasti hyödyllinen resurssi niille, jotka ovat hieman jumissa.
Huomautus: koodi esimerkkejä käytän pytest, mutta suurin osa, että ei pitäisi olla väliä.
unittest.pilkata tai pilkata
jotta ’pilkata’ resurssi, meidän tulee ensin mock moduuli, ja tämä on meidän ensimmäinen kompastuskivi: mikä versio tarvitaan? eli siellä on kaksi ja ne molemmat näyttävät olevan virallinen (mock ja unittest.mock).,
mock moduuli on taaksepäin yhteensopiva kirjasto voit ladata PyPy, jossa unittest.mock on sama asia, mutta vain yhteensopiva versio Python käytät.,
Niin, lähes kaikissa tapauksissa, sinun kannattaa tuoda sen näin:
import unittest.mock as mock
lisää esimerkkejä katso tämä pikaopas
Sisustusarkkitehti
yleisin tapa pilkata resursseja on käyttää Python sisustusarkkitehti noin testi-toiminto:
@mock.patch("thing")def test_stuff(mock_thing): mock_thing.return_value = 123
tässä tapauksessa, mitä olemme kauneuspilkku (thing) voi olla muuttuja tai funktio.,
Kun teet tämän sinun täytyy siirtää argumentti toiminto (voit nimetä sen mitä haluat †), joka tulee olemaan MagicMock.
Tämä tarkoittaa, että jos et tee mitään muuta, sitten puhelut thing tulee (yllä olevassa esimerkissä ainakin) tuloksen arvo – 123 palautetaan.
† yleissopimus on nimi muuttujan
mock_<noun>.,
Jos olet pilkaten useita asioita niin sinun täytyy pino mock sisustussuunnittelijan ontop toisiaan, ja kulkea niitä pitkin, jotta testi-toiminto:
@mock.patch("third")@mock.patch("second")@mock.patch("first")def test_stuff(mock_first, mock_second, mock_third): ...
Resource sijainti
on tärkeää tietää, että kun pilkkaa sinun pitäisi määritä sijainti resource pilkattavaksi, merkitystä mistä se on tuotu., Tämä on paras selitti, esimerkiksi…
Kuvittele, että minulla on moduuli app.foo ja sisällä, että moduuli I tuo toinen riippuvuus, kuten niin:
from app.bar import thing
voisi ajatella, että kun soitat mock.patch että ohitat sen viittaus resurssi, kuten app.bar.thing. Että olisi merkitystä ainoastaan, jos resurssi oltiin soitti, että koko polku sisällä app.foo moduuli (jos esim. app.foo kutsutaan app.bar.thing(...)).,
Jos koko nimiavaruus polku ei ole viitattu, jota se ei ole yllä olevassa esimerkissä (huomaa tuo vain thing resurssi). Se tarkoittaa, että meidän täytyy määrittää viittaus nimiavaruuteen pilkata kuin missä se on tuotu:
@mock.patch('app.foo.thing')
vaikka thing vallitsee app.bar me määritellä app.foo.thing kuten app.foo on, jos olemme tuoneet sitä käyttää. Tämä saa ihmiset aina ulos.,
Mock return_value vs side_effect
Jos toiminto on kokeile/paitsi sen ympärillä, voit käyttää side_effect aiheuttaa kutsuvan toiminto laukaista Poikkeus kuin palasi arvo:
@mock.patch('app.aws.sdk.confirm_sign_up', side_effect=Exception('whoops'))
Huomautus: jos olet käyttänyt
return_value=Exception('whoops')sitten mock palauttaa merkkijonoesityksen pikemminkin Poikkeus kuin nostaa poikkeus, kutenside_effectei.,menetelmä on pilkattu kohde oli nimeltään:syy tämä voi saada monimutkaisempi on vuoksi miten pilkata palauttaa uuden pilkata luettaessa kiinteistön pilkata:
edellä Oleva koodi tulee virhe:
AssertionError: expected call not found.Expected: listen(8080)Actual: listen(123)Sinun täytyy varmista, että olet puolustaa mock oikeaan aikaan:
Tarkista Poikkeukset
Jos haluamme varmistaa, että jotkut pala koodi heittää
Exceptiontyyppi, kun me tarvitsemme sitä, jotta voimme pilkata specific resources heittää poikkeus, ja sitten käyttääpytest.raisesas a context manager ympäri soittajan meidän koodi on tarkistettava.,Voimme mennä ja tehdä väitteitä vastaan odotettavissa käyttäytymistä ensimmäinen pilkaten resource haluamme heittää poikkeuksen ja saada se heittää oman fake poikkeus käyttäen
side_effectparametri.Seuraavaksi määritä tarkka poikkeuksen tyyppi odotamme voidaan nostaa käyttämällä
pytest.raises(T):Huom: älä tee sitä virhettä, että laitat kaikki väitteet sisällä
withcontext manager., Kun Poikkeus tulee esille toiminto on nimeltään sisälläwithyhteydessä manager, kaikki koodi, kun se sisällä lohko ohitetaan.Clearing lru_cache
Jos funktio haluat testi on
functools.lru_cachesisustusarkkitehti sovellettu, sitten sinun täytyy olla tietoinen pilkaten vastaus, että toiminto kuin se tallennetaan välimuistiin yksi testi ja välimuistissa tulos palautetaan kun soitat toiminto uudelleen testata joitakin muita käyttäytymiseen (ja ehkä todennäköisesti hämmentää sinua, kun näet odottamaton vastaus).,Voit korjata tämän kysymys on hyvin helppoa, koska
lru_cachetarjoaa lisää toimintoja, kun decoratoring toimintoja, se tarjoaa:
cache_infocache_clearjälkimmäinen (
cache_clear) on mitä sinun täytyy soittaa. Tämä on osoitettu alla:Huomautus: debugging tämä ei ole aina itsestään selvää., Myöhemmin osoitan, miten pilkata builtin
opentoiminto, ja että skenaario I kompastellut koko tämän kysymys, koska vaikka minulla ei ollut pilkkaa ylätason toiminto itse (olin pilkaten puhelunopensisällä), tiedoston sisältö avataan oli mitä oli, palasi ja välimuistissa.Mock-Moduuli Taso/Globaaleja Muuttujia
Kanssa moduuli muuttuja, voit joko asettaa arvo suoraan tai käyttää
mock.patch.,seuraavassa esimerkissä meillä on muuttuja
client_idjoka on globaali muuttuja sisälleapp.awsmoduuli, joka tuo viittaus muualla meidän koodi:
mock.patchesimerkiksi, on olemassa kaksi avain asioita huomata:
- emme käytä
return_value.- testifunktioon ei ole välitetty mock-instanssia.,
Tämä on, koska olemme muuttamalla muuttuja, eikä suora toiminta tai ’vaadittaessa’, joten sinun ei tarvitse siirtää pilkata testi toiminto (jos haluat muuttaa arvoa, pari kertaa sisällä testin itse sitten pilkkaavat vaihtelee, mutta ei välittömästi määrittää arvo sisustaja).
Mock Instance Method
instanssimenetelmän pilkkaamiseen on useita tapoja., Yksi yleinen tapa on käyttää
mock.patch.objectnäin:Toinen lähestymistapa on pilkata menetelmä kuin normaali toiminto, mutta voit viitata menetelmän kautta classname:
Toinen (vaikkakin raskas) lähestymistapa pilkaten luokka esimerkiksi tapa on hyödyntää sitä, että Pilkata palauttaa uuden pilkata esimerkiksi kun kutsutaan:
@mock.patch("foo.bar.SomeClass")def test_stuff(mock_class): mock_class.return_value.made_up_function.return_value = "123"Huomautus: tässä esimerkissä me pilkata koko luokka, joka saattaa olla mitä haluat. Jos ei, käytä sen sijaan edellistä
mock.patch.object– esimerkkiä.,syy edellä oleva esimerkki toimii, koska olemme asettaminen
return_valuemeidän pilkata. Koska tämä onMagicMockjokainen ominaisuus viitattu palauttaa uuden pilkata oikeusasteen tuomioistuin (toiminto tai ominaisuus voit soittaa mock ei ole olemassa) ja niin me kutsummemade_up_functionpalautettujen pilkata, ja että juuri luotu pilkata me asettaa lopullinenreturn_valueja123.,mutta kuten edellä mainitussa huomautuksessa todetaan, tämä lähestymistapa voi olla hieman liian tylppä riippuen tarpeistasi (riippumatta siitä, onko sinulla jokin mitä toimiva Luokka vai ei).
Mock-Luokan Menetelmä
pilkata luokan menetelmä on samanlainen lähestymistapa pilkaten esimerkiksi menetelmä.,
Yksi lähestymistapa voisi olla, että sinä pilkkaat koko luokan (mutta nyt sinulla on yksi vähemmän
return_valuemäärittää):mock_class.ClassMethodName.return_value = "123"Tai vielä parempi sinun pitäisi pilkata sitä kuin mitä tahansa normaalia toimintaa, mutta vain viittaus menetelmä luokan kautta:
Mock Koko Luokan
pilkata koko luokan sinun täytyy asettaa
return_valueuusi esiintymä luokan.,Katso muita class liittyviä pilkaten vinkkejä täällä
Mock Async Puhelut
Pilkaten asynkroninen koodi on luultavasti kaikkein hämmentävä piirre pilkaten. Minun ”siirry” – ratkaisu selitän ensin, mutta sen jälkeen jaan joitakin vaihtoehtoisia menetelmiä olen nähnyt ja kokeillut aiemmin.,
Ensimmäinen pitävät tätä asynkronisen koodin sisälle
app.foomoduuli:import app.stuffasync def do_thing(x): return await app.stuff.some_concurrent_function(x)– Jos meidän pitää pilkata coroutine
app.stuff.some_concurrent_function, niin voimme ratkaista tämän luomalla toiminto, joka toimii coroutine ja anna sen olla konfiguroitavissa erilaisia vastauksia:Huom: esimerkissä käytetään tornado käynnissä asynkroninen testi.,e vaihtoehtoja…
AsyncMock
Huomautus: tämä hyödyntää paketti
pytest-asyncioauttaa testaus asyncio-koodialoitetaan koodi pilkattavaksi…
import asyncioasync def sum(x, y): await asyncio.sleep(1) return x + yNyt tässä on, miten meidän pitäisi pilkata sitä…
Apina Patch
MagicMock Alaluokka
Async Inline Function
Mock Esimerkiksi Tyypit
Kun pilkka esine huomaat, että mock korvaa koko kohde ja niin se voi aiheuttaa testit siirtää (tai epäonnistua) odottamattomilla tavoilla.,
Eli, jos sinun täytyy tehdä pilkkaa enemmän kuin konkreettisia käyttöliittymä, sitten on olemassa kaksi tapaa tehdä se:
specwrapVoimme käyttää pilkata
specominaisuus matkia kaikki menetelmät/ominaisuuksia esine on pilkattu. Tämä varmistaa, että pilkoillasi on sama api kuin niillä esineillä, joita ne korvaavat.Huomautus: siellä on tiukemmat
spec_setjoka nostaaAttributeError.,Tämä on paras osoittaa esimerkki:
wrapparametri toisaalta antaa sinun ”vakooja” täytäntöönpanosta, sekä vaikuttaa sen käyttäytymiseen.,perusteella edellä, että pilkkaa koko esinettä, ei vain yksi metodi:Mock builtin avaa toiminto
Python on pilkata kirjasto tarjoaa abstraktio pilkkaavat sisäänrakennettu
opentoiminto paljon yksinkertaisempi.
create=Trueparam setmock.patchtarkoittaa, ettämock.MagicMockpalasi automaagisesti luo mitään ominaisuuksia, jotka ovat kehotti mock (tämä on koskaopentoiminto yrittää käyttää paljon eri asioita ja se on helpompi pilkata pilkata pois kaikki, että olet).,Conclusion
There we ’ ll end. Toivottavasti tämä luettelo pilkkaustekniikoita pystyy näkemään läpi jopa kaikkein monimutkainen koodi täytyy testata. Kerro mielipiteesi Twitterissä.