Java ํ๋ก๊ทธ๋จ ์ ๋ ํ ์คํธ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์ 6๊ฐ์ ์๊ตฌ์ฌํญ์ ๊ฐ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๋ง์กฑ ํด์ผ ํ๋ฏ๋ก, ๊ฐ ์๊ตฌ์ฌํญ ์์ฑ์ ๋ฐ๋ผ(R1-R6)๋ฅผ ๊ตฌ๋ณํ ์ ์๋ค.
- R1: ์ฌ์ฉ์๊ฐ ์ง์ํ ํ ์คํธ ์ผ์ด์ค๊ฐ ์คํ๋์ด์ผ ํจ
- R2: ์์ดํ ํ๊ฒฝ์์๋ ๋์ผํ ํ ์คํธ ์ฝ๋๋ ๋์ผํ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์คํํด์ผ ํจ
- R3: ์ ๋ ํ ์คํธ ์ฝ๋์ ์คํ์ ์ํธ ๊ฐ ์ํฅ์ ๋ฐ์ง ์์์ผ ํจ
- R4: ์คํ ๊ฒฐ๊ณผ๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ ๊ฒฝ์ฐ, ํ ์คํธ ์คํจ(test fail)๋ก ๊ด์ฐฐ๋์ด์ผ ํจ
- R5: ํ ์คํธ ์คํ ๊ฒฐ๊ณผ๊ฐ ์ฌ๋ฐ๋ฅธ ๊ฒฝ์ฐ, ํ ์คํธ ์ฑ๊ณต(test pass)๋ก ๊ด์ฐฐ๋์ด์ผ ํจ
- R6: ํ ์คํธ ๊ฒฐ๊ณผ๊ฐ ์ฌ์ฉ์์๊ฒ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ฌ๋์ด์ผ ํจ.
์ ๋ ํ ์คํธ ์ผ์ด์ค์ ๊ฐ ์คํ๊ณผ์ ์ ๋ค์์ 7๊ฐ์ง ์ข ๋ฅ๋ก ๊ตฌ๋ถํ์ฌ ๋ฒ์ฃผ(S1-S7)๋ก ์ ์ํ ์ ์๋ค.
- S1 (์ฌ์ฉ์ ์ ๋ ฅ์ ๋ฐ๋ฅธ ์ ๋ ํ ์คํธ ๊ตฌ๋): ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ํตํ๊ฑฐ๋ ์ฌ์ฉ์์ ์ง์ ์กฐ์์ ํตํด ์ฃผ์ด์ง๋ ๋ช ๋ น์ ํด์ํ์ฌ, ์คํํด์ผ ํ ์ ๋ ํ ์คํธ ์ฝ๋๋ฅผ ์ง์ ํ์ฌ ์ํ
- S2 (ํ ์คํธ ์คํํ๊ฒฝ ์ค์ ): ์ ๋ ํ ์คํธ์ ์คํ์ ํต์ ํ๊ธฐ ์ํด ๊ฒ์ฆ๋์ ๋ชจ๋์ ์คํ์ ์ํฅ์ ์ค ์ ์๋ ์ฌ๋ฌ ๋ณ์(ํ๊ฒฝ๋ณ์, ๊ณต์ ๋ณ์ ๋ฑ)๋ฅผ ํน์ ๊ฐ์ผ๋ก ์ค์
- S3 (ํ ์คํธ ์ ๋ ฅ ์ง์ ): ํ ์คํธ์ผ์ด์ค์ ๊ฒ์ฆ ๋ชฉ์ ์ ๋ฐ๋ผ ์กฐ์ ํ ํ ์คํธ ์ ๋ ฅ ๊ฐ์ ์ง์
- S4 (๊ฒ์ฆ๋์ ๋ชจ๋ ์คํ): ์ง์ ๋ ํ ์คํธ ์ ๋ ฅ ๊ฐ์ผ๋ก ๊ฒ์ฆ๋์ ๋ชจ๋์ ๊ธฐ๋ฅ์ ์คํ
- S5 (ํ ์คํธ ์คํ ๊ฒฐ๊ณผ ๊ฒ์ฌ): ์คํ ๊ฒฐ๊ณผ๋ฅผ ํ ์คํธ ์ ๋ ฅ ๊ฐ์ ๋ํ ๊ธฐ๋ ๊ฐ๊ณผ ๋น๊ตํ์ฌ ํ ์คํธ ํต๊ณผ ์ ๋ฌด๋ฅผ ํ๋ณ
- S6 (ํ ์คํธ ์คํํ๊ฒฝ ์ค์ ํด์ ): S2์์ ์ค์ ํ ์คํํ๊ฒฝ์ ํด์
- S7 (์ฌ์ฉ์์๊ฒ ํ ์คํธ ๊ฒฐ๊ณผ ๋ณด๊ณ ): ํ ์คํธ ํต๊ณผ ์ ๋ฌด๋ฅผ ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ํตํ๊ฑฐ๋ ํน์ ์ง์ ์ฌ์ฉ์์๊ฒ ์ ๋ฌ
์ ๋ ํ ์คํธ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์๋ก ๋ค๋ฅธ ๊ตฌ์กฐ๋ก ๊ตฌ์ฑ๋๋ฏ๋ก, ๊ฐ ์ฝ๋ ์์๋ ์ฐ๊ด๋ ์ฝ๋ ๋ถ์์ ๋ฐ๋ผ 4๊ฐ์ง ์ฝ๋ ๊ตฌ์ฑ์์(P1-P4)๋ก ๋ถ๋ฅํ ์ ์๋ค.
- P1: ํ ์คํธ์ผ์ด์ค ๋ณ๋ก ๊ณ ์ ์๋๋ฆฌ์ค๋ฅผ ์ ์ํ๋ ๋ถ์
- P2: ์ฐ๊ด๋ ํ ์คํธ์ผ์ด์ค๋ฅผ ์์ธ๋ฌ ํ๋์ ํ ์คํธ ์ค์ํธ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ๋ถ์
- P3: ๊ฒ์ฆ๋์ ๋ชจ๋์ด ํธ์ถํ๋ ํ ์คํธ ๋ชจํ์ ์ ์ํ๊ฑฐ๋, ํ ์คํธ ๋ชจํ ํ๋ ์์ํฌ์์ ์ธํฐํ์ด์ค ๋ถ์
- P4: ํ ์คํ ํ๋ ์์ํฌ ์ธํฐํ์ด์ค ๋ถ์๋ก, ํ ์คํธ ํ๋ ์์ํฌ์ ๊ธฐ๋ฅ์ ํธ์ถ/์ฐธ์กฐํ๋ ๋ถ์
- ๊ตฌ์ฑ ์์ : R1, S1, P1
- ์์ ์ฝ๋
import junit.framework.TestCase;
public class AssertMethodInvokedFromRunMethod extends TestCase {
public void testComplex() {
new Thread() {
@Override
public void run() {
assertTrue(true); // Appears to pass test
assertTrue(false); // AssertMethodFailedError occurs not test failure
}
}.start();
}
}- ์ค๋ช : JUnit TestCase๋ฅผ ์์ํ์ฌ Test Class์ด๋, ์ด๋ ํ test method๋ ๊ตฌํ๋์ด ์์ง ์๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S1, P2
- ์์ ์ฝ๋
public class BadSuiteMethod extends TestCase {
static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new MyTests("testEquals"));
suite.addTest(new MyTests("testNotEquals"));
return suite;
}
}- ์ค๋ช : suite()๋ ๋ฐ๋์ public static Test suite() ํน์ public static TestDuite suite() ๋ก ์ ์๋์ด์ผ ํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S1, P2
- ์์ ์ฝ๋
import junit.framework.TestCase;
public class BadStaticSuite extends TestCase{
public void suite() {} // oops, should be static
}-
์ค๋ช : JUnit3 ํ๋ ์์ํฌ๋ suite() method๋ฅผ ์ฌ์ฉํ์ฌ test suite๋ฅผ ๊ตฌ์ฑํ๋๋ฐ, JUnit4์์๋ @RunWith(Suite.class) annotation์ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
-
์ถ์ฒ
4. JMock ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋์์, ํด๋น Test Class ์์ JMock Runner๋ฅผ ์ฌ์ฉํ์ง ์์
- ๊ตฌ์ฑ ์์ : R1, S1, P4
- ์์ ์ฝ๋
17 // @RunWith(JMock.class) code using Mockery Class without JMock.class
18 public class PricingServiceTests {
19
20 private static final String SKU = "3283947";
21 private static final String BAD_SKU = "-9999993434";
22
23 private PricingService systemUnderTest;
24 private DataAccess mockedDependency;
25 private Mockery mockingContext;
26
27 @Before
28 public void doBeforeEachTestCase() {
29 mockingContext = new JUnit4Mockery();
30 systemUnderTest = new PricingServiceImpl();
31 mockedDependency = mockingContext.mock(DataAccess.class);
32 systemUnderTest.setDataAccess(mockedDependency);
33 }- ์ค๋ช : jMock ํ ์คํธ๋ ๋ฐ๋์ JMock Runner๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํ๋ค. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ํญ์ ํ ์คํธ๊ฐ ์ฑ๊ณตํ๊ฒ ๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S2, P3
- ์์ ์ฝ๋
public class BadSetUp extends TestCase {
protected void setUp() throws Exception {
// somePreparations();
}
...
}public class CorrectSetUp extends TestCase {
protected void setUp() throws Exception {
super.setUp();
// somePreparations();
}
...
}- ์ค๋ช : JUnit3 ์์ setUp() method๋ฅผ overrideํ ๋ ๋ฐ๋์ super.setUp()์ ํธ์ถํ์ฌ์ผ ํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S2, P4
- ์ค๋ช : JUnit4 ์์๋ @Before Annotation์ ์ฌ์ฉํ์ฌ ํ ์คํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ์คํ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
- ์์ ์ฝ๋
public class BadTest {
public void setUp() {
bad();
}
}public class GoodTest {
@Before
public void setUp() {
good();
}
}7. JUnit4 ์ @AfterClass๋ @BeforeClass annotation์ ์ฌ์ฉํ๋ฉด์ method๊ฐ static์ด ์๋ ๊ฒฝ์ฐ
- ๊ตฌ์ฑ ์์ : R1, S2, P4
- ์์ ์ฝ๋
public class JUnit4ClassAnnotationNonStaticPositiveCases {
@BeforeClass
public void beforeClassSetUp() {
setUpSomething();
}
@AfterClass
public void afterClassTearDown() {
releaseSomething();
}
}-
์ค๋ช : Beforeclass๋ AfterClass annotation์ ์ฌ์ฉํ๋ ๋ฉ์๋๋ ๋ฐ๋์ static ๋ฉ์๋๋ก ์ ์ธ๋์ด์ผ ํ๋ค.
-
์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S2, S6, P1
- ์์ ์ฝ๋
import junit.framework.TestCase;
public class JUnit3TestNotRunPositiveCases extends TestCase {
// TestCase๋ฅผ extendํ๋, @Test annotation์ ์ฌ์ฉํ๊ณ ์์ด,
// JUnit3์ ๊ตฌํํ ๊ฒ์ธ์ง, JUnit4 ์ ๊ตฌํํ ๊ฒ์ธ์ง ๋ถ๋ถ๋ช
ํ๋ค.
@Test
public void testName() {}
}- ์ค๋ช : JUnit3 ์์๋ ๋ฐ๋์ test* ํ์์ผ๋ก ๋ฉ์๋ ๋ช ์ด ์ ์๋์ด์ผ ํ๋๋ฐ, ์ด๋ฅผ ์งํค์ง ์๋ ๊ฒฝ์ฐ, ํ ์คํธ๊ฐ ์คํ๋์ง ์๋๋ค.
- ์ถ์ฒ
9. JDK9 ๋ก ํ ์คํธ ์ฝ๋๋ฅผ ์ปดํ์ผํ์ ๋ ์ค๋ฅ๊ฐ ๋๋ Mockito code pattern ์ ์ฌ์ฉํ ๊ฒฝ์ฐ
- ๊ตฌ์ฑ ์์ : R1, S3, P1
- ์์ ์ฝ๋
class Foo {
<T> T getFirst(Iterable<T> xs) {
return xs.iterator().next();
}
}
class Test {
@Mock Foo f;
@Test
public void test() {
Iterable<Boolean> it = Arrays.asList(false);
when(f.getFirst(it)).thenReturn(false);
}
}- ์ค๋ช : Jdk9์ผ๋ก ํด๋น ํ ์คํธ ์ฝ๋๋ฅผ ์ปดํ์ผ ํ๋ ๊ฒฝ์ฐ ์ฑ๊ณตํด์ผํ test๊ฐ ClassCastException์ด ๋ฐ์ํ๊ฒ ๋์ด failํ๊ฒ ๋๋ค.
- ์ถ์ฒ
10. JUnit3 ์์ tearDown()์ด ์ค๋ฒ๋ผ์ด๋๋์ด ์์ผ๋, super.tearDown() ์ ํธ์ถํ์ง ์์
- ๊ตฌ์ฑ ์์ : R1, S6, P3
- ์ค๋ช : JUnit3 ์์ setUp() method๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ ๋ ๋ฐ๋์, super.tearDown()์ ํธ์ถํ์ฌ์ผ ํ๋ค.
- ์์ ์ฝ๋
public class BadTearDown extends TestCase {
protected void tearDown() throws Exception {
// no super.tearDown();
}
}public class CorrectTearDown extends TestCase {
protected void tearDown() throws Exception {
super.teraDown();
}
}- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S6, P4
- ์์ ์ฝ๋
public class MyTest {
public void tearDown() {
bad();
}
}
public class MyTest2 {
@After
public void tearDown() {
good();
}
}- ์ค๋ช : JUnit4 ์์๋ @After Annotation์ ์ฌ์ฉํ์ฌ ํ ์คํธ๊ฐ ์คํ๋ ํ์ ์คํ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R2, S4, P1
- ์์ ์ฝ๋
ImmutableList xs;
assertThrows( UnsupportedOperationException.class, () ->
{ xs = ImmutableList.of(); // the test passes if this throws
xs.add(0); // this is never executed
});
assertThat(xs).isEmpty();- ์ค๋ช : assertThrows์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ง lambda์ ํ๊ฐ ์ด์์ statement๊ฐ ์๊ณ , ๋ด๋ถ์์ exception์ throwํ๋ค๋ฉด ๊ทธ ๋ค์ statement๋ค์ ๋ฌด์๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์์ ์ฝ๋
public class Foo extends TestCase {
public void testSomething() {
Bar b = findBar();
// This is better than having a NullPointerException
// assertNotNull("bar not found", b);
b.work();
}
}- ์ค๋ช : ํ ์คํธ์์ Assertion ๋ฉ์๋๊ฐ ์๋ ๊ฒฝ์ฐ์ด๋ค. NullPointerException์ ๊ธฐ๋ํ๋ ๊ฒฝ์ฐ assertNotNull์ ์ฌ์ฉ์ด ๊ถ์ฅ๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์ฝ๋ ์์
public class ImpossibleNullTest {
@Test
public void impossibleNullTest() {
Integer autoboxedInt = 30;
assertNotNull(autoboxedInt);
}
}- ์ค๋ช : assertNull() ์์ ์์์ wrapper class๊ฐ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ง๋ ๊ฒฝ์ฐ ํญ์ ๊ทธ assertion์ ํญ์ ์ฑ๊ณต passํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์์ ์ฝ๋
public class AssertUsedTest {
@Test
public void assertUsedTest() {
Integer actual = methodReturnsNonZeroNumber();
assert(actual != 0); // This is BAD
assertNotEquals(actual, 0); // This is GOOD
}
}- ์ค๋ช : Test framework๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ framework์์ ์ ๊ณตํ๋ assertion method๋ฅผ ์ฌ์ฉํด์ผํ๋ค. Runtime flag์ ๋ฐ๋ผ์, Test framework๊ฐ assert()์ ๊ฒฐ๊ณผ๋ฅผ ์ฒดํฌํ์ง ๋ชปํ ์ ์์ด, ์คํจํด์ผํ ํ ์คํธ๊ฐ ์ฑ๊ณตํ ์๋ ์๊ฒ ๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์์ ์ฝ๋
public class JUnitAssertSameCheckPositiveCase {
public void test(Object obj) {
// BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit
org.junit.Assert.assertSame(obj, obj);
// BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit
org.junit.Assert.assertSame("message", obj, obj);
// BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit
junit.framework.Assert.assertSame(obj, obj);
// BUG: Diagnostic contains: An object is tested for reference equality to itself using JUnit
junit.framework.Assert.assertSame("message", obj, obj);
}
}- ์ค๋ช : ๊ฐ์ ๊ฐ์ฒด์๋ํด reference๊ฐ ๊ฐ์์ง ํ์ธํ๋ ๊ฒฝ์ฐ assertion์ ๋ฐ๋์ passํ๊ฒ ๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์์ ์ฝ๋
// Calls to Mockito.when should always be accompanied by a call to a method like thenReturn.
when(mock.get()).thenReturn(answer); // correct
when(mock.get()) // oops!- ์ค๋ช : Mockito๋ฅผ ์ฌ์ฉํ๋ ํ ์คํธ์์ verify ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ง ์์, ํ ์คํธ๊ฐ ํญ์ ์ฑ๊ณตํ๊ฒ ๋๋ค.
- ์ถ์ฒ :
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์์ ์ฝ๋
public class TruthSelfEqualsPositiveCases {
public void testAssertThatEq() {
String test = Boolean.TRUE.toString();
// BUG: Diagnostic contains: new EqualsTester().addEqualityGroup(test).testEquals()
assertThat(test).isEqualTo(test);
}
...
}- ์ค๋ช : ๊ฐ์ ๊ฐ์ฒด์๋ํด equality๋ฅผ ๊ฒ์ฆํ๋ ๊ฒฝ์ฐ ํญ์ passํ๊ฒ ๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S7, P1
- ์์ ์ฝ๋
public class AssertMehtodInvodedFromeRunMethod extends TestCase {
public void testComplex() {
new Thread() {
@Override
public void run() {
assertTrue(true); // Appears to pass test
assertTrue(false); // AssertMethodFailedError occurs not test failure
}
}.start();
}
}- ์ค๋ช : JUnit์ ๊ฒฝ์ฐ, Test๋ฅผ ์คํํ๋ ์ค๋ ๋๊ฐ assertion method๋ฅผ ์คํํด์ผ ํ๋ค. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ test์ ์คํจ๋ก ์ด์ด์ง์ง ์๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, R5, S5, P1
- ์์ ์ฝ๋
import static com.google.common.truth.Truth.assertThat;
public class TruthConstantAssertsPositiveCases {
public void testAssertThat() {
// BUG: Diagnostic contains: assertThat(new TruthConstantAssertsPositiveCases()).isEqualTo(1);
assertThat(1).isEqualTo(new TruthConstantAssertsPositiveCases());
// BUG: Diagnostic contains: assertThat(someStaticMethod()).isEqualTo("my string");
assertThat("my string").isEqualTo(someStaticMethod());
...
}์ค๋ช : JUnit์ assertEquals๋ ํ๋ผ๋ฏธํฐ๋ก ๊ธฐ๋ํ๋ ๊ฐ(์์)์ ๋จผ์ , ์ค์ ํ ์คํธ ํ๊ณ ์ ํ๋ ๊ฐ์ ๋ค์์ ๋ฐ์์ผ ํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, R6, S5, P1
- ์์ ์ฝ๋
public class TruthIncompatibleTypePositiveCase {
assertThat(someMethodThatReturnsString()).isEqualTo(10);
}- ์ค๋ช : Truth framework์์ ์๋ก ํ์ ์ด ๋ค๋ฅธ ๋ ๊ฐ์ฒด์ equality ๋ฅผ ๋น๊ตํ๋ ๊ฒฝ์ฐ์ด๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R5, S5, P1
- ์์ ์ฝ๋
import junit.framework.TestCase;
public class JUnit3FloatingPointComparisonWithoutDeltaCases extends TestCase {
public void testFloat() {
float actual = 0.5 + 0.5;
assertEquals(1.0f, actual); // this is not good
}
}- ์ค๋ช
- JUnit3์์ ์ค๋ฅ ํ์ฉ ๋ฒ์ ์์ด assertionEquals()๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ๋ถ๋์์์ ์ ํน์ฑ์ ์ค๋ฅ ํ์ฉ ๋ฒ์ ์์ด ๋น๊ต๋ฅผ ํ ๋ ์๋ํ์ง ์์๋ ํ ์คํธ์ ์คํจ๋ก ์ด์ด์ง ์ ์๋ค.
- ์ถ์ฒ
23. Try ๋ธ๋ก ๋ด๋ถ์์ fail()์ด ์์ผ๋, catch ๋ธ๋ก์์ AssertionError ๋ฅผ catch ํ๋ ๊ฒฝ์ฐ
- ๊ตฌ์ฑ์์ : R5, S5, P1
- ์์ ์ฝ๋
try {
doSomething();
fail("expected doSomething to throw AssertionError");
} catch (AssertionError expected) {
// expected exception
}- ์ค๋ช : Exception throw ๋๊ธฐ๋ฅผ ๊ธฐ๋ํ๋ try block ์์์ ์ค์ ๋ก Exception์ด throw ๋์ง ์์ ํ ์คํธ๊ฐ ์คํจ๋์ผ ํ๋ฏ๋ก fail()์ ํธ์ถ๋์์ผ๋, catch block์์ AssertionError catchํ๋ ๊ฒฝ์ฐ, ํ ์คํธ๊ฐ failํ์ง ์๊ฒ ๋๋ค.
- ์ถ์ฒ
24. assertTrue() ๋ด๋ถ์ ํ๋ณ์์์ equals ๋ฅผ ํธ์ถํ์ฌ ๋ ๊ฐ์ฒด๊ฐ ๊ฐ์์ ํ์ธํ๋ ๊ฒฝ์ฐ
- ๊ตฌ์ฑ ์์ : R6, S5, P1
- ์์ ์ฝ๋
import org.testng.Assert;
import org.testng.annotations.Test;
public class TestHelloWorld {
@Test()
public void testUseAssertEquals() {
Object actual = getActual();
Object expected = getExpected;
Assert.assertTrue(expected.equals(actual)); // This is Bad
Assert.assertEquals(expected,actual); // This is Good
}
}- ์ค๋ช : AssertTrue() eqauls()๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๊ฐ์ฒด๊ฐ ๊ฐ์์ง ํ์ธํ๊ณ ์๋ค. equals()๋ ํธ์ถํ๋ ๊ฐ์ฒด๊ฐ null์ผ ๋ NullPointerException์ด ๋ฐ์๋๋ฏ๋ก, null-safeํ AssertSame()์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ถ์ฅ๋๋ค. ๋ํ Test์ ์คํจ์ AssertSame()์ ์ฌ์ฉํ๋ฉด Framework๊ฐ ๋์ฑ ์์ธํ ์ค๋ฅ ๋ฉ์ธ์ง๋ฅผ ์ถ๋ ฅํ๊ฒ ๋๋ค.
- ์ถ์ฒ
25. assertTrue() ๋ด๋ถ์ ํ๋ณ์์์ test ํ๊ณ ์ ํ๋ ๊ฐ์ฒด๊ฐ null ์ธ์ง๋ฅผ ํ์ธํ๋ ๊ฒฝ์ฐ
- ๊ตฌ์ฑ ์์ : R6, S5, P1
- ์์ ์ฝ๋
import org.testng.Assert;
import org.testng.annotations.Test;
public class TestHelloWorld {
@Test()
public void testUseAssertNull() {
Object actual = getActual();
Assert.assertEquals(actual == null ); // This is Bad
Assert.assertNull(actual) // This is Good
}
}- ์ค๋ช : AssertTrue() ๋ด๋ถ์ null๊ณผ์ ๋น๊ตํ๋ ์ฐ์ฐ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๊ฐ null์ธ์ง ํ์ธํ๊ณ ์๋ค. ์ด๋ฅผ ์ํด ๋ง๋ค์ด์ง AssertNull()์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ถ์ฅ๋๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S1, P4
- ์์ ์ฝ๋
public class MyTest {
public void testBad() {
doSomething(); // no execution of test
}
@Test
public void testGood() {
doSomething();
}
}- ์ค๋ช : JUnit4์์๋ test method์๋ ๋ฐ๋์ @Test annotation์ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S5, P1
- ์์ ์ฝ๋
public class SystemPrivilegesPermissionTest extends BaseTestCase {
private void assertEquivalentPermissions(Permission p1, Permission p2) {
...
assertEquals(p1.hashCode(), p2.hashCode());
assertTrue(p1.implies(p2));
- assertTrue(p1.implies(p2));
+ assertTrue(p2.implies(p1));
}
}- ์ค๋ช : Check both "p1 implies p2" and "p2 implies p1" in assertEquivalentPermissions(), instead of checking "p1 implies p2" twice.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S2, P1
- ์์ ์ฝ๋
pupblic class PredicatesTests extends AbstractQueryTest {
...
public void testEquality() throws RepositoryException {
- String stmt = "/" + jcrRoot + "/*[@" + jcrPrimaryType + "='" + nodeTypeName + "']";
+ String stmt = "/" + jcrRoot + "/" + testPath + "/*[@" + jcrPrimaryType + "='" + nodeTypeName + "']";
try {
qm.createQuery(stmt, Query.XPATH);
...
}
public abstract class Abstract JCRTest extends JUnitTest {
...
/***
* Absolute path to the test root node.
*/
protected String testRoot;
...
protected void setUp throws Exception {
super.setUp();
testRoot = getProperty(RepositoryStub.PROP_TESTROOT);
if (testRoot == null) {
fail("Property '" + RepositoryStub.PROP_TESTROOT + "' is not defined.");
}
...
// cut off '/' to build testPath
testPath = testRoot.substring(1);
...
}
} - ์ค๋ช : xml Query์ ์ฌ์ฉ๋๋ stmt ๋ณ์์ testPath๊ฐ concatenate ๋์ด์ผ ํ๋๋ฐ, PredicateTest class์์ ์ด๋ฅผ ๋๋ฝํ์๋ค. (PredicatesTest does not respect testroot configuration property)
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, S6, P1
- ์์ ์ฝ๋
@Test
public void testBZip2Codec() throws IOException {
...
// check the output to make sure it is what we expected.
// read the gzip file and verify the contents
BZip2Codec bz2Codec = new BZip2Codec();
InputStream bz2in = bz2Codec.createInputStream(new FileInputStream(f
- .getPath()
- + "/sub-foo.bz2"));
+ .getPath() + "/sub-foo.bz2"));
byte[] buf = new byte[1];
StringBuilder output = new StringBuilder();
while ((bz2in.read(buf)) > 0) {
output.append(new String(buf));
}
+ bz2in.close(); // Must close for windows to delete
assertEquals(expected, output.toString());
assertTrue("temp folder successfully deleted", FileUtil.rmr(f));
}- ์ค๋ช : InputStream์ ์์ฑํ ๋ค ํ ์คํธ ์ข ๋ฃ ์ close๋ฅผ ํ์ง ์์ ๊ฒฝ์ฐ์ด๋ค. (windows์์๋ close ๋์ง ์์)
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ :R4, S2, S3, S6, P1
- ์ฝ๋ ์์
public simpleThread(String argv[]) throws Exception {
ij.getPropertyArg(argv);
_connection = ij.startJBMS();
Connection conn = GetConnection();
Statement stmt = conn.createStatement();
...
+ Thread[] threads = {
+ new simpleThread(query,0),
+ new simpleThread(query,10000),
+ new simpleThread(query,10100),
+ new simpleThread(query,20000),
+ };
+
+ for (int i = 0; i < threads.length; i++) {
+ threads[i].join();
}
+
+ _connection.close();
+ _connection = null;
}-
์ค๋ช : ํ ์คํฐ๋ 5-8 ๋ผ์ธ์์ Exception์ด ๋ฐ์๋๋ ๊ฒ์ ๊ธฐ๋ํ๊ณ ์๊ณ , ๋ฐ๊ฒฌ๋์ง ์๋ ๊ฒฝ์ฐ๋ฅผ test fail๋ก ์ ์ํ์๋ค. 10-13 ๋ผ์ธ์ ์๋ก์ด ์ถ๊ฐ๋ ๋ถ๋ถ์ธ๋ฐ, ์ค๋ ๋๋ฅผ ์์ฑํ๊ณ ๋์ join()์ ํธ์ถํ์ง ์์๊ธฐ ๋๋ฌธ์, ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ธฐ๋ ์ ์ ํ ์คํธ๊ฐ ์ข ๋ฃ๋์ด ๋ฒ๋ฆฌ๊ฒ ๋๋ ๊ฒฝ์ฐ์ด๋ค.
-
์ถ์ฒ
30. org.junit.Test ๋ฅผ import ํ๋ java ํ์ผ์ public class ๋ช ์ด Test ๋ก ์์๋์ง ์์
- ๊ตฌ์ฑ ์์ : R1, R3, S1, P4
- public class SliderUtilsTest {
+ public class TestSliderUtils {
...
}- ์ค๋ช : Maven์์ ํ ์คํธ๋ช ์ด Test๋ก ์์ํด์ผ Test Class๋ก ์ธ์ํ๋ค (Default).
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R1, R4, S5, P1
- ์์ ์ฝ๋
/* DERBY-6088 */
try {
insert.setObject( 1, null, ILLEGAL_JDBC_TYPES[ i ] );
+ fail( "setObject() should have failed." );
}
catch (SQLException se) { assertUnimplemented( se ); }
}/* DERBY-3852*/
JDBCDataSource.setBeanProperty(ds, "shutdownDatabase", "shutdown");
try {
ds.getConnection();
+ fail("shutdown should raise exception");
} catch (SQLException sqle) {
assertSQLState("XJ015", sqle);
}-
์ค๋ช : Exception์ ์๋ํ ํ ์คํธ์ผ์ด์ค์์ ์๋ ํ์ง ์์ Exception์ด ๋ฐ์ํ์ง ์์ ๊ฒฝ์ฐ fail()์ด ์์ด์ ํ ์คํธ๊ฐ ํด๋น ๋ถ๋ถ์ ๋์ด๊ฐ๊ฒ ๋๋ค.
-
์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R2, S2, S3, P1
- ์์ ์ฝ๋
- SSLContext sc = SSLContext.getInstance("SSL");
+ SSLContext sc = null;
+ if (System.getProperty("java.vendor").contains("IBM")) {
+ sc = SSLContext.getInstance("SSL_TLS");
+ } else {
+ sc = SSLContext.getInstance("SSL");
+ }- ์ค๋ช : IBM JDK ๋ฒ์ ์ ๋ฐ๋ผ์ "SSL_TLS"๋ฅผ getInstance()์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ผ ํ๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R2, S3, P1
- **์ฝ๋ **
private static void delete(File dir) throws IOException {
- Path p = new Path("file://"+dir.getAbsolutePath());
Configuration conf = new Configuration();
- FileSystem fs = p.getFileSystem(conf);
+ FileSystem fs = FileSystem.getLocal(conf);
+ Path p = fs.makeQualified(new Path(dir.getAbsolutePath()));
fs.delete(p, true);
}-
์ค๋ช : The prior code for path construction fails on Windows due to the drive spec and backslashes. Using FileSystem#makeQualified against the local file system works cross-platform.
-
์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R2, S4, P1
- ์ฝ๋ ์์
public void testDirectoryScanner() throws Exception {
// Run the test with and without parallel scanning
- for (int parallelism = 1; parallelism < 2; parallelism++) {
+ for (int parallelism = 1; parallelism < 3; parallelism++) {
runTest(parallelism);
}
}- ์ค๋ช : for๋ฌธ์์ ์กฐ๊ฑด๋ฌธ์ ์๋ชป ์ ๋ ฅํ์ฌ test๊ฐ ์คํ๋์ง ์์๋ค.
- ์ถ์ฒ
35. ํ์ผ์ ์์ฑํ ๋ค try-catch ๋ธ๋ก ์ดํ finally ๋ธ๋ก์ close()๋ฅผ ํธ์ถํ์ง ์์ ๊ฒฝ์ฐ
-
๊ตฌ์ฑ ์์ : R2, S6, P1
-
์ฝ๋ ์์
public void testSessionGetcontentHandler() throws RepositoryException, IOException, SAXException {
FileInputSstrean in = new FileInputStream(file);
- exportRepository(SAVEBINARY, RECURSE);
- doImportNoSave(treeComparator.targetFoler, in, CONTENTHANDLER);
+ try {
+ exportRepository(SAVEBINARY, RECURSE);
+ doImportNoSave(treeComparator.targetFoler, in, CONTENTHANDLER);
+ } finally {
+ in.close();
+ }-
์ค๋ช : FileInputStream์ ์์ฑํ ๋ค ํ ์คํธ๊ฐ ๋๋๊ธฐ ์ try๋ธ๋ฝ ์์ exception์ด throw๋ ์ ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ดํ, finally ๋ธ๋ก ์์ FileInputStream์ close()๋ฅผ ํธ์ถํ์ง ์์ ๊ฒฝ์ฐ์ด๋ค. ์ด๊ฒฝ์ฐ ํ์ผ์ด ์์ฑ๋ ๋ค์ temporary files created by some jUnit test are not automatically removed
-
์ถ์ฒ
36. Test Suite ์์ ํ๋์ DB ๋ฅผ ์ฌ์ฉํ๊ณ , Sequence ๋ฅผ ์์ฑํ ๋ค Drop ํ์ง ์์ ๊ฒฝ์ฐ
-
๊ตฌ์ฑ ์์ : R3, S2, S5, P2
-
์ค๋ช : โalpha_seqโ ๋ผ๋ sequence๊ฐ ๋ง๋ค์ด์ง๊ณ testCase๊ฐ ์ข ๋ฃ๋๊ธฐ ์ drop ๋์ง ์์, ๋ค์ ํ ์คํธ์ ์คํ์ ์ํฅ์ ๋ฏธ์น๋ค. lang.SequenceTest fails w/ "Seqeunce 'ALPHA_SEQ' already exists." on phoneME/cvm. commit message : Do cleanup in testcases to make the testcases independent of running order.
-
์ฝ๋ ์ค๋ช
public class SequenceTest extends BaseJDBCTestCase {
public static Test suite() {
public void testCreateOtherSchemeSequence() throws SQLExecption {
..
assertStatementError("42507", stmtBeta, "CREATE SEQUENCE alpha.alpha_seq3");
+ // Cleanup:
+ stmtAlpha.executeUpdate("DROP SEQUENCE alpha_seq");
+
stmtAlpha.close();- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R3, S6, P1
- ์ฝ๋ ์ค๋ช
@Test
public void testShortCircuitReadFromServerWithoutShm() throws Exception {
TemporarySocketDirectory sockDir = new TemporarySocketDirectory();
//...
+ sockDir.close();
}-
์ค๋ช : socket์ ์์ฑํ๊ณ close๋ฅผ ํ์ง ์์ ๋ค์ ํ ์คํธ ์คํ ๊ฒฐ๊ณผ์ ์ํฅ์ ๋ฏธ์น ์ ์๋ค.
-
์ถ์ฒ
38. ํ ์คํธ ์คํ ๋์ค ๊ณต์ ๋ณ์์ ๊ฐ์ ์์๋ก ๋ณ๊ฒฝํ ํ ์ด๋ฅผ ์ด๊ธฐ ๊ฐ์ผ๋ก ๋๋๋ฆฌ์ง ์์
- ๊ตฌ์ฑ ์์ : R3, S6, P1, P2
- ์์ ์ฝ๋
@Test
public void testGzipOutputFormat() throws IOException, InterruptedException {
// set the output format.
FlumeConfiguration conf = FlumeConfiguration.get();
conf.set(FlumeConfiguration.COLLECTOR_OUTPUT_FORMAT, "syslog");
conf.set(FlumeConfiguration.COLLECTOR_DFS_COMPRESS_GZIP, "true");
...
}
@Test
public void testDefaultCodec() throws IOException, InterruptedException {
// set the output format.
FlumeConfiguration conf = FlumeConfiguration.get();
conf.set(FlumeConfiguration.COLLECTOR_OUTPUT_FORMAT, "syslog");
conf.set(FlumeConfiguration.COLLECTOR_DFS_COMPRESS_CODEC, "DefaultCodec");
+ conf.set(FlumeConfiguration.COLLECTOR_DFS_COMPRESS_GZIP, "false");
...
} -
์ค๋ช : ์ด์ ํ ์คํธ์์์ ์ค์ ์ด ๋ค์ ํ ์คํธ์์๋ ์ ์ฉ๋์ด ํ ์คํธ ๊ฒฐ๊ณผ๊ฐ ๋ฐ๋๋ ๊ฒฝ์ฐ์ด๋ค.
-
์ถ์ฒ
39. Ant 1.9.3 ์์ ant ๊ฐ test ๊ฒฐ๊ณผ๋ฅผ file ์ ์์ ํ ์ ์๋ ๊ถํ์ ์ค์ ํ์ง ์์
- ๊ตฌ์ฑ ์์ : R3, S7, P4
- ์์ ์ฝ๋
// java/testing/org/apache/derbyTesting/functionTests/util/derby_tests.policy
...
+ // Starting with Ant 1.9.3, write permission has to be granted to ant.jar
+ // as well so that Ant's JUnit runner can write test results to a file.
+ // Only needed when running the tests under Ant. See DERBY-6685.
+ grant codeBase "${derbyTesting.ant}" {
+ permission java.io.FilePermission "${user.dir}${/}*", "write";
+ };
+- ์ค๋ช : Ant 1.9.3 ๋ฒ์ ๋ถํฐ Test result๋ฅผ file์ ์ฐ๊ธฐ ์ํด ant.jar์ write permission์ด ํ์ํด์ก๋๋ฐ ๊ด๋ จ ๊ถํ ์ค์ ์ด ์คํ๋์ง ์์๋ค.
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S1, P4-
- ์์ ์ฝ๋
public static void runTests( final SecurityEvaluator securityEvaluator, final PrefixMapping prefixMapping ) throws Exception
{
...
Method lockTest = null;
for (final Method m : pmTest.getClass().getMethods())
{
if (m.isAnnotationPresent(Test.class))
{
// lock test must come last
if (m.getName().equals("testLock")) { lockTest = m; }
else { pmTest.setup(); m.invoke(pmTest); }
}
}
+ Assert.assertNotNull( "Did not find 'testLock' method", lockTest );
pmTest.setup();
lockTest.invoke(pmTest);
}-
์ค๋ช : ํ ์คํธ๋ฅผ ์คํ์ํค๋ ๋ถ๋ถ์์ ์ค์ ์๋ํ๋๋๋ก ํ ์คํธ๊ฐ ์คํ๋๋์ง ํ์ธํ๋ ์ฝ๋๊ฐ ์ถ๊ฐ๋์ง ์์๋ค.
-
์ถ์ฒ
41. test ๊ฐ ์ถ๊ฐ๋๊ธฐ ์ ์ ํธ์ถ๋์ด์ผ ํ ๋ฉ์๋ leasechecker.interruptAndJoin()์ด ๋๋ฝ๋จ
- ๊ตฌ์ฑ ์์ : R4, S2, P1
- ์์ ์ฝ๋
Index: src/test/hdfs/org/apache/hadoop/hdfs/TestReadWhileWriting.java
===================================================================
--- src/test/hdfs/org/apache/hadoop/hdfs/TestReadWhileWriting.java (revision 889032)
+++ src/test/hdfs/org/apache/hadoop/hdfs/TestReadWhileWriting.java (working copy)
@@ -83,6 +83,8 @@
//b. On another machine M2, open file and verify that the half-block
// of data can be read successfully.
01 @Test
02 public void pipeline_02_03() throws Exception {
03 ...
04 checkFile(p, half, conf);
+ 05 AppendTestUtil.LOG.info("leasechecker.interruptAndJoin()");
+ 06 ((DistributedFileSystem)fs).dfs.leasechecker.interruptAndJoin();
07 //c. On M1, append another half block of data. Close file on M1.
08 {
09 //sleep to let the lease is expired.
10 Thread.sleep(2*LEASE_LIMIT);
11
12 final DistributedFileSystem dfs = (DistributedFileSystem)FileSystem.newInstance(conf);
13 final FSDataOutputStream out = append(dfs, p);
14 write(out, 0, half);
15 out.close();
16 }
-
์ค๋ช : Test๊ฐ ์ถ๊ฐ๋๊ธฐ์ ์ ๋ฐ๋์ ํธ์ถ๋์ด์ผํ ๋ฉ์๋๊ฐ ๋๋ฝ๋์๋ค.
-
์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S2, P1
- ์ค๋ช : ํ ์คํธ ํ๊ฒฝ์ ์ค์ ํ๋ ๋ฉ์๋๋ฅผ ์ฐ์ํด์ ์ค๋ณต ํธ์ถํ์๋ค.
- ์์ ์ฝ๋
c.setInt("hbase.ipc.client.connect.max.retries", 1);
- c.setInt("hbase.ipc.client.connect.max.retries", 1);
c.setInt("dfs.client.block.recovery.retries", 1);- ์ถ์ฒ
43. setup() ์ด๋ teardown()์์ Tree์ child node๋ค์ ์ ๊ฑฐํ์ง ์์ (์ค์ ์ด๊ธฐํ ์ค๋ฅ)
- ๊ตฌ์ฑ ์์ : R4, S2, S6, P2
- ์์ ์ฝ๋
protected Node cleanUpTestRoot(Session s) throws RepositoryException
...
// clean test root
testRootNode = root.getNode(testPath);
for (NodeIterator children = testRootNode.getNodes(); children.hasNext();) {
- children.nextNode().remove();
+ Node child = children.nextNode();
+ NodeDefinition nodeDef = child.getDefinition();
+ if (!nodeDef.isMandatory() && !nodeDef.isProtected()) {
+ child.remove();
+ }
}- ์ค๋ช : ํ ์คํธ ํ๊ฒฝ์ ์ด๊ธฐํํ๋ ๋ฉ์๋์์ ์ ์ ํ ํ๊ฒฝ ์ค์ (children node์ ์ ๊ฑฐ)์ด ์ด๋ฃจ์ด์ง์ง ์์์, ์ค์ ์ ๋์ ์คํ๊ณผ๋ ์๊ด์์ด ํ ์คํธ๊ฐ ์คํจํ๋ค. JCR-505: TCK: AbstractJCRTest fails if setUp/tearDown cannot remove children of test node
- ์ถ์ฒ
- ๊ตฌ์ฑ ์์ : R4, S5, P1
- ์์ ์ฝ๋
public void testGetInvalidJob() throws Exception {
- RunningJob runJob = new JobClient(getJobConf()).getJob(JobID.forName("job_0_0"));
- assertNull(runJob);
+ try {
+ RunningJob runJob = new JobClient(getJobConf()).getJob(JobID.forName("job_0_0"));
+ fail("Exception is expected to thrown ahead!");
+ } catch (Exception e) {
+ assertTrue(e instanceof IOException);
+ assertTrue(e.getMessage().contains("ApplicationNotFoundException"));
+ }
}- ์ค๋ช : ํ ์คํธ ๋์ ์ฝ๋๊ฐ null์ ๋ฆฌํดํ๋ ๊ฒ์์ IOException์ throwํ๋ ๊ฒ์ผ๋ก ๋ณ๊ฒฝ๋์ด Test code๋ ๋ณ๊ฒฝ๋์ด์ผ ํ๋๋ฐ ๋ณ๊ฒฝ๋์ง ์์ Test๊ฐ ์คํจํ๋ค.
- ์ถ์ฒ