Domov arrow Programovanie arrow Parametrizované Unit Testy (PUT)
Parametrizované Unit Testy (PUT)
Hodnotenie čitateľov: / 1
SlabéVynikajúce 

you need some testsParametrizované Unit Testy (PUT) používame pre odhalenie chýb spôsobených nesprávnym zvládaním dátovej komplexity v programe. Týchto môže byť neúrekom, keďže častokrát je ťažké si vopred predstaviť rozmanitosť možných vstupov, hlavne ak testujeme komponent, do ktorého vniká priamy vstup od užívateľa. Viac na tematiku dátovej a štrukturálnej komplexity som sa vyjadroval v odkazovanom článku. Tu si ukážeme exemplár parametrizovaného JUnit testu triedy PostCode, ktorá z ľubovoľného String-u obsahujúceho UK poštové smerovacie číslo vyťaží informácui o distrikte. Povieme si čo-to o detailoch tohto parametrizovaného testu.

parameterized unit test sample
Ukážka parametrizovaného unit testu

Náš parametrizovaný unit test (PUT) má niekoľko charakterických čŕt, ktoré som v obrázku vyznačil písmenami. Teraz niekoľkými slovami ku každému z nich:

  • A - testovaciu triedu okrášlime anotáciou @RunWith, aby JUnit vedel použiť správny test runner. Triedu test runneru poskytneme ako argument pre RunWith anotáciu - pre náš PUT to bude práve org.junit.runners.Parameterized
  • Parameterized test runner bude v našej testovacej triede hľadať, za pomoci Java Reflection, tieto tri prvky: B - verejný konštruktor, C - verejnú statickú metódu navracajúcu kolekciu objektových polí, D - samotné parametrizované testy - ich metódy.
  • C - Parameterized JUnit test runner bude hľadať verejnú statickú metódu navracajúcu kolekciu objektových polí za pomoci anotácie @Parameters, ktorou označíme metódu poskytujúcu parametre pre jednotlivé testovacie behy. Ak metóda označená @Parameters nie je nájdená - máme problém. Ak podpis metódy označenej @Parameters nespĺňa požiadavky - máme problém (Pozor, Parameterized JUnit test runner v skutočnosti požaduje návratovú hodnotu typu Collection<Object[]>. My môžeme pokojne nadefinovať návratovú hodnotu List<Object[]> alebo Stack<Object[]> - keďže sú to implementácie rozhrania Collection<Object[]>). Viac o tejto metóde ešte o pár bodov nižšie.
  • Pre každé objektové pole v kolekcii navrátenej statickou metódou označenou @Parameters sa za pomocou konštruktoru B vytvorí nová inštancia testovacej triedy a všetky metódy v nej označené anotáciou @Test - D - budú zavolané štandardným spôsobom JUnit, ako sme zvyknutí z bežných (neparametrizovaných) unit testov.
  • Testy označené @Test budú preberať parametre z polí - F - do ktorých si pre každý test odložíme dáta v konštruktore - B.
  • Verejný konštruktor - B - bude mať typ a počet paramterov zodpovedajúci typu a počtu objektov v poli navrátenom zo statickej metódy C a je jeho povinnosťou tieto parametre z metódy C uložiť v poliach F pre použitie testom/testmi D.

Teda okrem anotácie @RunWith sa PUT líši od štandardného unit testu len konštruktorom B a statickou metódou C, ktoré spolu úzko súvisia. Parameterized JUnit test runner vytvorí novú inštanciu klasického JUnit test case-u pre každé objektové pole navrátené v kolekcii objektových polí z metódy C a spustí unit testy. Inštancie vytvorí zavolaním verejného konštruktora, ktorý vyhľadá pomocou Java Reflection na základe počtu a typu objektov v aktuálnom objektovom poli. Pozor, je povolený iba jeden konštruktor pre vašu testovaciu triedu.

@Parameters metóda a jej spojitosť s konštruktorom

Zrozumiteľne povedané - statická metóda označená anotáciou @Parameters poskytne test runneru sadu parametrov pre testy. Táto sada (kolekcia) bude pozostávať z jedného alebo viacerých objektových polí, ktoré bude tlačiť, jeden po druhom do konštruktora, ktorý musí mať typ a počet parametrov zhodujúci sa s typom a počtom objektov v poli.

Teda v našom príklade metóda data odovzdá parametrizovanému test runneru List (Arrays.asList(Object[]...)) objektových polí. Tieto polia obsahujú jednotlivé argumenty pre konštruktor testovacej triedy. Teda v príklade vidíme, že prvá inštancia bude vytvorená použitím objektového poľa

{ "BN1 1HG", "BN1" }
a teda test runner bude hľadať konštruktor s dvoma parametrami typu String (keďže naše objektové pole obsahuje dva objekty typu String: "BN1 1HG" a "BN1"), a na nej potom JUnit vykoná všetky testy označené @Test a potom vytvorí ďalšiu inštanciu, znovu zavolaním toho istého konštruktora, ktorému podá druhé pole objektov na zozname, a tak ďalej.

Tu je poskytnutý kopírovateľný kód vyššie uvedeného príkladu:

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class PostCodeParamTest {

	private final PostCode postCode;
	private final String district;

	public PostCodeParamTest(String postCode, String district) {
		this.postCode = new PostCode(postCode);
		this.district = district;
	}

	@Parameters
	public static Collection<Object[]> data() {
		Object[][] data = {
				{ "BN1 1HG", "BN1" }, 
				{ "BN11HG", "BN1" }, 
				{ "EC2V 7HN", "EC2V" }, 
				{ "EC2V7HN", "EC2V" }, 
				{ "INVALID", "" }, 
				{ "", "" }, 
			};
		return Arrays.asList(data);
	}

	@Test
	public void test() {
		assertEquals(district, postCode.getDistrict());
	}

}
Posledná úprava ( Tuesday, 07 May 2013 )
 
< Predchádzajúca   Ďalšia >