이렇게 선언 할 때 클래스 필드를 초기화해야합니까?
public class SomeTest extends TestCase
{
private final List list = new ArrayList();
public void testPopulateList()
{
// Add stuff to the list
// Assert the list contains what I expect
}
}
아니면 이와 같은 setUp ()에서?
public class SomeTest extends TestCase
{
private List list;
@Override
protected void setUp() throws Exception
{
super.setUp();
this.list = new ArrayList();
}
public void testPopulateList()
{
// Add stuff to the list
// Assert the list contains what I expect
}
}
더 간결하고 최종 필드를 사용할 수 있기 때문에 첫 번째 형식을 사용하는 경향이 있습니다. 설정 을 위해 setUp () 메서드를 사용할 필요 가없는 경우 에도 여전히 사용해야하며 그 이유는 무엇입니까?
설명 :
JUnit은 테스트 메서드 당 한 번씩 테스트 클래스를 인스턴스화합니다. 즉 list
, 내가 선언 한 위치에 관계없이 테스트 당 한 번 생성됩니다. 또한 테스트간에 시간적 종속성이 없음을 의미합니다. 따라서 setUp ()을 사용하는 데 이점이없는 것 같습니다. 그러나 JUnit FAQ에는 setUp ()에서 빈 컬렉션을 초기화하는 많은 예제가 있으므로 이유가 있다고 생각합니다.
답변
기본 테스트 템플릿 과 같은 JUnit FAQ의 예제에 대해 구체적으로 궁금하다면 테스트 중인 클래스가 setUp 메서드 (또는 테스트 메서드)에서 인스턴스화되어야한다는 것이 모범 사례라고 생각합니다. .
JUnit 예제가 setUp 메서드에서 ArrayList를 만들면 모두 testIndexOutOfBoundException, testEmptyCollection 등과 같은 경우를 사용하여 해당 ArrayList의 동작을 테스트합니다. 누군가가 수업을 작성하고 제대로 작동하는지 확인하는 관점입니다.
자신의 클래스를 테스트 할 때도 동일한 작업을 수행해야합니다. setUp 또는 테스트 메서드에서 개체를 만들어 나중에 중단 할 경우 적절한 출력을 얻을 수 있습니다.
반면에 테스트 코드에서 Java 컬렉션 클래스 (또는 다른 라이브러리 클래스)를 사용하는 경우 테스트를 원하기 때문이 아니라 테스트 픽스처의 일부일뿐입니다. 이 경우 의도 한대로 작동한다고 안전하게 가정 할 수 있으므로 선언에서 초기화해도 문제가되지 않습니다.
그만한 가치를 위해, 저는 상당히 크고 몇 년 된 TDD 개발 코드베이스를 작업합니다. 우리는 습관적으로 테스트 코드의 선언에있는 것들을 초기화하는데, 제가이 프로젝트에 참여한 지 1 년 반 동안 문제가 발생하지 않았습니다. 그래서 이것이 합리적이라는 증거가 적어도 몇 가지 있습니다.
답변
나는 스스로 파헤 치기 시작했고 setUp()
. 실행 중에 예외가 발생 setUp()
하면 JUnit은 매우 유용한 스택 추적을 인쇄합니다. 반면에 객체 생성 중에 예외가 발생하면 오류 메시지는 JUnit이 테스트 케이스를 인스턴스화 할 수없고 실패가 발생한 행 번호를 볼 수 없다는 메시지를 표시합니다. 아마도 JUnit이 리플렉션을 사용하여 테스트를 인스턴스화하기 때문일 것입니다. 클래스.
이것은 결코 던지지 않을 것이기 때문에 빈 컬렉션을 만드는 예제에는 적용되지 않지만 setUp()
메서드 의 장점입니다 .
답변
Alex B의 답변 외에도.
특정 상태에서 리소스를 인스턴스화하려면 setUp 메서드를 사용해야합니다. 생성자에서이 작업을 수행하는 것은 타이밍 문제 일뿐만 아니라 JUnit이 테스트를 실행하는 방식으로 인해 각 테스트 상태는 하나를 실행 한 후 지워집니다.
JUnit은 먼저 각 테스트 메서드에 대한 testClass의 인스턴스를 만들고 각 인스턴스가 생성 된 후 테스트 실행을 시작합니다. 테스트 방법을 실행하기 전에 설정 방법을 실행하여 일부 상태를 준비 할 수 있습니다.
데이터베이스 상태가 생성자에서 생성되는 경우 모든 인스턴스는 각 테스트를 실행하기 전에 서로 바로 db 상태를 인스턴스화합니다. 두 번째 테스트에서 테스트는 더티 상태로 실행됩니다.
JUnits 라이프 사이클 :
- 각 테스트 메서드에 대해 다른 테스트 클래스 인스턴스를 만듭니다.
- 각 testclass 인스턴스에 대해 반복합니다. 설정 호출 + testmethod 호출
두 가지 테스트 방법으로 테스트에서 일부 로깅을 사용하면 다음과 같은 결과를 얻을 수 있습니다. (숫자는 해시 코드입니다.)
- 새 인스턴스 생성 : 5718203
- 새 인스턴스 생성 : 5947506
- 설정 : 5718203
- TestOne : 5718203
- 설정 : 5947506
- TestTwo : 5947506
답변
JUnit 4 :
- 를 들어 클래스에서 테스트 , A의 초기화
@Before
캐치 실패에, 방법. - 들어 다른 클래스 , 선언에 초기화 …
- … 간결성
final
을 위해 질문에 명시된대로 필드를 표시하기 위해 - … 실패 할 수있는 복잡한 초기화 가 아니라면 ,이 경우를 사용
@Before
하여 실패를 포착합니다.
- … 간결성
- 들어 글로벌 상태 (특히. 느린 초기화 데이터베이스 같은)를 사용
@BeforeClass
하지만, 조심 시험 사이의 종속성. - 단일 테스트에 사용되는 객체의 초기화는 물론 테스트 메서드 자체에서 수행되어야합니다.
@Before
메서드 또는 테스트 메서드 에서 초기화 하면 실패에 대한 더 나은 오류보고를 얻을 수 있습니다. 이것은 테스트 대상 클래스 (깨질 수 있음)를 인스턴스화하는 데 특히 유용하지만 파일 시스템 액세스 ( “파일을 찾을 수 없음”) 또는 데이터베이스에 연결 ( “연결 거부”)과 같은 외부 시스템을 호출하는 데에도 유용합니다.
이다 허용 간단한 표준 항상 사용 가질 @Before
선언에 항상 초기화 (삭제 오류하지만 자세한 정보) 또는 (간결을하지만 혼란 오류를 제공) 복잡한 코딩 규칙을 따라야하기 어려운 있기 때문에, 이것은 큰 문제가되지 않습니다.
초기화 setUp
는 JUnit 3의 유물로, 모든 테스트 인스턴스가 열심히 초기화되어 값 비싼 초기화를 수행하면 문제 (속도, 메모리, 리소스 고갈)가 발생합니다. 따라서 모범 사례는 setUp
테스트가 실행될 때만 실행되는 에서 값 비싼 초기화를 수행하는 것입니다. 이것은 더 이상 적용되지 않으므로을 사용할 필요가 훨씬 적습니다 setUp
.
여기에는 특히 Craig P. Motlin (질문 자체 및 자체 답변), Moss Collum (테스트중인 클래스) 및 dsaff가 주도한 몇 가지 다른 답변이 요약되어 있습니다.
답변
JUnit 3에서 필드 이니셜 라이저는 테스트가 실행되기 전에 테스트 메소드 당 한 번 실행 됩니다. 필드 값이 메모리에서 작고 설정 시간이 거의 걸리지 않고 전역 상태에 영향을주지 않는 한 필드 이니셜 라이저를 사용하는 것은 기술적으로 괜찮습니다. 그러나 이것이 유지되지 않으면 첫 번째 테스트가 실행되기 전에 많은 메모리 또는 필드 설정 시간을 소비하고 메모리가 부족할 수도 있습니다. 이러한 이유로 많은 개발자는 항상 setUp () 메서드에서 필드 값을 설정합니다.이 메서드는 엄격하게 필요하지 않은 경우에도 항상 안전합니다.
JUnit 4에서 테스트 객체 초기화는 테스트 실행 직전에 발생하므로 필드 이니셜 라이저를 사용하는 것이 더 안전하고 권장되는 스타일입니다.
답변
귀하의 경우 (목록 작성) 실제로 차이가 없습니다. 하지만 일반적으로 setUp ()을 사용하는 것이 좋습니다. Junit이 예외를 올바르게보고하는 데 도움이되기 때문입니다. 테스트의 생성자 / 이니셜 라이저에서 예외가 발생하면 테스트 실패 입니다. 그러나 설정 중에 예외가 발생하면 테스트 설정시 일부 문제로 생각하는 것이 당연하며 junit은이를 적절하게보고합니다.
답변
나는 가장 자주 설정 방법을 사용하지 않는 가독성을 선호합니다. 기본 설정 작업에 시간이 오래 걸리고 각 테스트 내에서 반복되는 경우 예외를 만듭니다.
그 시점에서 @BeforeClass
주석을 사용하여 해당 기능을 설정 방법으로 이동합니다 (나중에 최적화).
@BeforeClass
설정 방법을 사용한 최적화의 예 : 일부 데이터베이스 기능 테스트에 dbunit을 사용합니다. 설정 방법은 데이터베이스를 알려진 상태 (매우 느리게 … 데이터 양에 따라 30 초-2 분)로 설정합니다. 주석이 달린 설정 방법으로이 데이터를로드 @BeforeClass
한 다음 각 테스트 내에서 데이터베이스를 다시로드 / 초기화하는 것과는 반대로 동일한 데이터 집합에 대해 10-20 개의 테스트를 실행합니다.
Junit 3.8 (예제에 표시된대로 TestCase 확장)을 사용하려면 주석을 추가하는 것보다 약간 더 많은 코드를 작성해야하지만 “클래스 설정 전에 한 번 실행”은 여전히 가능합니다.