mi a (majom-)folt a Python-ban?a
(monkey-) patching a kód viselkedésének megváltoztatására szolgáló technika a forrás megváltoztatása nélkül. Ez futási időben történik, általában a meglévő objektumok attribútumainak felülírásával. Az objektum lehet valamilyen példány, osztály vagy akár modul. A technikát leggyakrabban (ab)használják a tesztekhez, amikor nem tudjuk egyszerűen átadni a gúnyolódásokat.
egy másik lenyűgöző példa a gevent könyvtár, amely a szinkron kódot aszinkronvá alakítja a monkey-patching használatával.,
nézzük benchmark segítségével wrk:
Gevent kéréseket coroutine-Barát könyvtár és hála konkurencia, ez lehetővé tette a példa szerver kezelni több mint 13,5-szer több kérést másodpercenként.
a végén, van egy program, amely coroutine-alapú konkurencia (ugyanaz az elv, mint az asyncio vagy csomópont.js), de a kód még mindig úgy néz ki, mint a szinkron. Nincs szükségünk speciális, együttműködő könyvtárakra vagy async/várjuk a kulcsszavakat a kódunkban. Majdnem olyan, mint a varázslat.
Patch in tests
a Python tartalmaz egy javító segédprogramot, azaz unittest.mock.patch., A használat alapértelmezett módja a tesztfunkciónk díszítése. Tegyük fel, hogy van egy Django nézetünk, ami így néz ki…
és szeretnénk kipróbálni. Azt látjuk, hogy van egy függőség-ApiClient egy másik modulból. Ha azt akarjuk, hogy teszteljék get_stats nézet kiszámítható, megbízható módon kell használni a teszt-dupla helyett ApiClient. Ennek azonban nincs egyszerű módja. Ha érvként átadták, akkor egyszerűen átmentünk a Mock helyett.,
1
2
3
4
|
def get_stats(kérés, api_client_class):
…
api_client = api_client_class ()
…,
|
…de ez nem így van. Még mindig tudjuk használni patch lakberendező, bár!
Ez még nem ér véget, de ha hibakeresőt teszünk a tesztbe, észrevesszük, hogy az ApiClient.get_stats_for most egy MagicMock:
Ez azt jelenti, hogy a gúnyos sikeres volt. Egy problémás függőséget Helyettesítettünk egy modellel. By the way, ha a legjobb gyakorlatokat keresi a mocks használatához, nézd meg a (majdnem) végleges útmutatómat a Python gúnyolódásáról, vagy miért veszélyes lehet a gúnyolódás, ha túlhasználják.,
most a teszt még mindig sikertelen, mert a get_stats Magicmockot kap, miközben szótárt vár. Parameterizálni kell a makettet. Ezt megtehetjük egy második argumentum átadásával @patch:
Patch decorator nélkül
patch kontextus jászolként is használható. A visszatérési eredmény egy makett lesz beillesztve egy patched attribútum helyére:
“A Python javítás nem működik!”- hogyan kell csinálni?
néha szembe kell néznie azzal a helyzettel, amikor a patch decorator vagy a context manager jelenléte ellenére a függőség úgy fog kinézni, mintha egyáltalán nem lenne foltos., Röviden, ez azért lehet, mert több létező hivatkozás van arra a dologra, amelyet javítani próbál. A vizsgált kód egyet használ, de sikeresen kijavította a másikat. A műtét sikeres volt, de a beteg meghalt. Mi a teendő?
röviden, meg kell győződnie arról, hogy ugyanazt a hivatkozást javítja, amelyet a teszt alatt használt kód használ.
nézze meg, hol kell javítani a unittest részt.mock dokumentáció további részletekért. Alternatív megoldásként egy remek alternatívát is használhat a javításhoz, azaz a javításhoz.tárgy.
patch.object-egyszerűbb, hogy ez jobb
patch.,az objektum egyszerűen használható-csak importálja azt az objektumot, amelynek attribútumát javítani szeretné, majd alkalmazza a javítást.objektum:
ha javítást szeretne használni.objektum egy módszerhez, importál egy osztályt. Ha javítani akarsz.objektum egy függvény vagy egész osztály, importálja a modul élnek.
javítania kell?
(majom -) foltozást takarékosan kell használni. Ez lenne az utolsó lehetőséged. A kódomban nincs más lehetőségem, mint a tapasz a függőségi injekciónak köszönhetően.
hosszú távon az ilyen trükkök ára nagyon, nagyon magas., A javítás gyakran azt jelenti, hogy a megvalósítás részleteit oly módon kell megérinteni és megváltoztatni, ahogyan azt a szerzők nem tervezték. Ez extra kapcsolódást vezet be olyan dolgokkal,amelyeknek nem kellene. Ez azt jelenti, hogy nehezebb lesz változtatni.
ha valóban szüksége van rá, csak egy másik könyvtár nyilvános API-ját vagy egy modult javítson ki a kódban.
Vélemény, hozzászólás?