SysInf/materiały na wykład/08_testowanie_w_programowaniu_zwinnym.ipynb

475 lines
17 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n",
"<h1> Systemy informatyczne</h1>\n",
"<h2> 8. <i>Testowanie w programowaniu zwinnym</i>[wykład]</h2> \n",
"<h3>Krzysztof Jassem (2022)</h3>\n",
"</div>\n",
"\n",
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Przykłady katastrof spowodowanych złym testowaniem"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Start sondy kosmicznej Mariner-1 (1962) </h3>\n",
"<a href=\"https://plwiki.pl/Leksykon/Mariner_1\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Start sondy kosmicznej Mariner-1 (1962) </h3>\n",
"<a href=\"https://plwiki.pl/Leksykon/Mariner_1\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Maszyna do radioterapii Therac-25 (1985-1987) </h3>\n",
"<a href=\"https://ucgosu.pl/2018/09/therac-25-czyli-blad-w-sofcie-medycznym-powodujacy-smierc-pacjentow/\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Zestrzelenie Airbusa 290 (1988) </h3>\n",
"<a href=\"https://www.msn.com/pl-pl/wiadomosci/historia/jak-w-1988-roku-zestrzelono-ira%C5%84ski-samolot-pasa%C5%BCerski/ar-BBYPtLv?li=BBr5MK7\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Awaria sieci AT T (1990) </h3>\n",
"<a href=\"https://www.computerworld.pl/news/Najgorsze-skutki-bledow-programistow,369992.html\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Błąd systemu obrony przeciwrakietowej Patriot (1992) </h3>\n",
"<a href=\"https://www.konflikty.pl/technika-wojskowa/na-ladzie/patriot-dhahran-co-sie-stalo/\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Awaria rakiety Ariane-5 (1996) </h3>\n",
"<a href=\"https://ucgosu.pl/2018/09/ariane-5-int-overflow-ktory-wysadzil-w-powietrze-rakiete/\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Błąd konwersji w sondzie Mars Climate Orbiter (1999) </h3>\n",
"<a href=\"https://ichi.pro/pl/blad-konwersji-wynoszacy-328-milionow-dolarow-271395322355666\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"\n",
"<h3> Awaria systemu PEKA (2014) </h3>\n",
"<a href=\"https://www.fakt.pl/wydarzenia/polska/poznan/awaria-systemu-peka-w-poznaniu-awaria-kart-peka/9d1pbb1\">Przeczytaj w Internecie</a>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Podstawowe pojęcia testowania"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Błąd (error)</h3>\n",
" \n",
"<b>Błąd</b> to objaw nieoczekiwanego działania programu ujawniony podczas testów.\n",
" \n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Defekt (fault)</h3>\n",
" \n",
"<b>Defekt</b> to niedoskonałość w kodzie programu. \n",
"\n",
"<i>Błąd</i> ujawniony w czasie testów świadczy o <i>defekcie</i> w testowanym kodzie.\n",
" \n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Testowanie</h3>\n",
" \n",
"<b>Testowanie </b> to proces, który ma na celu <b><i>wykazanie</i></b> istnienia defektów w kodzie programu poprzez wywołanie błędów w działaniu.\n",
" \n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Usuwanie defektów</h3>\n",
" \n",
"<b>Usuwanie defektów </b> to proces lokalizacji i poprawiania defektów.\n",
"\n",
"Procesy testowania i usuwania defektów często przeplatają się w pętlach iteracyjnych:\n",
"<ol>\n",
"<li>Wywołaj błąd (testowanie)</li>\n",
"<li>Zlokalizuj defekt (usuwanie defektów)</li>\n",
"<li>Zaprojektuj naprawę defektu (usuwanie defektów)</li>\n",
"<li>Napraw defekt (usuwanie defektów)</li>\n",
"<li>Wróć do 1.</li>\n",
"</ol>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Testy bialej skrzynki</h3>\n",
" \n",
"<b>Testy białej skrzynki</b> zakładają wgląd w wewnętrzną strukturę (kod) programu na tej podstawie tworzone są przypadki testowe.\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Testy czarnej skrzynki</h3>\n",
" \n",
"W <b> testach czarnej skrzynki</b> program traktowany jest jak czarna skrzynka, której zawartość pozostaje nieznana; \n",
"<ul>\n",
"<li>Przypadki testowe tworzone są bez znajomości kodu.\n",
"<li>Celem testowania jest wykrycie sytuacji, w których dane wejściowe przekształcane są na wyniki niezgodnie z oczekiwaniami.\n",
"</ul>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info alert-success\">\n",
"<h3>Zasady testowania</h3>\n",
" \n",
"<ol>\n",
"<li> Programiści nie testują swoich programów (poza tworzeniem testów jednostkowych).\n",
"<li> Firma nie testuje swoich produktów (a dokładniej: niezbędne jest testowanie zewnętrzne)\n",
"<li> Przypadki testowe muszą być zapisane. Nie należy tworzyć przypadków ulotnych.\n",
"<li> Testowanie jest czynnością kreatywną.\n",
"</ol>\n",
"\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Przypadki testowe"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<h3>Przypadek testowy</h3>\n",
" \n",
"<b>Przypadek testowy</b> to eksperyment przeprowadzany w testowaniu, który można opisać w kategoriach:\n",
"<ul>\n",
"<li> wartości wprowadzanych danych, \n",
"<li> akcji wykonywanej przez użytkownika\n",
"<li> oczekiwanych wyników. \n",
"</ul>\n",
"\n",
"Przypadki testowe służą do <b>ograniczenia</b> przestrzeni sytuacji, które należy sprawdzić, aby wywołać błąd programu. \n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Jak tworzyć przypadki testowe?\n",
"\n",
" * Analiza klas równoważności:\n",
" * Klasa równoważności wszystkie możliwe wartości danych wejściowych przetwarzanych w ten sam sposób. \n",
" * Jeden przypadek testowy reprezentuje jedną klasę równoważności. \n",
"\n",
"**Przykład**: Testowany komponent systemu operuje na parze danych, z których pierwszy element oznacza godzinę, a drugi minutę. Ile można wyróżnić klas równoważności?\n",
" \n",
"<img src=\"obrazy/klasy równoważności.png\" alt=\"Klasy równoważności przypadków testowych\" width=400px>\n",
"\n",
" * Analiza wartości brzegowych\n",
" * Metoda zakłada, że błędy mogą być spowodowane nieprzewidzianym zachowaniem programu w okolicach wartości brzegowych.\n",
" * Jeden przypadek testowy odpowiada jednej wartości brzegowej.\n",
"\n",
"**Przykład**: Testowany komponent systemu operuje na parze danych, z których pierwszy element oznacza godzinę, a drugi minutę. Ile można wyróżnić przypadków testowych metodą analizy wartości brzegowych? \n",
"\n",
"<img src=\"obrazy/wartości brzegowe.png\" alt=\"Analiza wartości brzegowych\" width=400px>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Jak opisywać przypadki testowe?\n",
"\n",
" * W metodzie białej skrzynki za pomocą testów jednostkowych, stosując metodę analizy wartości brzegowych lub klas równoważności\n",
" * W metodzie czarnej skrzynki w postaci:\n",
" * Prostej instrukcji do testera\n",
" * Scenariusza przypadku testowego\n",
" \n",
"**Przykład opisu przypadków testowych z prostą instrukcją:**\n",
"<img src=\"obrazy/przypadki testowe.png\" alt=\"Opis przypadków testowych\" width=900px>\n",
"\n",
" \n",
"**Przykład opisu przypadku testowego ze scenariuszem:**\n",
"<img src=\"obrazy/przypadek testowy ze scenariuszem.png\" alt=\"Opis przypadku testowego ze scenariuszem\" width=900px>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Poziomy testowania\n",
"\n",
"* Znalezienie defektu jest tym trudniejsze, im dłuższa droga dzieli miejsce defektu od miejsca ujawnienia błędu.\n",
"\n",
"* Każdemu etapowi wytwarzania oprogramowania odpowiada określony poziom testowania.\n",
"\n",
"<img src=\"obrazy/poziomy testowania.gif\" alt=\"Poziomy testowania\" width=600px>\n",
"(źródło: https://edux.pjwstk.edu.pl/mat/200/lec/wyklady/11_3.html)\n",
"\n",
"* Zarządzanie poziomami testowania ma na celu skrócenie drogi od spowodowania defektu do wykrycia błędu.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Poziomy testowania w Scrumie\n",
"\n",
"* W programowaniu tradycyjnym testowanie odbywa się sekwencyjnie.\n",
"\n",
"* W Scrumie testowanie na wszystkich poziomach odbywa się równolegle (codziennie lub co przyrost).\n",
"\n",
"* Wnioski:\n",
"\n",
" * 1: Każdy zespół powinien zawierać osobę, która zajmuje się testowaniem „na pełen etat”.\n",
" * 2: W każdym sprincie powinno odbyć się testowanie na każdym poziomie.\n",
" * 3: W każdym kolejnym sprincie pojawiają się nowe przypadki testowe, ale wszystkie „stare” pozostają.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Testowanie jednostkowe\n",
"### Zasady testowania jednostkowego\n",
"\n",
" 1. Przedmiotem testowania są podstawowe jednostki programu.\n",
" 2. Testy jednostkowe tworzone są przez dewelopera - programistę.\n",
" 3. W testowaniu jednostkowym (jak i w całym procesie Scrum) polecana strategia to Test First.\n",
" 4. Test jednostkowy powinien testować jednostkę w izolacji.  "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.1. Przedmiotem testowania są podstawowe jednostki programu\n",
" * Every method needs to be tested.”\n",
" * W praktyce testowane są tylko metody publiczne…\n",
" * …Co oznacza, że testy metod publicznych muszą być tak dokładne, by testowały WSZYSTKIE wywoływane przez nie metody prywatne…\n",
" * …Co również oznacza, że defekty w metodach prywatnych ujawnione zostaną dopiero w testach dla metod publicznych.\n",
" * „Keep test logic out of production code”\n",
" * Nie wprowadzaj testów jednostkowych do kodu produkcyjnego."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.2. Testy jednostkowe tworzone są przez programistę\n",
" \n",
"<img src=\"obrazy/testy jednostkowe.png\" alt=\"Testy jednostkowe\" width=800px>\n",
"(rysunek na podstawie: Tilo Linz, \"Testing in Scrum\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.3. W testowaniu jednostkowym (jak i w całym procesie Scrum) polecana strategia to Test First\n",
"#### Zasady strategii Test First \n",
" * Zanim napiszesz linijkę kodu, napisz test automatyczny, który się nie powodzi.\n",
" * Pisz kod tak długo, aż powiodą się wszystkie testy.\n",
"#### Zalety strategii TestFirst\n",
" * Testowanie zastępuje metodę prób i błędów.\n",
" * Realizacja przypadków testowych jest obiektywną miarą postępów w pracy.\n",
" * Przypadki testowe zastępują formalną specyfikację.\n",
" * „Test first” wprowadza porządek w interfejsach między klasami.\n",
" * „Test first” świetnie wpisuje się w Scrum."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.4. Test jednostkowy powinien testować wyłącznie jednostkę (w izolacji)\n",
" * Każdy obiekt testowany jest indywidualnie…\n",
" * …Ale działanie obiektu może zależeć od innych komponentów…\n",
" * …Które mogą być niezaimplementowane w czasie testowania.\n",
" * Takie komponenty zastępuje się zamiennikami (ang. placeholder).\n",
"\n",
" * Typy zamienników:\n",
" * Stub (zalążek) - imituje obiekt zewnętrzny, który przekazuje dane do testowanego obiektu).\n",
" * Spy (szpieg) - zapamiętuje historię danych przekazywanych przez testowany obiekt).\n",
" * Mock (atrapa) - \"inteligentnie\" imituje obiekt zewnętrzny, który reaguje na dane przekazywane z testowanego obiektu.\n",
" * Fake (podróbka) - mocno uproszczona atrapa obiektu zewnętrznego, która nie ma wpływu na wynik testowania.\n",
" * Dummy (manekin) - pusty obiekt.\n",
" * Blog na temat zamienników:\n",
" [Przeczytaj o zamiennikach](https://dariuszwozniak.net/posts/kurs-tdd-19-mock-stub-fake-spy-dummy)\n",
" \n",
" **Przykład stuba (zalążka)**: \n",
" <img src=\"obrazy/stub.png\" alt=\"Przykład zalążka\" width=400px>\n",
"(rysunek na podstawie: wikipedia\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Testowanie integracyjne w Scrumie\n",
" * Celem testowania integracyjnego jest sprawdzenie, czy niezależne komponenty (np. klasy) prawidłowo ze sobą współpracują.\n",
" * Testowanie wykonują deweloperzy (na swojej maszynie) lub zespół testujący (w repozytorium).\n",
" * Metody testowania integracyjnego:\n",
" * Metoda wielkiego wybuchu\n",
" * Metoda stopniowej integracji i testowania\n",
" * W metodyce Scrum możliwe jest stosowanie obu metod:\n",
" * Metoda wielkiego wybuchu na zakończenie sprintu lub\n",
" * Metoda Ciągłej Integracji (testowanie po każdej zmianie)\n",
" * Systemy Ciągłej Integracji ułatwiają testowanie po każdej zmianie poprzez uruchamianie testów automatycznych. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Podsumowanie\n",
" * Niewykryte defekty w kodzie programu mogą doprowadzić do poważnej awarii lub katastrofy.\n",
" * Testowanie jest czynnością kreatywną, której celem jest wykazanie istnienia defektów w kodzie.\n",
" * Przypadki testowe mają na celu ograniczenie przestrzeni wyszukiwania defektów.\n",
" * Testowanie odbywa się na różnych poziomach w tradycyjnych systemach jest to proces sekwencyjny, a w Scrumie iteracyjny."
]
}
],
"metadata": {
"author": "Krzysztof Jassem",
"email": "jassem@amu.edu.pl",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"lang": "pl",
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
},
"subtitle": "08. Testowanie w programowaniu zwinnym[wykład]",
"title": "Przygotowanie do projektu badawczo-rozwojowego",
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 4
}