- JUnit3 μ κ²½μ° ν μ€νΈ μΌμ΄μ€μ μ΄λ¦μ test λ‘ μμν΄μΌ νλ€.
- test λ‘ μμν΄μΌ ν μ€νΈ μΌμ΄μ€λ‘ μΈμνλ€.
- TestCase ν΄λμ€λ₯Ό μμλ°μμΌ νλ€.
import junit.framework.*;
public class TestSample extends TestCase {
public TestSample(String name){ super(name); }
public void setUp(){}
public void tearDown(){}
// λͺ
λͺ
ν¨ν΄ - ν
μ€νΈ μΌμ΄μ€λ test λ‘ μμ
public void test01(){
//ν
μ€νΈ μ½λ
}
public static Test suite (){
return new TestSuite( TestSample.class );
}
public static void main(String args[]){
TesrFinder.run(TestSample.class,args);
}
}
[λ ν리μμ μ‘λμ¬λ :: λ¨μν
μ€νΈ JUNIT (3)]
(https://repilria.tistory.com/315)
- μ€νκ° λλ©΄ μΈμμ λͺ»νλ€.
- μΈμμ λͺ»νλ©΄ μ€λ₯λ©μΈμ§λ λ¨μ§ μμ κ²μ΄κ³ , ν μ€νΈκ° ν΅κ³Όνλ€κ³ μλͺ» μΈμν μ μλ€.
- μλν κ³³μμλ§ μ°μΌ κ²μ΄λΌ 보μ₯ν μ μλ€.
- μ¬μ©λ²μ μ λͺ¨λ₯΄λ μ¬μ©μκ° λ©μλκ° μλ ν΄λμ€μ Test λͺ λͺ ν¨ν΄μ μ μ©νκ³ κ·Έ ν΄λμ€μ ν μ€νΈ μΌμ΄μ€λ€μ΄ μ€νλκΈΈ κΈ°λν μ λ μλ€.
- λͺ λͺ ν¨ν΄μλ ν¨ν΄ μ€νμ νμν μΈμλ₯Ό 맀κ°λ³μλ‘ λκΈΈ λ°©λ²μ΄ λ§λ μΉ μλ€.
-> λͺ λͺ ν¨ν΄ λμ μλν μ΄μ μ μ°μ !
μλν μ΄μ μΈκ°λ₯Ό λ§λ€μ΄ 보면μ, μλν μ΄μ μ΄ λ¬΄μμΈμ§μ λͺ λͺ ν¨ν΄μ λ¨μ μ μ΄λ»κ² 보μ νλμ§ μμ보μ !
λͺ©ν : 맀κ°λ³μ μλ μ μ λ©μλμλ§ μΈ μ μλ ν μ€νΈ μλν μ΄μ μ λ§λ€μ΄λ³΄μ ! - Annotation Processor λ₯Ό μ¬μ©ν΄λ³΄μ.
- μλ‘μ΄ νλ‘μ νΈλ₯Ό λ§λ€κ³ , μ μ ν groupIdμ article μ μ§μ νλ€.
- κΈ°λ³Έ μμ±λλ μ€νλ§μ Application ν΄λμ€μ ν μ€νΈ ν΄λμ€λ€μ μμ νλ€. (μ ν)
/**
* μ΄ μλν
μ΄μ
μ 맀κ°λ³μ μλ μ μ λ©μλμλ§ λ¬ μ μλ λ§μ»€ μλν
μ΄μ
μ΄λ€.
*/
@Retention(RetentionPolicy.SOURCE) // μ»΄νμΌ ν μλν
μ΄μ
μ 보 μ¬λΌμ§
@Target(ElementType.METHOD) // λ©μλμλ§ λ¬ μ μμ
public @interface CustomTest {
}
- λ©ν μλν
μ΄μ
: μλν
μ΄μ
μ λ§λ€λ λΆμ΄λ μλν
μ΄μ
- @Retention : μΈμλ‘ μλν μ΄μ μ λ³΄κ° μΈμ κΉμ§ λ¨μμμμ§ μ§μ νλ€.
- @Target : μΈμλ‘ ν΄λΉ μλν μ΄μ μ΄ μ΄λμ λΆμ΄μμ μ μλμ§ μ§μ νλ€.
- λ§μ»€ μλν μ΄μ : μ무 맀κ°λ³μ μμ΄ λ¨μν λ§νΉμ μ¬μ©νλ μλν μ΄μ (ex. @Override)
- μλν μ΄μ νλ‘μΈμλ μλν μ΄μ μ μ½κ³ μ½λλ₯Ό μΆκ°νκ±°λ νΉμ μμ μ ν μ μκ² ν΄μ€λ€.
- μλν μ΄μ μ κΈ°λ³Έμ μΌλ‘ 리νλ μ μ μ΄μ©νμ¬ λμνλ€.
@SupportedAnnotationTypes("com.meetcoder.testannotation.CustomTest")
public class CustomTestProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(CustomTest.class);
for(Element element : elementsAnnotatedWith){
makeErrorIfNotStaticMethod(element);
}
return true;
}
private void makeErrorIfNotStaticMethod(Element element) {
if (isNotStaticMethod(element)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "static λ©μλκ° μλλλ€.");
}
}
private boolean isNotStaticMethod(Element element) {
return !element.getModifiers().contains(Modifier.STATIC);
}
}
mvn compile (λΉλλꡬ) λ‘ μ»΄νμΌνλ€.
- μλν μ΄μ νλ‘μΈμλ₯Ό μ΄μ©νκΈ° μν΄μλ μ ν΄μ§ μμΉμ λ±λ‘ν΄μΌ νλ€.
- μλν μ΄μ νλ‘μΈμλ₯Ό μ°κΈ° μν΄μλ λ€μ κ²½λ‘λ₯Ό λ§λ€κ³ , javax~ νμΌμ λ§λ€μ΄μΌ νλ€.
- μ΄ νμΌ μμ μλν μ΄μ νλ‘μΈμμ FQCN μ μμ±νλ€.
(κ°μμ μλν
μ΄μ
νλ‘μΈμ κ²½λ‘μ λ§κ² μμ±νκΈ° ! )
- pom.xml μ νμμλ μμ‘΄μ±κ³Ό νλ¬κ·ΈμΈμ μμ ν jar νμΌλ‘ λ§λ λ€.
(μλν
μ΄μ
νλ, μλν
μ΄μ
νλ‘μΈμ νλ, λ±λ‘νλ 리μμ€νμΌ νλ)
(λ°©κΈ λ§λ jar λ₯Ό κ°μ Έμ€κΈ° μν΄ μμ‘΄μ± μΆ)
(static μ΄ μλ λ©μλμ μλν
μ΄μ
λΆμμ μ, λ°νμμ΄ μλ μ»΄νμΌνμμ μλ¬κ° λ¬λ€.)
λͺ©ν : μμΈκ° λ°μνλ©΄ μ±κ³΅νλ ν μ€νΈ μλν μ΄μ μ λ§λ€μ΄ 보μ ! μ΄ μλν μ΄μ μ μΈμκ°μΌλ‘ μλ¬λ₯Ό μ§μ νκ³ , λ°λ³΅ μ¬μ©μΌλ‘ μ¬λ¬ μλ¬λ₯Ό μ§μ ν μ μμ΄μΌ νλ€.
μ΄λ²μλ λ©μΈλ©μλμ ν μ€νΈ λ¬λλ₯Ό μμ±ν κ²μ΄λ€. (μλν μ΄μ νλ‘μΈμ λ§λ€κΈ°μ μ€ν¨νμ΅λλ€....) μλν μ΄μ νλ‘μΈμμ μ₯μ μ μ»΄νμΌνμμ μ€λ₯λ₯Ό μ‘μ μ μλ€λ κ²μ΄λ€, ν μ€νΈ λ¬λλ₯Ό λ§λ€μ΄μ νλ©΄ λ°νμμ μ€λ₯λ₯Ό νμΈν μ μλ€.
@Repeatable(ExceptionTestContainer.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
Class<? extends Throwable> value();
}
- value() λΌλ μ΄λ¦μΌλ‘ μ§μ νλ©΄ μλν μ΄μ μ¬μ©μ νμ μ μ§μ νμ§ μμλ λ¨.
- κ°μ μλν μ΄μ μ μ¬λ¬κ° λ¬κΈ° μν΄ @Repeatable() λ©ν μλν μ΄μ μ¬μ©
- @Repeatable μ μ¬μ©νκΈ° μν΄μλ 컨ν μ΄λ ν΄λμ€κ° νμνλ€.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTestContainer {
ExceptionTest[] value();
}
public class RunTest {
private Class<?> testClass;
private int tests = 0;
private int passed = 0;
public RunTest(String path) {
try {
this.testClass = Class.forName(path);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Class<?> getTestClass() {
return testClass;
}
public void run(Class<?> runTest) {
for (Method method : runTest.getDeclaredMethods()) {
if (method.isAnnotationPresent(ExceptionTest.class) || method.isAnnotationPresent(ExceptionTestContainer.class)) {
tests++;
try {
method.invoke(null);
System.err.printf("**ν
μ€νΈ %s μ€ν¨ : μμΈλ₯Ό λμ§μ§ μμμ΅λλ€ !**%n", method.getName());
} catch (Throwable wrappedExc) {
Throwable exc = wrappedExc.getCause();
int oldPassed = passed;
ExceptionTest[] exceptionTests = method.getAnnotationsByType(ExceptionTest.class);
for (ExceptionTest exceptionTest : exceptionTests) {
if (exceptionTest.value().isInstance(exc)) {
passed++;
System.out.printf("**ν
μ€νΈ %s μμ μμλλ‘ %s μμΈκ° λ°μνμμ΅λλ€ !**%n", method.getName(), exc.getClass());
break;
}
}
if (passed == oldPassed) {
System.err.printf("**ν
μ€νΈ %s μ€ν¨ : λ€λ₯Έ μμΈ %s κ° λ°μνμμ΅λλ€ !**%n", method.getName(), exc.getClass());
}
}
}
}
}
public static void main(String[] args) throws ClassNotFoundException {
RunTest runTest = new RunTest("Chapter6.Day39.ExceptionTest.Tests");
Class<?> testClass = runTest.getTestClass();
runTest.run(testClass);
}
}
@Repeatable μλν μ΄μ μ΄ λΆμ΄ μλν μ΄μ μ μ¬λ¬λ² μΌλ€λ©΄, λ΄λΆμ μΌλ‘ 컨ν μ΄λ μλν μ΄μ μΌλ‘ μ μ©νλ€. νλ² μ΄ μλν μ΄μ κ³Ό ꡬλΆνκΈ° μν¨μ΄λ€.
- AnnotatedElement.getAnnotationsByType() : μλ μλν μ΄μ κ³Ό 컨ν μ΄λ μλν μ΄μ μ ꡬλΆνμ§ μμ. λ°λΌμ λ κ²½μ° λͺ¨λ κ°μ Έμ΄.
- AnnotatedElement.isAnnotationPresent() : μλ μλν μ΄μ κ³Ό 컨ν μ΄λ μλν μ΄μ μ ꡬλΆν¨. λ°λΌμ μλ μλν μ΄μ μ μ΄ λ©μλλ‘ κ²μ¬νλ€λ©΄ [μλλ€] λΌκ³ ν κ²μ΄λ€.
λ°λΌμ getAnnotationsByType() μΌλ‘ κ²μ¬νλ€.
- λͺ
λͺ
ν¨ν΄ λ¨μ 1 : μ€νλλ©΄ μΈμλͺ»ν¨
- μλν μ΄μ μ μ€νλλ©΄ μ»΄νμΌμ‘°μ°¨ μλλ€.
- λͺ
λͺ
ν¨ν΄ λ¨μ 2 : μ΄μν λ°μ μΈ μλ μμ
- @Target, λλ μλν μ΄μ νλ‘μΈμμμμ κ²μ¬λ₯Ό ν΅ν΄ μ νκ°λ₯
- λͺ
λͺ
ν¨ν΄ λ¨μ 3 : μ€νμ νμν μμ μ λ¬μ΄ λΆκ°
- μλν μ΄μ μ 맀κ°λ³μλ‘ μ λ¬ κ°λ₯
μλν μ΄μ μ°μ.