Proč testování?
-
Teprve otestovaný a uživatelem akceptovaný program je v pořádku.
-
Testování softwaru je klíčová součást vývoje - v podstatě ta nejdůležitější .
-
Některé metodiky vývoje se o testování zásadně opírají: agilní metodiky obecně, konkrétně pak typicky Extreme Programming.
-
Některé jsou jím přímo řízené — Test-Driven Development (vývoj řízený testy).
V čem spočívá testování?
-
Testování softwaru je mnohaúrovňový,
-
kontinuálně probíhající proces (v podstatě po celou dobu životního cyklu).
-
V případě tohoto předmětu testováním nemyslíme formální verifikaci (dokazování správnosti) programů, ale "pouze"
-
testování vybraných konkrétních případů běhu (case-based testing).
Úrovně testování?
-
Podle úrovně pohledu rozlišujeme testy:
- jednotek
-
elementů programu, někdy i vytržených z kontextu - např. jednotlivých tříd a jejich souhry
- integrační
-
určené k otestování právě integrované části kódu (např. po jeho změnách) do většího celku
- akceptační
-
ověřují, zda je SW přijatelný pro uživatele/klienta
-
Zde se zatím zaměříme na testování jednotek, tedy malých celků, které budeme testovat izolovaně.
Co je testování jednotek?
-
Testování jednotek (unit testing) je první fází každého testovacího procesu.
-
Testuje jednotlivé elementární části kódu - v případě objektového světa třídy.
-
Často probíhá formou "black-box" testování (tzn. jen pohled z venku, tedy na veřejné vlastnosti — typicky metody), ale
-
může se kombinovat s nahlížením dovnitř objektů — např. na "package-local" metody a atributy, může testovat "package-local" třídy a rozhraní.
Jak probíhá v Javě
-
Pro testování jednotek obvykle používáme vhodný testovací rámec,
-
i když by šlo dělat i bez něj, vlastními ad-hoc vytvořenými nástroji.
-
v Javě se nejčastěji používá volně dostupný balík jUnit
-
existují jeho porty pro jiné jazyky/prostředí (C, C#, PHP, Perl,…)
-
pro Javu existují také koncepčně velmi podobné nebo i pokročilejší (ale zase méně známé) alternativy (TestNG)
-
starší verze (JUnit 3.x — ten již nepoužíváme) nepracovaly s tzv. anotacemi, novější již ano (JUnit 4.x)
-
novější mají též systematické pojmenovávání balíků a tříd — např.
org.junit.Assert
Struktura testu v junit
Jednotkové testy v JUnit mají v zásadě tuto strukturu:
-
Elementárním testem je testovací metoda — její název začíná předponou
test
nebo je opatřena příslušnou anotací@Test
(JUnit 4.x) nebo obojí. -
Elementární testy se dají skládat do souborů testů, test suites.
Postup vykonání testu
-
Vykonání tohoto elementárního testu probíhá následovně:
-
konstrukce objektu testu, tj. instance testovací třídy;
-
inicializace testu metodou
setUp
(nebo i jinou metodou anotovanou@Before
) — taková metoda obvykle vytvoří tzv. testovací přípravek (fixture); -
proběhne příslušná (jedna z) testovací metoda;
-
test je "uklizen" voláním metody
tearDown
nebo metodou anotovanou@After
.
-
Note
|
Inicializační a uklizecí metody, stejně jako metody testu mají ve sterších JUnit (3.x) napevno předepsané názvy nebo přípony. Od 4.x lze označit anotacemi - ale pro přehlednost se jmenné konvence drží nadále. |
Příklad
Testovaná třída Calculator
, jednoduchá sčítačka čísel
public class Calculator { public int evaluate(String expression) { int sum = 0; for (String summand: expression.split("\\+")) sum += Integer.valueOf(summand); return sum; } }
Testovací třída CalculatorTest
import static org.junit.Assert.assertEquals; import org.junit.Test; public class CalculatorTest { @Test // takto značíme testovací metodu public void evaluatesExpression() { Calculator calculator = new Calculator(); int sum = calculator.evaluate("1+2+3"); assertEquals(6, sum); // takto ověřujeme, zda se suma rovná } }
Spuštění testu
- překlad testu
-
javac -cp .:junit-4.XX.jar CalculatorTest.java
- spuštění testu
-
java -cp .:junit-4.XX.jar:hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
- výstup
-
JUnit version 4.12 . Time: 0,006 OK (1 test)
Note
|
Lze také (a typičtěji se tak děje) spustit test přímo v integrovaném vývojovém prostředí (NetBeans apod.). |
Označení metody za testovací: @Test
-
Stručně: lze použít následující anotace (konstrukce s
@
) -
@Test
před metodou označí tuto metodu za testovací. -
Metoda se nemusí nijak speciálně jmenovat (žádné
testXXX
).@Test public void addition() { assertEquals(12, simpleMath.add(7, 5)); }
Provedení před a po testu: @Before
a @After
-
Metoda anotovaná
@Before
bude spuštěna před každým testem. -
Obdobně metoda s
@After
po každém testu. -
Ve starších verzích JUnit se užívaly metody
setup
atearDown
.@Before public void runBeforeEveryTest() { simpleMath = new SimpleMath(); }
Očekávání výjimky
-
Takto označená metoda očekává, že v ní vznikne výjimka uvedeného typu.
-
Nestane-li se tak,test selže.
@Test(expected = ArithmeticException.class) public void divisionWithException() { // divide by zero simpleMath.divide(1, 0); }
Dočasné vynechání: @Ignore
-
Označením
@Ignore
(obvykle dočasně) testovací metodu vyloučíme z provádění. -
Lze uvést vysvětlující hlášku.
@Ignore(“Not Ready to Run”) @Test public void multiplication() { assertEquals(15, simpleMath.multiply(3, 5)); }
Časový limit testu
-
Bude-li u takto anotované metody při spuštění testu překročen časový limit, test selže.
-
Časový limit je v milisekundách.
@Test(timeout = 1000) public void infinity() { while (true) ; }