{
 "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> Przygotowanie do projektu badawczo-rozwojowego</h1>\n",
    "<h2> 8. <i>Testowanie w programowaniu zwinnym</i>[wykład]</h2> \n",
    "<h3>Krzysztof Jassem (2021)</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.8.5"
  },
  "subtitle": "08. Testowanie w programowaniu zwinnym[wykład]",
  "title": "Przygotowanie do projektu badawczo-rozwojowego",
  "year": "2021"
 },
 "nbformat": 4,
 "nbformat_minor": 4
}