PengTory

[Spring] 테스트 본문

Spring

[Spring] 테스트

펭토리 2022. 10. 14. 19:06

애플리케이션은 계속 변하고 복잡해져간다. 그 변화에 대응할 수 있는 첫 번째 전략이 앞서 블로그에 정리한 IoC/DI와 같은 기술이라면, 두 번째 전략은 만들어진 코드를 확신할 수 있게 해주고, 변화에 유연하게 대처할 수 있는 자신감을 주는 테스트 기술이다.

UserDaoTest

지금까지 만들었던 main() 메소드로 작성된 테스트 코드를 살펴보자.

public class UserDaoTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException{
        ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
        
        UserDao dao = context.getBean("userDao", UserDao.class);
        
        User user = new User();
        user.setId("user");
        user.setName("백기선");
        user.setPassword("married");
        
        dao.add(user);
        
        System.out.println(user.getId() + "등록 성공");
        
        User user2 = dao.get(user.getId());
        System.out.println(user2.getName());
        System.out.println(user2.getPassword());
        
        System.out.println(user2.getId() + "조회 성공");
    }
}

자바에서 가장 손쉽게 실행 가능한 main()메소드를 이용해 테스트할 대상인 UserDao의 오브젝트를 가져와 메소드를 호출했다.

테스트에 사용할 입력 값을 직접 코드에 만들어 넣어 테스트 결과를 콘솔에 출력해준다.

 

작은 단위의 테스트

테스트를 한번에 몰아서 하게 되면 테스트 수행 과정도 복잡해지고 오류가 발생했을 때 정확한 원인을 찾기 어려워진다.

이를 해결하기 위해 테스트에도 관심사의 분리 원리를 적용해보자. 테스트의 관심이 다르다면 테스트할 대상을 분리하고 집중해서 접근해야한다. 이렇게 작은 단위의 코드에 대해 테스트를 수행하는 것은 단위 테스트(unit test)라고 한다. 일반적으로 단위는 작을 수록 좋다.

단위테스트를 하는 이유는 개발자가 설계하고 만든 코드가 원래 의도한 대로 동작하는지를 개발자 스스로가 빨리 확인받기 위해서다. 이때 확인과 대상의 조건이 간단하고 명확할 수록 확인이 쉬울 것이다. 그래서 작은 단위로 제한해 테스트하는 것이 편리한 것이다.

 

자동수행 테스트 코드

UserDaoTest의 한 가지 특징은 테스트할 데이터가 코드를 통해 제공되고, 테스트 작업 역시 코드를 통해 자동으로 실행한다는 점이다.

이렇게 테스트는 자동으로 수행되도록 코드로 만들어지는 것이 중요하다. 자동으로 수행되는 테스트이 장점은 자주 반복할 수 있다는 것이다. 번거로운 작업이 없고 테스트를 빠르게 실행할 수 있기 때문에 언제튼 코드를 수정하고 간편하게 테스트를 해볼 수 있다.

 

UserDaoTest의 문제점과 개선

UserDaoTest의 문제점을 찾아보자.

  • 수동 확인 작업의 번거로움: 테스트를 수행하는 과정과 입력 데이터의 준비는 모두 자동으로 만들어졌지만 입력한 값과 가져온 값이 일치하는지를 테스트하기 위해서는 사람이 직접 확인해야한다.
  • 실행 작업의 번거로움: 만약 DAO가 수백개가 되어 main() 메소드도 그만큼 만들어진다면 매우 귀찮은 작업이 된다. 따라서 main()메소드를 사용하는 것 보더 더 편리하고 체계적으로 테스트를 실행하며 그 결과를 확인하는 방법이 필요하다.

첫번째 문제점인 수동 확인 작업의 번거로움을 해결해보자.

public class UserDaoTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException{
        ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");

        UserDao dao = context.getBean("userDao", UserDao.class);

        User user = new User();
        user.setId("user");
        user.setName("백기선");
        user.setPassword("married");

        dao.add(user);

        System.out.println(user.getId() + "등록 성공");

        User user2 = dao.get(user.getId());
        if(!user.getPassword().equals(user2.getName())){
            System.out.println("테스트 실패(name)");
        }
        else if(!user.getPassword().equals(user2.getPassword())){
            System.out.println("테스트 실패 (password)");
        }else{
            System.out.println("조회 테스트 성공!");
        }
    }
}

위 처럼 코드를 수정하면 사람이 데이터 값의 일치 여부를 직접 확인할 필요가 없다. 이렇게 해서 테스트의 수행과 테스트 값 적용, 그리고 결과를 검증하는 것까지 모두 자동화했다.

 

JUnit 테스트로 전환

지금까지 만들었던 main() 메소드 테스트를 JUnit을 이용해 다시 작성해보겠다. 

JUnit은 자바로 단위 테스트를 만들 때 유용하게 쓸수 있는 프레임워크다. 프레임워크에서 동작하는 코드는 main() 메소드도 필요 없고 오브젝트를 만들어서 실행시키는 코드를 만들 필요도 없다. 

JUnit 프레임워크가 요구하는 조건은 두가지가 있는데 첫째는 메소드가 public으로 선언돼야하는 것이고, 다른 하나는 메소드에 @Test라는 애노테이션을 붙여주는 것이다.

public class UserDaoTest {
    @Test
    public void addAndGet() throws SQLException{
        ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");

        UserDao dao = context.getBean("userDao", UserDao.class);

        User user = new User();
        user.setId("user");
        user.setName("백기선");
        user.setPassword("married");

        dao.add(user);

        User user2 = dao.get(user.getId());
        
        assertThat(user2.getName(), is(user.getName()));
        assertThat(user2.getPassword(), is(user.getPassword()));
    }
}

asserThat() 메소드는 첫 번째 파라미터의 값을 뒤에 나오는 매처라고 불리는 조건으로 비교해서 일치하면 다음으로 넘어가고, 아니면 테스트가 실패하도록 만들어준다.

가장 좋은 JUnit 테스트 실행 방법은 자바 IDE에 내장된 JUnit테스트 지원 도구를 사용하는 것이다.

 

테스트 결과의 일관성

지금까지 테스트를 실행할때 매번 UserDaoTest 테스트를 실행하기 전에 DB의 USER 테이블 데이터를 모두 삭제해줘야 했다. 왜냐하면 이전 테스트를 실행했을 때 등록됐던 사용자 정보와 기본키가 중복된다면 add() 메소드 실행 중 에러가 발생하기 때문이다.

일관성 있는 결과를 보장하기 위해 UserDao에 deleteAll()과 getCount()를 추가해보자.

  • deleteAll(): USER 테이블의 모든 레코드를 삭제해주는 간단한 기능이다.
public void deleteAll() throws SQLException{
    Connection c = dataSource.getConnection();

    PreparedStatement ps = c.prepareStatement("delete from users");
    ps.executeUpdate();
    
    ps.close();
    c.close();
}
  • getCount(): USER 테이블의 레코드 개수를 돌려준다.
public int getCount() throws SQLException{
    Connection c = dataSource.getConnection();

    PreparedStatement ps = c.prepareStatement("select count(*) from users");

    ResultSet rs = ps.executeQuery();
    rs.next();
    int count = rs.getInt(1);
    
    rs.close();
    ps.close();
    c.close();
    
    return count;
}

addAndGet()테스트에 deleteAll()과 getCount()를 추가하자.

public void addAndGet() throws SQLException{
    ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");

    UserDao dao = context.getBean("userDao", UserDao.class);
    dao.deleteAll();
    assertThat(dao.getCount(), is(0));

    User user = new User();
    user.setId("user");
    user.setName("백기선");
    user.setPassword("married");

    dao.add(user);
    assertThat(dao.getCount(), is(1));

    User user2 = dao.get(user.getId());

    assertThat(user2.getName(), is(user.getName()));
    assertThat(user2.getPassword(), is(user.getPassword()));
}

이전에는 테스트를 하기 전 매번 DB에서 데이터를 삭제해야 했지만 이제는 그러한 과정이 필요없어졌다.

테스트가 어떤 상황에서 반복적으로 실행된다 하더라도 동일한 결과가 나올 수 있게 된 것이다.

하지만 두 개이상의 레코드를 add() 했을 때 get Count()의 실행 결과가 어떻게 될지는 아직 확신할 수 없다. 조금 더 꼼꼼한 테스트를 만들어보자.

public User(String id, string name, String password){
    this.id = id;
    this.name = name;
    this.password = password;
}
public User(){
}

파라미터가 있는 User 클래스 생성자를 만들면 addAndGet() 테스트의 코드도 아래와 같이 간략히 수정할 수 있다.

UserDao dao = context.getBean("userDao", UserDao.class);
User user = new User("gyumee", "박상철", "springno1");

 

get() 예외조건에 대한 테스트

한 가지 더 생각해볼 문제가 있다. get() 메소드에 전달된 id 값에 해당하는 사용자 정보가 없을 수도 있다. 주어진 id에 해당하는 정보가 없다는 의미를 가진 예외 클래스가 하나 필요하다.  JUnit의 예외 테스트 기능을 이용하면 아래와 같이 테스트를 만들 수 있다.

@Test(expected = EmptyResultDataAccessException.class)
public void getUserFailure() throws SQLException{
    ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");

    UserDao dao = context.getBean("userDao", UserDao.class);
    dao.deleteAll();
    assertThat(dao.getCount(), is(0));
    
    dao.get("unkown_id");
}

 

@Test에 expected를 추가해놓으면 보통의 테스트와 반대로 정상적인 테스트 메소드를 마치면 테스트가 실패하고, expected에서 지정한 예외가 던져지만 테스트가 성공한다. 하지만 아직 UserDao 코드에는 손을 대지 않았기 때문에 실패할 것이다.

public User get(String id) throws SQLException{
    //..
    ResultSet rs = ps.executeQuery();
    
    User user = null;
    if(rs.next()){
        user = new User();
        user.setId(rs.getString("id"));
        user.setName(rs.getString("name"));
        user.setPassword(rs.getString("password"));
    }
    rs.close();
    ps.close();
    c.close();
    
    if(user == null) throws new EmpthResultDataAccessException(1);
    
    return user;
}

위와 같이 수정해서 테스트를 다시 실행하면 성공할 것이다.

 

테스트 주도 개발

만들고자 하는 기능의 내용을 담고 있으면서 만들어진 코드를 검증도 해줄 수 있도록 테스트 코드를 먼저 만들고, 테스트를 성공하게 해주는 코드를 작성하는 방식을 테스트 주도 개발(TDD)라고 한다. 또는 테스트를 코드보다 먼저 작성한다고 해서 테스트우선개발(TDD)라고도 한다. TDD를 하면 자연스럽게 단위 테스트를 만들 있다. 빠르게 자동으로 실행할 수 있는 단위 테스트가 아니고서는 이런 식의 개발이 불가능하기 때문이다.  TDD의 장점 중 하나는 코드를 만들어 테스트를 실행하는 그 사이의 간격이 매우 짧다는 점이다. 개발한 코드의 오류는 빨리 발견할 수록 좋다.

 

테스트 코드 개선

JUnit이 하나의 테스트 클래스를 가져와 테스트를 수행하는 방식은 아래 단계를 따른다.

1. 테스트 클래스에서 @Test가 붙은 public이고 void형이며 파라미터가 없는 테스트 메소드를 모두 찾는다.

2. 테스트 클래스의 오브젝트를 하나 만든다.

3. @Before가 붙은 메소드가 있으면 실행한다.

4. @Test가 붙은 메소드를 하나 호출하고 테스트 결과를 저장해둔다.

5. @After가 붙은 메소드가 있으면 실행한다.

6. 나머지 테스트 메소드에 대해 2~5번을 반복한다.

7. 모든 테스트의 결과를 종합해서 돌려준다.

 

JUnitdml 테스트 메소드 실행 방법

픽스처

테스트를 수행하는데 필요한 정보나 오브젝트를 픽스처 라고 한다. 일반적으로 픽스처는 여러 테스트에서 반복적으로 사용되기 때문에 @Before 메소드를 이용해 생서해두면 편하다.

User 픽스처를 적용한 UserDaoTest는 다음과 같다.

public class UserDaoTest {
    private UserDao dao;
    private User user1;
    private User user2;
    private User user3;

    @Before
    public void setUp() {
        // ...
        this.user1 = new User("gyumee", "박상철", "springno01");
        this.user2 = new User("leegw700", "이길원", "springno02");
        this.user3 = new User("bumjin", "박범진", "springno03");
    }

}

 

테스트를 위한 애플리케이션 컨텍스트 관리

스프링은 JUnit을 이용하는 테스트 컨텍스트 프레임워크를 제공한다. 테스트 컨텍스트의 지원을 받으면 간단한 애노테이션 설정만으로 테스트에서 필요로하는 애플리케이션 컨텍스트를 만들어서 모든 테스트가 공유하게 할수 있다. UserDaoTest에 스프링 텍스트 컨텍스트 프레임워크를 적용해보자.

@RunWith(SpringJUit4ClassRunner.class)
@ContextConfiguration(locatons="/applicationContext.xml")
public class UserDaoTest {
    @Autowired
    private ApplicationContext context;

    @Before
    public void setUp() {
        this.dao = this.context.getBean("userDao", UserDao.class);

    }

}

@RunWith는 프레임워크의 테스트 실행 방법을 확장할 때사용하는 애노테이션이다.

SpringJUnit4ClassRunner라는 JUnit용 테스트 컨텍스트 프레임워크 확장 클래스를 지정해주면 JUnit이 테스트를 진행하는 중에 테스트가 애플리케이션 컨텍스트를 만들고 관리하는 작업을 진행해준다.

@ContextConfiguration은 자동으로 만들어줄 애플리케이션 컨텍스트의 설정파일 위치를 지정한 것이다.

 

테스트 클래스의 컨텍스트 공유

스프링 테스트 컨텍스트 프레임워크의 기능은 하나의 테스트 클래스 안에서 애플리케이션 컨텍스트를 공유해주는 것이 전부가 아니다. 여러개의 테스트 클래스가 있는데 모두 같은 설정파일을 가진 애플리케이션 컨텍스트를 사용한다면, 스프링은 태스트 래스 사이에서도 애플라케이션 컨텍스트를 공유하게 해준다.

따라서 수백 개의 태스트 클래스를 만들었는데 모두 같은 설정파일을 사용한다고 테스트 전체에 걸쳐 단 한 개의 애플리케이션 컨텍스트만 만들어져 시용된다.

public class UserDaoTest {
    @Autowired
    UserDao dao;

위 코드는 UserDao를 직접 DI 받도록 만든 테스트이다.

@Autowired가 붙은 인스턴스 변수가 있다면 테스트 컨텍스트 프레임워크는 변수 타입과 일치하는 컨텍스트 내 빈을 찾는다. 타입이 일치하는 빈이 있으면 인스턴스 변수를 주입해준다. 따라서 클래스 타입은 물론이고 앞 블로그에서 포스팅한 인터페이스인 DataSource타입으로 변수를 선언해도 된다.

단, @Autowired는 같은 타입의 빈이 이상 있는 경우에는 타입만으로는 어떤 빈을 가져올지 결정할 수 없다.

 

테스트는 필요하다면 얼마든지 애플리케이션 클래스와 밀접한 관계를 맺고 있어도 상관없다. 하지만 꼭 필요하지 않다면 테스트에서도 가능한 인터페이스를 사용해 애플리케이션 코드와 느슨하게 연결해두는 편이 좋다.

DI와 테스트

1) 테스트 코드에 의한 DI

DI는 테스트 코드 내에서 직접 할 수 도 있다. UserDao가 사용할 DataSource 오브젝트를 테스트 코드에서 변경할 수 잇다는 뜻이다.

@DirtiesContext
public class UserDaoTest {
    @Autowired
    UserDao dao;

    @Before
    public void setUp() {  
        // ...
        DataSource dataSource = new SingleConnectionDataSource(
                "jdbc:mysql://localhost/testdb", "spring", "book", true
        );
        dao.setDataSource(dataSource);
    }

테스트를 위한 수동 DI를 적용한 UserDaoTest이다.

이 방법의 장점은 XML 설정파일을 수정하지 않고도 테스트 코드를 통해 오브젝트 관계를 재구성할 수 있다는 것이다.

하지만 애플리케이션 컨텍스트에서 applicationContext.xml 파일의 설정 정보를 따라 구성한 오브젝트를 가져와 의존관계를 강제로 변경했기 때문에 매우 주의해서 사용해야 하며 별로 바람직하지 않다.

그래서 @DirtiesContext라는 애노테이션을 추가한 것이다. 이 애노테이션은 스프링의 테스트 컨텍스트 프레임워크에게 해당 클래스의 테스트에서 애플리케이션 컨텍스트의 상태를 변경한다는 것을 알려준다. 이 애노테이션이 붙은 테스트 클래스에는 애플리케이션 컨텍스트 공유를 허용하지 않는다. @DirtiesContext를 이용하면 일단은 문제를 해결할 수 있다. 하지만 이러한 이유로 애플리케이션 컨텍스트를 매번 만드는 것은 좋지 않다.

 

2) 테스트를 위한 별도의 DI 설정

테스트 코드에서 빈 오브젝트에 수동으로 DI 하는 방법은 장점보다 단점이 많다.

이 방법 외에 DI의 장점을 살려서 DAO가 테스트에서만 다른 DataSource를 사용할 수 있게 하는 방법이 있다.

아예 테스트에서 사용될 DataSource 클래스가 빈으로 정의된 테스트 전용 설정파일을 따로 만들어두는 방법을 이용해도 된다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/test-applicationContext.xml")
public class UserDaoTest{
    
}

 위 처럼 다른 테스트용 설정 파일을 적용하면 된다.

 

3) 컨테이너 없는 DI 테스트

DI를 테스트에 이용하는 마지막 방법은 아예 스프링 컨테이너를 사용하지 않고 테스트를 만드는 것이다.

원한다면 스프링 컨테이너를 이용해 IoC 방식으로 생성되고 DI되도록 하는 대신, 테스트 코드에서 직접 오브젝트를 만들고 DI 해서 사용해도 된다.

public class UserDaoTest {
    @Autowired
    UserDao dao;

    @Before
    public void setUp() {
        // ...
        dao = new UserDao();
        DataSource dataSource = new SingleConnectionDataSource(
                "jdbc:mysql://localhost/testdb", "spring", "book", true
        );
        dao.setDataSource(dataSource);
    }

스프링 컨테이너 없이 테스트 코드의 수동 DI만을 이용해 만들어진 테스트 코드이다.

@RunWith를 사용해서 스프링 테스트 컨텍스트 프레임워크를 적용하지도 않았고, @Autowired를 사용해서 애플리케이션 컨텍스트에서 UserDao를 가져오지도 않았다. 대신 @Before 메소드에서 직접 UserDao의 오브젝트를 생성하고 테스트용 DataSource 오브젝트를 만들어 직접 DI 해주었다.

 

DI를 이용한 테스트 방법 선택

그렇다면 DI를 테스트에 이용하는 1), 2), 3), 세가지 방법 중 어떤 것을 선택해야 할까?

항상 스프링 컨테이너 없이 테스트할 수 있는 방법을 가장 우선으로 고려하자. 이 방법이 테스트 수행 속도가 가장 빠르고 테스트 자체가 간결하다. 테스트를 위해 필요한 오브젝트의 생성과 초기화가 단순하다면 이 방법을 가장 먼저 고려하자.

여러 오브젝트와 복잡한 의존관계를 갖고 있는 오브젝트를 테스트할 경우가 있다. 이때는 스프링의 설정을 이용한 DI 방식의 테스트를 이용하면 편리하다. 테스트에서 애플리케이션 컨텍스트를 사용하는 경우에는 테스트 전용 설정파일을 따로 만들어 사용하는 편이 좋다. 

테스트 설정을 따로 만들었다고 하더라도 때로는 예외적인 의존관계를 강제로 구성해서 테스트해야 할 경우가 있다. 이때는 컨텍스트에서 DI 받은 오브젝트에 다시 테스트 코드로 수동 DI 해서 테스트하는 방법을 사용하면 된다.

 

학습 테스트로 배우는 스프링

자신이 만들지 않은 프레임워크나 다른 개발팀에서 만들어서 제공한 라이브러리 등에 대해서도 테스트를 작성해야한다. 이런 테스트를 학습테스트 라고 한다. 학습테스트의 목적은 자신이 사용할 API나 프레임워크의 기능을 테스트로 보면서 사용 방법을 익히려는 것이다.

 

학습 테스트의 장점

  • 다양한 조건에 따른 기능을 손쉽게 확인해볼 수 있다.
  • 학습 테스트 보드를 개발 중에 참고할 수 있다.
  • 프레임워크나 제품을 업그레이드할 때 호환성 검증을 도와준다.
  • 테스트 작성에 대한 좋은 훈련이 된다.
  • 새로운 기술을 공부하는 과정이 즐거워진다.

학습 테스트 예제

JUnit 테스트 오브젝트 테스트

public class JUnitTest{
    static JUnitTest testObject;
    
    @Test public void test1(){
        assertThat(this, is(not(sameInstance(testObject)));
        testObject = this;
    }

    @Test public void test2(){
        assertThat(this, is(not(sameInstance(testObject)));
        testObject = this;
    }

    @Test public void test3(){
        assertThat(this, is(not(sameInstance(testObject)));
        testObject = this;
    }
}

이 방식으로는 직전 테스트에서 만들어진 테스트 오브젝트와만 비교한다는 단점이 있다. 만약 첫 번째와 세 번째 테스트 오브젝트가 같은 경우에는 검증이 안된다. 세개의 테스트 오븢게트 중 어떤 것도 중복이 되지 않는다는 것을 확인하도록 검증 방법을 바꿔보자.

 

public class JUnitTest{
    static Set<JUnitTest> testObjects = new HashSet<JUnitTest>();

    @Test public void test1(){
        assertThat(this, is(not(sameInstance(testObject)));
        testObject = this;
    }

    @Test public void test2(){
        assertThat(this, is(not(sameInstance(testObject)));
        testObject = this;
    }

    @Test public void test3(){
        assertThat(this, is(not(sameInstance(testObject)));
        testObject = this;
    }
}

스태틱 변수로 테스트 오브젝트를 저장할 수 있는 컬렉션을 만들었다. 테스트마다 현재 테스트 오브젝트가 컬렉션에 이미 등록되어 있는지 확인하고, 없으면 자기 자신을 추가하며 이 과정을 반복한다.

 

스프링 테스트 컨텍스트 테스트

이번에는 스프링 테스트 컨엑스트 프레임워크에 대한 학습 테스트를 만들어보자. JUnit과 반대로 스프링의 테스트용 애플리케이션 컨텍스트는 테스트 개수에 상관없이 한 개만 만들어진다.

JUnitTest 같은 패키지 안에 다음과 같은 설정파일을 생성한다.

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.spingframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.spingframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

이제 앞에서 만들었던 JUnitTest에 @RunWith와 @ContextConfiguration 애노테이션을 추가하고 방금 만든 설정 파일을 사용하는 테스트 컨텍스트를 적용한다. 그리고 @Autowired로 주입된 context 변수가 같은 오브젝트인지 확인하는 코드를 추가한다. 코드는 다음과 같다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class JUnitTest{
    @Autowired ApplicationContext context;
    
    static Set<JUnitTest> testObjects = new HashSet<JUnitTest>();
    static ApplicationContext contextObject = null;
    
    @Test public void test1(){
        assertThat(this, is(not(hasItem(this)));
        testObject.add(this);
        
        assertThat(contextObject == null || contextObject == this.context, is(true));
        contextObject = this.context;
    }

    @Test public void test2(){
        assertThat(this, is(not(hasItem(this)));
        testObject.add(this);

        assertThat(contextObject == null || contextObject == this.context, is(true));
        contextObject = this.context;
    }

    @Test public void test3(){
        assertThat(this, is(not(hasItem(this)));
        testObject.add(this);

        assertThat(contextObject == null || contextObject == this.context, is(true));
        contextObject = this.context;
    }
}

 

버그 테스트

버그 테스트란 코드에 오류가 있을 때 그 오류를 가장 잘 드러낼 수 있는 테스트를 말한다.

버그 테스트는 일단 실패하도록 만들어야한다. 그리고 나서 버그 테스트가 성공할 수 있도록 애플리케이션 코드를 수정한다. 테스트가 성공하면 버그는 해결된 것이다.

버그 테스트의 필요성과 장점은 다음과 같다.

  • 테스트의 완성도를 높여준다.
  • 버그의 내용을 명확하게 분석하게 해준다.
  • 기술적인 문제를 해결하는 데 도움이 된다.

 

 

[참고자료] 토비의 스프링 3.1 Vol.1 스프링의 이해와 원리