κ³Όκ±°μλ ν
μ€νΈ νλ μμν¬κ° λ©μλμ μ΄λ¦μ νΉμ ν¨ν΄μΌλ‘ λͺ
λͺ
νμ¬ νΉμ μμ
μ μννλ λ©μλμμ ꡬλΆνκ³€ νλ€. μλ₯Ό λ€μ΄ JUnit 3λ ν
μ€νΈ λ©μλ μ΄λ¦μ΄ testλ‘ μμν΄μΌλ§ ν
μ€νΈ νλ μμν¬μμ ν΄λΉ λ©μλλ₯Ό ν
μ€νΈ λ©μλλ‘ μΈμνλ€.
κ·Έλ¬λ μ΄ λ°©μμλ λͺ κ°μ§ λ¬Έμ κ° μλ€
- μ€ν λ¬Έμ :
tsetSafetyOverrideμ²λΌ μ€νκ° μμΌλ©΄ JUnitμ ν μ€νΈ λ©μλλ‘ μΈμνμ§ μμ 무μνλ©°, ν μ€νΈκ° μ€ν¨νμ§ μμμΌλ―λ‘ κ°λ°μλ μ΄ ν μ€νΈκ° ν΅κ³Όνλ€κ³ μ€ν΄ν μ μλ€. - μ¬λ°λ₯Έ μμμ λν λ³΄μ¦ μμ: λͺ λͺ ν¨ν΄μΌλ‘λ μλͺ»λ μμΉ(μ: ν΄λμ€ μ΄λ¦)μ μ€μ λ ν¨ν΄μ κ²μ¬ν μ μλ€. μλ₯Ό λ€μ΄ λ©μλκ° μλ ν΄λμ€ μ΄λ¦μ TestSafetyλ‘ μ§μ΄ JUnitμκ² μ€λ, JUnitμ μ΄ ν΄λμ€ μ΄λ¦μ κ΄μ¬μ΄ μμΌλ©°, ν μ€νΈλ μνλμ§ μμΌλ©° Junitμ κ²½κ³ λ©μμ§μ‘°μ°¨ μΆλ ₯νμ§ μλλ€.
- λ§€κ°λ³μ μ λ¬μ μ΄λ €μ: νΉμ μμΈκ° λ°μν΄μΌ μ±κ³΅νλ ν μ€νΈλ₯Ό ꡬννκ³ μ ν λ μμΈ νμ μ λͺ μμ μΌλ‘ μ§μ νλ λ°©λ²μ΄ μκΈ° λλ¬Έμ, ν μ€νΈ μ΄λ¦μ μμΈ μ΄λ¦μ ν¬ν¨μν€λ λ°©μμΌλ‘ μ°ννλ κ²½μ°κ° μλ€. νμ§λ§ μ΄λ¬ν λ°©μμ κ°λ μ±μ΄ λ¨μ΄μ§κ³ κΉ¨μ§κΈ° μ¬μ°λ©°, μ»΄νμΌλ¬κ° λ©μλ μ΄λ¦μ ν¬ν¨λ λ¬Έμμ΄μ΄ μμΈμ κ΄λ ¨μ΄ μλμ§ νμΈν λ°©λ²μ΄ μλ€.
μμ: JUnit 3μ ν μ€νΈ λ©μλ λͺ λͺ ν¨ν΄
public class MyTests {
// ν
μ€νΈ λ©μλλ μ΄λ¦μ΄ "test"λ‘ μμν΄μΌ ν¨
public void testAddition() {
assert (1 + 1 == 2);
}
public void testSubtraction() {
assert (2 - 1 == 1);
}
public void utilityMethod() {
// μΌλ°μ μΈ μ νΈλ¦¬ν° λ©μλλ‘, ν
μ€νΈκ° μλ
}
}μ λν μ΄μ μ, μ΄λ¬ν λͺ λͺ ν¨ν΄μ λ¬Έμ λ€μ ν΄κ²°ν΄μ£Όλ λ©μ§ λμμ΄λ€.
import org.junit.Test;
public class MyTests {
@Test
public void addition() {
assert (1 + 1 == 2);
}
@Test
public void subtraction() {
assert (2 - 1 == 1);
}
public void utilityMethod() {
// μΌλ° λ©μλ
}
}μ λν μ΄μ μ λ€μκ³Ό κ°μ μ₯μ μ μ 곡νλ€.
- λͺ νν μν ꡬλΆ: μ λν μ΄μ μ λ©μλ μ΄λ¦μ μμ‘΄νμ§ μκ³ λ λͺ ννκ² νΉμ κΈ°λ₯μ μννλ λ©μλλ₯Ό ꡬλΆν μ μκ² ν΄μ€λ€. λ©μλ μ΄λ¦μ΄ μλ μ λν μ΄μ μ ν΅ν΄ μν μ ννν μ μλ€.
- μ μ°μ±κ³Ό νμ₯μ±: μΆκ°μ μΈ μ 보λ₯Ό μ λν μ΄μ μΌλ‘ μ μ₯ν μ μμ΄ λ λ§μ κΈ°λ₯μ μ½κ² νμ₯ν μ μλ€.
- μ»΄νμΌλ¬μ λꡬμ μ§μ: μ λν μ΄μ μ ν΅ν΄ μ»΄νμΌλ¬κ° μΆκ° κ²μ¦μ μνν μ μμΌλ©°, 리νλ μ μ ν΅ν΄ λμ μΌλ‘ λ©μλλ₯Ό μ μ΄ν μ μλ€.
μλ₯Ό λ€μ΄, @TestλΌλ μ λν
μ΄μ
μ λ§λ€κ³ μ΄λ₯Ό νΉμ λ©μλμ λΆμ΄λ©΄ κ·Έ λ©μλκ° ν
μ€νΈ λ©μλμμ λͺ
ννκ² μ μ μλ€. μ΄λ₯Ό ν΅ν΄ ν
μ€νΈ μ½λλ₯Ό λμ± μ½κΈ° μ½κ² λ§λ€κ³ μ μ§ λ³΄μλ₯Ό μ©μ΄νκ² ν μ μλ€.
TestλΌλ μλμΌλ‘ μνλλ κ°λ¨ν ν μ€νΈμ© μ λν μ΄μ μΌλ‘, μμΈκ° λ°μνλ©΄ ν μ€νΈλ₯Ό μ€ν¨λ‘ μ²λ¦¬νλ€.
@Test μ λν
μ΄μ
μ λ©μλκ° ν
μ€νΈ λ©μλμμ νμνκΈ° μν λ§μ»€ μ λν
μ΄μ
μ΄λ€. μ΄ μ λν
μ΄μ
μ λ§€κ°λ³μλ₯Ό κ°μ§μ§ μμΌλ©°, λ©ν μ λν
μ΄μ
μ ν΅ν΄ νΉμ 쑰건μμλ§ μ¬μ©ν μ μλλ‘ μ ννλ€.
import java.lang.annotation.*;
/**
* ν
μ€νΈ λ©μλμμ μ μΈνλ μ λν
μ΄μ
* λ§€κ°λ³μ μλ μ μ λ©μλ μ μ©
*/
@Retention(RetentionPolicy.RUNTIME) // λ°νμκΉμ§ μ μ§
@Target(ElementType.METHOD) // λ©μλμλ§ μ μ© κ°λ₯
public @interface Test {
}{% hint style="info" %}
@Test μλν
μ΄μ
νμ
μ μΈ μ체μ λ κ°μ§μ λ€λ₯Έ μ λν
μ΄μ
μ΄ λ¬λ € μλλ°, μ΄λ₯Ό λ©ν μ λν
μ΄μ
(meta-annotation)μ΄λΌ νλ€.
{% endhint %}
@Retention(RetentionPolicy.RUNTIME): μ λν μ΄μ μ λ°νμμλ μ μ§νλλ‘ μ€μ νμ¬ λ¦¬νλ μ μ ν΅ν΄ μ κ·Όν μ μκ² νλ€. λ©ν μ λν μ΄μ μ@Testκ° λ°νμμλ μ μ§λμ΄μΌ νλ€λ μλ―Έμ΄λ©°, λ§μ½ μ΄λ₯Ό μλ΅νλ©΄ ν μ€νΈ λꡬλ@Testλ₯Ό μΈμν μ μκ² λλ€.@Target(ElementType.METHOD): μ λν μ΄μ μ λ©μλμλ§ μ¬μ©ν μ μλλ‘ μ ννμ¬ μλͺ»λ μμΉμμ μ¬μ©νμ§ λͺ»νλλ‘ νλ€.( ν΄λμ€ μ μΈ, νλ μ μΈ λ± λ€λ₯Έ νλ‘κ·Έλ¨ μμμλ λ¬ μ μμ )
μ΄μ κ°μ΄ λ§€κ°λ³μκ° μλ μ λν
μ΄μ
μ @Testμ κ°μ μ λν
μ΄μ
μ, "μ무 λ§€κ°λ³μ μμ΄ λ¨μν λμμ λ§νΉνλ€"λΌλ λ»μμλ§μ»€ μ λν
μ΄μ
μ΄λΌ λΆλ₯΄λ©°, λ©μλμλ§ λΆμΌ μ μκ² μ€μ νμ¬ μ¬μ©μκ° ν΄λμ€λ νλμ μλͺ» μ μ©νμ λ μ»΄νμΌλ¬κ° μ€λ₯λ₯Ό λ°ννλλ‘ ν μ μλ€.
μ¦, νλ‘κ·Έλλ¨Έκ° Testμ΄λ¦μ μ€νλ₯Ό λ΄κ±°λ λ©μλ μ μΈ μΈμ νλ‘κ·Έλ¨ μμμ λ¬λ©΄ μ»΄νμΌ μ€λ₯λ₯Ό λ΄μ€λ€.
2) Sample ν΄λμ€μ @Test μ λν μ΄μ μ¬μ© :λ§μ»€ μ λν μ΄μ μ μ¬μ©ν νλ‘κ·Έλ¨ μμ
Sample ν΄λμ€μμ @Test μ λν
μ΄μ
μ μ¬μ©νμ¬ λ©μλλ₯Ό ν
μ€νΈ λ©μλλ‘ μ§μ ν μ μλ€.
public class Sample {
@Test
public static void m1() { } // μ±κ³΅ν΄μΌ νλ ν
μ€νΈ λ©μλ
public static void m2() { } // ν
μ€νΈ λ©μλκ° μλ
@Test
public static void m3() { // μ€ν¨ν΄μΌ νλ ν
μ€νΈ λ©μλ
throw new RuntimeException("μ€ν¨");
}
public static void m4() { } // ν
μ€νΈ λ©μλκ° μλ
@Test
public void m5() { } // μλͺ»λ μ¬μ© μ: μ μ λ©μλκ° μλ
}m1,m3,m5λ@Testμ λν μ΄μ μ΄ μ§μ λ ν μ€νΈ λ©μλm5λ μ μ λ©μλκ° μλκΈ° λλ¬Έμ@Testμ μꡬμ¬νμ λ§μ§ μλλ€.
@Test μ λν
μ΄μ
μ Sample ν΄λμ€μ μλ―Έμ μ§μ μ μΈ μν₯μ μ£Όμ§ μκ³ , λ¨μ§ κ΄μ¬ μλ νλ‘κ·Έλ¨μκ² μΆκ° μ 보λ₯Ό μ 곡νλ€. μ¦ λμ μ½λμ μλ―Έλ κ·Έλλ‘ λ μ± κ·Έ μ λν
μ΄μ
μ κ΄μ¬ μλ λꡬμμ νΉλ³ν μ²λ¦¬λ₯Ό ν κΈ°νλ₯Ό μ£Όλ κ²μ΄λ€.
3) μ λν μ΄μ μ νμ©ν ν μ€νΈ λꡬ ꡬν : λ§μ»€ μ λν μ΄μ μ μ²λ¦¬νλ νλ‘κ·Έλ¨
@Test μ λν
μ΄μ
μ΄ λΆμ λ©μλλ§μ μ€ννλ κ°λ¨ν ν
μ€νΈ λꡬ
import java.lang.reflect.*;
public class RunTests {
public static void main(String[] args) throws Exception {
int tests = 0;
int passed = 0;
Class<?> testClass = Class.forName(args[0]);
for (Method m : testClass.getDeclaredMethods()) {
if (m.isAnnotationPresent(Test.class)) {
tests++;
try {
m.invoke(null);
passed++;
} catch (InvocationTargetException wrappedExc) {
Throwable exc = wrappedExc.getCause();
System.out.println(m + " μ€ν¨: " + exc);
} catch (Exception exc) {
System.out.println("μλͺ» μ¬μ©ν @Test: " + m);
}
}
}
System.out.printf("μ±κ³΅: %d, μ€ν¨: %d%n", passed, tests - passed);
}
}m.isAnnotationPresent(Test.class):@Testμ λν μ΄μ μ΄ λΆμ λ©μλλ₯Ό μ°Ύμ μ€ννλ€.- μμΈ μ²λ¦¬:
InvocationTargetExceptionμΌλ‘ κ°μΈμ§ μμΈλgetCause()λ₯Ό ν΅ν΄ μλ³Έ μμΈλ₯Ό μΆλ ₯νλ€. - κ²°κ³Ό μΆλ ₯: μ΄ ν μ€νΈ κ°μμ μ±κ³΅/μ€ν¨ κ°μλ₯Ό μΆλ ₯νμ¬ ν μ€νΈμ κ²°κ³Όλ₯Ό μμ½νλ€.
μ΄ ν
μ€νΈ λ¬λλ λͺ
λ Ήμ€λ‘λΆν° μμ μ κ·νλ ν΄λμ€ μ΄λ¦μ λ°μ, ν΄λμ€μμ @Test μ λν
μ΄μ
μ΄ λ¬λ¦° λ©μλλ₯Ό μ°Ύμ μ°¨λ‘λ‘ νΈμΆνλ€. κ·Έλ¦¬κ³ μ λν
μ΄μ
μ μλͺ» μ¬μ©ν΄ μμΈκ° λ°μνλ€λ©΄ μ€λ₯ λ©μΈμ§λ₯Ό μΆλ ₯νλ€.
νΉμ μμΈλ₯Ό λ°μν΄μΌλ§ μ±κ³΅νλ ν μ€νΈκ° νμν κ²½μ°,
@ExceptionTestμ λν μ΄μ μ μ¬μ©ν΄ μμΈλ₯Ό λͺ μν μ μλ€.
λ§€κ°λ³μλ₯Ό νλλ₯Ό λ°λ μ λν
μ΄μ
νμ
, @ExceptionTest μ λν
μ΄μ
νμ
μ μ
import java.lang.annotation.*;
/**
* μ§μ ν μμΈκ° λ°μν΄μΌ μ±κ³΅νλ ν
μ€νΈ λ©μλλ₯Ό μν μ λν
μ΄μ
.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
Class<? extends Throwable> value(); // λ§€κ°λ³μλ‘ μμΈ νμ
μ λ°μ
}@ExceptionTestλ νΉμ μμΈ νμ
μ λ§€κ°λ³μλ‘ λ°μ, ν΄λΉ μμΈκ° λ°μν΄μΌλ§ ν
μ€νΈκ° μ±κ³΅νλμ§ κ²μ¬νλ€.
μμ : @ExceptionTest μ λν
μ΄μ
μ¬μ©
public class Sample2 {
@ExceptionTest(ArithmeticException.class)
public static void m1() { // μ±κ³΅ν΄μΌ νλ ν
μ€νΈ
int i = 0;
i = i / i;
}
@ExceptionTest(ArithmeticException.class)
public static void m2() { // μ€ν¨: λ€λ₯Έ μμΈ λ°μ
int[] a = new int[0];
int i = a[1];
}
@ExceptionTest(ArithmeticException.class)
public static void m3() { // μ€ν¨: μμΈκ° λ°μνμ§ μμ
}
}μ΄μ @ExceptionTestλ₯Ό νμ©ν΄ ν
μ€νΈ λ©μλκ° μ¬λ°λ₯Έ μμΈλ₯Ό λμ§λμ§ νμΈνλ λ‘μ§μ μΆκ°νλ€. μμ μ½λμ ν κ°μ§ μ°¨μ΄λΌλ©΄, μ΄ μ½λλ μ λν
μ΄μ
λ§€κ°λ³μμ κ°μ μΆμΆνμ¬ ν
μ€νΈ λ©μλκ° μ¬λ°λ₯Έ μμΈλ₯Ό λμ§λμ§ νμΈνλλ° μ¬μ©νλ€.
μμ : λ§μ»€ μ λν μ΄μ κ³Ό λ§€κ°λ³μ νλμ§λ¦¬ μ λνμ΄μ μ μ²λ¦¬νλ νλ‘κ·Έλ¨
if (m.isAnnotationPresent(ExceptionTest.class)) {
tests++;
try {
m.invoke(null); // λ©μλλ₯Ό μ€ν
System.out.printf("ν
μ€νΈ %s μ€ν¨: μμΈλ₯Ό λμ§μ§ μμ%n", m);
} catch (InvocationTargetException wrappedEx) {
Throwable exc = wrappedEx.getCause();
Class<? extends Throwable> excType = m.getAnnotation(ExceptionTest.class).value();
if (excType.isInstance(exc)) { // μμΈ νμ
μΌμΉ μ¬λΆ νμΈ
passed++;
} else {
System.out.printf("ν
μ€νΈ %s μ€ν¨: κΈ°λν μμΈ %s, λ°μν μμΈ %s%n", m, excType.getName(), exc);
}
} catch (Exception exc) {
System.out.println("μλͺ» μ¬μ©ν @ExceptionTest: " + m);
}
}m.getAnnotation(ExceptionTest.class).value():@ExceptionTestμ λν μ΄μ μμ μ§μ ν μμΈ νμ μ κ°μ Έμ¨λ€.excType.isInstance(exc): λ°μν μμΈκ° κΈ°λν μμΈ νμ κ³Ό μΌμΉνλμ§ νμΈνλ€.
@ExceptionTestμ λ°°μ΄ λ§€κ°λ³μλ₯Ό μ¬μ©νμ¬, λ€μμ μμΈ μ€ νλλ§ λ°μν΄λ ν
μ€νΈκ° μ±κ³΅νλλ‘ μ€μ ν μ μλ€.
@ExceptionTest μ λν μ΄μ μ λ§€κ°λ³μ νμ μ Class κ°μ²΄μ λ°°μ΄λ‘ μμ νλ©΄ λλ€.
μμ : λ°°μ΄ λ§€κ°λ³μλ₯Ό λ°λ μ λν μ΄μ νμ
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
Class<? extends Throwable>[] value(); // μ¬λ¬ μμΈ νμ
μ λ°°μ΄λ‘ λ°μ
}μμ : λ°°μ΄ λ§€κ°λ³μλ₯Ό μ¬μ©νλ @ExceptionTest μ λν
μ΄μ
μ¬μ© μ
@ExceptionTest({ IndexOutOfBoundsException.class, NullPointerException.class })
public static void doublyBad() {
List<String> list = new ArrayList<>();
// μλ° API λͺ
μΈμ λ°λ₯΄λ©΄ λ€μ λ©μλλ IndexOutOfBoundsExceptionμ΄λ
// NullPointerExceptionμ λμ§ μ μλ€.
list.addAll(5, null);
}μμ : λ°°μ΄ λ§€κ°λ³μλ₯Ό μ²λ¦¬νλ ν μ€νΈ λꡬ μ½λ
jif (m.isAnnotationPresent(ExceptionTest.class)) {
tests++;
try {
m.invoke(null);
System.out.printf("ν
μ€νΈ %s μ€ν¨: μμΈλ₯Ό λμ§μ§ μμ%n", m);
} catch (Throwable wrappedExc) {
Throwable exc = wrappedExc.getCause();
int oldPassed = passed;
Class<? extends Throwable>[] excTypes = m.getAnnotation(ExceptionTest.class).value();
for (Class<? extends Throwable> excType : excTypes) {
if (excType.isInstance(exc)) { // μμΈ νμ
μ€ μΌμΉνλ κ²μ΄ μμΌλ©΄ μ±κ³΅
passed++;
break;
}
}
if (passed == oldPassed)
System.out.printf("ν
μ€νΈ %s μ€ν¨: %s %n", m, exc);
}
}νμ§λ§ μμ μ½λλ₯Ό λ κ°λ¨νκ² κ°μ νκ³ μΆλ€λ©΄, μλ° 8μμλ μ¬λ¬κ°μ κ°μ λ°λ μ λν μ΄μ μ, λ°°μ΄ λ§€κ°λ³μλ₯Ό μ¬μ©νλ λμ
@Repeatableλ©ν μ λν μ΄μ μ λ€λ λ°©μμ μ ννμ¬ μ½λ κ°λ μ±μ λμΌ μ μλ€.
@Repeatableλ₯Ό λ¨ μ λν
μ΄μ
μ νλμ νλ‘κ·Έλ¨ μμμ μ¬λ¬ λ² λ¬ μ μλ€.
μ£Όμ μ¬ν
@Repeatableμ μ¬μ©νλ €λ©΄ 컨ν μ΄λ μ λν μ΄μ μ λ³λλ‘ μ μν΄μΌ νλ€.@Repeatableμ 컨ν μ΄λ μ λν μ΄μ ν΄λμ€λ₯Ό μ λ¬ν΄μΌ νλ€.- 컨ν
μ΄λ μ λν
μ΄μ
μ μ λν
μ΄μ
λ°°μ΄μ λ°ννλ
valueλ©μλλ₯Ό ν¬ν¨ν΄μΌ νλ€. - 컨ν μ΄λ μ λν μ΄μ νμ μλ μ μ ν 보쑴 μ μ± (@Retention)κ³Ό μ μ© λμ(@Target)μ λͺ μν΄μΌ νλ€. κ·Έλ μ§ μμΌλ©΄ μ»΄νμΌμ΄ λμ§ μλλ€.
μμ : λ°λ³΅ κ°λ₯ν μ λν μ΄μ νμ κ³Ό 컨ν μ΄λ μ λν μ΄μ μ μ
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(ExceptionTestContainer.class) // 컨ν
μ΄λ μ λν
μ΄μ
ν΄λμ€
public @interface ExceptionTest {
Class<? extends Throwable> value();
}
// 컨ν
μ΄λ μ λν
μ΄μ
μ μ
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTestContainer {
ExceptionTest[] value();
}λ°λ³΅ κ°λ₯ μ ν°λ€μ΄μ
μ, μ²λ¦¬ν λλ μ£Όμ μ¬νμ΄ μ‘΄μ¬νλ€.
λ¨Όμ , μ λν
μ΄μ
μ μ¬λ¬κ° λ¬λ©΄ νλλ§ λ¬μμ λμ ꡬλΆνκΈ° μν΄ ν΄λΉ '컨ν
μ΄λ' μ λν
μ΄μ
νμ
μ΄ μ μ©λκΈ° λλ¬Έμ m.isAnnotationPresent() μμ λμ λͺ
νν ꡬλΆνκ³ μλ κ²μ λ³Ό μ μλ€.
νμ§λ§, ν΄λΉ λ©μλλ‘ λ°λ³΅ κ°λ₯ μ λν μ΄μ μ΄ λ¬λ Έλμ§ κ²μ¬νλ€λ©΄ κ²μ¬μ μ€ν¨ν κ²μ΄κ³ (μ λν μ΄μ μ μ¬λ¬ λ² λ¨ λ©μλλ€μ 무μ) 컨ν μ΄λ μ λν μ΄μ μ΄ λ¬λ Έλμ§λ§ κ²μ¬νμ¬λ λ°λ³΅ κ°λ₯ μ λν μ΄μ μ νλ²λ§ λ¨ λ©μλλ₯Ό 무μνκ³ μ§λμΉκΈ° λλ¬Έμ λμ λ°λ‘λ°λ‘ νμΈν΄μΌ νλ€.
μμ : λ°λ³΅ κ°λ₯ν μ λν μ΄μ μ¬μ© μ
@ExceptionTest(IndexOutOfBoundsException.class)
@ExceptionTest(NullPointerException.class)
public static void doublyBad() {
List<String> list = new ArrayList<>();
list.addAll(5, null); // μμΈ λ°μ κ°λ₯
}μμ : λ°λ³΅ κ°λ₯ν μ λν μ΄μ μ μ²λ¦¬νλ ν μ€νΈ λꡬ μ½λ
if (m.isAnnotationPresent(ExceptionTest.class) || m.isAnnotationPresent(ExceptionTestContainer.class)) {
tests++;
try {
m.invoke(null);
System.out.printf("ν
μ€νΈ %s μ€ν¨: μμΈλ₯Ό λμ§μ§ μμ%n", m);
} catch (Throwable wrappedExc) {
Throwable exc = wrappedExc.getCause();
int oldPassed = passed;
ExceptionTest[] excTests = m.getAnnotationsByType(ExceptionTest.class);
for (ExceptionTest excTest : excTests) {
if (excTest.value().isInstance(exc)) {
passed++;
break;
}
}
if (passed == oldPassed)
System.out.printf("ν
μ€νΈ %s μ€ν¨: %s %n", m, exc);
}
}@Repeatableμ μ¬μ©ν λ°λ³΅ κ°λ₯ν μ λν
μ΄μ
μ μ²λ¦¬ν λλ, getAnnotationsByType λ©μλλ₯Ό ν΅ν΄ κ°λ³ μ λν
μ΄μ
μ λ°°μ΄ ννλ‘ κ°μ Έμ¬ μ μλ€.
μ λν μ΄μ μΌλ‘ ν μ μλ μΌμ λͺ λͺ ν¨ν΄μΌλ‘ μ²λ¦¬ν μ΄μ λ μμΌλ©°, μλ° νλ‘κ·Έλλ¨ΈλΌλ©΄ μμΈ μμ΄ μλ°κ° μ 곡νλ μ λν μ΄μ νμ λ€μ μ¬μ©ν΄μΌ νλ€.(μμ΄ν 40, 27)
μ λν μ΄μ μ ν΅ν΄ μ½λλ₯Ό λμ± μ½κΈ° μ½κ³ μ μ§ λ³΄μνκΈ° μ©μ΄νκ² λ§λ€ μ μμ΅λλ€.
μ°Έκ³