co je (monkey-)záplatování v Pythonu?
(monkey-) patching je technika pro změnu chování kódu bez změny jeho zdroje. To se provádí za běhu, obvykle přepsáním atributů existujících objektů. Objekt může být instancí nějakého druhu, třídy nebo dokonce modulu. Tato technika se nejčastěji (ab)používá pro testy, když nemůžeme jednoduše předat posměšky.
dalším působivým příkladem je knihovna gevent, která pomocí opičího záplatování změní synchronní kód na asynchronní.,
Ať je měřítko, pomocí wrk:
Gevent žádosti o coroutine-friendly knihovna a díky souběžnosti, je povoleno našem příkladu serveru zpracovat více než 13,5 krát více žádostí za sekundu.
nakonec, máme program, který má coroutine na bázi souběžnosti (stejný princip jako v asyncio nebo uzel.js) ale jeho kód stále vypadá jako synchronní. Nepotřebujeme speciální, kooperativní knihovny nebo async / čekají klíčová slova v našem kódu. Je to skoro jako magie.
Patch v testech
Python obsahuje nástroj pro záplatování, tj. unitest.vysmívat.Oprava., Výchozí způsob použití je ozdobit naši testovací funkci. Předpokládejme, že máme Django pohled, který vypadá takto …
a rádi bychom ho vyzkoušeli. Všimneme si, že má závislost-ApiClient z jiného modulu. Pokud chceme testovat zobrazení get_stats předvídatelným a spolehlivým způsobem, musíme místo Apiclientu použít test-double. Neexistuje však žádný jednoduchý způsob, jak to udělat. Pokud by to bylo předáno get_stats jako argument, mohli bychom místo toho jednoduše předat Mock.,
1
2
3
4
|
def get_stats(žádost, api_client_class):
…
api_client = api_client_class ()
…,
|
…ale není tomu tak. Stále můžeme použít patch dekoratér, ačkoli!
to ještě není konec, ale pokud do testu vložíme ladicí program, všimneme si toho Apiklientu.get_stats_for je nyní MagicMock:
znamená to, že naše zesměšňování bylo úspěšné. Problematickou závislost jsme nahradili výsměchem. Mimochodem, pokud hledáte osvědčené postupy pro používání zesměšňování, podívejte se na můj (téměř) definitivní průvodce posměchem v Pythonu nebo proč může být zesměšňování nebezpečné, když je nadužíváno.,
nyní test stále selhává, protože get_stats obdrží MagicMock, zatímco očekává slovník. Musíme ten výsměch parametrizovat. Můžeme tak učinit předáním druhého argumentu @patch:
Patch bez dekorátoru
patch lze také použít jako kontextový jesle. Výsledkem návratu bude posměch, který bude vložen na místo záplatovaného atributu:
„Oprava Pythonu nefunguje!“- jak to udělat správně?
Někdy budete čelit situaci, kdy i přes přítomnost patch dekoratér nebo kontextu manager, závislost bude vypadat, jako kdyby to nebylo opravené., Stručně řečeno, může to být proto, že existuje více existujících odkazů na věc, kterou se snažíte opravit. Testovaný kód používá jeden, ale úspěšně jste opravili další. Operace byla úspěšná, ale pacient zemřel. Co dělat?
stručně řečeno, musíte se ujistit, že opravíte stejný odkaz, jaký používá testovaný kód.
podívejte se, kde opravit část unittest.mock dokumentace pro více informací. Případně můžete použít šikovnou alternativu k patch, tedy patch.předmět.
náplast.objekt-jednodušší, aby si to právo
náplast.,objekt je mrtvý jednoduché použití – stačí importovat objekt, jehož atribut chcete opravit a použít patch.objekt:
Pokud chcete použít patch.objekt pro metodu, můžete importovat třídu. Pokud chcete opravit.objekt funkce nebo celá třída, importovat modul, ve kterém žijí.
měli byste opravit?
(monkey-) patching by měl být používán střídmě. To by mělo být vaše poslední možnost. V mém kódu nemám jinou možnost než náplast díky injekci závislosti.
v dlouhodobé ceně za takové triky je velmi, velmi vysoká., Záplatování často znamená dotýkat se a měnit detaily implementace způsobem, který autoři nepředpokládali. To představuje další spojení s věcmi, které by to neměly mít. To znamená, že budou těžší změnit.
Pokud opravdu musíte, opravte pouze veřejné API jiné knihovny nebo modul ve vašem kódu.
Napsat komentář