Wydaje się, że „teoria testowania oprogramowania” daje teorie w miękkim tego słowa znaczeniu; Nie byłem w stanie znaleźć niczego, co klasyfikowałoby jako teorię w sensie matematycznym, teoretycznym informacji lub w jakiejś innej dziedzinie naukowej.
To, czego szukam, to coś, co formalizuje, czym jest testowanie, użyte pojęcia, czym jest przypadek testowy, wykonalność testowania czegoś, praktyczność testowania czegoś, zakres, w jakim coś powinno być testowane, formalna definicja / wyjaśnienie zasięg kodu itp.
AKTUALIZACJA: Ponadto, nie jestem pewien, intuicyjnie, co do związku między formalną weryfikacją a tym, o co prosiłem, ale najwyraźniej istnieje jakiś związek.
testing
math
theory
formal-methods
information-theory
Erik Kaplun
źródło
źródło
double pihole(double value) { return (value - Math.PI) / (value - Math.PI); }
którego nauczyłem się od mojego nauczyciela matematyki . Ten kod ma dokładnie jedną dziurę , której nie można wykryć automatycznie na podstawie samych testów czarnej skrzynki. W matematyce nie ma takiej dziury. W rachunku różniczkowym możesz zamknąć otwór, jeśli jednostronne limity są równe.(a,b)=>a/b
, która musi zostać powiększona o wartość przepełnienia, aby mogła być poprawnie skomponowana.Odpowiedzi:
W przypadku książki eksplorującej matematykę związaną z testowaniem oprogramowania ... najważniejszą książką jest The Art of Computer Systems Performance Analysis: Techniki for Experimental Design, Measurement, Simulation, and Modeling
Chociaż został opublikowany po raz pierwszy w 1991 roku, jest nadal popularny, ponieważ jest to książka do matematyki stosowanej, która koncentruje się wyłącznie na analizie wyników, symulacji i pomiarach.
źródło
Nie mogę wskazać na dobry zasób online (artykuły w angielskiej Wikipedii na te tematy są zazwyczaj poprawialne), ale mogę streścić wykład, który słyszałem, który obejmował także podstawową teorię testowania.
Tryby testowania
Istnieją różne klasy testów, takie jak testy jednostkowe lub testy integracyjne . Test jednostkowy stwierdza, że spójny fragment kodu (funkcja, klasa, moduł) wzięty z własnych prac zgodnie z oczekiwaniami, podczas gdy test integracyjny potwierdza, że wiele takich elementów działa poprawnie.
Przypadek testowy jest znanym środowiskiem, w którym wykonywany jest fragment kodu, np. Przy użyciu określonego wejścia testowego lub przez wyśmiewanie innych klas. Zachowanie kodu jest następnie porównywane z oczekiwanym zachowaniem, np. Określoną wartością zwracaną.
Test może jedynie udowodnić obecność błędu, nigdy braku wszystkich błędów. Testy ustalają górną granicę poprawności programu.
Pokrycie kodu
Aby zdefiniować metryki pokrycia kodu, kod źródłowy można przetłumaczyć na wykres przepływu sterowania, gdzie każdy węzeł zawiera liniowy segment kodu. Kontrola przepływa między tymi węzłami tylko na końcu każdego bloku i zawsze jest warunkowa (jeśli warunek, to jest goto węzeł A, w przeciwnym razie goto węzeł B). Wykres ma jeden węzeł początkowy i jeden węzeł końcowy.
Dlatego często przydatne jest sprawdzenie pokrycia warunków .
true
ifalse
. Oznacza to pełne pokrycie oddziałów, ale jest raczej drogie. Program może mieć dodatkowe ograniczenia, które wykluczają pewne kombinacje. Ta technika jest dobra do uzyskania zasięgu gałęzi, może znaleźć martwy kod, ale nie może znaleźć błędów wynikających ze złego stanu.Podczas konstruowania danych wejściowych testowych z wykorzystaniem pokrycia warunków należy wziąć pod uwagę zwarcie. Na przykład,
musi zostać przetestowany z
foo(false, whatever)
,foo(true, false)
ifoo(true, true)
dla pełnego minimalnego pokrycia wielu warunków.Jeśli masz obiekty, które mogą znajdować się w wielu stanach, sensowne wydaje się testowanie wszystkich przejść stanu analogicznych do przepływów sterowania.
Istnieje kilka bardziej złożonych wskaźników zasięgu, ale są one zasadniczo podobne do wskaźników przedstawionych tutaj.
Są to metody testowania białych skrzynek i mogą być częściowo zautomatyzowane. Należy pamiętać, że pakiet testów jednostkowych powinien dążyć do uzyskania wysokiego zasięgu kodu według dowolnej wybranej metryki, ale 100% nie zawsze jest możliwe. Szczególnie trudno jest przetestować obsługę wyjątków, w których błędy muszą być wstrzykiwane w określone miejsca.
Testy funkcjonalne
Następnie są testy funkcjonalne, które potwierdzają, że kod jest zgodny ze specyfikacją, widząc implementację jako czarną skrzynkę. Takie testy są przydatne zarówno w testach jednostkowych, jak i testach integracyjnych. Ponieważ niemożliwe jest testowanie przy użyciu wszystkich możliwych danych wejściowych (np. Testowanie długości łańcucha ze wszystkimi możliwymi łańcuchami), przydatne jest grupowanie danych wejściowych (i danych wyjściowych) w równoważne klasy - jeśli
length("foo")
jest poprawne,foo("bar")
prawdopodobnie również zadziała. Dla każdej możliwej kombinacji klas równoważności danych wejściowych i wyjściowych wybiera się i testuje co najmniej jedno reprezentatywne dane wejściowe.Należy dodatkowo przetestować
length("")
,foo("x")
,length(longer_than_INT_MAX)
,length(null)
, orazlength("null byte in \x00 the middle")
…W
0, ±1, ±x, MAX, MIN, ±∞, NaN
przypadku liczb oznacza to testowanie , aw przypadku porównań zmiennoprzecinkowych testowanie dwóch sąsiednich liczb zmiennoprzecinkowych. Jako kolejne uzupełnienie losowe wartości testowe można wybrać z klas równoważności. Aby ułatwić debugowanie, warto zapisać użyte ziarno…Testy niefunkcjonalne: testy obciążenia, testy warunków skrajnych
Oprogramowanie ma niefunkcjonalne wymagania, które również muszą zostać przetestowane. Obejmują one testowanie na określonych granicach (testy obciążenia) i poza nimi (testy warunków skrajnych). W przypadku gry komputerowej może to oznaczać minimalną liczbę klatek na sekundę w teście obciążenia. Witryna może być poddana testom warunków skrajnych w celu zaobserwowania czasów reakcji, gdy dwukrotnie więcej odwiedzających niż przewidywano obija serwery. Testy te dotyczą nie tylko całych systemów, ale także pojedynczych jednostek - jak degraduje się tablica skrótów z milionem wpisów?
Innymi rodzajami testów są testy całego systemu, w których symulowane są scenariusze, lub testy akceptacyjne potwierdzające spełnienie umowy deweloperskiej.
Metody niezwiązane z testowaniem
Opinie
Istnieją techniki niezwiązane z testowaniem, które można wykorzystać do zapewnienia jakości. Przykładami są instrukcje, formalne przeglądy kodu lub programowanie w parach. Chociaż niektóre części można zautomatyzować (np. Za pomocą włókien), są one na ogół czasochłonne. Jednak przeglądy kodu przez doświadczonych programistów mają wysoki wskaźnik wykrywanych błędów i są szczególnie cenne podczas projektowania, w którym nie jest możliwe automatyczne testowanie.
Kiedy recenzje kodu są tak świetne, dlaczego wciąż piszemy testy? Dużą zaletą pakietów testowych jest to, że mogą one uruchamiać się (głównie) automatycznie i jako takie są bardzo przydatne w testach regresyjnych .
Formalna weryfikacja
Formalna weryfikacja przebiega i potwierdza pewne właściwości kodu. Weryfikacja ręczna jest przeważnie możliwa w przypadku części krytycznych, a mniej w przypadku całych programów. Dowody stawiają dolną granicę poprawności programu. Dowody mogą być do pewnego stopnia zautomatyzowane, np. Za pomocą sprawdzania typu statycznego.
Niektóre niezmienniki można jawnie sprawdzić za pomocą
assert
instrukcji.Wszystkie te techniki mają swoje miejsce i się uzupełniają. TDD zapisuje testy funkcjonalne z góry, ale testy można ocenić na podstawie wskaźników zasięgu po wdrożeniu kodu.
Pisanie testowalnego kodu oznacza pisanie małych jednostek kodu, które można testować osobno (funkcje pomocnicze o odpowiedniej szczegółowości, zasada pojedynczej odpowiedzialności). Im mniej argumentów pobiera każda funkcja, tym lepiej. Taki kod nadaje się również do wstawiania fałszywych obiektów, np. Poprzez wstrzykiwanie zależności.
źródło
Może „testowanie oparte na specyfikacji” również stanowi odpowiedź na twoje pytanie. Sprawdź te moduły testowe (których jeszcze nie używałem). Wymagają one napisania wyrażenia matematycznego w celu określenia zestawów wartości testowych zamiast pisania testu jednostkowego przy użyciu wybranych pojedynczych wartości danych.
Test :: Lectrotest
Jak mówi autor, ten moduł Perla został zainspirowany modułem szybkiego sprawdzania Haskella . Na tej stronie znajduje się więcej linków, z których niektóre nie żyją.
źródło
Jednym podejściem matematycznym jest testowanie wszystkich par . Chodzi o to, że większość błędów jest aktywowana przez wybór jednej opcji konfiguracji, a większość pozostałych jest aktywowana przez pewną parę opcji wziętych jednocześnie. Dlatego większość można złapać, testując „wszystkie pary”. Wyjaśnienie matematyczne (z uogólnieniami) znajduje się tutaj:
System AETG: podejście do testowania oparte na konstrukcji kombinatorycznej
(istnieje wiele innych takich referencji)
źródło
Istnieje kilka równań matematycznych, ale zależy to od rodzaju testowanego oprogramowania. Na przykład założenie krytycznego uszkodzenia zakłada, że awarie nie są wynikiem dwóch lub więcej jednoczesnych awarii. Następujące równanie to: f = 4n + 1. f = funkcja, która oblicza liczbę przypadków testowych dla danej liczby zmiennych ( n) + 1 jest dodatkiem stałej, w której wszystkie zmienne przyjmują wartość nominalną.
Innym rodzajem testowania, który wymaga równań matematycznych, jest Testowanie odporności Testowanie odporności lub poprawności przypadków testowych w procesie testowym. W tym teście wprowadzałeś zmienne z legalnego zakresu wejściowego (czyste przypadki testowe) i zmienne wejściowe poza zakresem wejściowym (brudne przypadki testowe). Użyłbyś następującego równania matematycznego: f = 6n + 1 . 6n oznacza, że każda zmienna musi przyjmować 6 różnych wartości, podczas gdy inne wartości przyjmują wartość nominalną. * + 1 * oznacza dodanie stałej 1.
źródło