- 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
open
toiminto - 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_effect
ei.,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ää
Exception
tyyppi, kun me tarvitsemme sitä, jotta voimme pilkata specific resources heittää poikkeus, ja sitten käyttääpytest.raises
as 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_effect
parametri.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ä
with
context manager., Kun Poikkeus tulee esille toiminto on nimeltään sisälläwith
yhteydessä manager, kaikki koodi, kun se sisällä lohko ohitetaan.Clearing lru_cache
Jos funktio haluat testi on
functools.lru_cache
sisustusarkkitehti 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_cache
tarjoaa lisää toimintoja, kun decoratoring toimintoja, se tarjoaa:
cache_info
cache_clear
jä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
open
toiminto, ja että skenaario I kompastellut koko tämän kysymys, koska vaikka minulla ei ollut pilkkaa ylätason toiminto itse (olin pilkaten puhelunopen
sisä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_id
joka on globaali muuttuja sisälleapp.aws
moduuli, joka tuo viittaus muualla meidän koodi:
mock.patch
esimerkiksi, 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.object
nä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_value
meidän pilkata. Koska tämä onMagicMock
jokainen ominaisuus viitattu palauttaa uuden pilkata oikeusasteen tuomioistuin (toiminto tai ominaisuus voit soittaa mock ei ole olemassa) ja niin me kutsummemade_up_function
palautettujen pilkata, ja että juuri luotu pilkata me asettaa lopullinenreturn_value
ja123
.,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_value
mää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_value
uusi 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.foo
moduuli: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-asyncio
auttaa testaus asyncio-koodialoitetaan koodi pilkattavaksi…
import asyncioasync def sum(x, y): await asyncio.sleep(1) return x + y
Nyt 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:
spec
wrap
Voimme käyttää pilkata
spec
ominaisuus 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_set
joka nostaaAttributeError
.,Tämä on paras osoittaa esimerkki:
wrap
parametri 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
open
toiminto paljon yksinkertaisempi.
create=True
param setmock.patch
tarkoittaa, ettämock.MagicMock
palasi automaagisesti luo mitään ominaisuuksia, jotka ovat kehotti mock (tämä on koskaopen
toiminto 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ä.