Python pilkaten siellä on jotain unintuitive sinusta. Et ole helppo tarttua ja se vaatii useita ” Ah, nyt ymmärrän!”hetki ennen kuin sinut ymmärretään paremmin., Olet tehokas, fantastinen työkalu automatisoitujen yksikkötestien mahdollistamiseksi, mutta tiedän monia kehittäjiä, jotka ”selviävät” tietämyksestään ja näiden testien kirjoittaminen kestää kauemmin kuin sen pitäisi.
pilkkaamisesta on paljon artikkeleita, ja kyllä, kirjoitan nyt toista. Haluan kuitenkin todella yrittää selittää sen selkeästi, erityisesti ne ” Aha!”hetkiä, jotka veivät ymmärrystäni eteenpäin.
ensinnäkin, mitä pilkataan? Tässä on lainaus docs:
mock on kirjaston testaus Python., Sen avulla voit korvata testattavan järjestelmäsi osia pilkkakohteilla ja esittää väitteitä siitä, miten niitä on käytetty.
Joten ”sen avulla voit vaihtaa osia systems”, mutta mitä osia? On käynyt ilmi, voit pilkata melko paljon mitään voit määritellä, kuten:
- tehtävät
- luokat
- esineet
Voit korvata ne ”mock objects”, jotka ovat tapauksia, Pilkata tai MagicMock luokan.,
sitten ”tehdä väitteitä” siitä, että Mock esimerkiksi, mikä on keino tarkistaa, että Mock tapauksessa oli käytetty, niin kuin olit odottanut.
tässä artikkelissa aion kattaa perusasiat korvaa osia järjestelmissä, mutta en saa kattaa tehdä väitteitä.
aloitetaan yksinkertaisesta esimerkistä. Aion luoda uuden moduuli nimeltään simple.py ja, että moduuli aion määritellä toiminto nimeltään simple_function, että vain palauttaa merkkijonon, kuten niin:
def simple_function():
return "You have called simple_function"
Nyt aion luoda toisen moduuli nimeltään use_simple.py., Moduulissa aion tuoda pilkata paketti unittest ja tuoda yksinkertainen moduuli:
from unittest import mockimport simple
Seuraavaksi aion kirjoittaa kaksi toimintoa, yksi, joka kutsuu simple_function normaalisti ja yksi, joka pilkkaa soittaa sitä. Huomaa, että normaalisti tekisit tämän testauksen yhteydessä, mutta olen määrätietoisesti strippaus, että pois, jotta voin keskittyä pilkaten osa. Ensimmäinen tehtävä:
def use_simple_function():
result = simple.simple_function()
print(result)use_simple_function()
Kuten näette, se vain tulostaa tuloksen simple_function., Erityisesti, lähtö on:
You have called simple_function
toinen toiminto, pilkata simple_function aion käyttää pilkata.patch decorator. Tämä decorator voit määrittää, mitä haluat pilkata syöttämällä sen merkkijono muodossa ” paketti.moduuli.Funktionimi”., Tässä esimerkissä ei ole paketti, mutta moduuli on nimeltään yksinkertainen ja toiminto on nimeltään simple_function, joten sisustusarkkitehti näyttää:
@mock.patch('simple.simple_function')
sitten on kirjoittaa meidän toinen toiminto, kuten niin:
@mock.patch('simple.simple_function')
def mock_simple_function():
olen kutsunut sitä mock_simple_function, mutta se voi olla nimeltään mitä tahansa. Meiltä puuttuu parametri täällä, koska kun koristella funktio @mock.patch se menee ohi esimerkiksi MagicMock luokka (MagicMock objekti), jota käytetään korvaamaan toiminto olet pilkaten., Näin se näyttää:
@mock.patch('simple.simple_function')
def mock_simple_function(mock_simple_func):
so täsmentämällä @mock.patch (’yksinkertainen.simple_function’) sanon, että haluan korvata simple_function magicmock-objektin, joka on osoitettu mock_simple_func-parametrille.
Aluksi lähdetään rakentamaan toiminta tulostamalla mock_simple_func ja sitten kutsua sitä:
Kun ajaa, lähtö on:
<MagicMock name='simple_function'>
Joka on MagicMock esine, joka on nimeltään sijaan simple_function., On tärkeää huomata, että kohteen nimiominaisuus on asia, jota pilkataan, ja tunnus on objektille yksilöllinen numero.
Jos meillä on nyt myös tulostaa simple_function (mutta ei kutsua):
Joka tuottaa ulostulo:
<MagicMock name='simple_function'>
<MagicMock name='simple_function'>
Voit nähdä, että alkaen matching tunnukset, että mock_simple_func on sama MagicMock objektin simple_function.
toistaiseksi niin hyvä. Olemme pilkanneet simple_function. Olla selkeä, simple_function on pilkattu, koska se on korvattu MagicMock kohde.,
katsotaanpa lisätä rivejä ensimmäinen tehtävä:
Kun ajaa, lähtö on:
Kuten voitte nähdä kolmannen linjan lähtö, kun simple_function on todella kutsutaan, se luo eri MagicMock kohde. Muista, että koska olemme pilkanneet simple_function, se on oikeastaan MagicMock objekti,joten kun kutsumme simple_function olemme todella kutsumassa MagicMock objekti!
minulle, tässä sekaannus sijoittuu.
- miksi Uusi MagicMock-objekti on luotu?
- And how on earth can you call anyway an object?, Yleensä saat” TypeError: ’* * * ’object is not callable” kun yrität.
pysähdytään hetkeksi katsomaan tarkemmin Magicmockia.
Magicmockilla on magiaa sen nimissä, koska sillä on oletustoteutuksia useimmista Pythonin taikamenetelmistä. Mikä on python magic menetelmä kysyt? Kyseessä ovat kaikki erityiset python-toiminnot, joilla on kaksinkertainen alisuoritus nimensä alussa ja lopussa. Listan niistä löydät täältä. Yksi kiinnostavista tässä on__soita__., Puhelu toiminto on kuvattu seuraavasti:
Kutsutaan, kun objektia kutsutaan funktion
Joten jos luokka toteuttaa tämän toiminnon avulla voit luoda esimerkiksi luokan, ja sitten soittaa, että esimerkiksi kuin-toiminto eli :
näin Ollen, kun MagicMock kutsutaan toiminto, the __call__ funktiota kutsutaan. Magicmockin tämän toiminnon toteuttaminen luo uuden pilkan!
joten kun kutsumme simple_function() Uusi mock luodaan ja palautetaan. Sen lisäksi meillä on vanhemman ja lapsen pilkan käsite., Kun yksi pilkka luo toisen, siitä tulee vanhempi ja vasta luotu lapsi. Se pilkka voi luoda muita pilkkuja, – jotta päädyt irvikohteisiin.
Learning kohta 1: Kun MagicMock esine on nimeltään kuten funktio, oletuksena se luo ja palauttaa uuden MagicMock kohde.
takaisin esimerkkiimme. Toistaiseksi meillä on vain pilkkasivat simple_function mutta ei tehnyt mitään muuta kuin tulostaa MagicMocks, jotka on luotu seurauksena. Sano, että halusin muuttaa mitä palautettiin simple_function (), miten tekisin sen?, Haluan tehdä, että käyttämällä return_value omaisuutta MagicMock kuten niin (olen myös menossa poistaa kaksi ensimmäistä tulostaa, kun niitä ei enää tarvita):
Kun ajaa, lähtö on:
You have mocked simple_function
Kuten voit nähdä, kun simple_function() on nyt nimeltään MagicMock return_value palautetaan sen sijaan, että luodaan toinen MagicMock kohde.
Learning kohta 2: muuta, mitä palautetaan, kun MagicMock esine on nimeltään kuin toiminto, aseta return_value.
Jos haluat tehdä enemmän kuin muuttaa palautusarvoa, voit käyttää Magicmockia.side_effect-ominaisuus., Sen avulla voit määrittää täysin uuden funktion, jota kutsutaan sen sijaan, jota pilkkaat. Tehdään tämä. Ensinnäkin, aion määritellä uusi funktio, joka on side_effect (huom se tarvitsee on sama parametri asettaa toiminnon olet pilkaten):
def side_effect_function():
return "SKABLAM!"
Nyt voimme määritellä uuden toiminnon, joka käyttää tätä sivuvaikutus kuten niin:
Kaikki on sama kuin mock_simple_function edelleen paitsi olen asettaminen side_effect ja mock_simple_func sijaan return_value.,
lähtö on:
SKABLAM!
hyvä käyttää tapauksessa, että käytät sivuvaikutus on, jos haluat testata virheen virtaus ja siksi haluat nostaa poikkeus teidän testi. Aion muuttaa side_effect_function nostaa virheen sijaan:
def side_effect_function():
raise FloatingPointError("A disastrous floating point error has occurred")
Nyt lähtö on (olen poistanut osan kehittäjä selvyyden vuoksi):
Traceback (most recent call last):
File "use_simple.py”, line 18, in side_effect_function
raise FloatingPointError("A disastrous floating point error has occurred”)
FloatingPointError: A disastrous floating point error has occurred
Learning kohta 3: tehdä enemmän kuin vain muuttaa return_value on MagicMock, asettaa side_effect.
Pilkkaluokat
toistaiseksi olemme juuri pilkanneet funktiota, mutta miten olisi Luokka?, Olkaamme määritellä luokan simple.py kutsutaan SimpleClass kanssa menetelmää, jota kutsutaan räjähtää:
class SimpleClass(object):
def explode(self):
return "KABOOM!"
Nyt use_simple.py anna on kirjoittaa funktio, joka käyttää SimpleClass ja sitten soittaa, että toiminto:
def use_simple_class():
inst = simple.SimpleClass()
print(inst.explode())use_simple_class()
Kun suorittaa lähtö on:
KABOOM!
Nyt tehdä määritä toinen toiminto ja valitse pilkata kokonaisuudessaan simple_class käyttää @pilkata.laastari sisustaja:
@mock.patch("simple.SimpleClass")
def mock_simple_class(mock_class):
kun pilkaten toiminto, @pilkata.,laastari sisustusarkkitehti kulkee MagicMock esine, joka korvaa luokan olet pilkaten osaksi toiminto, se on koristelu. MagicMock-objekti on tässä tapauksessa osoitettu argumentille mock_class.
tällä hetkellä minulla on vain tulostaa MagicMock kohde ja suorita sitten toiminto:
@mock.patch("simple.SimpleClass")
def mock_simple_class(mock_class):
print(mock_class)mock_simple_class()
Kun suorittaa lähtö on:
<MagicMock name='SimpleClass'>
Kuten pilkaten toiminto MagicMock objekti on luotu ja kulunut., Nyt voit tulostaa SimpleClass, jotta voit nähdä, se on pilkattu ja korvata samalla MagicMock objekti:
@mock.patch("simple.SimpleClass")
def mock_simple_class(mock_class):
print(mock_class)
print(simple.SimpleClass)
lähtö nyt on:
<MagicMock name='SimpleClass'>
<MagicMock name='SimpleClass'>
katsotaanpa luoda esimerkiksi SimpleClass eli soittaa SimpleClass(), ja sitten tulostaa sen. Muista, koska meillä on pilkattu SimpleClass, mitä todella tapahtuu on, että me voidaan soittaa MagicMock esine, kuten toiminto:
lähtö on:
Niin kuin odotettavissa, soittamalla SimpleClass() ja siksi soittaa MagicMock objektin toiminto luo uuden MagicMock kohde.,
tähän asti luokan pilkkaaminen on ollut paljon funktion pilkkaamista. Todellisuudessa kuitenkin, kun me määritellä luokan me sitten luoda esineitä käyttäen kyseisen luokan ja se on nämä esineet, useammin kuin ei, että me todella haluamme pilkata. Kysymys kuuluu, miten pilkkaat luokasta luotua instanssia? No, kun mock-luokan ja näin ollen MagicMock objekti on luotu, jos viittaat return_value, että MagicMock esine, se luo uuden MagicMock esine, joka edustaa esimerkiksi luokan luotu. Hemmetti! Se oli puolitoista lausetta! Tämä oli ehdottomasti yksi minun ” Aha!,”hetkiä, mutta edes sen kirjoittaminen ylös ei tee sitä selväksi. Katsotaanpa tulostaa return_value niin näet mitä tarkoitan:
lähtö on:
kolmas linja on tulostamasta esimerkiksi luokan luotu, ja neljäs rivi on peräisin tulostus return_value ja MagicMock objekti toiminnon. Kuten näette, ne viittaavat samaan MagicMock-objektiin.
Oppimispiste 4: kun pilkkaa luokkaa, syntyy MagicMock-objekti. Kun luot kyseisen luokan instanssin, syntyy Uusi MagicMock-objekti., Kun viittaat kyseisen luokan MagicMock-objektin return_valueen, saat saman MagicMock-objektin, joka luotiin, kun kyseisen luokan instanssi luotiin.
” Ahhhhhh, miksi se on tärkeää?!?!?”Kuulen sinun itkevän!
”on tärkeää, jos haluat pilkata räjähtävää funktiota” I bellow in return!
seuraava kysymys, joka sinun on kysyttävä, on: onko menetelmä, jolla haluan pilkata luokkamenetelmää vai instanssimenetelmää? Koska miten muuttaa return_value menetelmän on erilainen riippuen vastaus.,
Jos menetelmä oli luokan menetelmä sitten voit asettaa return_value kuten niin:
MagicMockObject.ClassMethodName.return_value = "A delightful return value"
Mutta jos se on esimerkiksi menetelmä olisi tehdä:
MagicMockObject.return_value.InstanceMethodName.return_value = "A daring return value"
tässä mielessä katsotaanpa muuttaa return_value ja räjähtää, mikä on esimerkiksi menetelmä (minä poistaa useimmat tulostaa liitetiedot selvyyden vuoksi) :
yllä oleva koodi, mock_class.return_value palauttaa Magicmock-objektin, joka edustaa Simpleclassin tapausta.
mock_class.palaa takaisin.,explode palauttaa Magicmock-objektin, joka edustaa räjähtävää menetelmää Simpleclassin tapauksessa.
asettaen siis mock_class-paluumuuttajan_valuen.palaa takaisin.räjähtää asettaa return_value räjähtävän menetelmän tapauksessa Simpleclassin.
lähtö on:
BOO!
aivan kuten kun pilkaten toiminto, voit asettaa side_effect menetelmiä, luokat ja esineitä, liian.
Toivottavasti tämä artikkeli auttoi sinua ymmärtämään pilkkaamista hieman enemmän. Suosittelen sitä, jos haluat sen ja voit vapaasti jättää vastauksen, koska haluaisin kuulla sinusta.