• Bevezetés
  • unittest.,makett, vagy ál
  • Lakberendező
  • Erőforrás helye
  • Mock return_value vs side_effect
  • Mock Beágyazott Hívásokat
  • Ellenőrizze Kivételek
  • Elszámolási lru_cache
  • Mock Modul Szint/Globális Változók
  • Mock Például Módszer
  • Mock Osztály Módszer
  • Ál Egész Osztály
  • Mock Aszinkron Hívást
  • Mock Például Típusok
  • Mock beépített open függvény
  • Következtetés

Bevezető

Gúnyos források írásakor vizsgálatok Python zavaró lehet, ha nincs tisztában vele, hogy ilyen dolgokat., Ebben a bejegyzésben fogom fedezni különböző aspektusait gúnyos kód, amely remélhetőleg hasznos forrás azok számára, akik egy kicsit beragadt.

megjegyzés: a kódpéldákban a pytest-et használom, de a legtöbb esetben nem számít.

unittest.mock vagy mock

egy erőforrás “mock” – jához először a mock modulra lesz szükségünk, és ez az első botlásunk: melyik verzióra van szükségünk? vagyis kettő van, és mindkettő hivatalosnak tűnik (mockés unittest.mock).,

a mock modul egy visszafelé kompatibilis könyvtár letölthető PyPy, ahol a unittest.mock ugyanaz a dolog, de csak kompatibilis a verzió Python használ.,

Tehát szinte minden esetben azt akarja, hogy importáljuk, így:

import unittest.mock as mock

további lehetőségekért látod, ez a referencia útmutató

Lakberendező

A leggyakoribb módja, hogy kigúnyolja a források használata, a Python lakberendező körül a teszt funkció:

@mock.patch("thing")def test_stuff(mock_thing): mock_thing.return_value = 123

ebben Az esetben mi vagyunk folt (thing) lehet egy változó vagy függvény.,

amikor ezt megteszi, át kell adnia egy argumentumot a funkciójához (megnevezheti azt, amit akar†), amely egy MagicMocklesz.

Ez azt jelenti, hogy ha nem csinálsz mást, akkor a thing hívás (legalább a fenti példában) a 123 értéket eredményezi.

† a mock_<noun> változó megnevezése.,

Ha több dolgot gúnyol, akkor egymásra rakja a modell dekorátorokat, és átadja őket a tesztfunkcióhoz:

forrás helye

fontos tudni, hogy gúnyolódáskor meg kell adnia a gúnyolódítandó erőforrás helyét, amely releváns a ” P ” funkcióhoz.ahol importálják., Ez a legjobb magyarázható például…

Képzeld el, van egy modul app.foo belül, hogy a modul nem behozatali egy másik függőség, mint így:

from app.bar import thing

Azt gondolhatnánk, hogy amikor telefonál mock.patch, hogy át egy hivatkozás, hogy az erőforrás, mint a app.bar.thing. Ez csak akkor lenne releváns, ha az erőforrást a app.foo modulon belüli teljes elérési úttal hívnák (például ha app.foo app.bar.thing(...)).,

Ha a teljes névtér elérési útja nincs hivatkozva, ami nem szerepel a fenti példában (megjegyzés csak a thing erőforrást importáljuk). Ez azt jelenti, hogy meg kell adnunk a referencia névteret, ahol az importált:

@mock.patch('app.foo.thing')

Tehát annak ellenére, hogy thing létezik a app.bar meg kell adnunk app.foo.thing mint app.foo itt importáltuk felhasználásra. Ez elkapja az embereket minden alkalommal.,

Mock return_value vs side_effect

Ha a funkció egy try/except körül, akkor használhatjuk a side_effect okozhat a hívó a funkciót ravaszt Kivételt, mint a visszaadott érték:

@mock.patch('app.aws.sdk.confirm_sign_up', side_effect=Exception('whoops'))

Megjegyzés: ha használt volna, return_value=Exception('whoops') akkor a modell visszatér a string ábrázolása inkább Kivétel, mint felnevelni egy kivétel, mint a side_effect nem.,a módszer egy kigúnyolta tárgy volt a címe, hogy:

Az oka, hogy itt még bonyolultabb lesz köszönhető, hogy egy ál visszatér egy új mock elérésekor egy ingatlan egy ál:

A fenti kód error:

AssertionError: expected call not found.Expected: listen(8080)Actual: listen(123)

kell, hogy győződjön meg róla, hogy érvényesíthesse a modell a megfelelő pillanatban:

Ellenőrizze Kivételek

Ha szeretnénk ellenőrizni, hogy egy darab kód dob egy Exception típus, amikor szükségünk van rá, hogy meg tudjuk ál konkrét források dob egy kivételt, akkor használjuk a pytest.raises mint összefüggésben manager körül a hívó fél a kódot ellenőrizni.,

tudjuk fogni, és állításokat ez ellen a várható viselkedés először gúnyos erőforrás szeretnénk dobni egy kivételt, és kap, hogy dobja a saját hamis kivétel a side_effect paraméter.

ezután adja meg a pontos kivétel típusa számítunk fel a pytest.raises(T):

Megjegyzés: ne kövesd el azt a hibát, hogy egyetlen állítások belül a with összefüggésben menedzser., Miután a kivételt a with kontextuskezelőben hívott függvény emeli, a blokk belsejében lévő összes kódot kihagyja.

Elszámolási lru_cache

Ha egy funkciót szeretné, hogy tesztelje a functools.lru_cache lakberendező alkalmazott, akkor kell figyelnünk a gúnyos válasz, hogy a funkciója, mint ez lesz a gyorsítótárazott egy teszt, valamint a gyorsítótárazott eredmény lesz tért vissza, amikor a függvény hívása újra tesztelni egy másik magatartás (lehet, hogy valószínű, hogy összezavarjon, amikor látod, hogy a váratlan válasz).,

a probléma megoldása nagyon egyszerű, mert a lru_cache további funkciókat biztosít a funkciók díszítésekor:

  • cache_info
  • cache_clear

A ez utóbbi (cache_clear) az, amit fel kell hívnia. Ezt az alábbiakban mutatjuk be:

megjegyzés: a hibakeresés ez nem mindig nyilvánvaló., Később bemutatom, hogyan kell kigúnyolni a builtin openfüggvényt, és ebben a forgatókönyvben belebotlottam ebbe a problémába, mert bár nem gúnyoltam magát a felső szintű függvényt (gúnyoltam aopen within), a megnyitott fájl tartalma az volt, amit visszatértek és gyorsítótáraztak.

Mock modul szint/globális változók

egy modulváltozóval közvetlenül beállíthatja az értéket, vagy használhatja a mock.patch.,

a következő példa van a változó client_id ami egy globális változó belül a app.aws modul importálunk, hogy referencia máshol a kódot:

a mock.patch példa, van két alapvető dolog, amit észre:

  1. nem használjuk a return_value.
  2. nincs álpéldány át a teszt függvény.,

Ez azért van, mert módosítjuk egy változó, nem pedig egy funkció közvetlen vagy ‘lehívható’, tehát nem kell, hogy átmenjen egy ál a teszt funkció (ha meg szeretné változtatni az érték néhány alkalommal belül magát a vizsgálatot, akkor kigúnyolják a változó, de nem azonnal rendel értéket a dekoratőr).

Mock Instance Method

többféle módon lehet elérni egy példány metódus gúnyolódását., Egy közös megközelítés, hogy a mock.patch.object, valahogy így:

egy Másik megközelítés, hogy kigúnyolja a módszer, mint egy normális működését, de a referencia módszer segítségével a classname:

egy Másik (bár keménykezű) megközelítés gúnyos egy osztályban például az a módszer, hogy kihasználják azt a tényt, hogy egy Ál visszatér egy új mock például, amikor címe:

@mock.patch("foo.bar.SomeClass")def test_stuff(mock_class): mock_class.return_value.made_up_function.return_value = "123"

Megjegyzés: a fenti példában gúnyoljuk az egész osztály, amely lehet, hogy nem, hogy mit akarsz. Ha nem, akkor használja az előző mock.patch.object példát.,

a fenti példa azért működik, mert a return_value értéket állítjuk be a modellünkre. Mert ez egy MagicMock minden attribútum hivatkozott visszatér egy új mock például (egy funkció vagy tulajdonság, egy makett nem létezik), ezért hívjuk made_up_function a vissza ál, valamint az újonnan létrehozott ál beállítottuk a végleges return_value, hogy a 123.,

de amint azt a fenti megjegyzés is említi, ez a megközelítés kissé túl tompa lehet, attól függően, hogy mi az Ön igényei (függetlenül attól, hogy érdekel-e valami, ami működik, vagy sem).

Mock Class Method

egy osztály metódus kigúnyolásához hasonló megközelítés.,

az egyik megközelítés az lehet, hogy az egész osztályt kigúnyolja (de most van egy kevesebb return_value, hogy hozzárendelje):

mock_class.ClassMethodName.return_value = "123"

vagy még jobb, ha gúnyolódna, mintha bármilyen normális funkció lenne, de csak hivatkozzon a módszerre az osztályon keresztül:

Mock egész osztály

osztály a return_value értéket kell beállítania, hogy az osztály új példánya legyen.,

lásd a többi osztályhoz kapcsolódó gúnyos tippeket itt

Mock Async hívások

gúnyos aszinkron kód valószínűleg a leginkább zavaró szempont a gúnyolódás. A “go to” megoldásomat először elmagyarázom, de utána megosztom néhány alternatív módszert, amelyeket a múltban láttam és kipróbáltam.,

Először tekintsük ezt aszinkron kód belsejében egy app.foo modul:

import app.stuffasync def do_thing(x): return await app.stuff.some_concurrent_function(x)

Ha meg kell ál a coroutine app.stuff.some_concurrent_function, akkor meg tudjuk ezt oldani azáltal, hogy egy funkció úgy működik, mint egy coroutine, valamint lehetővé teszik, hogy beállítható a különböző típusú válaszok:

Megjegyzés: a példában tornádó a futó aszinkron teszt.,e alternatívák…

AsyncMock

Megjegyzés: ezt hasznosítja a csomag pytest-asyncio, hogy segítsen a vizsgálat asyncio kód

kezdjük a kódot, hogy kigúnyolják…

import asyncioasync def sum(x, y): await asyncio.sleep(1) return x + y

Most itt van, hogy gúnyolódjon.

Majom Javítás

MagicMock Ns

Aszinkron Inline Függvény

Mock Például Típusok

Ha a gúnyos egy tárgyat fogsz jönni, hogy az ál helyettesíti a teljes objektum, ezért okozhat tesztek át (vagy nem) váratlan módon.,

jelentése, Ha meg kell, hogy egy mock több, mint a Konkrét felület, akkor kétféle módon lehet csinálni, hogy:

  1. spec
  2. wrap

használhatjuk mock spec funkció, hogy utánozza az összes módszer / attribútumok az objektum gúnyolódik. Ez biztosítja, hogy a gúnyolódásoknak ugyanaz az api-ja legyen, mint az általuk helyettesített objektumoknak.

megjegyzés: van egy szigorúbb spec_set, amely felveti a AttributeError.,

ezt legjobban egy példa bizonyítja:

a wrap paraméter másrészt lehetővé teszi, hogy “kémkedjen” a megvalósításban, valamint befolyásolja annak viselkedését.,a fenti, hogy kigúnyolja az egész tárgy, nem csak egy módszer:

Mock beépített nyitva funkció

Python ál könyvtár rendelkezik egy absztrakció gúnyolódik a beépített open funkció sokkal egyszerűbb…

A create=True param set a mock.patch azt jelenti, hogy a mock.MagicMock vissza fog automatikusan hoz létre attribútumok, hogy hívják a mock (ez azért van, mert a open funkció elérésére irányuló próbálkozás sok különböző dolgokat könnyebb makett, hogy gúnyold ki, hogy az ön számára).,

következtetés

ott véget érünk. Remélhetőleg ez a lista a gúnyos technikák képes lesz látni végig még a legösszetettebb kódot kell vizsgálni. Hadd tudja, mit gondol a Twitteren.