Testování error kódu výjimky v TestNG

Testovací framework TestNG umožňuje testovat nejen to, že metoda vrací výjimku a zároveň typ (třídu) vracené výjimky, ale též umožňuje otestovat zprávu, kterou tato výjimka obsahuje. To je vhodné například u vlastní výjimky, která vrací nějaký chybový kód. Otestujeme tedy nejen, že metoda v určitých případech vyhazuje chybu, ale také, zda vrací správný chybový kód.

Enum obsahující chybové kódy

public enum ErrorCode {

	X_IS_TO_BIG("X1111"),
	Y_IS_TO_BIG("Y1122"),
	Y_IS_BIGGER_THAN_X("Y1133");
	
	private final String code;
	
	private ErrorCode(String code) {
		this.code = code;
	}
	
	public String getCode() {
		return this.code;
	}
}

Třída představující naši chybu (exception)

public class MyException extends RuntimeException {

	public MyException(String errorCode) {
		super(errorCode);
	}
}

Třída, jejíž metodu budeme testovat

public class MyObject {
	
	private static final int X_MAX_VALUE = 100;
	private static final int Y_MAX_VALUE = 50;

	public int count(int x, int y) {
		
		if (x > X_MAX_VALUE) {
			throw new MyException(ErrorCode.X_IS_TO_BIG.getCode());
		}
		
		if (y >= Y_MAX_VALUE) {
			throw new MyException(ErrorCode.Y_IS_TO_BIG.getCode());
		}
		
		if (y > x) {
			throw new MyException(ErrorCode.Y_IS_BIGGER_THAN_X.getCode());
		}
		
		return (x + y) / (x + y);
	}
}

Budeme testovat, zda metoda správně vrací výsledek (public void countOk()) a zda vyhazuje chybu se správných kódem v případě, že zadané číslo x nebo y je příliš velké (public void countXToBig(), public void countYToBig()), nebo když je y větší než x (public void countYBiggerThanX()).

import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;

public class MyObjectTest {

	@Test(expectedExceptions = {MyException.class}, expectedExceptionsMessageRegExp = ".*X111.*")
	public void countXToBig() {
		int result = new MyObject().count(10_000, 12);
	}
	
	@Test(expectedExceptions = {MyException.class}, expectedExceptionsMessageRegExp = "Y.*22")
	public void countYToBig() {
		int result = new MyObject().count(9, 5_000);
	}
	
	@Test(expectedExceptions = {MyException.class}, expectedExceptionsMessageRegExp = "Y1133")
	public void countYBiggerThanX() {
		int result = new MyObject().count(22, 27);
	}
	
	@Test()
	public void countOk() {
		int result = new MyObject().count(8, 5);
		assertEquals(result, 1);
	}
}

Time test

JUnit i TestNG umožňují pomocí parametru timeout anotace @Test nastavit podmínku testu tak, aby test, pokud má být úspěšný, proběhl do určité doby (definované v milisekundách). V případě, že test trvá déle, jeho běh je ukončen a test je označen jako neúspěšný (failure).

Metoda, která se bude testovat.

public void longMethod() {
	for (int i = 0; i < 1_000_000; i++) {
		System.out.println("myMethod");
	}
}

Test.

@Test(timeout=1000)
public void longMethodTest() {
	longMethod();
}

Kód je stený jak pro JUnit tak pro TestNG. Pro JUnit test se používá anotace org.junit.Test a pro TestNG org.testng.annotations.Test. Pokud bude výše uvedený test trvat déle jak 1000 milisekund, bude označen jako neúspěšný.