Mam moduł Pythona, który używa biblioteki argparse. Jak napisać testy dla tej sekcji bazy kodu?
python
unit-testing
argparse
pydanny
źródło
źródło
foo()
to wywoływana jest funkcja ”. Kpinysys.argv
jest odpowiedzią, jeśli tak jest. Spójrz na pakiet cli-test-helpers Python. Zobacz także stackoverflow.com/a/58594599/202834Odpowiedzi:
Powinieneś refaktoryzować swój kod i przenieść parsowanie do funkcji:
Następnie w swojej
main
funkcji powinieneś po prostu wywołać to za pomocą:(gdzie pierwszy element
sys.argv
reprezentujący nazwę skryptu jest usuwany, aby nie wysyłać go jako dodatkowego przełącznika podczas operacji CLI).W swoich testach możesz następnie wywołać funkcję parsera z dowolną listą argumentów, z którymi chcesz ją przetestować:
W ten sposób nigdy nie będziesz musiał wykonywać kodu swojej aplikacji tylko po to, aby przetestować parser.
Jeśli chcesz później zmienić i / lub dodać opcje do parsera w aplikacji, utwórz metodę fabryczną:
Jeśli chcesz, możesz później nim manipulować, a test może wyglądać następująco:
źródło
2
...argparse
nie jest zbyt przyjazny testowi, ponieważ drukuje bezpośrednio dosys.stderr
...„część argparse” jest nieco niejasna, więc ta odpowiedź skupia się na jednej części:
parse_args
metodzie. Jest to metoda, która współdziała z wierszem poleceń i pobiera wszystkie przekazane wartości. Zasadniczo można kpić z tego, coparse_args
zwraca, aby nie musiało faktycznie pobierać wartości z wiersza poleceń.mock
Pakiet można zainstalować poprzez pip dla wersji Pythona 2.6-3.2. Jest częścią biblioteki standardowej począwszyunittest.mock
od wersji 3.3.Musisz uwzględnić wszystkie argumenty metody poleceń,
Namespace
nawet jeśli nie zostały one przekazane. Nadaj tym argumentom wartośćNone
. (zobacz dokumentację ) Ten styl jest przydatny do szybkiego testowania przypadków, w których dla każdego argumentu metody przekazywane są różne wartości. Jeśli zdecydujesz się kpić zNamespace
samego siebie, aby w testach całkowicie nie polegać na argparse, upewnij się, że zachowuje się podobnie do rzeczywistejNamespace
klasy.Poniżej znajduje się przykład wykorzystujący pierwszy fragment z biblioteki argparse.
źródło
argparse
i jegoNamespace
klasy. Powinieneś kpićNamespace
.from unittest import mock
jest teraz poprawną metodą importu - przynajmniej dla pythona3Namespace
klasy jest dokładnie tym, czego szukałem. Mimo, że test wciąż sięargparse
opiera, nie opiera się na konkretnej implementacjiargparse
testowanego kodu, co jest ważne dla moich testów jednostkowych. Ponadto, jest to łatwe w użyciupytest
„sparametrize()
metody, aby szybko przetestować różne kombinacje argument z matrycy mock, który zawierareturn_value=argparse.Namespace(accumulate=accumulate, integers=integers)
.Niech twoja
main()
funkcja będzie traktowanaargv
jako argument, zamiast pozwolić jej czytaćsys.argv
tak, jak będzie domyślnie :Następnie możesz normalnie przetestować.
źródło
sys.argv.append()
a następnie zadzwońparse()
, sprawdź wyniki i powtórz.if __name__ == "__main__":
przeanalizuj wywołanie i zrzuć / oceń wyniki, a następnie przetestuj to z pliku wsadowego / bash.źródło
Nie chciałem modyfikować oryginalnego skryptu serwującego, więc po prostu wyszydziłem
sys.argv
część w argparse.To zepsuje się, jeśli argparse zmieni się w implementacji, ale wystarczy do szybkiego skryptu testowego. W każdym razie wrażliwość jest znacznie ważniejsza niż konkretność w skryptach testowych.
źródło
Prosty sposób na przetestowanie parsera to:
Innym sposobem jest modyfikacja
sys.argv
i dzwonienieargs = parser.parse_args()
Istnieje wiele przykładów testowania
argparse
wlib/test/test_argparse.py
źródło
parse_args
wyrzuca aSystemExit
i drukuje na stderr, możesz złapać oba z nich:Sprawdzasz stderr (używając,
err.seek(0); err.read()
ale generalnie ta szczegółowość nie jest wymagana.Teraz możesz użyć
assertTrue
lub dowolnego testu, który Ci się podoba:Alternatywnie możesz chcieć wyłapać i ponownie zgłosić inny błąd (zamiast
SystemExit
):źródło
Podczas przekazywania wyników z
argparse.ArgumentParser.parse_args
do funkcji czasami używam a,namedtuple
aby podrobić argumenty do testowania.źródło
Aby przetestować CLI (interfejs wiersza poleceń), a nie wyjście polecenia , zrobiłem coś takiego
źródło