• 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, kuten side_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 puhelun open 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älle app.aws moduuli, joka tuo viittaus muualla meidän koodi:

mock.patch esimerkiksi, on olemassa kaksi avain asioita huomata:

  1. emme käytä return_value.
  2. 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ä on MagicMock jokainen ominaisuus viitattu palauttaa uuden pilkata oikeusasteen tuomioistuin (toiminto tai ominaisuus voit soittaa mock ei ole olemassa) ja niin me kutsumme made_up_function palautettujen pilkata, ja että juuri luotu pilkata me asettaa lopullinen return_value ja 123.,

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-koodi

aloitetaan 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:

  1. spec
  2. 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 nostaa AttributeError.,

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 set mock.patch tarkoittaa, että mock.MagicMock palasi automaagisesti luo mitään ominaisuuksia, jotka ovat kehotti mock (tämä on koska open 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ä.