Facebook - konwersja

Testy jednostkowe. Świat niezawodnych aplikacji. Wydanie II - ebook

Wydawnictwo:
Tłumacz:
Data wydania:
29 sierpnia 2014
Format ebooka:
EPUB
Format EPUB
czytaj
na czytniku
czytaj
na tablecie
czytaj
na smartfonie
Jeden z najpopularniejszych formatów e-booków na świecie. Niezwykle wygodny i przyjazny czytelnikom - w przeciwieństwie do formatu PDF umożliwia skalowanie czcionki, dzięki czemu możliwe jest dopasowanie jej wielkości do kroju i rozmiarów ekranu. Więcej informacji znajdziesz w dziale Pomoc.
Multiformat
E-booki w Virtualo.pl dostępne są w opcji multiformatu. Oznacza to, że po dokonaniu zakupu, e-book pojawi się na Twoim koncie we wszystkich formatach dostępnych aktualnie dla danego tytułu. Informacja o dostępności poszczególnych formatów znajduje się na karcie produktu.
, PDF
Format PDF
czytaj
na laptopie
czytaj
na tablecie
Format e-booków, który możesz odczytywać na tablecie oraz laptopie. Pliki PDF są odczytywane również przez czytniki i smartfony, jednakze względu na komfort czytania i brak możliwości skalowania czcionki, czytanie plików PDF na tych urządzeniach może być męczące dla oczu. Więcej informacji znajdziesz w dziale Pomoc.
Multiformat
E-booki w Virtualo.pl dostępne są w opcji multiformatu. Oznacza to, że po dokonaniu zakupu, e-book pojawi się na Twoim koncie we wszystkich formatach dostępnych aktualnie dla danego tytułu. Informacja o dostępności poszczególnych formatów znajduje się na karcie produktu.
, MOBI
Format MOBI
czytaj
na czytniku
czytaj
na tablecie
czytaj
na smartfonie
Jeden z najczęściej wybieranych formatów wśród czytelników e-booków. Możesz go odczytać na czytniku Kindle oraz na smartfonach i tabletach po zainstalowaniu specjalnej aplikacji. Więcej informacji znajdziesz w dziale Pomoc.
Multiformat
E-booki w Virtualo.pl dostępne są w opcji multiformatu. Oznacza to, że po dokonaniu zakupu, e-book pojawi się na Twoim koncie we wszystkich formatach dostępnych aktualnie dla danego tytułu. Informacja o dostępności poszczególnych formatów znajduje się na karcie produktu.
(3w1)
Multiformat
E-booki sprzedawane w księgarni Virtualo.pl dostępne są w opcji multiformatu - kupujesz treść, nie format. Po dodaniu e-booka do koszyka i dokonaniu płatności, e-book pojawi się na Twoim koncie w Mojej Bibliotece we wszystkich formatach dostępnych aktualnie dla danego tytułu. Informacja o dostępności poszczególnych formatów znajduje się na karcie produktu przy okładce. Uwaga: audiobooki nie są objęte opcją multiformatu.
czytaj
na laptopie
Pliki PDF zabezpieczone watermarkiem możesz odczytać na dowolnym laptopie po zainstalowaniu czytnika dokumentów PDF. Najpowszechniejszym programem, który umożliwi odczytanie pliku PDF na laptopie, jest Adobe Reader. W zależności od potrzeb, możesz zainstalować również inny program - e-booki PDF pod względem sposobu odczytywania nie różnią niczym od powszechnie stosowanych dokumentów PDF, które odczytujemy każdego dnia.
Informacje na temat zabezpieczenia e-booka znajdziesz na karcie produktu w "Szczegółach na temat e-booka". Więcej informacji znajdziesz w dziale Pomoc.
czytaj
na tablecie
Aby odczytywać e-booki na swoim tablecie musisz zainstalować specjalną aplikację. W zależności od formatu e-booka oraz systemu operacyjnego, który jest zainstalowany na Twoim urządzeniu może to być np. Bluefire dla EPUBa lub aplikacja Kindle dla formatu MOBI.
Informacje na temat zabezpieczenia e-booka znajdziesz na karcie produktu w "Szczegółach na temat e-booka". Więcej informacji znajdziesz w dziale Pomoc.
czytaj
na czytniku
Czytanie na e-czytniku z ekranem e-ink jest bardzo wygodne i nie męczy wzroku. Pliki przystosowane do odczytywania na czytnikach to przede wszystkim EPUB (ten format możesz odczytać m.in. na czytnikach PocketBook) i MOBI (ten fromat możesz odczytać m.in. na czytnikach Kindle).
Informacje na temat zabezpieczenia e-booka znajdziesz na karcie produktu w "Szczegółach na temat e-booka". Więcej informacji znajdziesz w dziale Pomoc.
czytaj
na smartfonie
Aby odczytywać e-booki na swoim smartfonie musisz zainstalować specjalną aplikację. W zależności od formatu e-booka oraz systemu operacyjnego, który jest zainstalowany na Twoim urządzeniu może to być np. iBooks dla EPUBa lub aplikacja Kindle dla formatu MOBI.
Informacje na temat zabezpieczenia e-booka znajdziesz na karcie produktu w "Szczegółach na temat e-booka". Więcej informacji znajdziesz w dziale Pomoc.
57,00

Testy jednostkowe. Świat niezawodnych aplikacji. Wydanie II - ebook

Poznaj możliwości testów jednostkowych!

System informatyczny to inteligentne połączenie modułów i zależności, otoczone setkami tysięcy, a nawet milionami linii kodu źródłowego. Zmiana w jednym obszarze może mieć fatalny wpływ na działanie systemu w zupełnie innym miejscu. Ta zależność prowadzi do ogromnych kosztów wprowadzenia nawet najdrobniejszej zmiany w oprogramowaniu. Czy istnieje rozwiązanie tego problemu? Jak stworzyć system, w którym błyskawiczna weryfikacja lub wprowadzona zmiana nie spowodują nowych błędów w innej części? Oczywiście, że można to zrobić! Odpowiedzią na te i wiele innych problemów są testy automatyczne.

Ten przewodnik to doskonała okazja, by głębiej poznać temat testów jednostkowych. Jeżeli uważasz, że ich pisanie jest uciążliwe, czasochłonne, trudne lub po prostu nie wiesz, jak je tworzyć, ta książka rozwiąże wszystkie Twoje problemy! W trakcie lektury dowiesz się, jak pisać testy, tworzyć zestawy testowe oraz przygotowywać makiety i namiastki. Poznasz narzędzia Moq, FakeItEasy oraz Typemock Isolator. Ponadto zdobędziesz wiedzę na temat organizacji testów oraz strategii testowania kodu odziedziczonego. Książka ta jest obowiązkową lekturą dla wszystkich programistów C# szukających świetnego przewodnika po świecie testów jednostkowych!

Dzięki tej książce:

  • rozwiejesz swoje wątpliwości dotyczące testów
  • poznasz najpopularniejsze narzędzia wspomagające testowanie
  • zorganizujesz swoje testy jednostkowe
  • zapoznasz się z kluczowymi elementami dobrych testów
  • stworzysz niezawodny i tani w utrzymaniu kod

Niezawodny kod jest w Twoim zasięgu!

Spis treści

Słowo wstępne do drugiego wydania (11)

Słowo wstępne do pierwszego wydania (13)

Przedmowa (15)

Podziękowania (17)

O tej książce (19)

O ilustracji na okładce (24)

CZĘŚĆ I. ZACZYNAMY (25)

Rozdział 1. Podstawowe informacje o testach jednostkowych (27)

  • 1.1. Definicja testu jednostkowego krok po kroku (28)
    • 1.1.1. Dlaczego ważne jest pisanie "dobrych" testów jednostkowych (29)
    • 1.1.2. Wszyscy piszemy testy jednostkowe (w pewnym sensie) (30)
  • 1.2. Właściwości dobrego testu jednostkowego (31)
  • 1.3. Testy integracyjne (31)
    • 1.3.1. Wady niezautomatyzowanych testów integracyjnych w porównaniu z automatycznymi testami jednostkowymi (33)
  • 1.4. Co sprawia, że test jednostkowy jest dobry (36)
  • 1.5. Prosty przykład testu jednostkowego (37)
  • 1.6. Wytwarzanie oprogramowania sterowane testami (40)
  • 1.7. Trzy zasadnicze umiejętności potrzebne do skutecznego stosowania technik TDD (43)
  • 1.8. Podsumowanie (44)

Rozdział 2. Pierwszy test jednostkowy (45)

  • 2.1. Frameworki testów jednostkowych (46)
    • 2.1.1. Co oferują frameworki testów jednostkowych (46)
    • 2.1.2. Frameworki xUnit (49)
  • 2.2. Wprowadzenie w tematykę projektu LogAn (49)
  • 2.3. Pierwsze kroki z NUnit (49)
    • 2.3.1. Instalacja frameworka NUnit (50)
    • 2.3.2. Ładowanie rozwiązania (51)
    • 2.3.3. Wykorzystanie atrybutów NUnit w kodzie (54)
  • 2.4. Piszemy pierwszy test (55)
    • 2.4.1. Klasa Assert (55)
    • 2.4.2. Uruchomienie pierwszego testu za pomocą frameworka NUnit (56)
    • 2.4.3. Dodanie testów pozytywnych (58)
    • 2.4.4. Od czerwonego do zielonego: dążenie do spełnienia testów (59)
    • 2.4.5. Styl kodu testów (59)
  • 2.5. Refaktoryzacja w kierunku testów z parametrami (59)
  • 2.6. Więcej atrybutów NUnit (62)
    • 2.6.1. Atrybuty Setup i TearDown (62)
    • 2.6.2. Testowanie występowania oczekiwanych wyjątków (65)
    • 2.6.3. Ignorowanie testów (67)
    • 2.6.4. Składnia fluent frameworka NUnit (68)
    • 2.6.5. Ustawianie kategorii testowych (69)
  • 2.7. Testowanie wyników metod, które nie zwracają wartości, tylko zmieniają stan systemu (70)
  • 2.8. Podsumowanie (74)

CZĘŚĆ II. PODSTAWOWE TECHNIKI (75)

Rozdział 3. Wykorzystanie namiastek do rozwiązywania zależności (77)

  • 3.1. Wprowadzenie w tematykę namiastek (77)
  • 3.2. Identyfikacja zależności od systemu plików w klasie LogAnalyzer (78)
  • 3.3. Określenie sposobu łatwego testowania klasy LogAnalyzer (79)
  • 3.4. Refaktoryzacja projektu w celu ułatwienia testowania (82)
    • 3.4.1. Wyodrębnienie interfejsu umożliwiającego zastąpienie istniejącej implementacji (84)
    • 3.4.2. Wstrzykiwanie zależności: wstrzyknięcie sztucznej implementacji do testowanej jednostki (86)
    • 3.4.3. Wstrzyknięcie sztucznego obiektu na poziomie konstruktora (86)
    • 3.4.4. Symulowanie wyjątków z poziomu sztucznych obiektów (90)
    • 3.4.5. Wstrzyknięcie sztucznego obiektu za pomocą gettera lub settera właściwości (91)
    • 3.4.6. Wstrzyknięcie sztucznego obiektu bezpośrednio przed wywołaniem metody (93)
  • 3.5. Odmiany technik refaktoryzacji (100)
    • 3.5.1. Wykorzystanie techniki "wyodrębnij i przesłoń" do tworzenia sztucznych wyników (100)
  • 3.6. Pokonanie problemu hermetyzacji (102)
    • 3.6.1. Korzystanie ze składowych internal oraz atrybutu [InternalsVisibleTo\ (103)
    • 3.6.2. Wykorzystanie atrybutu [Conditional\ (103)
    • 3.6.3. Korzystanie z dyrektyw #if i #endif do warunkowej kompilacji (104)
  • 3.7. Podsumowanie (104)

Rozdział 4. Testowanie interakcji z wykorzystaniem obiektów-makiet (107)

  • 4.1. Testy bazujące na wartości, testy bazujące na stanach a testy integracyjne (108)
  • 4.2. Różnica pomiędzy obiektami-makietami a namiastkami (110)
  • 4.3. Napisany ręcznie prosty przykład obiektu-makiety (111)
  • 4.4. Wykorzystywanie obiektów-makiet razem z namiastkami (114)
  • 4.5. Jedna makieta na test (118)
  • 4.6. Łańcuch sztucznych obiektów: namiastki, które generują makiety lub inne namiastki (119)
  • 4.7. Problemy z pisanymi ręcznie makietami i namiastkami (120)
  • 4.8. Podsumowanie (121)

Rozdział 5. Frameworki izolacji (123)

  • 5.1. Dlaczego stosujemy frameworki izolacji? (124)
  • 5.2. Dynamiczne tworzenie sztucznych obiektów (126)
    • 5.2.1. Wykorzystanie frameworka NSubstitute w testach (126)
    • 5.2.2. Zastąpienie sztucznego obiektu napisanego ręcznie obiektem dynamicznym (127)
  • 5.3. Symulacja sztucznych wartości (130)
    • 5.3.1. Wprowadzamy do testu makietę razem z namiastką (131)
  • 5.4. Testowanie działań związanych ze zdarzeniami (136)
    • 5.4.1. Testowanie obiektu nasłuchującego zdarzenia (136)
    • 5.4.2. Testowanie, czy zostało wyzwolone zdarzenie (138)
  • 5.5. Współczesne frameworki izolacji dla środowiska .NET (138)
  • 5.6. Zalety i pułapki frameworków izolacji (140)
    • 5.6.1. Pułapki, których należy unikać w przypadku korzystania z frameworków izolacji (140)
    • 5.6.2. Nieczytelny kod testu (141)
    • 5.6.3. Weryfikacja niewłaściwych rzeczy (141)
    • 5.6.4. Więcej niż jedna makieta w teście (141)
    • 5.6.5. Nadspecyfikacja testów (141)
  • 5.7. Podsumowanie (142)

Rozdział 6. Bardziej zaawansowane zagadnienia związane z frameworkami izolacji (145)

  • 6.1. Frameworki ograniczone i nieograniczone (146)
    • 6.1.1. Frameworki ograniczone (146)
    • 6.1.2. Frameworki nieograniczone (146)
    • 6.1.3. Jak działają nieograniczone frameworki bazujące na profilerze (148)
  • 6.2. Wartość dobrych frameworków izolacji (151)
  • 6.3. Własności wspierające długowieczność i użyteczność (152)
    • 6.3.1. Imitacje rekurencyjne (152)
    • 6.3.2. Domyślne ignorowanie argumentów (153)
    • 6.3.3. Rozległe imitacje (153)
    • 6.3.4. Nieścisłe zachowania sztucznych obiektów (154)
    • 6.3.5. Nieścisłe makiety (154)
  • 6.4. Antywzorce projektowe frameworków izolacji (155)
    • 6.4.1. Mylące pojęcia (155)
    • 6.4.2. Zarejestruj i odtwórz (156)
    • 6.4.3. Lepkie zachowania (158)
    • 6.4.4. Złożona składnia (158)
  • 6.5. Podsumowanie (159)

CZĘŚĆ III. KOD TESTU (161)

Rozdział 7. Hierarchie testów i ich organizacja (163)

  • 7.1. Testy uruchamiane w ramach automatycznych kompilacji (164)
    • 7.1.1. Anatomia skryptu kompilacji (165)
    • 7.1.2. Inicjowanie kompilacji i integracji (167)
  • 7.2. Klasyfikacja testów na podstawie szybkości i typu (168)
    • 7.2.1. Czynnik ludzki oddzielenia testów jednostkowych od testów integracyjnych (169)
    • 7.2.2. Bezpieczna zielona strefa (170)
  • 7.3. Zadbanie o umieszczenie testów w repozytorium z kodem źródłowym (171)
  • 7.4. Odwzorowanie klas testowych na testowany kod (171)
    • 7.4.1. Odwzorowanie testów na projekty (171)
    • 7.4.2. Odwzorowanie testów na klasy (172)
    • 7.4.3. Odwzorowanie testów na punkty wejścia metod konkretnych jednostek pracy (173)
  • 7.5. Wstrzykiwanie zależności cross-cutting (173)
  • 7.6. Budowanie API obsługi testów dla aplikacji (176)
    • 7.6.1. Wykorzystanie wzorców dziedziczenia w klasach testowych (176)
    • 7.6.2. Tworzenie narzędziowych klas i metod obsługi testów (189)
    • 7.6.3. Zapoznanie deweloperów ze stworzonym API (190)
  • 7.7. Podsumowanie (191)

Rozdział 8. Filary dobrych testów jednostkowych (193)

  • 8.1. Pisanie wiarygodnych testów (194)
    • 8.1.1. Decydowanie o tym, kiedy należy usunąć lub zmodyfikować testy (194)
    • 8.1.2. Unikanie logiki w testach (199)
    • 8.1.3. Testowanie tylko jednego aspektu (201)
    • 8.1.4. Oddzielenie testów jednostkowych od integracyjnych (202)
    • 8.1.5. Zapewnienie przeglądów kodu (203)
  • 8.2. Pisanie testów łatwych w utrzymaniu (205)
    • 8.2.1. Testowanie metod prywatnych lub chronionych (205)
    • 8.2.2. Usuwanie duplikatów (207)
    • 8.2.3. Korzystanie z metod konfiguracyjnych w sposób ułatwiający utrzymanie (210)
    • 8.2.4. Wymuszanie izolacji testu (213)
    • 8.2.5. Unikanie wielu asercji dotyczących różnych aspektów (220)
    • 8.2.6. Porównywanie obiektów (222)
    • 8.2.7. Unikanie nadmiernej specyfikacji (225)
  • 8.3. Pisanie czytelnych testów (227)
    • 8.3.1. Nazwy testów jednostkowych (227)
    • 8.3.2. Nazwy zmiennych (228)
    • 8.3.3. Dobre komunikaty asercji (229)
    • 8.3.4. Oddzielenie asercji od akcji (230)
    • 8.3.5. Konfigurowanie i rozbiórka (231)
  • 8.4. Podsumowanie (231)

CZĘŚĆ IV. PROJEKTOWANIE I PROCES (233)

Rozdział 9. Wdrażanie testów jednostkowych w organizacji (235)

  • 9.1. Jak zostać agentem zmian? (236)
    • 9.1.1. Bądź przygotowany na trudne pytania (236)
    • 9.1.2. Przekonaj inne osoby z organizacji: mistrzów i oponentów (236)
    • 9.1.3. Określenie możliwych punktów wejścia (237)
  • 9.2. Sposoby na odniesienie sukcesu (239)
    • 9.2.1. Wdrożenie po partyzancku (dół-góra) (239)
    • 9.2.2. Przekonanie kierownictwa (góra-dół) (240)
    • 9.2.3. Mistrz z zewnątrz (240)
    • 9.2.4. Zadbanie o widoczność postępów (241)
    • 9.2.5. Dążenie do konkretnych celów (242)
    • 9.2.6. Uświadomienie sobie istnienia przeszkód (244)
  • 9.3. Czynniki wpływające na porażkę (244)
    • 9.3.1. Brak siły napędowej (245)
    • 9.3.2. Brak politycznego wsparcia (245)
    • 9.3.3. Złe implementacje i pierwsze wrażenia (245)
    • 9.3.4. Brak wsparcia ze strony zespołu (246)
  • 9.4. Czynniki wpływające na zachowania członków zespołu (246)
  • 9.5. Trudne pytania i odpowiedzi (248)
    • 9.5.1. Ile dodatkowego czasu będzie trzeba poświęcić? (248)
    • 9.5.2. Czy ze względu na wprowadzenie testów jednostkowych będzie zagrożone moje stanowisko inżyniera jakości? (250)
    • 9.5.3. Skąd wiemy, że testy jednostkowe się sprawdzają? (250)
    • 9.5.4. Czy istnieje dowód, że testy jednostkowe pomagają? (251)
    • 9.5.5. Dlaczego dział kontroli jakości ciągle znajduje błędy? (251)
    • 9.5.6. Istnieje mnóstwo kodu, dla którego nie ma testów. Od czego zacząć? (252)
    • 9.5.7. Kodujemy w kilku językach 3 czy testy jednostkowe są wykonalne? (252)
    • 9.5.8. Co zrobić, jeśli produkt obejmuje kombinację oprogramowania i sprzętu? (253)
    • 9.5.9. Skąd możemy wiedzieć, że nie ma błędów w testach? (253)
    • 9.5.10. Debuger pokazuje, że mój kod działa 3 do czego są mi potrzebne testy? (253)
    • 9.5.11. Czy trzeba stosować kodowanie w stylu TDD? (253)
  • 9.6. Podsumowanie (254)

Rozdział 10. Praca z kodem odziedziczonym (255)

  • 10.1. Od czego należy zacząć przy dodawaniu testów? (256)
  • 10.2. Wybór strategii selekcji (258)
    • 10.2.1. Plusy i minusy strategii "najpierw łatwe" (258)
    • 10.2.2. Plusy i minusy strategii "najpierw trudne" (259)
  • 10.3. Pisanie testów integracyjnych przed refaktoryzacją (259)
  • 10.4. Ważne narzędzia do testów jednostkowych odziedziczonego kodu (261)
    • 10.4.1. Łatwe izolowanie zależności za pomocą frameworków izolacji bez ograniczeń (261)
    • 10.4.2. Wykorzystanie programu JMockit do pracy z kodem odziedziczonym w Javie (262)
    • 10.4.3. Wykorzystanie programu Vise do refaktoryzacji kodu w Javie (264)
    • 10.4.4. Przeprowadzenie testów akceptacyjnych przed refaktoryzacją (265)
    • 10.4.5. Przeczytaj książkę Michaela Feathersa na temat pracy z kodem odziedziczonym (266)
    • 10.4.6. Wykorzystanie programu NDepend do analizy kodu produkcyjnego (266)
    • 10.4.7. Wykorzystanie programu ReSharper do refaktoryzacji i poruszania się po kodzie produkcyjnym (267)
    • 10.4.8. Wykrywanie powielonego kodu (oraz błędów) za pomocą narzędzi Simian i TeamCity (267)
  • 10.5. Podsumowanie (268)

Rozdział 11. Projekt a sprawdzalność (269)

  • 11.1. Dlaczego należy dbać o sprawdzalność podczas projektowania? (269)
  • 11.2. Sprawdzalność jako cel projektowy (270)
    • 11.2.1. Domyślne stosowanie metod wirtualnych (271)
    • 11.2.2. Projekt bazujący na interfejsach (272)
    • 11.2.3. Domyślne stosowanie klas niezapieczętowanych (272)
    • 11.2.4. Unikanie tworzenia egzemplarzy klas skonkretyzowanych wewnątrz metod zawierających logikę (272)
    • 11.2.5. Unikanie bezpośrednich wywołań do metod statycznych (273)
    • 11.2.6. Unikanie konstruktorów lub konstruktorów statycznych zawierających logikę (273)
    • 11.2.7. Oddzielenie logiki singletona od posiadaczy singletona (274)
  • 11.3. Plusy i minusy projektowania z myślą o sprawdzalności (275)
    • 11.3.1. Ilość pracy (276)
    • 11.3.2. Złożoność (276)
    • 11.3.3. Eksponowanie wrażliwych IP (277)
    • 11.3.4. Czasami nie można (277)
  • 11.4. Alternatywy dla projektowania z myślą o sprawdzalności (277)
    • 11.4.1. Dyskusje o projektach i języki o dynamicznych typach (277)
  • 11.5. Przykład projektu trudnego do testowania (279)
  • 11.6. Podsumowanie (283)
  • 11.7. Dodatkowe materiały (284)

Dodatek A. Narzędzia i frameworki (287)

  • A.1. Frameworki izolacji (288)
  • A.2. Frameworki testów (292)
  • A.3. API testów (296)
  • A.4. Kontenery IoC (299)
  • A.5. Testowanie baz danych (302)
  • A.6. Testowanie stron WWW (303)
  • A.7. Testowanie interfejsu użytkownika (w aplikacjach desktop) (305)
  • A.8. Testowanie aplikacji wielowątkowych (306)
  • A.9. Testy akceptacyjne (306)
  • A.10. Frameworki API w stylu BDD (308)

Skorowidz (309)

Kategoria: Programowanie
Zabezpieczenie: Watermark
Watermark
Watermarkowanie polega na znakowaniu plików wewnątrz treści, dzięki czemu możliwe jest rozpoznanie unikatowej licencji transakcyjnej Użytkownika. E-książki zabezpieczone watermarkiem można odczytywać na wszystkich urządzeniach odtwarzających wybrany format (czytniki, tablety, smartfony). Nie ma również ograniczeń liczby licencji oraz istnieje możliwość swobodnego przenoszenia plików między urządzeniami. Pliki z watermarkiem są kompatybilne z popularnymi programami do odczytywania ebooków, jak np. Calibre oraz aplikacjami na urządzenia mobilne na takie platformy jak iOS oraz Android.
ISBN: 978-83-246-8777-0
Rozmiar pliku: 6,4 MB

BESTSELLERY

Kategorie: