[JUnit] JUnit์ ์ด์ฉํ TDD(Test-Driven Development)
- -
์ค๋์ JUnit์ ์ด์ฉํ TDD(Test-Driven Development) ๊ธฐ๋ณธ ๋ฌธ๋ฒ๊ณผ ํ์ฉ ์์ ์ ๋ํด์ ํฌ์คํ ํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ์ ๋ ์ด๋ฒ์ ๊ณต๋ถํ๋ ๋ง์์ผ๋ก ์๋ฃ๋ฅผ ์ฐพ์์ ์ ๋ฆฌ๋ฅผ ํด๋ดค์ต๋๋ค. ์๋ชป๋ ์ ์ ๊ฐ๊ฐ ์์ด ํผ๋๋ฐฑ ์ฃผ์๋ฉด ํฐ ๋์์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ค๋๋ ๊ณต๋ถ๋ฅผ ์์ํด ๋ณด๊ฒ ์ต๋๋ค. ๐
Junit ?!
JUnit์ ์๋ฐ์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ํ ์คํธ ํ๋ ์์ํฌ ์ค ํ๋์ ๋๋ค. TDD๋ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ ํ, ๊ทธ์ ํด๋นํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฐ๋ฐ ๋ฐฉ๋ฒ์ ๋๋ค. JUnit์ ์ด์ฉํ TDD๋ฅผ ์ ์ฉํ๋ฉด ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด์ ๊ฐ๋ฐํ๋ ๊ณผ์ ์์ ์์ ์ ์ด๊ณ ๊ฒฌ๊ณ ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
ํ ์คํธ ํด๋์ค ์์ฑ
JUnit์ ์ด์ฉํ์ฌ ํ ์คํธ ํด๋์ค๋ฅผ ์์ฑํ๊ธฐ ์ํด์๋ @Test ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ์ฌ ํ ์คํธ ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค.
import org.junit.Test;
public class MyTestClass {
@Test
public void myTestMethod() {
// ํ
์คํธํ ์ฝ๋ ์์ฑ
}
}
Assert ์ฌ์ฉ
JUnit์์๋ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๊ธฐ ์ํด Assert ํด๋์ค๋ฅผ ์ด์ฉํฉ๋๋ค. Assert ํด๋์ค์์ ์ ๊ณตํ๋ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
import org.junit.Test;
import static org.junit.Assert.*;
public class MyTestClass {
@Test
public void myTestMethod() {
int a = 5;
int b = 10;
int result = a + b;
assertEquals(15, result);
}
}
์ ์์ ์์๋ assertEquals ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ result ๋ณ์์ ๊ฐ์ด 15์ธ์ง ๊ฒ์ฆํ๊ณ ์์ต๋๋ค. Assert ํด๋์ค์์๋ ๋ค์ํ ๊ฒ์ฆ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ฏ๋ก, ํด๋น ๋ฉ์๋๋ฅผ ์ ์ ํ ์ด์ฉํ์ฌ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
์์ธ ์ฒ๋ฆฌ
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ ๋, ์์ธ ์ํฉ๋ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. JUnit์์๋ ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ด๋ ธํ ์ด์ ์ธ @Test(expected=Exception.class)์ ์ด์ฉํ ์ ์์ต๋๋ค.
import org.junit.Test;
public class MyTestClass {
@Test(expected=NullPointerException.class)
public void myTestMethod() {
String str = null;
str.length();
}
}
์ ์์ ์์๋ str ๋ณ์๊ฐ null์ธ ์ํฉ์์ length() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฏ๋ก, NullPointerException์ด ๋ฐ์ํฉ๋๋ค. @Test(expected=NullPointerException.class)๋ฅผ ์ด์ฉํ์ฌ ํด๋น ์์ธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๊ฒ์ฆํ๊ณ ์์ต๋๋ค.
ํ ์คํธ ์คํ ์์
JUnit์์๋ ํ ์คํธ ์คํ ์์๋ฅผ ๋ณด์ฅํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์, ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์์์ ์์กดํ์ง ์๋๋ก ์ฃผ์ํด์ผ ํฉ๋๋ค.
ํ ์คํธ ์ผ์ด์ค ์์ฑ
๋จผ์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ํ ์คํธ ์ผ์ด์ค๋ ํน์ ๊ธฐ๋ฅ์ด ์ ์์ ์ผ๋ก ๋์ํ๋์ง ๊ฒ์ฆํ๊ธฐ ์ํ ์ ๋ ฅ๊ฐ๊ณผ ์์ ๊ฒฐ๊ณผ๊ฐ์ ๋ด์ ์ฝ๋์ ๋๋ค. ์๋ฅผ ๋ค์ด, ๊ณ์ฐ๊ธฐ ํ๋ก๊ทธ๋จ์ ๋ง์ ๊ธฐ๋ฅ์ ๊ฒ์ฆํ๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
import static org.junit.Assert.*;
import org.junit.*;
public class CalculatorTest {
@Test
public void testAddition() {
Calculator calculator = new Calculator();
int result = calculator.add(5, 10);
assertEquals(15, result);
}
}
์ ์์ ์์๋ Calculator ํด๋์ค์ add ๋ฉ์๋๋ฅผ ๊ฒ์ฆํ๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ๊ณ ์์ต๋๋ค. Calculator ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ add ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ฐํ๊ฐ์ด ์์ํ ๊ฐ๊ณผ ๋์ผํ์ง ๊ฒ์ฆํ๊ณ ์์ต๋๋ค.
๊ธฐ๋ฅ ๊ตฌํ
์ด์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ์ผ๋ฏ๋ก ํด๋น ๊ธฐ๋ฅ์ ๊ตฌํํด์ผ ํฉ๋๋ค. TDD์์๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ๋จผ์ ์์ฑํ ํ ํด๋น ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๋ฐฉ์์ผ๋ก ๊ฐ๋ฐ์ ์งํํฉ๋๋ค.
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}
์ ์์ ์์๋ add ๋ฉ์๋๋ฅผ ๊ตฌํํ์ฌ ์ ๋ ฅ๋ฐ์ ๋ ์ ์๋ฅผ ๋ํ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํํ๊ณ ์์ต๋๋ค.
๊ฒ์ฆ
ํ ์คํธ ์ผ์ด์ค์ ํด๋น ๊ธฐ๋ฅ์ ๋ชจ๋ ์์ฑํ์์ผ๋ฏ๋ก ์ด์ ๊ฒ์ฆ์ ์งํํฉ๋๋ค. JUnit์ ์ด์ฉํ์ฌ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์คํํ๋ฉด ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ๊ฒฐ๊ณผ๊ฐ ์์ํ ๋๋ก ๋์ํ๋ฉด ํด๋น ๊ธฐ๋ฅ์ ์์ ์ ์ผ๋ก ๊ฐ๋ฐํ ๊ฒ์ ๋๋ค.
JUnit์ ์ด ์ธ์๋ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์๋ฅผ ๋ค์ด, @Before, @After ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ์ฌ ํ ์คํธ ์ผ์ด์ค ์คํ ์ ๊ณผ ํ์ ์คํํ ๋ฉ์๋๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. ๋ํ, @RunWith ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ์ฌ JUnit ์คํ ์ ์ปค์คํ ์คํ์๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ ์ด์ฉํ์ฌ ํจ์จ์ ์ธ ํ ์คํธ ์ฝ๋ ์์ฑ์ ์งํํ ์ ์์ต๋๋ค.
JUnit์ Java ์ธ์ด๋ฅผ ์ํ ์ ๋ ํ ์คํธ ํ๋ ์์ํฌ๋ก, ์ฝ๋์ ์์ ์ฑ๊ณผ ๋์์ ๊ฒ์ฆํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ํ ์คํธ ์ฝ๋ ์์ฑ์ ํจ์จ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
์ด๋ ธํ ์ด์
JUnit์์๋ ์ด๋ ธํ ์ด์ (annotation)์ ์ด์ฉํ์ฌ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ผ๋ฉฐ, ํ ์คํธ ์ผ์ด์ค ์คํ์ ํ์ํ ํ๊ฒฝ์ ์ง์ ํ ์ ์์ต๋๋ค.
- @Test: ํด๋น ๋ฉ์๋๊ฐ ํ ์คํธ ์ผ์ด์ค์์ ๋ํ๋ ๋๋ค.
- @Before: ํด๋น ๋ฉ์๋๊ฐ ๊ฐ๊ฐ์ ํ ์คํธ ์ผ์ด์ค ์คํ ์ ์ ์คํ๋ฉ๋๋ค.
- @After: ํด๋น ๋ฉ์๋๊ฐ ๊ฐ๊ฐ์ ํ ์คํธ ์ผ์ด์ค ์คํ ํ์ ์คํ๋ฉ๋๋ค.
- @BeforeClass: ํด๋น ๋ฉ์๋๊ฐ ํ ์คํธ ํด๋์ค์ ๋ชจ๋ ํ ์คํธ ์ผ์ด์ค ์คํ ์ ์ ํ ๋ฒ ์คํ๋ฉ๋๋ค.
- @AfterClass: ํด๋น ๋ฉ์๋๊ฐ ํ ์คํธ ํด๋์ค์ ๋ชจ๋ ํ ์คํธ ์ผ์ด์ค ์คํ ํ์ ํ ๋ฒ ์คํ๋ฉ๋๋ค.
- @Ignore: ํด๋น ํ ์คํธ ์ผ์ด์ค๋ฅผ ๋ฌด์ํ๊ณ ์คํํ์ง ์์ต๋๋ค.
์ด์์
JUnit์์๋ ์ด์์ (assertion)์ ์ด์ฉํ์ฌ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํฉ๋๋ค. ์ด์์ ์ ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์์ ๊ฒฝ์ฐ AssertionError๋ฅผ ๋ฐ์์ํต๋๋ค. ๋ค์ํ ์ด์์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ ๊ฒ์ฆํ ์ ์๋ ์กฐ๊ฑด์ ์ข ๋ฅ๊ฐ ๋งค์ฐ ๋ค์ํฉ๋๋ค.
- assertEquals(expected, actual): ๋ ๊ฐ์ด ๋์ผํ์ง ๊ฒ์ฆํฉ๋๋ค.
- assertArrayEquals(expected, actual): ๋ ๋ฐฐ์ด์ด ๋์ผํ์ง ๊ฒ์ฆํฉ๋๋ค.
- assertTrue(condition): ์กฐ๊ฑด์ด true์ธ์ง ๊ฒ์ฆํฉ๋๋ค.
- assertFalse(condition): ์กฐ๊ฑด์ด false์ธ์ง ๊ฒ์ฆํฉ๋๋ค.
- assertNull(object): ๊ฐ์ฒด๊ฐ null์ธ์ง ๊ฒ์ฆํฉ๋๋ค.
- assertNotNull(object): ๊ฐ์ฒด๊ฐ null์ด ์๋์ง ๊ฒ์ฆํฉ๋๋ค.
- assertSame(expected, actual): ๋ ๊ฐ์ฒด๊ฐ ๋์ผํ ๊ฐ์ฒด์ธ์ง ๊ฒ์ฆํฉ๋๋ค.
- assertNotSame(expected, actual): ๋ ๊ฐ์ฒด๊ฐ ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด์ธ์ง ๊ฒ์ฆํฉ๋๋ค.
ํ ์คํธ ๋ฌ๋
JUnit์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ ์คํธ ์ผ์ด์ค๋ฅผ ์คํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ํ์ง๋ง, ๋ค์ํ ํ ์คํธ ๋ฌ๋(test runner)๋ฅผ ์ด์ฉํ์ฌ ํ ์คํธ ์ผ์ด์ค ์คํ ๋ฐฉ์์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ํ ์คํธ ์ผ์ด์ค ์คํ ์์๋ฅผ ๋ฌด์์๋ก ์ค์ ํ๊ฑฐ๋, ํน์ ํ ํ ์คํธ ์ผ์ด์ค๋ง ์คํํ๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
- @RunWith: JUnit์ ํ ์คํธ ๋ฌ๋๋ฅผ ์ง์ ํฉ๋๋ค.
- @SuiteClasses: ํน์ ํ ์คํธ ํด๋์ค
Parameterized Tests
JUnit์์๋ Parameterized Tests๋ฅผ ํตํด ๋์ผํ ๋ก์ง์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ๋ค์ํ ์ ๋ ฅ๊ฐ์ผ๋ก ์คํํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ํ ์คํธ ์ผ์ด์ค ์์ฑ์ ํจ์จ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
- @RunWith(Parameterized.class): Parameterized runner๋ฅผ ์ฌ์ฉํ ๋ ์ง์ ํฉ๋๋ค.
- @Parameters: ์ ๋ ฅ๊ฐ์ผ๋ก ์ฌ์ฉํ ๋ฐฐ์ด์ ๋ฐํํ๋ static ๋ฉ์๋์ ์ง์ ํฉ๋๋ค.
Exception Tests
JUnit์์๋ ์์ธ ์ฒ๋ฆฌ ๋ก์ง์ด ์๋ ๋ฉ์๋์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ ๋, Exception Tests๋ฅผ ์ด์ฉํ์ฌ ์์ธ ์ฒ๋ฆฌ ๋ก์ง์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋์ง ๊ฒ์ฆํ ์ ์์ต๋๋ค.
- @Test(expected=Exception.class): ํด๋น ํ ์คํธ ์ผ์ด์ค์์ ๋ฐ์ํ ๊ฒ์ผ๋ก ์์๋๋ ์์ธ ํด๋์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- @Rule: ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ Rule์ ์ง์ ํฉ๋๋ค.
Timeout Tests
JUnit์์๋ Timeout Tests๋ฅผ ์ด์ฉํ์ฌ ํน์ ๋ฉ์๋์ ์คํ ์๊ฐ์ด ์ผ์ ์๊ฐ ์ด์์ธ ๊ฒฝ์ฐ, ํด๋น ํ ์คํธ ์ผ์ด์ค๋ฅผ ์คํจ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- @Test(timeout=millis): ํด๋น ํ ์คํธ ์ผ์ด์ค๊ฐ ์คํ๋๋ ๋์ ํ์ฉ๋๋ ์ต๋ ์๊ฐ์ ๋ฐ๋ฆฌ์ด ๋จ์๋ก ์ง์ ํฉ๋๋ค.
Test Suites
JUnit์์๋ Test Suites๋ฅผ ์ด์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ํ ์คํธ ํด๋์ค๋ฅผ ๋ฌถ์ด์ ํ ๋ฒ์ ์คํํ ์ ์์ต๋๋ค.
- @RunWith(Suite.class): Suite runner๋ฅผ ์ฌ์ฉํ ๋ ์ง์ ํฉ๋๋ค.
- @SuiteClasses: ์คํํ ํ ์คํธ ํด๋์ค๋ฅผ ๋ฐฐ์ด๋ก ์ง์ ํฉ๋๋ค.
ํ ์คํธ ์ปจํ ์คํธ ๊ด๋ฆฌ
Spring Framework์ ํจ๊ป ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ, JUnit์ ํ ์คํธ ์ปจํ ์คํธ ๊ด๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค. ์ด๋ฅผ ํตํด ํ ์คํธ ํ๊ฒฝ์์ ์คํ๋ง ๋น๊ณผ ๊ฐ์ ์์กด์ฑ ๊ด๋ฆฌ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
- @RunWith(SpringJUnit4ClassRunner.class): Spring๊ณผ ํจ๊ป ์ฌ์ฉํ ๋ ์ง์ ํฉ๋๋ค.
- @ContextConfiguration: ํ ์คํธ ์ปจํ ์คํธ๊ฐ ๋ก๋๋ XML ํ์ผ์ด๋ ํด๋์ค๋ฅผ ์ง์ ํฉ๋๋ค.
๋ง์น๋ฉฐ..
์์ ๊ฐ์ JUnit์ ๋ค์ํ ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉด, ํ ์คํธ ์ฝ๋ ์์ฑ์ ํจ์จ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์ผ๋ฉฐ, ์ฝ๋์ ์์ ์ฑ๊ณผ ๋์์ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
์ด๋ฒ ๊ธฐํ์ ์ ์ ๊ฐ์ด ๋์ฑ๋ ์์ ํ ์ฝ๋๋ฅผ ๋ง๋ค๊ธฐ ์ํ ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ์ JUnit์ ์ด์ฉํด์ ์ค์ฒํด ๋ณด๋ ๊ฑด ์ด๋จ๊น์?
ps) Hoxy.. ์ ๋ง ์ ํ๊ณ ์์๋ ๊ฑฐ๋ผ๋ฉด.. ์ง์ง ๋ฐ์ฑํ๊ฒ ์ต๋๋ค. ๐ข
'Back-End > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Java 8] Stream API ๊ธฐ๋ณธ ๋ฌธ๋ฒ ๋ฐ ํ์ฉ ์์ (0) | 2023.02.28 |
---|---|
[Java] ์ค์ผ์ค๋ฌ ๋ฐฐ์น (2) | 2023.02.04 |
[Java] ํธ๋ฆฌํ Lombok ๊ธฐ๋ฅ ์ ๋ฆฌ (0) | 2023.02.04 |
[Java] IntelliJ์์ lombok ์ฌ์ฉํ๊ธฐ (0) | 2023.02.04 |
[Java] ํ๊ฒฝ๋ณ์ ์ค์ (0) | 2023.02.04 |
์์คํ ๊ณต๊ฐ ๊ฐ์ฌํฉ๋๋ค. ๐