Czy możemy założyć podczas testowania oprogramowania, że ​​użytkownik nie wykonałby tak głupich działań na oprogramowaniu?

71

Na przykład: Podczas przeprowadzania testów funkcjonalnych formularza w aplikacji internetowej przetestujemy pola, wprowadzając różnego rodzaju losowe wartości wejściowe.

Zasadniczo my jako użytkownicy aplikacji internetowej nie wprowadzamy losowo wartości w polach.

Po co więc uwzględniać wszystkie te przypadki testowe, które mogą / mogą nie prowadzić do błędów, gdy prawdopodobieństwo pojawienia się tego rodzaju problemów w produkcji jest znacznie mniejsze?

Uwaga: powyższy przykład jest tylko przykładem; takie problemy mogą wystąpić w dowolnej funkcji / module.

Zadaję to pytanie tylko po to, aby wiedzieć, czy należy zastosować jakieś standardowe praktyki, czy też całkowicie zależy to od produktu, dziedziny i wszystkich innych czynników.

Nagarani Dubbaka
źródło
4
Być może istotne: testowanie małp , plusy i minusy
Christophe

Odpowiedzi:

190

Możesz nie wprowadzać losowych wartości w polach aplikacji internetowej, ale na pewno są ludzie, którzy to robią.

Niektóre osoby wchodzą przypadkowo, a inne robią to celowo, próbując przerwać aplikację. W obu przypadkach nie chcesz, aby aplikacja ulegała awarii lub wykazywała inne niepożądane zachowania.
W przypadku pierwszego typu użytkownika nie jest to konieczne, ponieważ zapewnia im złe wrażenia i może ich odrzucić.
W przypadku drugiego typu użytkownika zwykle nie mają oni zaszczytnych intencji i nie chcesz pozwolić im mieć dostępu do informacji, do których nie powinni mieć dostępu, ani nie pozwolić im odmówić prawdziwym użytkownikom dostępu do twoich usług.

Standardowa praktyka testowania polega na sprawdzeniu nie tylko, czy działa przy dobrej pogodzie, ale także na zbadaniu nietypowych przypadków, aby znaleźć potencjalne problemy i mieć pewność, że atakujący nie mogą łatwo uzyskać dostępu do twojego systemu. Jeśli aplikacja już ulega awarii przy losowym wprowadzaniu danych, nie chcesz wiedzieć, co osoba atakująca może zrobić przy użyciu specjalnie spreparowanych danych wejściowych.

Bart van Ingen Schenau
źródło
16
Są też rzeczy, które nie są ludźmi, którzy to robią. 👽
kojiro
110
Lub mogą próbować wprowadzić swoje rzeczywiste imię i nazwisko, takie jak „O'Malley”, „姓名” lub „Robert”); DROP TABLE Studenci; - ” .
l0b0,
90
A może prawdziwe nazwy firm ; TABELA DROP „FIRMY”; - LTD .
Ben,
25
Myślę, że ostatni akapit można wzmocnić, podkreślając, że jeśli program ulegnie awarii z przypadkowymi danymi wejściowymi kota chodzącego po klawiaturze, prawie na pewno ulegnie awarii (i gorzej) przy złośliwych danych wejściowych.
phihag
11
Ponadto wiele osób wprowadza dane losowe, ponieważ nie chcą podawać rzeczywistych danych (takich jak imię i nazwisko, urodziny itp.). Niektórzy zakładają również, że komputer jest tak inteligentny jak opiekun i mogą wpisać coś w stylu „w zeszłym roku” zamiast „2016” i oczekiwać, że aplikacja sobie z tym poradzi, tak jak zrobiłby to człowiek.
Luaan,
102

Nigdy niczego nie zakładaj

Nie możesz zakładać, że żaden użytkownik nie zrobi czegoś „głupiego” z twoim oprogramowaniem przez przypadek lub celowo. Użytkownicy mogą przypadkowo nacisnąć niewłaściwy przycisk, kot może przejść po klawiaturze, system może działać nieprawidłowo, ich komputer może zostać przejęty przez złośliwe oprogramowanie itp.

Ponadto sam użytkownik może być złośliwy, celowo szukając sposobów na złamanie oprogramowania w nadziei, że znajdzie sposób na wykorzystanie go na swoją korzyść. Nawet jeśli znajdą błąd, którego nie mogą wykorzystać, wszystko, co znajdą, może zachęcić ich do zbadania twojego systemu pod kątem czegoś, co mogą zaatakować, wiedząc, że brakuje ci procedur kontroli jakości.

Jeśli chodzi o testowanie, przydatne jest zabezpieczenie przed przypadkowymi danymi wejściowymi, jednak wybór danych wejściowych testowych całkowicie losowo (tj. Bez szczególnego uwzględnienia przypadków użycia lub przypadków brzegowych) jest bezużyteczny. Celem testowania jest sprawdzenie poprawności rozwiązania pod kątem wymagań i oczekiwań pracodawcy / klientów / użytkowników; oznacza to, że musisz skupić się na kierowaniu na wszystkie przypadki brzegowe i warunki brzegowe, a także wszelkie przypadki „zdegenerowane”, które nie pasują do oczekiwanego przepływu pracy użytkownika.

Oczywiście możesz uruchomić testy, które ujawnią błędy, które później uważasz, że nie są warte naprawy; może to być z wielu powodów - błąd może być zbyt drogi, aby naprawić w stosunku do jego wpływu na użytkownika, lub możesz odkryć błędy w funkcjach, których nikt nie używa, lub błąd może być tak dobrze ustalony w systemie, że niektóre użytkownicy traktują to jako funkcję.

Ewentualnie możesz pisać oprogramowanie na zamówienie, które ma ściśle ograniczoną grupę użytkowników „ekspertów”, w przypadku których nie ma korzyści komercyjnych ze spędzania czasu na naprawianiu błędów, ponieważ ci użytkownicy są w stanie wykonywać swoje zadania przy użyciu błędnego oprogramowania (na przykład narzędzie diagnostyczne używane przez wewnętrzny zespół IT nie przynosi żadnych dochodów, więc jeśli od czasu do czasu ulega awarii, nikt prawdopodobnie nie będzie chciał zapłacić za czas potrzebny na jego naprawę - po prostu powie zespołowi IT, aby zamiast tego mieszkał z błędami) .

Jednak możesz podejmować te decyzje tylko wtedy, gdy wiesz o tych błędach. Na przykład użytkownik może wprowadzić złośliwe dane, które wymazują całą bazę danych - jeśli nie masz wyraźnej ochrony przed tym scenariuszem i nie przetestowałeś go, nie ma możliwości, aby mieć pewność, czy tak się stanie. Ryzyko pozostawienia nieodkrytych błędów w systemie oznacza, że ​​potencjalnie narażasz się na prawdziwe problemy, jeśli jeden z tych błędów ujawni się w prawdziwym świecie i ma duży wpływ na twoich użytkowników.

Tak więc, podczas gdy decyzja o tym, czy naprawić błędy, może wymagać pewnego wkładu od właściciela oprogramowania (zwykle tego, kto płaci twoją pensję), decyzja o tym, czy testować pod kątem błędów i które przypadki testować, jest kwestią inżynierską, którą należy podjąć uwzględnione w szacunkach i planowaniu projektu, gdzie celem powinno być osiągnięcie tak bliskiego pełnego pokrycia, jak to możliwe, biorąc pod uwagę ograniczenia czasu / pieniędzy / zasobów.

Ben Cottrell
źródło
12
Chociaż testowanie całkowicie losowe nie jest przydatne i na pewno powinieneś wyraźnie przetestować tyle przypadkowych przypadków, ile możesz sobie wyobrazić, pewna liczba losowych fuzzingów może czasami być przydatna do sprawdzenia problemów, których możesz nie przewidzieć.
Sean Burton,
10
Mamy powiedzenie: „Trudno jest pisać oprogramowanie odporne na idioty, ponieważ idioci to tacy sprytni ludzie”. Więc przetestuj pod kątem „nonsensownych” danych wejściowych!
Ralf Kleberhoff
For example, a user may enter a malicious input which wipes the entire database - if you haven't explicitly protected against and tested for this scenario, then there's no way you can be sure whether or not this can happen.Jak małe stoły Bobby'ego z tego komiksu XKCD? ;)
nick012000,
12
„Nigdy niczego nie zakładaj”. Zakładam, że to dobra rada.
candied_orange
Dziękujemy za zwrócenie uwagi, że nie wszystkie „błędy” to „poprawki”. Jest duża różnica w byciu świadomym przypadku krawędzi i poświęcaniu czasu i pieniędzy na naprawę przypadku krawędzi. Byłoby na pewno świetnie, aby zezwolić na wszelkie możliwe dane wejściowe do formularza internetowego i mieć ustaloną odpowiedź dla wszystkich przypadków, ale być może nie jest to istotne dla konkretnego oprogramowania. Być może twoje dane wejściowe dopuszczają tylko liczby z przodu, więc nie można odbierać liczb z tyłu. „Naprawianie” potencjalnego błędu związanego z brakiem liczb w postaci wyłącznie liczbowej jest stratą czasu i pieniędzy.
EvSunWoodard
60

Należy wziąć pod uwagę kilka czynników. Aby zilustrować te punkty, wykorzystam przykład pola, w którym użytkownik powinien wprowadzić wartość procentową w kontekście przydziału określonego dla określonego zadania pod względem ilości miejsca na dysku, które zadanie może wykorzystać. 0% oznacza, że ​​zadanie nie byłoby w stanie zapisać niczego na dysku; 100% oznacza, że ​​zadanie może wypełnić całe miejsce na dysku. Wartości pomiędzy oznaczają, co oznaczają.

Jako programista prawdopodobnie bierzesz pod uwagę, że dopuszczalne wartości to [0, 1, 2, 3, ⋯ 99, 100], a wszystko inne jest głupie. Zobaczmy, dlaczego użytkownicy nadal mogą wprowadzać te „głupie” wartości.

Literówki

%^

Użytkownik wprowadzał wartość 56, ale przez pomyłkę został wciśnięty Shiftpodczas wprowadzania (na przykład dlatego, że na klawiaturze francuskiej należy nacisnąć, Shiftaby wprowadzić cyfry, a użytkownik stale przełączał się między klawiaturą francuską a QWERTY).

W ten sam sposób możesz uzyskać liczbę, z czymś po niej, przed nią lub pomiędzy:

56q

Tutaj użytkownik prawdopodobnie wprowadzał cyfry, a następnie tabulator, aby przejść do następnego pola. Zamiast naciskać   ⇆  , użytkownik nacisnął klawisz sąsiada.

Nieporozumienia i błędne interpretacje

Puste dane wejściowe są prawdopodobnie najbardziej powszechne. Użytkownik wyobrażał sobie, że pole jest opcjonalne lub nie wiedział, co wpisać w to pole.

56.5

Użytkownik pomyślał, że wartości zmiennoprzecinkowe są dopuszczalne. Albo użytkownik się myli, a aplikacja powinna uprzejmie wyjaśnić, dlaczego akceptowane są tylko wartości całkowite, lub początkowe wymagania były błędne, i warto pozwolić użytkownikom na wprowadzanie wartości zmiennoprzecinkowych.

none

Użytkownik źle zrozumiał, że zapytany o miejsce, które zadanie może zająć, aplikacja spodziewała się liczby. Może to wskazywać na zły interfejs użytkownika. Na przykład pytanie użytkownika „Ile miejsca na dysku powinno zająć zadanie?” Zachęca do tego rodzaju danych wejściowych, podczas gdy pole ze znakiem procentu otrzyma mniej tego rodzaju danych wejściowych, ponieważ „brak%” nie powoduje dużo rozsądku.

150

Użytkownik źle zrozumiał, co oznacza procent w tym przypadku. Być może użytkownik chciał powiedzieć, że zadanie może zająć 150% aktualnie używanego miejsca, więc jeśli na dysku o pojemności 2 TB użyto 100 GB, zadanie może zużyć 150 GB. Ponownie może pomóc lepszy interfejs użytkownika. Na przykład, zamiast mieć puste pole wejściowe ze znakiem procentu, można to zrobić:

[____] % of disk space (2 TB)

Gdy użytkownik zaczyna pisać, zmienia tekst w locie, tworząc:

[5___] % of disk space (102.4 GB of 2 TB)

Reprezentacje

Duże liczby lub liczby zmiennoprzecinkowe mogą być reprezentowane w różny sposób. Na przykład, liczba 1234,56 mogłyby być napisane tak: 1,234.56. W zależności od kultury reprezentacja tekstowa tego samego numeru może się różnić. W języku francuskim, taka sama liczba będzie napisane tak: 1 234,56. Zobacz przecinek, w którym nie spodziewałbyś się, i spację.

Zawsze oczekiwanie określonego formatu przy użyciu określonych ustawień regionalnych prędzej czy później spowoduje kłopoty, ponieważ użytkownicy z różnych krajów mieliby różne nawyki pisania liczb, dat i godzin itp.

Ludzie kontra komputery

Twenty-four

Zwykli ludzie nie myślą tak samo jak komputery. „Dwadzieścia cztery” to rzeczywista liczba, niezależnie od tego, co powiedziałby komputer.

Chociaż (1) większość systemów w ogóle nie obsługuje tego typu danych wejściowych i (2) prawie każdy użytkownik nie wyobrażałby sobie wprowadzenia liczby zapisanej pełnymi literami, nie oznacza to, że takie dane wejściowe są głupie. W About Face 3 Alan Cooper zwraca uwagę, że brak obsługi takich danych wejściowych wskazuje na niezdolność komputerów do przystosowania się do ludzi i idealnie, interfejs powinien być w stanie poprawnie obsługiwać te dane wejściowe.

Jedyne, co muszę dodać do książki Alana Coopera, to to, że w wielu przypadkach cyfry są pomyłkowo zapisywane cyframi . Fakt, że komputery oczekują od swoich użytkowników błędów (i nie będzie tolerował użytkownika, który pisze poprawnie) jest denerwujący.

Unicode

5𝟨

Unicode zastrzega sobie własne niespodzianki: postacie, które mogłyby wyglądać tak samo, nie są takie same. Nieprzekonany? Skopiuj i wklej "5𝟨" === "56"do narzędzi dla programistów przeglądarki i naciśnij Enter.

Powodem, dla którego te ciągi nie są równe, jest to, że znak Unicode 𝟨nie jest taki sam jak znak 6. Spowodowałoby to sytuację, w której zadzwoniłby zły klient, informując, że aplikacja nie działa, udostępniając zrzut ekranu z danymi, które wyglądają na zgodne z prawem, i twierdząc, że dane wejściowe są nieprawidłowe.

Dlaczego ktoś miałby wprowadzać znak Unicode, który wygląda jak cyfra? Chociaż nie spodziewałbym się, że użytkownik przypadkowo wprowadzi jedną, wklejenie kopii z innego źródła może to spowodować, a ja miałem przypadek, w którym użytkownik faktycznie wykonał taki wklejanie ciągu zawierającego znak Unicode, który nie byłby pojawiają się na ekranie.

Wniosek

Takie są przypadki, w których można wprowadzić pole wprowadzania liczb elementarnych. Pozwolę ci sobie wyobrazić, co możesz zrobić w przypadku bardziej złożonych formularzy, takich jak data lub adres.

Moja odpowiedź koncentruje się na tym, co nazywasz „głupim” wkładem. Testowanie nie polega na sprawdzaniu szczęśliwych ścieżek; chodzi również o sprawdzenie, czy aplikacja się nie psuje, gdy złośliwy użytkownik celowo wprowadza dziwne rzeczy, próbując je złamać. Oznacza to, że gdy prosisz o procent, musisz również sprawdzić, co się dzieje, gdy użytkownik odpowiada ciągiem zawierającym 1 000 000 znaków, liczbą ujemną lub tabelą bobby .

Arseni Mourzenko
źródło
9
Ach, U + 1D7E8: MATEMATYCZNA CYFROWA SANS-SERIF.
Andreas Rejbrand
23
Drugi znak Unicode: w japońskich klawiaturach bardzo często zmienia się cyfry normalne na cyfry pełnej szerokości, gdzie cyfra jest tak szeroka jak kanji. Tak więc japoński użytkownik mógł mieć włączony język japoński (a nie angielski) i przypadkowo wprowadził cyfry o pełnej szerokości.
stycznia
3
Zanim zobaczyłem sekcję 5𝟨 dotyczącą tego samego problemu z homoglyfem, faktycznie spodziewałem się 1 234,56ciągu (używając U + 00A0 SPACJA NO-BREAK zamiast U + 0020 SPACE), co jest właściwym sposobem na skodyfikowanie tych znaczników liczb (lub za pomocą U + 202F WĄSKA PRZESTRZEŃ BEZ PRZERW, peroahps). Skopiowanie wartości z dowolnej aplikacji, która formatuje liczby zgodnie z ustawieniami regionalnymi przed przedstawieniem jej użytkownikowi, bardzo łatwo to wygeneruje.
Ángel
4
wklejanie kopii jest znacznie większym problemem. Powszechne jest kopiowanie spacji, podziałów wierszy, niewidocznych znaków ...
Sulthan,
7
@Arseni Mourzenko Musisz mieć szczęście. Kopiowanie np. Z pliku PDF i wklejanie może wkleić wszystkie znaki, które mogą być niepożądane w zależności od cyrkulacji, np. Ligatury (dla fi itp.), Inteligentne cytaty, en lub em myślnik tam, gdzie pożądany był ASCII minus itp.
Rosie F
12

Istnieje wiele dobrych odpowiedzi, które opisują, dlaczego jest to ważne, ale nie ma zbyt wielu porad, jak rozsądnie chronić swoją aplikację. „Standardową praktyką” jest stosowanie niezawodnej weryfikacji danych wejściowych zarówno na kliencie, jak i na serwerze. Niemądry wkład jest łatwy do obrony; po prostu odrzucasz wszystko, co nie ma sensu w tym konkretnym kontekście. Na przykład numer ubezpieczenia społecznego składa się wyłącznie z myślników i cyfr; możesz bezpiecznie odrzucić wszystko, co użytkownik wpisze w polu numeru ubezpieczenia społecznego.

Istnieją dwa rodzaje testów, które powinny mieć miejsce w każdej pisanej aplikacji, a każda z nich ma inne cele. Testy przeprowadzane na własnej aplikacji są testami pozytywnymi; jego celem jest udowodnienie, że program działa. Testowanie, które dodatkowo testują w twojej aplikacji, to testowanie negatywne; jego celem jest udowodnienie, że twój program nie działa. Dlaczego tego potrzebujesz? Ponieważ nie jesteś najlepszą osobą do testowania własnego oprogramowania. W końcu napisałeś coś, więc oczywiście to już działa, prawda?

Podczas pisania sprawdzania poprawności danych wejściowych zastosujesz testy pozytywne, aby udowodnić, że sprawdzanie poprawności działa. Testerzy użyją losowych danych wejściowych, aby udowodnić, że to nie działa. Zauważ, że przestrzeń problemowa dla losowych danych wejściowych jest zasadniczo nieograniczona; Twoim celem nie jest przetestowanie każdej możliwej permutacji, ale ograniczenie przestrzeni problemowej poprzez odrzucenie nieprawidłowych danych wejściowych.

Pamiętaj również, że użytkownik końcowy nie jest jedynym, który zapewnia dane wejściowe do twojego programu. Każda klasa, którą piszesz, ma swój własny interfejs API i własne ograniczenia dotyczące tego, co jest uważane za prawidłowe dane wejściowe, więc niezawodna weryfikacja (tj. „Umowy kodowe”) jest ważna również dla twoich klas. Chodzi o to, aby zahartować oprogramowanie, aby nieoczekiwane zachowanie było rzadkie lub nie występowało w maksymalnym możliwym zakresie.

Wreszcie przepływ pracy jest ważny. Widziałem, jak aplikacje się przewracają, nie dlatego, że użytkownik wprowadził coś nie sensownego, ale dlatego, że robił to w aplikacji w nieoczekiwanej kolejności. Twoja aplikacja powinna być świadoma tej możliwości i albo płynnie obsługiwać nieoczekiwane przepływy pracy, albo wymagać od użytkownika wykonywania operacji w określonej kolejności.

Robert Harvey
źródło
Typowym przykładem aplikacji, która oczekuje określonej kolejności, jest funkcja „porzucenia”, która zwalnia uchwyty, które nigdy nie były zarezerwowane.
wizzwizz4,
2
Niestety, standardową praktyką jest odrzucanie wszystkiego, co nie ma sensu i pozostawianie użytkownika zdezorientowanego i sfrustrowanego. Prawidłowa praktyka polega na dokładnym wyjaśnieniu (np. Przy użyciu komunikatów o błędach / opinii), dlaczego dane wejściowe zostały odrzucone, aby użytkownik wiedział, jak je poprawić i jak je zaakceptować. Proste „pobierz liczbę całkowitą od 1 do 100” wymaga co najmniej 4 różnych komunikatów o błędach (pusty ciąg, nieobsługiwany znak, za duży, za mały); plus testowanie w celu zapewnienia właściwej informacji zwrotnej w każdym przypadku.
Brendan
2
@Brendan: Wymagana jest tylko jedna wiadomość: „Musi to być liczba od 1 do 100”. Użytkownik nie wie (i nie musi wiedzieć), co to jest łańcuch lub co oznaczają „nieobsługiwane znaki”. Są to wpływ na programistę, a nie pomoc użytkownika.
Robert Harvey,
@RobertHarvey Prawdopodobnie dodam do tego wyrażenia coś w stylu „złożony z cyfr”. Ponieważ wejście „Siedemdziesiąt dziewięć” jest liczbą od 1 do 100, ale nie jest wejściem, z którym większość programów może pracować.
Delioth,
1
@Delioth: Nie można naprawić głupiego.
Robert Harvey,
11

Zwykle wartości „losowe” nie są losowe. Próbujesz uchwycić przypadki skrajne, „nieznane nieznane”.

Powiedzmy na przykład, że znak # spowoduje awarię aplikacji. Nie znasz tego z góry i nie byłoby możliwe napisanie przypadków testowych dla każdego możliwego wkładu. Ale możemy napisać test "¬!"£$%^&*()_+-=[]{};'#:@~,./<>?|\"i sprawdzić, czy się zepsuje

Ewan
źródło
2
+1 Zaskakujące jest na pierwszy rzut oka, jak często te losowe znaki znajdą błąd. Dane pochodzące od użytkowników mogą dużo podróżować przez wiele komponentów / usług. Tylko jeden element w łańcuchu nie przetwarza go prawidłowo, aby system miał błąd.
Lan
4
esp. teraz, gdy wszystkie klawiatury mobilne mają emotikony
Ewan
dla programistów .Net narzędzie IntelliTest (wcześniej nazywane Pex) jest naprawdę dobrym sposobem na ćwiczenie ścieżek kodu w celu znalezienia przypadków brzegowych, jest szczególnie przydatne do sprawdzania poprawności danych wejściowych i uzyskania dobrego pokrycia kodu.
James Snell,
7

Kiedyś napisałem program, który przetestowałem na żywo w laboratorium z 60 studentami. Stałem za 60 ekranami komputerów i widziałem, jak z nich korzystają. Liczba śmiesznych rzeczy, które robili, to wychowywanie włosów. Byłem mokry od potu, obserwując ich „kreatywność”. Zrobili znacznie więcej niż jakakolwiek pojedyncza osoba może fantazjować w ciągu całego życia. Oczywiście jeden z nich to złamał.

Następnie stosuję podejście: if "a very specific use case" do, else show error

Jeśli mam kilka przypadków użycia, ściśle je definiuję i łączę powyższe.

Artur Tarasow
źródło
1
Jednak te szczególne przypadki użycia mogą być zbyt szczegółowe. Zawsze nie doceniamy przestrzeni ważnych danych wejściowych. (O'Hara, lokalnie sformatowane miejsca dziesiętne itp.). Ile procedur finansowych przygotowano na obsługę ujemnych stóp procentowych?
Guran,
6

Co ty opisujesz to fuzz lub Fuzz Testowanie : rzucać wejście losowe i nieprawidłową w systemie i zobaczyć co się dzieje. Nie robisz tego, ponieważ oczekujesz, że użytkownik to zrobi. Robisz to, aby ujawnić własne założenia i uprzedzenia, aby podkreślić krawędzie twojego systemu i zobaczyć, co się stanie.

Normalne wejście testowe napisane przez człowieka będzie zawierało założenia i uprzedzenia. Te tendencje mogą być pewnymi klasami błędów, które nigdy nie zostaną wykryte podczas testowania.

Na przykład, jeśli większość danych wejściowych znajduje się w zakresie Unicode bezpiecznym dla ASCII, założenia dotyczące kodowania znaków w kodzie nie są uwzględniane. A może zawsze jest poniżej określonego rozmiaru, więc pole lub bufor o stałej wielkości nie są trafiane. A może istnieją znaki specjalne, które są interpretowane w zaskakujący sposób, ujawniając, że dane wejściowe użytkownika są podawane do powłoki lub wykorzystywane do tworzenia zapytań w niebezpieczny sposób. A może po prostu zbyt wiele testów „szczęśliwej ścieżki” i zbyt mało prób wykonania obsługi błędów.

Fuzzing nie ma takich uprzedzeń na temat danych wejściowych. Będzie brutalnie ćwiczył Twój system z każdą możliwą kombinacją „prawidłowych” danych wejściowych. Unicode, ASCII, duży, mały i wiele błędów. Twój system powinien reagować z wdziękiem na wszystkie z nich. Nigdy nie powinno się zawiesić. Użytkownik powinien zawsze otrzymywać rozsądny komunikat o tym, co poszło nie tak i jak to naprawić. To nie jest Garbage In / Garbage Out, to Garbage In / Error Out .

Chociaż można odrzucić powstałe w ten sposób eksplozje, ponieważ „żaden prawdziwy użytkownik tego nie zrobi”, nie ma to sensu w ćwiczeniu. Fuzzing to tani sposób na wyeliminowanie uprzedzeń dotyczących możliwych danych wejściowych. Jest to tani sposób na wyrzucenie wszystkich dziwnych rzeczy, które użytkownicy będą próbować robić w twoim systemie. Jako inżynier masz za zadanie dopilnować, aby twój system nie uległ awarii.


Co więcej, fuzzing „input” to nie tylko użytkownicy. Może to być wynik zapytania API do usługi innej firmy, co jeśli zacznie się wysyłać pomieszane wyniki? Jak radzi sobie z tym twój system? Właściwy system powinien ostrzec administratora, że ​​jakiś komponent uległ awarii. Niewłaściwy system po cichu odrzuci złe zapytanie lub, co gorsza, zaakceptuje je jako dobre dane.

Wreszcie, niektórzy użytkownicy są złośliwi. Jeśli nie rozwiążesz problemów z testowaniem systemu, zrobi to ktoś inny. Sprawdzą krawędzie twojego systemu pod kątem typowych błędów i spróbują wykorzystać je jako dziury w zabezpieczeniach. Testy Fuzz mogą do pewnego stopnia to symulować, a Ty możesz poradzić sobie z wszelkimi możliwymi lukami bezpieczeństwa odkrytymi, zanim staną się one problemem.

Schwern
źródło
I są narzędzia do testowania Quick Check , które robią podobne rzeczy
icc97
4

Jeśli Twoim celem jest stworzenie produktu wysokiej jakości, przetestuj każdy możliwy rodzaj danych wejściowych, które użytkownik będzie mógł fizycznie przesłać. W przeciwnym razie czekasz tylko na dzień, w którym ktoś prześle ten typ danych wejściowych, który nie byłby potrzebny do testowania.

Podczas dużej demonstracji nowego oprogramowania do e-aukcji w lokalnym urzędzie, w którym pracowałem, mój menedżer zdecydował (co prawda z pewną psotą), że czuł potrzebę zobaczenia, co się stanie, jeśli złoży ofertę aukcyjną o wartości ujemnej. Ku mojemu prawdziwemu zaskoczeniu oprogramowanie aukcyjne pozwoliło na bezsensowną licytację i cały proces aukcyjny zatrzymał się. Przedstawiony rodzaj aukcji nigdy nie powinien pozwalać na składanie ujemnych kwot.

Część dużej grupy zebranych urzędników odpowiedzialnych za zamówienia i finanse była zirytowana moim przełożonym za przedstawianie bezsensownych wartości. Ale inni, w tym ja, byli zirytowani twórcami oprogramowania za to, że nie przetestowali i nie odrzucili tak oczywistego rodzaju nieprawidłowych danych wejściowych. Mogę sobie tylko wyobrazić, jak słabe musiało być oprogramowanie przy odchylaniu innych typów nieprawidłowych danych wejściowych (próby wprowadzenia kodu, egzotyczne znaki, których nie można przedstawić w tabeli bazy danych itp.).

Gdyby to zależało ode mnie, zwróciłbym oprogramowanie i uznałem, że nie nadaje się do określonego celu. Różnica między słabym a silnym oprogramowaniem to poziom testów, którym został poddany.

Arkanon
źródło
2
test every possible type of input that a user will be physically able to submit.- Ta przestrzeń problemowa jest zasadniczo nieskończona i marnujesz czas, próbując to wszystko przetestować. Sprawdzanie negatywnych danych wejściowych jest pojedynczym rozgałęzieniem; jest to nie tylko rozsądne, ale także oczekiwane od kompetentnych programistów. Nie musisz sprawdzać każdej liczby ujemnej, aby udowodnić, że taka weryfikacja działa.
Robert Harvey
13
Właśnie dlatego powiedziałem każdy rodzaj danych wejściowych, a nie wszystkie możliwe dane wejściowe. Powtórzę mój punkt: jeśli nie przetestujesz każdego rodzaju danych wejściowych, użytkownicy w końcu to zrobią.
Arkanon,
1

Na przykład: Podczas przeprowadzania testów funkcjonalnych formularza w aplikacji internetowej przetestujemy pola, wprowadzając różnego rodzaju losowe wartości wejściowe.

Tak. Jest to rodzaj testu, ale nie jest to test funkcjonalny . To właśnie nazywa się testami warunków skrajnych . Jest to wywieranie nacisku na system, aby sprawdzić, czy sobie z tym poradzi.

Po co więc uwzględniać wszystkie te przypadki testowe, które mogą / mogą nie prowadzić do błędów, gdy prawdopodobieństwo pojawienia się tego rodzaju problemów w produkcji jest znacznie mniejsze?

Kiedy jesteś stres testowania oprogramowania próbujesz odkryć granice tego, co ogranicza oprogramowania są.

Testy są z natury wyczerpujące. Tam, gdzie musisz odkryć ograniczenia użytkowania, punkty przełomowe, sprawdź wszystkie logiczne gałęzie lub zobaczyć, jak częściowe awarie wpływają na cały system.

Możesz zdać wszystkie testy funkcjonalne, ale test obciążeniowy nadal się nie powiedzie .

Zadaję to pytanie tylko po to, aby wiedzieć, czy należy zastosować jakieś standardowe praktyki, czy też całkowicie zależy to od produktu, dziedziny i wszystkich innych czynników.

Tak, to standardowa praktyka.

Testowanie oprogramowania polega na zadaniu pytania na temat oczekiwanego zachowania, a kiedy wszystkie testy zakończą się pomyślnie, oznacza to, że oprogramowanie działa zgodnie z przeznaczeniem. Dlatego testy zapewniają dobre warunki wstępne podczas wdrażania aktualizacji.

Testy warunków skrajnych nie zapewniają wyraźnych wskaźników pozytywnego lub negatywnego wyniku. Wyniki są bardziej pouczające. Mówi ci, co twój system może obsłużyć i podejmujesz decyzje na podstawie tych informacji.

Możesz zdefiniować konkretne cele testów warunków skrajnych, które należy przejść, aby przejść do następnego etapu rozwoju. Można je uwzględnić w ramach procesu zapewniania jakości, ale zmiany w otoczeniu mogą zmienić wyniki testu warunków skrajnych. Dlatego ludzie przeprowadzają testy warunków skrajnych w różnych momentach, aby zobaczyć, jak system radzi sobie ze zmieniającymi się warunkami.

Chodzi mi o to, że nie można po prostu uruchamiać testów warunków skrajnych za każdym razem, gdy wdrażasz nową wersję oprogramowania, i zakładam, że oznacza to, że wszystko przejdzie testy warunków skrajnych później.

Reactgular
źródło