Představ si, že jsi naprogramoval robota, aby ti uvařil čaj. Dal jsi mu přesné instrukce (algoritmus). Ale co když robot místo čaje uvaří kávu? Nebo se mu konvice vůbec nezapne? To znamená, že v tvém programu (nebo algoritmu) je chyba! V této kapitole se naučíme, jak zkontrolovat, jestli náš program funguje správně, a co dělat, když najdeme chybu.
Program je vlastně jen jiný název pro algoritmus, který je napsaný tak, aby mu rozuměl počítač. Je to posloupnost příkazů, které počítač provádí krok za krokem.
Program je sada přesných instrukcí (algoritmus) napsaných v jazyce, kterému rozumí počítač, aby vykonal určitý úkol.
Když něco naplánujeme nebo napíšeme program, musíme zkontrolovat, jestli to funguje tak, jak má. Tomu říkáme ověření správnosti.
Kdybychom neověřovali, mohli bychom si myslet, že náš program funguje, ale ve skutečnosti by dělal něco špatně. To by mohlo vést k velkým problémům.
V informatice se ověřování správnosti programu říká testování. Znamená to, že program spustíme a zkusíme, jestli dělá to, co má.
Testování programu je proces, při kterém zkoušíme, zda program funguje správně a bez chyb.
Když program nefunguje, jak má, znamená to, že v něm je chyba. V informatice se chybám říká bugy (z anglického "brouci"). A proces hledání a opravování chyb se nazývá ladění (debugging).
Oprava chyby je jako hledání jehly v kupce sena. Musíš se podívat na svůj program krok za krokem a zjistit, kde jsi udělal chybu.
Scratch je skvělé prostředí pro učení, protože ti umožňuje snadno testovat a opravovat programy. Pojďme si ukázat, jak to funguje!
Chyba 1: Program se nespustí
Chyba 2: Sprite se pohybuje špatně
Chyba 3: Cyklus běží věčně
V digitálním světě se neustále setkáváme s programy, které nám usnadňují život. Ale i ty nejlepší programy mohou mít chyby. Schopnost rozpoznat, že něco nefunguje správně, a umět požádat o pomoc nebo se pokusit chybu opravit, je důležitá pro každého uživatele. Učíme se tak kriticky přistupovat k technologiím a nenechat se odradit, když něco nefunguje na první pokus.
V profesionální praxi existuje mnoho typů testování:
Profesionální testování vyžaduje systematický přístup:
Profesionální vývojáři používají debuggery:
Jako IT specialista budeš psát testy jako součást své každodenní práce. Naučíš se používat testovací frameworky a automatizovat testování.
pytest je nejpopulárnější testovací framework pro Python:
# kalkulacka.py - kód k testování
def secti(a, b):
return a + b
def odecti(a, b):
return a - b
def vydel(a, b):
if b == 0:
raise ValueError("Nelze dělit nulou")
return a / b
# test_kalkulacka.py - testy
import pytest
from kalkulacka import secti, odecti, vydel
def test_secti_kladna_cisla():
assert secti(2, 3) == 5
def test_secti_zaporna_cisla():
assert secti(-1, -1) == -2
def test_odecti():
assert odecti(5, 3) == 2
def test_vydel():
assert vydel(10, 2) == 5
def test_vydel_nulou():
with pytest.raises(ValueError):
vydel(10, 0)
# Spuštění: pytest test_kalkulacka.py
TDD je metodika, kde nejdřív napíšeš test, pak kód:
# Krok 1: RED - napiš test, který selže
def test_je_prvocislo():
assert je_prvocislo(2) == True
assert je_prvocislo(7) == True
assert je_prvocislo(4) == False
assert je_prvocislo(1) == False
# Krok 2: GREEN - napiš minimální kód, aby test prošel
def je_prvocislo(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
# Krok 3: REFACTOR - vylepši kód, testy stále procházejí
Profesionální vývojáři používají debugger v IDE (VS Code, PyCharm):
# Příklad pro debugging
def najdi_chybu(seznam):
vysledek = []
for i in range(len(seznam)):
if seznam[i] > 0:
vysledek.append(seznam[i] * 2) # Nastav breakpoint zde
return vysledek
# Spusť s debuggerem a sleduj, co se děje
data = [1, -2, 3, -4, 5]
print(najdi_chybu(data))
V profesionálním prostředí se testy spouštějí automaticky při každé změně kódu:
# .github/workflows/test.yml - GitHub Actions
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: pip install pytest
- name: Run tests
run: pytest
Pokračujeme v projektu Správce kontaktů. V této kapitole přidáme správce kontaktů, ukládání do souboru a testy.
# models/spravce.py
"""Modul pro správu kolekce kontaktů."""
import json
from models.kontakt import Kontakt
class SpravceKontaktu:
"""Třída pro správu seznamu kontaktů."""
def __init__(self, soubor="data/kontakty.json"):
"""
Inicializace správce.
Args:
soubor: Cesta k souboru pro ukládání
"""
self.soubor = soubor
self.kontakty = []
self.nacti()
def pridej(self, kontakt):
"""Přidá nový kontakt."""
self.kontakty.append(kontakt)
self.uloz()
def odeber(self, jmeno):
"""Odebere kontakt podle jména."""
puvodni_delka = len(self.kontakty)
self.kontakty = [k for k in self.kontakty
if k.jmeno.lower() != jmeno.lower()]
if len(self.kontakty) < puvodni_delka:
self.uloz()
return True
return False
def vyhledej(self, dotaz):
"""Vyhledá kontakty obsahující dotaz v jménu nebo telefonu."""
dotaz = dotaz.lower()
return [k for k in self.kontakty
if dotaz in k.jmeno.lower() or dotaz in k.telefon]
def zobraz_vsechny(self):
"""Vrátí seznam všech kontaktů."""
return self.kontakty
def uloz(self):
"""Uloží kontakty do JSON souboru."""
import os
os.makedirs(os.path.dirname(self.soubor), exist_ok=True)
data = [k.to_dict() for k in self.kontakty]
with open(self.soubor, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def nacti(self):
"""Načte kontakty z JSON souboru."""
try:
with open(self.soubor, "r", encoding="utf-8") as f:
data = json.load(f)
self.kontakty = [Kontakt.from_dict(d) for d in data]
except FileNotFoundError:
self.kontakty = []
# tests/test_kontakt.py
"""Testy pro modul Kontakt."""
import pytest
from models.kontakt import Kontakt
def test_vytvoreni_kontaktu():
"""Test vytvoření kontaktu."""
k = Kontakt("Jan Novák", "123456789", "jan@email.cz")
assert k.jmeno == "Jan Novák"
assert k.telefon == "123456789"
assert k.email == "jan@email.cz"
def test_kontakt_bez_emailu():
"""Test kontaktu bez emailu."""
k = Kontakt("Eva Černá", "987654321")
assert k.email == ""
def test_str_reprezentace():
"""Test textové reprezentace."""
k = Kontakt("Jan", "123")
assert "Jan" in str(k)
assert "123" in str(k)
def test_to_dict():
"""Test převodu na slovník."""
k = Kontakt("Jan", "123", "jan@test.cz")
d = k.to_dict()
assert d["jmeno"] == "Jan"
assert d["telefon"] == "123"
assert d["email"] == "jan@test.cz"
def test_from_dict():
"""Test vytvoření ze slovníku."""
d = {"jmeno": "Eva", "telefon": "456", "email": "eva@test.cz"}
k = Kontakt.from_dict(d)
assert k.jmeno == "Eva"
assert k.telefon == "456"
# Nainstaluj pytest
pip install pytest
# Spusť testy
pytest tests/
# Spusť s podrobným výstupem
pytest tests/ -v
# Spusť s měřením pokrytí
pip install pytest-cov
pytest tests/ --cov=models
# Zkontroluj změny
git status
git diff
# Přidej a commitni
git add .
git commit -m "Přidán správce kontaktů a testy
- Implementována třída SpravceKontaktu
- Ukládání a načítání z JSON
- Vyhledávání kontaktů
- Přidány unit testy pro Kontakt"
# Nahraj na GitHub
git push
spravce-kontaktu/
├── .git/
├── .gitignore
├── README.md
├── models/
│ ├── __init__.py
│ ├── kontakt.py # ✓ Třída Kontakt
│ └── spravce.py # ✓ NOVÉ - SpravceKontaktu
├── utils/
│ └── __init__.py
├── tests/
│ ├── __init__.py
│ └── test_kontakt.py # ✓ NOVÉ - Testy
└── data/ # Vytvoří se automaticky
└── kontakty.json
V další kapitole: Přidáme hlavní program s menu (CLI interface).