소프트웨어 개발 안에서 테스트를 (with JUnit)

Written by kwSeo

#테스트 소프트웨어 개발에서 테스트에 대한 생각을 정리해보았다. 경험한 테스트에 얽힌 이야기와 테스트 중요성을 강조하고 테스트하는 방법들을 간단히 소개한다.

#테스트를 하자 테스트란 말은 IT 개발자로 살면서 가장 많이 듣는 말일 것이다. 소프트웨어를 개발하였으면 제대로 작동하는지 테스트를 해야되며, 논문을 쓰더라도 그 연구 결과를 증명할 테스트가 필요하다. 당장 학교를 다니면서 강의 과제로 소프트웨어를 개발해서 제출해야 할 때도 수도 없이 많은 테스트를 할 것이다. 테스트를 통과해야지 제대로 독작하는 소프트웨어라고 말할 수 있을테니까. 그런데 간혹, 아니 학교에서는 자주 테스트를 하지 않는 학생 개발자가 많이 존재한다. 실제 실무에서도 그런 개발자가 많은지는 잘모르겠다. 아직 학생이나보니… 어쨋든 같이 프로젝트를 진행하다보면 테스트를 하지 않는 사람이 있다. 함께 한 프로젝트를 같이 개발할 때 자신이 개발한 소스코드가 제대로 동작하는지 테스트도 안해보고 그냥 주는 것이다. ‘커밋 했으니 확인부탁해~’, 변경된 코드를 실행하면 어김없이 에러가 발생하는 경우가 많다. (본인이 팀으로 진행했던 프로젝트에서는 심지어 신텍스 에러로 인해 컴파일도 안되는데 완성했다고 하는 경우도 있었다) 이러면 결국 방법은 두 가지이다. 내가 직접 고치고나, 그 코드를 작성한 당사자에게 연락해서 코쳐달라고 말하거나. 어느쪽이든 시간을 잡아먹는 작업이다.

소프트웨어를 개발할때 테스트는 절대로 빠져서는 안되는 작업이다. 소프트웨어의 견고함과 완성도는 테스트에서 결정이 난다고해도 과언이 아니다. 소프트웨어 자체를 테스트하든, 기능을 테스트하든, UI를 테스트하든, 자신이 개발한 모듈을 테스트하든, 할 수 있는 모든 테스트는 수행되어야하며 버그가 발견된다면 당연히 고쳐야한다. 그런데 간혹 테스트를 하지 않는 이유로 시간문제를 말하는 사람이 있다. 정말 시간이 부족하면 테스트를 수행하지 것이 비효율적인 것일까? 위 단락 마지막에서 언급한 내용이 있다. 구현된 기능(또는 모듈, 클래스 등등…)을 실행한다. 에러가 발생한다. 에러를 고치기 위한 행동에 들어간다. 내가 직접 고치거나, 그 코드를 작성한 당사자에게 연락하거나… 어느쪽이든 시간을 잡아먹는다! 과연 테스트르 수행하는 것이 시간이 덜 들까? 아니면 나중에 발견된 에러를 고치는데 시간이 더 들까?

#테스트를 어떻게 하지? 테스트를 수행하면 버그를 조기에 밸견하여 수정할 수 있고, 해당 모듈이 정상 동작한다는 것을 보일 수 있으며, 소프트웨어의 품질 상승과 함께 같이 일하는 다른 동료들도 편해진다. 그렇다면 테스트를 어떻게 수행해야 할까? 가장 간단하고 기초적인 방법은 main메서드를 통해 테스트하는 것이다. 처음에는 이게 제일 편하다. 직접 구현한 모듈을 main메서드를 통해 실행해보고 결과를 확인한다. 하나 하나 눈으로. 그런데 테스트가 많아진다면? 수천개의 결과값드을 눈으로 확인해야한다면? 물론 똑똑한 사람은 따로 검증기를 만들어서 사용할 수도 있을 것이다. 그래도 테스트 종류가 많아질 경우의 문제를 해결하지는 못한다. main메서드는 한번에 하나만 실행할 수 있다. 또한 중간에 소스코드가 변경되었다면 변경된 사항에 문제는 없는지 다시 모든 테스트를 일일이 수행해야 할 것이다. 그런데 더 똑똑한 사람이 이 문제도 해결했다. Java에는 테스트를 위한 아주 유명한 도구가 존재한다. 이 도구를 사용하면 어떤 종류의 테스트라도 수행할 수 있으며, 테스트는 모두 독립적으로 수행되어 꼬일 걱정도 없고, 모든 테스트를 모두 한꺼번에 수행할 수도 있다. 그 도구의 이름은 JUnit이다.

##JUnit으로 테스트하기 JUnit은 단위 테스트, 통합 테스트, 시스템 테스트, UI 테스트 등 모든 수준의 테스트를 해볼 수 있는 가단한 인터페이스를 제공한다. JUnit으로 테스트하기는 정말 간단하다. 처음하는 사람이라도 처음 main메서드를 통해서 ‘Hello World’를 출력하는 것보다 더 간단하다. 테스트를 수행하는 코드를 가지고 있는 메서드에 @Test라는 어노테이션을 추가하면 된다!(사실 이것외에도 더 다양한 기능이 있지만 일단 핵심부터)

public class SampleTest {
	@Test
	public void testThis(){
		//testing code...
	}
}

정말 간단하다. 작성 후에 만일 이클립스를 사용한다면 테스트 실행도 아주 간단하게 할 수 있다. JUnit은 IDE와도 아주 조화롭게 융합되어 있기 때문이다. 테스트하고자하는 클래스코드에서 Run을 눌러도 되고, 클래스나 프로젝트에서 오른쪽 마우스 클릭 -> Run As -> JUnit Test를 통해 테스트를 수행할 수도 있다. 이때 클래스에서 테스트룰 수행하면 해당 테스트 클래스(테스크 캐이스)에 속한 테스트만 수행되며, 프로젝트를 선택하고 테스트를 수행하면 프로젝트 내의 모든 테스트가 수행된다. 그리고 결과값들을 테스트하기 위한 정적 메서드도 제공한다. 대표젹으로 아래와 같은 것들이 있다.

위 메서드들은 비교할 개체만을 받는 메서드와 개체와 오류메시지를 받는 메서드가 각각 오버로딩되어 존재한다.

assertTrue(a > 10);
assertTrue("a는 10보다 커야 합니다.", a > 10);

JUnit은 여러 빌드툴에도 포함되어 있기 때문에 Maven이나 Gradle, Ant 등의 빌드툴을 통해서도 테스트할 수 있으며, 빌드시에도 자동으로 테스트를 수행한다.(따로 옵션을 주어서 테스트를 수행하지 않을 수도 있다) 이러한 간단한 도구 덕분에 간단하게 테스트를 수행할 수 있으며 여러 테스트를 동시에 수행할 수도 있고 통합테스트도 빠르게 수행하여 간단한 결과화면을 통해 수행결과를 확인할 수 있다. 또한 중간에 몇몇 소스코드가 변경되면 다른 문제가 발생하지는 않는지 여러 테스트를 한꺼번에 수행할 수도 있다. 정말 유용하고, 편리하고, 효율적인 도구인 것이다.

#’테스트 가능한’ 코드 사실 테스트는 개발 프로세스의 시작 단계부터 고려하는 것이 좋다. 그래야 전체적으로 테스트하기 더 유용해지며, ‘테스트 가능한’ 코드를 작성하기 좋다. 좋은 소프트웨어는 하나의 소프트웨어로서 테스트가 가능해야하며, 세분화하여 각 구성요소 별로도 테스트가 가능해야한다. 그리고 모듈들은 높은 응집력과 약한 결합력(high cohesion loose coupling)을 가져야지 테스트하기 더 유용한다. 즉 각 모듈들을 테스트가 가능해야한다.

#TDD 아예 테스트에 핵심을 둔 TDD(Test-Driven Development)라는 개발 방법론이 존재한다. TDD는 테스트코드부터 작성하고 개발에 들어가는 방법론이다. 개발 절차는 다음과 같다.

  1. 개발하고자하는 모듈(기능, 인터페이스, 클래스 등등)을 테스트하는 코드를 작성한다. 물론 아직 해당 모듈의 코드를 작성하지 않은 상태이기 때문에 테스트는 실패한다.
  2. 앞에서 정의한 테스트가 통과되도록 코드를 작성한다.
  3. 테스트가 통과한다면, 다음 모듈 개발을 1번부터 다시 수행한다. 모든 모듈을 완료했다면 4번으로 간다.
  4. 코드 작성을 완료한 뒤, 모든 테스트가 통과되는지 확인한다. (예로 들어 통합테스트)

#테스트를 꼭하자 JUnit은 위에서 설명한 기능 외에도 강락한 다양한 기능을 제공한다. JUnit은 모든 유형의 테스트를 수행할 수 있고, 각 테스트는 독립적이며, 생명주기를 통해 원하는 테스트 준비, 수행시간을 제한할 수 있으며, 예외를 예상할 수 있고, 임의의 샘플 데이터 생성할 수 있는 등 매우 간단하지만 강력한 도구이다. 앞으로 Java언어를 사용할 것이라면 JUnit과 같은 테스트도구는 반드시 숙지해야할 필요가 있을 것이다. 테스트는 소프트웨어의 품질을 향상시킬 수 있는 가장 간단하고 효율적인 방법이며, 협업시에는 꼭 지켜야할 매너이다. 자신이 만든 모듈이 제대로 실행되는지 확인도 안하고 건내주는 일은 절대 없어야한다. 또한 테스트 코드를 작성해두면 나중에 자신의 개발 내역을 다른 사람에게 인수인계하기도 좋으며, 또 다른 사람이 자신이 개발한 내용 및 모듈 사용법을 파악하기도 편하다. 테스트는 가장 기본적인 매너이며, 소프트웨어 개발에 가장 중요한 요소이다.

Done At: Sep 2,2015
Categories: