Aby przetestować moją aplikację Django, używam prostego testera opartego na testach jednostkowych.
Moja aplikacja jest skonfigurowana do korzystania z podstawowego loggera w settings.py przy użyciu:
logging.basicConfig(level=logging.DEBUG)
A w kodzie mojej aplikacji za pomocą:
logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))
Jednak podczas uruchamiania unittests chciałbym wyłączyć rejestrowanie, aby nie zaśmiecało moich wyników testu. Czy istnieje prosty sposób na wyłączenie logowania w sposób globalny, tak aby rejestratory specyficzne dla aplikacji nie zapisywały informacji na konsoli, gdy uruchamiam testy?
python
django
unit-testing
logging
shreddd
źródło
źródło
Odpowiedzi:
wyłączy wszystkie wywołania logowania z poziomami mniejszymi lub równymi
CRITICAL
. Rejestrowanie można ponownie włączyć za pomocąźródło
logging.disable
(z zaakceptowanej odpowiedzi) na górzetests.py
aplikacji, która rejestruje.tearDown()
metodzie:logging.disable(logging.NOTSET)
starannie odkłada logowanie na miejsce.tests
modułu jest bardzo przydatne.Ponieważ jesteś w Django, możesz dodać te linie do swojego settings.py:
W ten sposób nie musisz dodawać tej linii we wszystkich
setUp()
testach.W ten sposób możesz również wprowadzić kilka przydatnych zmian dla swoich potrzeb testowych.
Istnieje inny „przyjemniejszy” lub „czystszy” sposób dodawania szczegółów do testów, a mianowicie tworzenie własnego narzędzia do uruchamiania testów.
Po prostu utwórz taką klasę:
A teraz dodaj do swojego pliku settings.py:
Pozwala to na jedną naprawdę przydatną modyfikację, której nie ma w przypadku drugiego podejścia, a mianowicie sprawienie, że Django po prostu testuje aplikacje, które chcesz. Możesz to zrobić, zmieniając
test_labels
dodanie tej linii do testu runner:źródło
Inne odpowiedzi zapobiegają „zapisywaniu rzeczy na konsolę” przez globalne ustawienie infrastruktury rejestrowania tak, aby cokolwiek ignorowała. To działa, ale uważam, że jest to zbyt tępe podejście. Moje podejście polega na wprowadzeniu zmiany konfiguracji, która robi tylko to, co jest potrzebne, aby zapobiec wydostawaniu się dzienników na konsolę. Dlatego dodaję niestandardowy filtr rejestrowania do mojego
settings.py
:I skonfigurowałem logowanie Django, aby użyło filtra:
Wynik końcowy: kiedy testuję, nic nie trafia do konsoli, ale wszystko inne pozostaje takie samo.
Czemu to robić?
Projektuję kod, który zawiera instrukcje logowania, które są uruchamiane tylko w określonych okolicznościach i który powinien podawać dokładne dane potrzebne do diagnozy, jeśli coś pójdzie nie tak. Dlatego testuję , że robią to, co powinni, a zatem całkowite wyłączenie logowania nie jest dla mnie opłacalne. Nie chcę znaleźć, gdy oprogramowanie jest już w produkcji, że to, co myślałem, że zostanie zarejestrowane, nie jest rejestrowane.
Co więcej, niektóre programy uruchamiające testy (na przykład Nos) przechwytują dzienniki podczas testowania i wyświetlają odpowiednią część dziennika wraz z niepowodzeniem testu. Jest to przydatne w ustalaniu przyczyny niepowodzenia testu. Jeśli rejestrowanie jest całkowicie wyłączone, nic nie można przechwycić.
źródło
test_settings.py
plik, który znajduje się obok mojego projektusettings.py
. Jest ustawiony na ładowaniesettings.py
i wprowadzanie zmian, takich jak ustawioneTESTING_MODE
naTrue
. Moje programy uruchamiające testy są tak zorganizowane, żetest_settings
jest to moduł załadowany dla ustawień projektu Django. Można to zrobić na wiele sposobów. Zwykle wybieram ustawienie zmiennej środowiskowejDJANGO_SETTINGS_MODULE
naproj.test_settings
.Podoba mi się pomysł niestandardowego testera Hasseka. Należy zauważyć, że
DjangoTestSuiteRunner
nie jest już domyślnym programem uruchamiającym testy w Django 1.6+, został zastąpiony przezDiscoverRunner
. W przypadku zachowania domyślnego program uruchamiający testy powinien wyglądać bardziej jak:źródło
helpers
, która zawiera tylko narzędzia, które nie są importowane z żadnego innego miejsca w projekcie.Zauważyłem, że w przypadku testów w ramach
unittest
lub podobnej strukturze najskuteczniejszym sposobem bezpiecznego wyłączenia niechcianego logowania w testach jednostkowych jest włączenie / wyłączenie wsetUp
/tearDown
Methods konkretnego przypadku testowego. Pozwala to na jeden cel konkretnie, w którym dzienniki powinny być wyłączone. Możesz to również zrobić jawnie w programie rejestrującym testowanej klasy.źródło
Używam dekoratora prostej metody, aby wyłączyć rejestrowanie tylko w określonej metodzie testowej.
A potem używam go jak w poniższym przykładzie:
źródło
Istnieje pewna ładna i przejrzysta metoda zawieszania logowania testów za pomocą
unittest.mock.patch
metody.foo.py :
tests.py :
I nie
python3 -m unittest tests
będzie generować żadnych danych logowania.źródło
Czasami potrzebujesz dzienników, a czasami nie. Mam ten kod w moim
settings.py
Jeśli więc uruchomisz test z
--no-logs
opcjami, otrzymasz tylkocritical
dzienniki:Jest to bardzo pomocne, jeśli chcesz przyspieszyć testy w przepływie ciągłej integracji.
źródło
Jeśli nie chcesz, aby to wielokrotnie włączało / wyłączało się w setUp () i tearDown () dla unittest (nie widzisz powodu), możesz to zrobić raz na zajęcia:
źródło
W przypadkach, w których chcę tymczasowo ukryć określony rejestrator, napisałem mały menedżer kontekstu, który okazał się przydatny:
Następnie używasz go tak:
Ma to tę zaletę, że rejestrator jest ponownie włączany (lub przywracany do poprzedniego stanu) po
with
zakończeniu.źródło
Możesz umieścić to w katalogu najwyższego poziomu dla
__init__.py
pliku testów jednostkowych . Spowoduje to wyłączenie globalnego rejestrowania w zestawie testów jednostkowych.źródło
W moim przypadku mam plik ustawień
settings/test.py
stworzony specjalnie do celów testowych, oto jak to wygląda:Umieściłem zmienną środowiskową
DJANGO_SETTINGS_MODULE=settings.test
w/etc/environment
.źródło
Jeśli masz różne moduły inicjalizacyjne do testowania, tworzenia i produkcji, możesz wyłączyć cokolwiek lub przekierować to w inicjatorze. Mam local.py, test.py i production.py, które dziedziczą po common.y
common.py wykonuje całą główną konfigurację, w tym ten fragment:
Następnie w test.py mam to:
Zastępuje to obsługę konsoli przez FileHandler i oznacza, że nadal rejestruję, ale nie muszę dotykać bazy kodu produkcyjnego.
źródło
Jeśli używasz
pytest
:Ponieważ pytest przechwytuje komunikaty dziennika i wyświetla je tylko w przypadku testów zakończonych niepowodzeniem, zazwyczaj nie chcesz wyłączać żadnego rejestrowania. Zamiast tego użyj oddzielnego
settings.py
pliku do testów (np.test_settings.py
) I dodaj do niego:To mówi Django, aby całkowicie pominął konfigurowanie logowania.
LOGGING
Ustawienie zostanie zignorowany i mogą być usunięte z ustawieniami.Dzięki takiemu podejściu nie otrzymujesz żadnego rejestrowania dla zdanych testów, a otrzymasz wszystkie dostępne rejestracje dla testów zakończonych niepowodzeniem.
Testy zostaną uruchomione przy użyciu rejestrowania skonfigurowanego przez
pytest
. Można go skonfigurować według własnych upodobań wpytest
ustawieniach (nptox.ini
.). Aby dołączyć komunikaty dziennika poziomu debugowania, użyjlog_level = DEBUG
(lub odpowiedniego argumentu wiersza poleceń).źródło